awesome-wm-widgets/_tips/awesome-buttons.md

6.7 KiB

layout
page

Awesome Buttons

Here I want to share a way of creating fancy looking interactive buttons:

![awesome-buttons]({{ "/assets/img/tips/awesome-buttons.png" | relative_url }}){:.center-image}

Prerequisite

Add the section below to your rc.lua, which will be used as a canvas:

local buttons_example = wibox {
    visible = true,
    bg = '#2E3440',
    ontop = true,
    height = 1E00,
    width = 200,
    shape = function(cr, width, height)
        gears.shape.rounded_rect(cr, width, height, 3)
    end
}

local button = {} -- <- code examples go here

buttons_example:setup {
    button,
    valigh = 'center',
    layout = wibox.container.place
}

awful.placement.top(buttons_example, { margins = {top = 40}, parent = awful.screen.focused()})

Button

Buttons usually consist of text, icon or both. Let's start with a simple text button:

```lua local button = wibox.widget{ text = "I'm a button!", widget = wibox.widget.textbox } ```
![awesome-buttons]({{ "/assets/img/tips/awesome-buttons/ab-1.png" | relative_url }}){:.center-image}

For the image button replace the textbox by the imagebox. For the icon and text button, combine both of them in the fixed horizontal layout:

{
    {
        {
            image = icon,
            resize = true,
            forced_height = 20,
            widget = wibox.widget.imagebox
        },
        margins = 4,
        widget = wibox.container.margin
    },
    {
        {
            text = 'Click me!',
            widget = wibox.widget.textbox
        },
        top = 4, bottom = 4, right = 8,
        widget = wibox.container.margin
    },
    layout = wibox.layout.align.horizontal
}

Next step is to add some margins and a background. For background we'll use wibox.container.background, it allows to set the background itself (bg = '#4C566A'). By using alpha channel it's possible to make a transparent background (bg = '#00000000') which will be useful in the next step when adding hover effect. Apart from a background, it also sets shape and borders, which allows to create 'outline' buttons (shape_border_width = 1, shape_border_color = '#4C566A'). These three types are shown in the example below:

```lua local button = wibox.widget{ { { text = "I'm a button!", widget = wibox.widget.textbox }, top = 4, bottom = 4, left = 8, right = 8, widget = wibox.container.margin }, bg = '#4C566A', -- basic bg = '#00000000', --tranparent shape_border_width = 1, shape_border_color = '#4C566A', -- outline shape = function(cr, width, height) gears.shape.rounded_rect(cr, width, height, 4) end, widget = wibox.container.background } ```
![awesome-buttons]({{ "/assets/img/tips/awesome-buttons/ab-2.png" | relative_url }}){:.center-image} ![awesome-buttons]({{ "/assets/img/tips/awesome-buttons/ab-3.png" | relative_url }}){:.center-image} ![awesome-buttons]({{ "/assets/img/tips/awesome-buttons/ab-4.png" | relative_url }}){:.center-image}

Hover effects

Now the button looks like a button, but doesn't behave like one. First thing is to change colors when mouse cursor hovers over the button. To do it we can leverage the signals: mouse::enter and mouse::leave. When using signals, we have access the to widget, so it's pretty simple to change the color. Below I use alpha channel to darken the color of the button a bit, for all three types of button discussed above it works well:

```lua button_basic:connect_signal("mouse::enter", function(c) c:set_bg("#00000066") end) button_basic:connect_signal("mouse::leave", function(c) c:set_bg('#4C566A') end) button_tranparent:connect_signal("mouse::enter", function(c) c:set_bg("#00000066") end) button_tranparent:connect_signal("mouse::leave", function(c) c:set_bg('#00000000') end) button_outline:connect_signal("mouse::enter", function(c) c:set_bg("#00000066") end) button_outline:connect_signal("mouse::leave", function(c) c:set_bg('#00000000') end) ```
![awesome-buttons]({{ "/assets/img/tips/awesome-buttons/ab-5.gif" | relative_url }}){:.center-image}

Note that you need to set the initial color of the button for the mouse::leave signal.

Second thing is to change the cursor:

```lua local old_cursor, old_wibox button_basic:connect_signal("mouse::enter", function(c) c:set_bg("#00000066") local wb = mouse.current_wibox old_cursor, old_wibox = wb.cursor, wb wb.cursor = "hand1" end) button_basic:connect_signal("mouse::leave", function(c) c:set_bg('#4C566A') if old_wibox then old_wibox.cursor = old_cursor old_wibox = nil end end) ```
![awesome-buttons]({{ "/assets/img/tips/awesome-buttons/ab-6.gif" | relative_url }}){:.center-image}

Button click effects

Another effect is changing the color of the button when the button is pressed/released:

```lua button_basic:connect_signal("button::press", function(c) c:set_bg("#000000") end) button_basic:connect_signal("button::release", function(c) c:set_bg('#00000066') end) ```
![awesome-buttons]({{ "/assets/img/tips/awesome-buttons/ab-7.gif" | relative_url }}){:.center-image}

Onclick action

To perform some action when the button is clicked you need to handle press/release signal. The important part here is to properly handle the button which was used, otherwise any click will trigger the function execution:

button_basic:connect_signal("button::press", function(c, _, _, button) 
    if button == 1 then  naughty.notify{text = 'Left click'} 
    elseif button == 2 then naughty.notify{text = 'Wheel click'} 
    elseif button == 3 then naughty.notify{text = 'Right click'} 
    end
end)

Summary

As you can see it is pretty easy to create interactive nice-looking buttons. But if you use multiple buttons in your widget, you may have quite a lot of boilerplate code. To solve this issue I created an awesome-buttons library, which simplifies this process:

awesomebuttons.with_text{ type = 'flat', text = 'Ola', color = '#f8f', text_size = 12 },
awesomebuttons.with_icon{ type = 'outline', icon = 'zoom-in', color = '#f8f', shape = 'rounded_rect' },
awesomebuttons.with_icon_and_text{ icon = 'check-circle', text = 'With Icon!', color = '#f48' },

Please refer to the repo's README for more details. It is still in progress.