Coverage for src / lexigram / ui / molecules / popover.py: 46%

13 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-08-10 04:11 +0800

1from __future__ import annotations 

2 

3from typing import Any 

4 

5from lexigram.ui.core.base import Component, el, raw, render_to_string 

6 

7 

8class Popover(Component): 

9 """ 

10 Popover component for richer content than tooltips. 

11 """ 

12 

13 def __init__( 

14 self, 

15 trigger: str | Any, 

16 position: str = "bottom", 

17 width: str = "md", 

18 **props, 

19 ) -> None: 

20 super().__init__(trigger=trigger, position=position, width=width, **props) 

21 self.trigger = trigger 

22 self.position = position 

23 self.width = width 

24 

25 def render(self) -> Any: 

26 width_cls = {"sm": "w-48", "md": "w-72", "lg": "w-96", "xl": "w-[30rem]"}.get( 

27 self.width, 

28 "w-72", 

29 ) 

30 

31 children_html = [ 

32 raw(render_to_string(c)) 

33 if hasattr(c, "__html__") or hasattr(c, "render") 

34 else str(c) 

35 for c in self.children 

36 ] 

37 

38 return el( 

39 "div", 

40 {"x-data": "{ open: false }", "class": "relative inline-block"}, 

41 el( 

42 "div", 

43 { 

44 "x-on:click": "open = !open", 

45 "x-on:click.outside": "open = false", 

46 "class": "cursor-pointer", 

47 "tabindex": "0", 

48 "role": "button", 

49 ":aria-expanded": "open", 

50 }, 

51 self.trigger, 

52 ), 

53 el( 

54 "div", 

55 { 

56 "x-show": "open", 

57 "x-transition": "", 

58 "class": f"absolute z-10 mt-2 {width_cls} px-4 transform -translate-x-1/2 left-1/2 sm:px-0 lg:max-w-3xl", 

59 }, 

60 el( 

61 "div", 

62 { 

63 "class": "overflow-hidden rounded-lg shadow-lg ring-1 ring-border/10", 

64 }, 

65 el( 

66 "div", 

67 {"class": "relative grid bg-popover text-popover-foreground p-4 gap-4"}, 

68 *children_html, 

69 ), 

70 ), 

71 ), 

72 )