phlex_ui 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/lib/phlex_ui/alert/description.rb +17 -0
  3. data/lib/phlex_ui/alert/title.rb +17 -0
  4. data/lib/phlex_ui/alert.rb +36 -0
  5. data/lib/phlex_ui/alert_dialog/action.rb +17 -0
  6. data/lib/phlex_ui/alert_dialog/cancel.rb +21 -0
  7. data/lib/phlex_ui/alert_dialog/content.rb +45 -0
  8. data/lib/phlex_ui/alert_dialog/description.rb +17 -0
  9. data/lib/phlex_ui/alert_dialog/footer.rb +17 -0
  10. data/lib/phlex_ui/alert_dialog/header.rb +17 -0
  11. data/lib/phlex_ui/alert_dialog/title.rb +17 -0
  12. data/lib/phlex_ui/alert_dialog/trigger.rb +18 -0
  13. data/lib/phlex_ui/alert_dialog.rb +26 -0
  14. data/lib/phlex_ui/aspect_ratio.rb +33 -0
  15. data/lib/phlex_ui/avatar/fallback.rb +17 -0
  16. data/lib/phlex_ui/avatar/image.rb +26 -0
  17. data/lib/phlex_ui/avatar.rb +49 -0
  18. data/lib/phlex_ui/badge.rb +46 -62
  19. data/lib/phlex_ui/button.rb +86 -63
  20. data/lib/phlex_ui/card/content.rb +17 -0
  21. data/lib/phlex_ui/card/description.rb +17 -0
  22. data/lib/phlex_ui/card/footer.rb +17 -0
  23. data/lib/phlex_ui/card/header.rb +17 -0
  24. data/lib/phlex_ui/card/title.rb +17 -0
  25. data/lib/phlex_ui/card.rb +17 -0
  26. data/lib/phlex_ui/checkbox.rb +18 -0
  27. data/lib/phlex_ui/clipboard/popover.rb +36 -0
  28. data/lib/phlex_ui/clipboard/source.rb +19 -0
  29. data/lib/phlex_ui/clipboard/trigger.rb +20 -0
  30. data/lib/phlex_ui/clipboard.rb +39 -0
  31. data/lib/phlex_ui/codeblock.rb +105 -0
  32. data/lib/phlex_ui/collapsible/content.rb +18 -0
  33. data/lib/phlex_ui/collapsible/trigger.rb +19 -0
  34. data/lib/phlex_ui/collapsible.rb +25 -0
  35. data/lib/phlex_ui/context_menu/content.rb +25 -0
  36. data/lib/phlex_ui/context_menu/item.rb +66 -0
  37. data/lib/phlex_ui/context_menu/label.rb +24 -0
  38. data/lib/phlex_ui/context_menu/separator.rb +19 -0
  39. data/lib/phlex_ui/context_menu/trigger.rb +20 -0
  40. data/lib/phlex_ui/context_menu.rb +26 -0
  41. data/lib/phlex_ui/dialog/content.rb +78 -0
  42. data/lib/phlex_ui/dialog/description.rb +17 -0
  43. data/lib/phlex_ui/dialog/footer.rb +17 -0
  44. data/lib/phlex_ui/dialog/header.rb +17 -0
  45. data/lib/phlex_ui/dialog/middle.rb +17 -0
  46. data/lib/phlex_ui/dialog/title.rb +17 -0
  47. data/lib/phlex_ui/dialog/trigger.rb +19 -0
  48. data/lib/phlex_ui/dialog.rb +25 -0
  49. data/lib/phlex_ui/dropdown_menu/content.rb +22 -0
  50. data/lib/phlex_ui/dropdown_menu/item.rb +28 -0
  51. data/lib/phlex_ui/dropdown_menu/label.rb +17 -0
  52. data/lib/phlex_ui/dropdown_menu/separator.rb +19 -0
  53. data/lib/phlex_ui/dropdown_menu/trigger.rb +17 -0
  54. data/lib/phlex_ui/dropdown_menu.rb +26 -0
  55. data/lib/phlex_ui/form/item.rb +17 -0
  56. data/lib/phlex_ui/form/spacer.rb +17 -0
  57. data/lib/phlex_ui/form.rb +34 -0
  58. data/lib/phlex_ui/hint.rb +17 -0
  59. data/lib/phlex_ui/hover_card/content.rb +22 -0
  60. data/lib/phlex_ui/hover_card/trigger.rb +19 -0
  61. data/lib/phlex_ui/hover_card.rb +27 -0
  62. data/lib/phlex_ui/input.rb +29 -0
  63. data/lib/phlex_ui/input_error.rb +17 -0
  64. data/lib/phlex_ui/label.rb +17 -0
  65. data/lib/phlex_ui/link.rb +97 -0
  66. data/lib/phlex_ui/popover/content.rb +22 -0
  67. data/lib/phlex_ui/popover/trigger.rb +19 -0
  68. data/lib/phlex_ui/popover.rb +25 -0
  69. data/lib/phlex_ui/shortcut_key.rb +17 -0
  70. data/lib/phlex_ui/table/body.rb +17 -0
  71. data/lib/phlex_ui/table/builder.rb +77 -0
  72. data/lib/phlex_ui/table/caption.rb +17 -0
  73. data/lib/phlex_ui/table/cell.rb +17 -0
  74. data/lib/phlex_ui/table/footer.rb +17 -0
  75. data/lib/phlex_ui/table/head.rb +17 -0
  76. data/lib/phlex_ui/table/header.rb +17 -0
  77. data/lib/phlex_ui/table/row.rb +17 -0
  78. data/lib/phlex_ui/table.rb +19 -0
  79. data/lib/phlex_ui/tabs/content.rb +26 -0
  80. data/lib/phlex_ui/tabs/list.rb +17 -0
  81. data/lib/phlex_ui/tabs/trigger.rb +28 -0
  82. data/lib/phlex_ui/tabs.rb +25 -0
  83. data/lib/phlex_ui/theme_toggle.rb +41 -0
  84. data/lib/phlex_ui/tooltip/content.rb +22 -0
  85. data/lib/phlex_ui/tooltip/trigger.rb +17 -0
  86. data/lib/phlex_ui/tooltip.rb +25 -0
  87. data/lib/phlex_ui/typography/blockquote.rb +17 -0
  88. data/lib/phlex_ui/typography/h1.rb +17 -0
  89. data/lib/phlex_ui/typography/h2.rb +17 -0
  90. data/lib/phlex_ui/typography/h3.rb +17 -0
  91. data/lib/phlex_ui/typography/h4.rb +17 -0
  92. data/lib/phlex_ui/typography/inline_code.rb +17 -0
  93. data/lib/phlex_ui/typography/large.rb +17 -0
  94. data/lib/phlex_ui/typography/lead.rb +17 -0
  95. data/lib/phlex_ui/typography/list.rb +47 -0
  96. data/lib/phlex_ui/typography/list_item.rb +17 -0
  97. data/lib/phlex_ui/typography/muted.rb +17 -0
  98. data/lib/phlex_ui/typography/p.rb +17 -0
  99. data/lib/phlex_ui/typography/small.rb +17 -0
  100. metadata +112 -2
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class Link < Base
5
+ def initialize(href: "#", variant: :link, size: :md, icon: false, **attrs)
6
+ @href = href
7
+ @variant = variant.to_sym
8
+ @size = size.to_sym
9
+ @icon = icon
10
+ super(**attrs)
11
+ end
12
+
13
+ def template(&)
14
+ a(href: @href, **attrs, &)
15
+ end
16
+
17
+ private
18
+
19
+ def size_classes
20
+ if @icon
21
+ case @size
22
+ when :sm then "h-6 w-6"
23
+ when :md then "h-9 w-9"
24
+ when :lg then "h-10 w-10"
25
+ when :xl then "h-12 w-12"
26
+ end
27
+ else
28
+ case @size
29
+ when :sm then "px-3 py-1.5 h-8 text-xs"
30
+ when :md then "px-4 py-2 h-9 text-sm"
31
+ when :lg then "px-4 py-2 h-10 text-base"
32
+ when :xl then "px-6 py-3 h-12 text-base"
33
+ end
34
+ end
35
+ end
36
+
37
+ def primary_classes
38
+ tokens(
39
+ "whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-text shadow hover:bg-primary/90",
40
+ size_classes
41
+ )
42
+ end
43
+
44
+ def link_classes
45
+ tokens(
46
+ "whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 text-primary underline-offset-4 hover:underline",
47
+ size_classes
48
+ )
49
+ end
50
+
51
+ def secondary_classes
52
+ tokens(
53
+ "whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-muted-background text-text shadow-sm hover:bg-opacity-80",
54
+ size_classes
55
+ )
56
+ end
57
+
58
+ def destructive_classes
59
+ tokens(
60
+ "whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-destructive text-white shadow-sm hover:bg-destructive/90",
61
+ size_classes
62
+ )
63
+ end
64
+
65
+ def outline_classes
66
+ tokens(
67
+ "whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 border border-input bg-background shadow-sm hover:bg-accent-background hover:text-accent-text",
68
+ size_classes
69
+ )
70
+ end
71
+
72
+ def ghost_classes
73
+ tokens(
74
+ "whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 hover:bg-accent-background hover:text-accent-text",
75
+ size_classes
76
+ )
77
+ end
78
+
79
+ def default_classes
80
+ case @variant
81
+ when :primary then primary_classes
82
+ when :link then link_classes
83
+ when :secondary then secondary_classes
84
+ when :destructive then destructive_classes
85
+ when :outline then outline_classes
86
+ when :ghost then ghost_classes
87
+ end
88
+ end
89
+
90
+ def default_attrs
91
+ {
92
+ type: "button",
93
+ class: default_classes,
94
+ }
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class Popover::Content < Base
5
+ def template(&)
6
+ template_tag(data: { popover_target: "content" }) do
7
+ div(**attrs, &)
8
+ end
9
+ end
10
+
11
+ private
12
+
13
+ def default_attrs
14
+ {
15
+ data: {
16
+ state: :open
17
+ },
18
+ class: "z-50 rounded-md border bg-background p-2 text-text shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2"
19
+ }
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class Popover::Trigger < Base
5
+ def template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ data: {
14
+ popover_target: 'trigger'
15
+ }
16
+ }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class Popover < Base
5
+ def initialize(options: {}, **attrs)
6
+ @options = options
7
+ super(**attrs)
8
+ end
9
+
10
+ def template(&)
11
+ div(**attrs, &)
12
+ end
13
+
14
+ private
15
+
16
+ def default_attrs
17
+ {
18
+ data: {
19
+ controller: "popover",
20
+ popover_options_value: @options.to_json
21
+ }
22
+ }
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class ShortcutKey < Base
5
+ def template(&)
6
+ kbd(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted-background px-1.5 font-mono text-[10px] font-medium text-muted-text opacity-100"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class Table::Body < Base
5
+ def template(&)
6
+ tbody(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "[&_tr:last-child]:border-0"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class Table::Builder < Base
5
+ include Phlex::DeferredRender
6
+
7
+ Column = Struct.new(:header, :header_attrs, :footer, :footer_attrs, :block, keyword_init: true)
8
+
9
+ def initialize(records = [], caption: nil, **attrs)
10
+ @records = records
11
+ @columns = []
12
+ @caption = caption
13
+ super(**attrs)
14
+ end
15
+
16
+ def template(&block)
17
+ render PhlexUI::Table.new(**attrs) do
18
+ header
19
+ body
20
+ caption if @caption
21
+ footer if @columns.any?(&:footer)
22
+ end
23
+ end
24
+
25
+ def column(header, footer = nil, header_attrs: {}, footer_attrs: {}, &block)
26
+ @columns << Column.new(
27
+ header: header,
28
+ header_attrs: header_attrs,
29
+ footer: footer,
30
+ footer_attrs: footer_attrs,
31
+ block: block
32
+ )
33
+ end
34
+
35
+ def header
36
+ render PhlexUI::Table::Header.new do
37
+ render PhlexUI::Table::Row.new do
38
+ @columns.each do |column|
39
+ render PhlexUI::Table::Head.new(**column.header_attrs) do
40
+ column.header
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ def body
48
+ render PhlexUI::Table::Body.new do
49
+ @records.each do |record|
50
+ render PhlexUI::Table::Row.new do
51
+ @columns.each do |column|
52
+ render PhlexUI::Table::Cell.new do
53
+ column.block.call(record)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ def footer
62
+ render PhlexUI::Table::Footer.new do
63
+ render PhlexUI::Table::Row.new do
64
+ @columns.each do |column|
65
+ render PhlexUI::Table::Head.new(**column.footer_attrs) do
66
+ column.footer
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ def caption
74
+ render PhlexUI::Table::Caption.new { @caption }
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class Table::Caption < Base
5
+ def template(&)
6
+ caption(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "mt-4 text-sm text-muted-text"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class Table::Cell < Base
5
+ def template(&)
6
+ td(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class Table::Footer < Base
5
+ def template(&)
6
+ tfoot(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "border-t bg-muted-background bg-opacity-50 font-medium[& amp;>tr]:last:border-b-0"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class Table::Head < Base
5
+ def template(&)
6
+ th(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "h-10 px-2 text-left align-middle font-medium text-muted-text [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class Table::Header < Base
5
+ def template(&)
6
+ thead(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "[&_tr]:border-b"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class Table::Row < Base
5
+ def template(&)
6
+ tr(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "border-b transition-colors hover:bg-muted-background hover:bg-opacity-50 data-[state=selected]:bg-muted-background"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class Table < Base
5
+ def template(&)
6
+ div(class: "relative w-full overflow-auto") do
7
+ table(**attrs, &)
8
+ end
9
+ end
10
+
11
+ private
12
+
13
+ def default_attrs
14
+ {
15
+ class: "w-full caption-bottom text-sm"
16
+ }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class Tabs::Content < Base
5
+ def initialize(value:, **attrs)
6
+ @value = value
7
+ super(**attrs)
8
+ end
9
+
10
+ def template(&)
11
+ div(**attrs, &)
12
+ end
13
+
14
+ private
15
+
16
+ def default_attrs
17
+ {
18
+ data: {
19
+ tabs_target: :content,
20
+ value: @value
21
+ },
22
+ class: "mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 hidden",
23
+ }
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class Tabs::List < Base
5
+ def template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "inline-flex h-9 items-center justify-center rounded-lg bg-muted-background p-1 text-muted-text"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class Tabs::Trigger < Base
5
+ def initialize(value:, **attrs)
6
+ @value = value
7
+ super(**attrs)
8
+ end
9
+
10
+ def template(&)
11
+ button(**attrs, &)
12
+ end
13
+
14
+ private
15
+
16
+ def default_attrs
17
+ {
18
+ type: :button,
19
+ data: {
20
+ tabs_target: :trigger,
21
+ action: "click->tabs#show",
22
+ value: @value
23
+ },
24
+ class: "inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-text data-[state=active]:shadow"
25
+ }
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class Tabs < Base
5
+ def initialize(default: nil, **attrs)
6
+ @default = default
7
+ super(**attrs)
8
+ end
9
+
10
+ def template(&)
11
+ div(**attrs, &)
12
+ end
13
+
14
+ private
15
+
16
+ def default_attrs
17
+ {
18
+ data: {
19
+ controller: 'tabs',
20
+ tabs_default_value_value: @default
21
+ }
22
+ }
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class ThemeToggle < Base
5
+ def template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ def light_mode(**user_attrs, &)
10
+ light_attrs = PhlexUI::AttributeMerger.new(default_light_attrs, user_attrs).call
11
+ div(**light_attrs, &)
12
+ end
13
+
14
+ def dark_mode(**user_attrs, &)
15
+ dark_attrs = PhlexUI::AttributeMerger.new(default_dark_attrs, user_attrs).call
16
+ div(**dark_attrs, &)
17
+ end
18
+
19
+ private
20
+
21
+ def default_attrs
22
+ {
23
+ data: { controller: 'toggle-theme' }
24
+ }
25
+ end
26
+
27
+ def default_light_attrs
28
+ {
29
+ class: 'dark:hidden',
30
+ data: { action: 'click->toggle-theme#setDarkTheme' }
31
+ }
32
+ end
33
+
34
+ def default_dark_attrs
35
+ {
36
+ class: 'hidden dark:inline-block',
37
+ data: { action: 'click->toggle-theme#setLightTheme' }
38
+ }
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class Tooltip::Content < Base
5
+ def template(&)
6
+ template_tag(data: { popover_target: "content" }) do
7
+ div(**attrs, &)
8
+ end
9
+ end
10
+
11
+ private
12
+
13
+ def default_attrs
14
+ {
15
+ data: {
16
+ state: :open # used for animate-in and animate-out on tooltip
17
+ },
18
+ class: "z-50 rounded-md text-sm border bg-background px-2 py-0.5 text-text shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2"
19
+ }
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class Tooltip::Trigger < Base
5
+ def template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ data: { popover_target: 'trigger' }
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class Tooltip < Base
5
+ def initialize(options: {}, **attrs)
6
+ @options = options
7
+ super(**attrs)
8
+ end
9
+
10
+ def template(&)
11
+ div(**attrs, &)
12
+ end
13
+
14
+ private
15
+
16
+ def default_attrs
17
+ {
18
+ data: {
19
+ controller: "popover",
20
+ popover_options_value: @options.to_json
21
+ }
22
+ }
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class Typography::Blockquote < Base
5
+ def template(&)
6
+ blockquote(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "mt-6 border-l-2 pl-6 italic"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class Typography::H1 < Base
5
+ def template(&)
6
+ h1(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "scroll-m-20 text-3xl font-semibold leading-normal lg:leading-normal tracking-tight lg:text-4xl"
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PhlexUI
4
+ class Typography::H2 < Base
5
+ def template(&)
6
+ h2(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ class: "scroll-m-20 text-3xl font-semibold tracking-tight transition-colors first:mt-0"
14
+ }
15
+ end
16
+ end
17
+ end