Coverage for src / lexigram / ui / molecules / alert.py: 100%
21 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-10 04:11 +0800
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-10 04:11 +0800
1from __future__ import annotations
3from typing import Any, Literal
5from lexigram.ui.core.base import Component, el
6from lexigram.ui.molecules.action_button import ActionButton
7from lexigram.ui.styles import get_alert_classes
8from lexigram.ui.styles.tokens import get_semantic_icon
10AlertVariant = Literal["info", "success", "warning", "error", "danger"]
13class Alert(Component):
14 """Alert component for notifications and messages."""
16 def __init__(
17 self,
18 message: str,
19 variant: AlertVariant = "info",
20 dismissible: bool = False,
21 **props,
22 ) -> None:
23 super().__init__(
24 message=message,
25 variant=variant,
26 dismissible=dismissible,
27 **props,
28 )
29 self.message = message
30 self.variant = variant
31 self.dismissible = dismissible
33 def render(self) -> Any:
34 from lexigram.ui.atoms.icons import get_icon
36 variant_cls = get_alert_classes(self.variant)
37 icon_name = get_semantic_icon(self.variant)
39 content = [
40 el(
41 "div",
42 get_icon(icon_name, class_name="w-5 h-5"),
43 class_="mr-2 flex-shrink-0",
44 ),
45 el("span", self.message, class_="flex-1"),
46 ]
48 if self.dismissible:
49 content.append(
50 ActionButton(
51 label="",
52 icon="x",
53 color="ghost",
54 size="sm",
55 type="button",
56 onclick="this.parentElement.remove()",
57 class_="ml-auto text-xl font-bold opacity-50 hover:opacity-100",
58 aria_label="Dismiss alert",
59 ).render(),
60 )
62 return el(
63 "div",
64 *content,
65 class_=f"flex items-center px-4 py-3 rounded-lg border {variant_cls}",
66 role="alert",
67 )