File size: 2,888 Bytes
6ff3d12
18f7b1e
 
 
6ff3d12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18f7b1e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2b894e4
 
 
18f7b1e
 
 
 
 
 
 
 
 
 
 
 
2b894e4
18f7b1e
 
 
 
 
 
2b894e4
18f7b1e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
from typing import Callable, Literal, Any

import mesop as me

from components import helpers


@me.component()
def button(
  label: str | None = None,
  *,
  on_click: Callable[[me.ClickEvent], Any] | None = None,
  type: Literal["raised", "flat", "stroked"] | None = None,
  color: Literal["primary", "accent", "warn"] | None = None,
  disable_ripple: bool = False,
  disabled: bool = False,
  style: me.Style | None = None,
  key: str | None = None,
) -> None:
  me.button(
    label=label,
    on_click=on_click,
    type=type,
    color=color,
    disable_ripple=disable_ripple,
    disabled=disabled,
    key=key,
    style=helpers.merge_styles(me.Style(border_radius=10), style),
  )


@me.component()
def button_toggle(
  labels: list[str],
  selected: str = "",
  on_click: Callable | None = None,
  key: str = "",
):
  """Simple version of Angular Component Button toggle.

  Only supports single selection for now.

  Args:
    labels: Text labels for buttons
    selected: Selected label
    on_click: Event to handle button clicks on the button toggle
    key: The key will be used as as prefix along with the selected label
  """
  with me.box(style=me.Style(display="flex", font_weight="bold", font_size=14)):
    last_index = len(labels) - 1

    for index, label in enumerate(labels):
      if index == 0:
        element = "first"
      elif index == last_index:
        element = "last"
      else:
        element = "default"

      with me.box(
        key=key + "_" + label,
        on_click=on_click,
        style=me.Style(
          align_items="center",
          display="flex",
          # Handle selected case
          background=_SELECTED_BG
          if label == selected
          else me.theme_var("surface-container-lowest"),
          padding=_SELECTED_PADDING if label == selected else _PADDING,
          cursor="default" if label == selected else "pointer",
          # Handle single button case (should just use a button in this case)
          border=_LAST_BORDER if last_index == 0 else _BORDER_MAP[element],
          border_radius=_BORDER_RADIUS if last_index == 0 else _BORDER_RADIUS_MAP[element],
        ),
      ):
        if label in selected:
          me.icon("check")
        me.text(label)


_SELECTED_BG = me.theme_var("primary-container")

_PADDING = me.Padding(left=15, right=15, top=10, bottom=10)
_SELECTED_PADDING = me.Padding(left=15, right=15, top=5, bottom=5)

_BORDER_RADIUS = "20px"

_DEFAULT_BORDER_STYLE = me.BorderSide(width=1, color=me.theme_var("outline"), style="solid")
_BORDER = me.Border(
  left=_DEFAULT_BORDER_STYLE, top=_DEFAULT_BORDER_STYLE, bottom=_DEFAULT_BORDER_STYLE
)
_LAST_BORDER = me.Border.all(_DEFAULT_BORDER_STYLE)

_BORDER_MAP = {
  "first": _BORDER,
  "last": _LAST_BORDER,
  "default": _BORDER,
}

_BORDER_RADIUS_MAP = {
  "first": "20px 0 0 20px",
  "last": "0px 20px 20px 0",
  "default": "0",
}