Skip to content

Feedback Components

Components to provide visual feedback to the user, like loaders or notifications.

pymiro.components.feedback

Feedback components for pymiro.

Badge

Badge(
    text: str,
    variant: str = "info",
    style: dict[str, str] | None = None,
    class_name: str | None = None,
    key: str | None = None,
) -> VNode

Renders a Badge component.

Parameters:

Name Type Description Default
text str

Configuration for text.

required
variant str

Configuration for variant.

'info'
style dict[str, str] | None

Configuration for style.

None
class_name str | None

Configuration for class_name.

None
key str | None

Configuration for key.

None

Returns:

Name Type Description
VNode VNode

The virtual DOM node representing this component.

Example
from pymiro.components import Badge

Badge()
Source code in pymiro/components/feedback.py
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
@component
def Badge(
    text: str,
    variant: str = "info",
    style: dict[str, str] | None = None,
    class_name: str | None = None,
    key: str | None = None,
) -> VNode:
    """
    Renders a Badge component.

    Args:
        text: Configuration for text.
        variant: Configuration for variant.
        style: Configuration for style.
        class_name: Configuration for class_name.
        key: Configuration for key.

    Returns:
        VNode: The virtual DOM node representing this component.

    Example:
        ```python
        from pymiro.components import Badge

        Badge()
        ```
    """
    theme = use_theme()
    c = theme.colors
    t = theme.typography
    s = {
        "padding": f"2px {theme.spacing.sm}px",
        "border-radius": f"{theme.radius.xl}px",
        "font-size": f"{t.size_xs}px",
        "font-weight": str(t.weight_bold),
        "color": c.text_primary,
        "background-color": c.surface,
    }

    if variant == "success":
        s["background-color"] = c.success
        s["color"] = c.success_text
    elif variant == "warning":
        s["background-color"] = c.warning
        s["color"] = c.warning_text
    elif variant == "error":
        s["background-color"] = c.error
        s["color"] = c.error_text
    else:
        s["background-color"] = c.info
        s["color"] = c.info_text

    if style:
        s.update(style)

    props = _build_props({"text": text}, s, class_name)
    return VNode(type="badge", props=props, children=[], key=key)

ProgressBar

ProgressBar(
    value: float,
    color: str | None = None,
    height: int = 8,
    style: dict[str, str] | None = None,
    class_name: str | None = None,
    key: str | None = None,
) -> VNode

Renders a ProgressBar component.

Parameters:

Name Type Description Default
value float

Configuration for value.

required
color str | None

Configuration for color.

None
height int

Configuration for height.

8
style dict[str, str] | None

Configuration for style.

None
class_name str | None

Configuration for class_name.

None
key str | None

Configuration for key.

None

Returns:

Name Type Description
VNode VNode

The virtual DOM node representing this component.

Example
from pymiro.components import ProgressBar

ProgressBar()
Source code in pymiro/components/feedback.py
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
@component
def ProgressBar(
    value: float,
    color: str | None = None,
    height: int = 8,
    style: dict[str, str] | None = None,
    class_name: str | None = None,
    key: str | None = None,
) -> VNode:
    # Progress bar styling is mainly handled by QSS, but we can emit a chunk color property
    # or just rely on QSS entirely if color is None.
    """
    Renders a ProgressBar component.

    Args:
        value: Configuration for value.
        color: Configuration for color.
        height: Configuration for height.
        style: Configuration for style.
        class_name: Configuration for class_name.
        key: Configuration for key.

    Returns:
        VNode: The virtual DOM node representing this component.

    Example:
        ```python
        from pymiro.components import ProgressBar

        ProgressBar()
        ```
    """
    clamped_value = max(0, min(100, int(value)))
    s = {"min-height": f"{height}px", "max-height": f"{height}px"}
    if color is not None:
        # Actually it's hard to set chunk color dynamically without updating QSS,
        # but let's just pass what we can or assume QSS handles it.
        pass

    if style:
        s.update(style)
    props = _build_props({"value": clamped_value}, s, class_name)
    return VNode(type="progressbar", props=props, children=[], key=key)

Spinner

Spinner(
    size: int = 24,
    color: str | None = None,
    style: dict[str, str] | None = None,
    class_name: str | None = None,
    key: str | None = None,
) -> VNode

Renders a Spinner component.

Parameters:

Name Type Description Default
size int

Configuration for size.

24
color str | None

Configuration for color.

None
style dict[str, str] | None

Configuration for style.

None
class_name str | None

Configuration for class_name.

None
key str | None

Configuration for key.

None

Returns:

Name Type Description
VNode VNode

The virtual DOM node representing this component.

Example
from pymiro.components import Spinner

Spinner()
Source code in pymiro/components/feedback.py
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
@component
def Spinner(
    size: int = 24,
    color: str | None = None,
    style: dict[str, str] | None = None,
    class_name: str | None = None,
    key: str | None = None,
) -> VNode:
    """
    Renders a Spinner component.

    Args:
        size: Configuration for size.
        color: Configuration for color.
        style: Configuration for style.
        class_name: Configuration for class_name.
        key: Configuration for key.

    Returns:
        VNode: The virtual DOM node representing this component.

    Example:
        ```python
        from pymiro.components import Spinner

        Spinner()
        ```
    """
    theme = use_theme()
    _c = color if color is not None else theme.colors.primary
    s = {
        "min-width": f"{size}px",
        "min-height": f"{size}px",
        "max-width": f"{size}px",
        "max-height": f"{size}px",
    }
    if style:
        s.update(style)
    s["color"] = _c
    props = _build_props({}, s, class_name)
    return VNode(type="spinner", props=props, children=[], key=key)

Toast

Toast(
    message: str,
    variant: str = "info",
    duration: int = 3000,
    style: dict[str, str] | None = None,
    class_name: str | None = None,
    key: str | None = None,
) -> VNode

Renders a Toast component.

Parameters:

Name Type Description Default
message str

Configuration for message.

required
variant str

Configuration for variant.

'info'
duration int

Configuration for duration.

3000
style dict[str, str] | None

Configuration for style.

None
class_name str | None

Configuration for class_name.

None
key str | None

Configuration for key.

None

Returns:

Name Type Description
VNode VNode

The virtual DOM node representing this component.

Example
from pymiro.components import Toast

Toast()
Source code in pymiro/components/feedback.py
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
@component
def Toast(
    message: str,
    variant: str = "info",
    duration: int = 3000,
    style: dict[str, str] | None = None,
    class_name: str | None = None,
    key: str | None = None,
) -> VNode:
    """
    Renders a Toast component.

    Args:
        message: Configuration for message.
        variant: Configuration for variant.
        duration: Configuration for duration.
        style: Configuration for style.
        class_name: Configuration for class_name.
        key: Configuration for key.

    Returns:
        VNode: The virtual DOM node representing this component.

    Example:
        ```python
        from pymiro.components import Toast

        Toast()
        ```
    """
    theme = use_theme()
    visible = use_signal(True)

    def auto_hide() -> Any:
        task = asyncio.create_task(asyncio.sleep(duration / 1000.0))

        def on_done(t: asyncio.Task[Any]) -> None:
            if not t.cancelled():
                visible.set(False)

        task.add_done_callback(on_done)

        def dispose() -> None:
            task.cancel()

        return dispose

    use_effect(auto_hide)

    if not visible():
        return VNode("spacer", {"style": "display: none"}, [], key)

    c = theme.colors
    s = {
        "padding": f"{theme.spacing.sm}px {theme.spacing.lg}px",
        "border-radius": f"{theme.radius.lg}px",
        "color": c.text_primary,
        "background-color": c.surface,
        "border": f"1px solid {c.border}",
    }

    if variant == "success":
        s["background-color"] = c.success
        s["color"] = c.success_text
        s["border"] = f"1px solid {c.success}"
    elif variant == "warning":
        s["background-color"] = c.warning
        s["color"] = c.warning_text
        s["border"] = f"1px solid {c.warning}"
    elif variant == "error":
        s["background-color"] = c.error
        s["color"] = c.error_text
        s["border"] = f"1px solid {c.error}"
    else:
        # info
        s["background-color"] = c.info
        s["color"] = c.info_text
        s["border"] = f"1px solid {c.info}"

    if style:
        s.update(style)

    props = _build_props({"text": message}, s, class_name)
    return VNode(type="text", props=props, children=[], key=key)