better_ui 0.3.0 → 0.7.0

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 (183) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +257 -212
  3. data/Rakefile +11 -2
  4. data/app/components/better_ui/action_messages_component/action_messages_component.html.erb +48 -0
  5. data/app/components/better_ui/action_messages_component.rb +544 -0
  6. data/app/components/better_ui/application_component.rb +66 -0
  7. data/app/components/better_ui/button_component/button_component.html.erb +31 -0
  8. data/app/components/better_ui/button_component.rb +307 -0
  9. data/app/components/better_ui/card_component/card_component.html.erb +17 -0
  10. data/app/components/better_ui/card_component.rb +460 -0
  11. data/app/components/better_ui/drawer/header_component/header_component.html.erb +24 -0
  12. data/app/components/better_ui/drawer/header_component.rb +238 -0
  13. data/app/components/better_ui/drawer/layout_component/layout_component.html.erb +44 -0
  14. data/app/components/better_ui/drawer/layout_component.rb +270 -0
  15. data/app/components/better_ui/drawer/nav_group_component/nav_group_component.html.erb +10 -0
  16. data/app/components/better_ui/drawer/nav_group_component.rb +155 -0
  17. data/app/components/better_ui/drawer/nav_item_component/nav_item_component.html.erb +13 -0
  18. data/app/components/better_ui/drawer/nav_item_component.rb +225 -0
  19. data/app/components/better_ui/drawer/sidebar_component/sidebar_component.html.erb +17 -0
  20. data/app/components/better_ui/drawer/sidebar_component.rb +263 -0
  21. data/app/components/better_ui/forms/base_component.rb +450 -0
  22. data/app/components/better_ui/forms/checkbox_component/checkbox_component.html.erb +28 -0
  23. data/app/components/better_ui/forms/checkbox_component.rb +419 -0
  24. data/app/components/better_ui/forms/checkbox_group_component/checkbox_group_component.html.erb +40 -0
  25. data/app/components/better_ui/forms/checkbox_group_component.rb +363 -0
  26. data/app/components/better_ui/forms/number_input_component/number_input_component.html.erb +40 -0
  27. data/app/components/better_ui/forms/number_input_component.rb +320 -0
  28. data/app/components/better_ui/forms/password_input_component/password_input_component.html.erb +71 -0
  29. data/app/components/better_ui/forms/password_input_component.rb +206 -0
  30. data/app/components/better_ui/forms/text_input_component/text_input_component.html.erb +40 -0
  31. data/app/components/better_ui/forms/text_input_component.rb +258 -0
  32. data/app/components/better_ui/forms/textarea_component/textarea_component.html.erb +40 -0
  33. data/app/components/better_ui/forms/textarea_component.rb +329 -0
  34. data/app/form_builders/better_ui/ui_form_builder.rb +467 -0
  35. data/app/helpers/better_ui/application_helper.rb +325 -51
  36. data/app/views/layouts/better_ui/application.html.erb +1 -1
  37. data/config/routes.rb +1 -0
  38. data/lib/better_ui/engine.rb +34 -5
  39. data/lib/better_ui/version.rb +1 -1
  40. data/lib/better_ui.rb +32 -4
  41. data/lib/generators/better_ui/install/USAGE +44 -0
  42. data/lib/generators/better_ui/install/install_generator.rb +87 -0
  43. data/lib/generators/better_ui/install/templates/better_ui_theme.css.tt +280 -0
  44. data/lib/tasks/better_ui_tasks.rake +39 -4
  45. metadata +52 -185
  46. data/app/components/better_ui/application/card/component.html.erb +0 -20
  47. data/app/components/better_ui/application/card/component.rb +0 -214
  48. data/app/components/better_ui/application/main/component.html.erb +0 -9
  49. data/app/components/better_ui/application/main/component.rb +0 -123
  50. data/app/components/better_ui/application/navbar/component.html.erb +0 -92
  51. data/app/components/better_ui/application/navbar/component.rb +0 -136
  52. data/app/components/better_ui/application/sidebar/component.html.erb +0 -227
  53. data/app/components/better_ui/application/sidebar/component.rb +0 -130
  54. data/app/components/better_ui/general/accordion/component.html.erb +0 -5
  55. data/app/components/better_ui/general/accordion/component.rb +0 -92
  56. data/app/components/better_ui/general/accordion/item_component.html.erb +0 -12
  57. data/app/components/better_ui/general/accordion/item_component.rb +0 -176
  58. data/app/components/better_ui/general/alert/component.html.erb +0 -32
  59. data/app/components/better_ui/general/alert/component.rb +0 -242
  60. data/app/components/better_ui/general/avatar/component.html.erb +0 -20
  61. data/app/components/better_ui/general/avatar/component.rb +0 -301
  62. data/app/components/better_ui/general/badge/component.html.erb +0 -23
  63. data/app/components/better_ui/general/badge/component.rb +0 -248
  64. data/app/components/better_ui/general/breadcrumb/component.html.erb +0 -15
  65. data/app/components/better_ui/general/breadcrumb/component.rb +0 -187
  66. data/app/components/better_ui/general/button/component.html.erb +0 -34
  67. data/app/components/better_ui/general/button/component.rb +0 -214
  68. data/app/components/better_ui/general/divider/component.html.erb +0 -10
  69. data/app/components/better_ui/general/divider/component.rb +0 -226
  70. data/app/components/better_ui/general/dropdown/component.html.erb +0 -25
  71. data/app/components/better_ui/general/dropdown/component.rb +0 -170
  72. data/app/components/better_ui/general/dropdown/divider_component.html.erb +0 -1
  73. data/app/components/better_ui/general/dropdown/divider_component.rb +0 -41
  74. data/app/components/better_ui/general/dropdown/item_component.html.erb +0 -6
  75. data/app/components/better_ui/general/dropdown/item_component.rb +0 -119
  76. data/app/components/better_ui/general/field/component.html.erb +0 -27
  77. data/app/components/better_ui/general/field/component.rb +0 -37
  78. data/app/components/better_ui/general/heading/component.html.erb +0 -22
  79. data/app/components/better_ui/general/heading/component.rb +0 -257
  80. data/app/components/better_ui/general/icon/component.html.erb +0 -7
  81. data/app/components/better_ui/general/icon/component.rb +0 -239
  82. data/app/components/better_ui/general/input/checkbox/component.html.erb +0 -5
  83. data/app/components/better_ui/general/input/checkbox/component.rb +0 -238
  84. data/app/components/better_ui/general/input/datetime/component.html.erb +0 -5
  85. data/app/components/better_ui/general/input/datetime/component.rb +0 -223
  86. data/app/components/better_ui/general/input/radio/component.html.erb +0 -5
  87. data/app/components/better_ui/general/input/radio/component.rb +0 -230
  88. data/app/components/better_ui/general/input/select/component.html.erb +0 -16
  89. data/app/components/better_ui/general/input/select/component.rb +0 -184
  90. data/app/components/better_ui/general/input/select/select_component.html.erb +0 -5
  91. data/app/components/better_ui/general/input/select/select_component.rb +0 -37
  92. data/app/components/better_ui/general/input/text/component.html.erb +0 -5
  93. data/app/components/better_ui/general/input/text/component.rb +0 -171
  94. data/app/components/better_ui/general/input/textarea/component.html.erb +0 -5
  95. data/app/components/better_ui/general/input/textarea/component.rb +0 -166
  96. data/app/components/better_ui/general/link/component.html.erb +0 -18
  97. data/app/components/better_ui/general/link/component.rb +0 -258
  98. data/app/components/better_ui/general/modal/component.html.erb +0 -5
  99. data/app/components/better_ui/general/modal/component.rb +0 -47
  100. data/app/components/better_ui/general/modal/modal_component.html.erb +0 -52
  101. data/app/components/better_ui/general/modal/modal_component.rb +0 -160
  102. data/app/components/better_ui/general/pagination/component.html.erb +0 -85
  103. data/app/components/better_ui/general/pagination/component.rb +0 -216
  104. data/app/components/better_ui/general/panel/component.html.erb +0 -28
  105. data/app/components/better_ui/general/panel/component.rb +0 -249
  106. data/app/components/better_ui/general/progress/component.html.erb +0 -11
  107. data/app/components/better_ui/general/progress/component.rb +0 -160
  108. data/app/components/better_ui/general/spinner/component.html.erb +0 -35
  109. data/app/components/better_ui/general/spinner/component.rb +0 -93
  110. data/app/components/better_ui/general/table/component.html.erb +0 -5
  111. data/app/components/better_ui/general/table/component.rb +0 -217
  112. data/app/components/better_ui/general/table/tbody_component.html.erb +0 -3
  113. data/app/components/better_ui/general/table/tbody_component.rb +0 -30
  114. data/app/components/better_ui/general/table/td_component.html.erb +0 -3
  115. data/app/components/better_ui/general/table/td_component.rb +0 -44
  116. data/app/components/better_ui/general/table/tfoot_component.html.erb +0 -3
  117. data/app/components/better_ui/general/table/tfoot_component.rb +0 -28
  118. data/app/components/better_ui/general/table/th_component.html.erb +0 -6
  119. data/app/components/better_ui/general/table/th_component.rb +0 -51
  120. data/app/components/better_ui/general/table/thead_component.html.erb +0 -3
  121. data/app/components/better_ui/general/table/thead_component.rb +0 -28
  122. data/app/components/better_ui/general/table/tr_component.html.erb +0 -3
  123. data/app/components/better_ui/general/table/tr_component.rb +0 -30
  124. data/app/components/better_ui/general/tabs/component.html.erb +0 -11
  125. data/app/components/better_ui/general/tabs/component.rb +0 -120
  126. data/app/components/better_ui/general/tabs/panel_component.html.erb +0 -3
  127. data/app/components/better_ui/general/tabs/panel_component.rb +0 -37
  128. data/app/components/better_ui/general/tabs/tab_component.html.erb +0 -13
  129. data/app/components/better_ui/general/tabs/tab_component.rb +0 -111
  130. data/app/components/better_ui/general/tag/component.html.erb +0 -3
  131. data/app/components/better_ui/general/tag/component.rb +0 -104
  132. data/app/components/better_ui/general/tooltip/component.html.erb +0 -7
  133. data/app/components/better_ui/general/tooltip/component.rb +0 -239
  134. data/app/helpers/better_ui/application/components/card/card_helper.rb +0 -96
  135. data/app/helpers/better_ui/application/components/card.rb +0 -11
  136. data/app/helpers/better_ui/application/components/main/main_helper.rb +0 -64
  137. data/app/helpers/better_ui/application/components/navbar/navbar_helper.rb +0 -77
  138. data/app/helpers/better_ui/application/components/sidebar/sidebar_helper.rb +0 -51
  139. data/app/helpers/better_ui/general/components/accordion/accordion_helper.rb +0 -73
  140. data/app/helpers/better_ui/general/components/accordion.rb +0 -11
  141. data/app/helpers/better_ui/general/components/alert/alert_helper.rb +0 -57
  142. data/app/helpers/better_ui/general/components/avatar/avatar_helper.rb +0 -29
  143. data/app/helpers/better_ui/general/components/badge/badge_helper.rb +0 -53
  144. data/app/helpers/better_ui/general/components/breadcrumb/breadcrumb_helper.rb +0 -37
  145. data/app/helpers/better_ui/general/components/button/button_helper.rb +0 -65
  146. data/app/helpers/better_ui/general/components/container/container_helper.rb +0 -60
  147. data/app/helpers/better_ui/general/components/divider/divider_helper.rb +0 -63
  148. data/app/helpers/better_ui/general/components/dropdown/divider_helper.rb +0 -32
  149. data/app/helpers/better_ui/general/components/dropdown/dropdown_helper.rb +0 -79
  150. data/app/helpers/better_ui/general/components/dropdown/item_helper.rb +0 -62
  151. data/app/helpers/better_ui/general/components/field/field_helper.rb +0 -26
  152. data/app/helpers/better_ui/general/components/heading/heading_helper.rb +0 -72
  153. data/app/helpers/better_ui/general/components/icon/icon_helper.rb +0 -16
  154. data/app/helpers/better_ui/general/components/input/checkbox/checkbox_helper.rb +0 -81
  155. data/app/helpers/better_ui/general/components/input/datetime/datetime_helper.rb +0 -91
  156. data/app/helpers/better_ui/general/components/input/radio/radio_helper.rb +0 -79
  157. data/app/helpers/better_ui/general/components/input/radio_group/radio_group_helper.rb +0 -124
  158. data/app/helpers/better_ui/general/components/input/select/select_helper.rb +0 -70
  159. data/app/helpers/better_ui/general/components/input/text/text_helper.rb +0 -138
  160. data/app/helpers/better_ui/general/components/input/textarea/textarea_helper.rb +0 -73
  161. data/app/helpers/better_ui/general/components/link/link_helper.rb +0 -89
  162. data/app/helpers/better_ui/general/components/modal/modal_helper.rb +0 -85
  163. data/app/helpers/better_ui/general/components/modal.rb +0 -11
  164. data/app/helpers/better_ui/general/components/pagination/pagination_helper.rb +0 -82
  165. data/app/helpers/better_ui/general/components/panel/panel_helper.rb +0 -83
  166. data/app/helpers/better_ui/general/components/progress/progress_helper.rb +0 -53
  167. data/app/helpers/better_ui/general/components/spinner/spinner_helper.rb +0 -19
  168. data/app/helpers/better_ui/general/components/table/table_helper.rb +0 -53
  169. data/app/helpers/better_ui/general/components/table/tbody_helper.rb +0 -13
  170. data/app/helpers/better_ui/general/components/table/td_helper.rb +0 -19
  171. data/app/helpers/better_ui/general/components/table/tfoot_helper.rb +0 -13
  172. data/app/helpers/better_ui/general/components/table/th_helper.rb +0 -19
  173. data/app/helpers/better_ui/general/components/table/thead_helper.rb +0 -13
  174. data/app/helpers/better_ui/general/components/table/tr_helper.rb +0 -13
  175. data/app/helpers/better_ui/general/components/tabs/panel_helper.rb +0 -62
  176. data/app/helpers/better_ui/general/components/tabs/tab_helper.rb +0 -55
  177. data/app/helpers/better_ui/general/components/tabs/tabs_helper.rb +0 -95
  178. data/app/helpers/better_ui/general/components/tag/tag_helper.rb +0 -26
  179. data/app/helpers/better_ui/general/components/tooltip/tooltip_helper.rb +0 -60
  180. data/app/jobs/better_ui/application_job.rb +0 -4
  181. data/app/mailers/better_ui/application_mailer.rb +0 -6
  182. data/config/initializers/lookbook.rb +0 -23
  183. data/lib/better_ui/railtie.rb +0 -20
@@ -0,0 +1,307 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterUi
4
+ class ButtonComponent < ApplicationComponent
5
+ renders_one :icon_before
6
+ renders_one :icon_after
7
+
8
+ SIZES = {
9
+ xs: { padding: "px-2 py-1", text: "text-xs", icon: "w-3 h-3", gap: "gap-1" },
10
+ sm: { padding: "px-3 py-1.5", text: "text-sm", icon: "w-4 h-4", gap: "gap-1.5" },
11
+ md: { padding: "px-4 py-2", text: "text-base", icon: "w-5 h-5", gap: "gap-2" },
12
+ lg: { padding: "px-5 py-2.5", text: "text-lg", icon: "w-6 h-6", gap: "gap-2.5" },
13
+ xl: { padding: "px-6 py-3", text: "text-xl", icon: "w-7 h-7", gap: "gap-3" }
14
+ }.freeze
15
+
16
+ STYLES = %i[solid outline ghost soft].freeze
17
+ TYPES = %i[button submit reset].freeze
18
+
19
+ def initialize(
20
+ variant: :primary,
21
+ style: :solid,
22
+ size: :md,
23
+ show_loader: false,
24
+ show_loader_on_click: false,
25
+ disabled: false,
26
+ type: :button,
27
+ href: nil,
28
+ target: nil,
29
+ rel: nil,
30
+ method: nil,
31
+ container_classes: nil,
32
+ **options
33
+ )
34
+ @variant = validate_variant(variant)
35
+ @style = validate_style(style)
36
+ @size = validate_size(size)
37
+ @show_loader = show_loader
38
+ @show_loader_on_click = show_loader_on_click
39
+ @disabled = disabled
40
+ @type = validate_type(type) unless href
41
+ @href = href
42
+ @target = target
43
+ @rel = compute_rel(target, rel)
44
+ @method = method
45
+ @container_classes = container_classes
46
+ @options = options
47
+ end
48
+
49
+ def link?
50
+ @href.present?
51
+ end
52
+
53
+ private
54
+
55
+ attr_reader :variant, :style, :size, :show_loader, :show_loader_on_click, :disabled, :type,
56
+ :href, :target, :rel, :method, :container_classes, :options
57
+
58
+ def component_classes
59
+ css_classes([
60
+ base_classes,
61
+ style_classes,
62
+ size_classes,
63
+ state_classes,
64
+ @container_classes
65
+ ].flatten.compact)
66
+ end
67
+
68
+ def component_attributes
69
+ link? ? link_attributes : button_attributes
70
+ end
71
+
72
+ def button_attributes
73
+ data_attrs = {
74
+ controller: "better-ui--button",
75
+ action: "click->better-ui--button#handleClick"
76
+ }
77
+
78
+ data_attrs[:"better-ui--button-show-loader-on-click-value"] = @show_loader_on_click if @show_loader_on_click
79
+
80
+ {
81
+ type: @type,
82
+ disabled: @disabled || @show_loader,
83
+ data: data_attrs,
84
+ **@options
85
+ }
86
+ end
87
+
88
+ def link_attributes
89
+ data_attrs = {
90
+ controller: "better-ui--button",
91
+ action: "click->better-ui--button#handleClick"
92
+ }
93
+
94
+ data_attrs[:"better-ui--button-show-loader-on-click-value"] = @show_loader_on_click if @show_loader_on_click
95
+ data_attrs[:turbo_method] = @method if @method
96
+
97
+ attrs = {
98
+ href: disabled_or_loading? ? nil : @href,
99
+ target: @target,
100
+ rel: @rel,
101
+ data: data_attrs,
102
+ **@options
103
+ }
104
+
105
+ if disabled_or_loading?
106
+ attrs[:"aria-disabled"] = "true"
107
+ attrs[:tabindex] = "-1"
108
+ end
109
+
110
+ attrs.compact
111
+ end
112
+
113
+ def disabled_or_loading?
114
+ @disabled || @show_loader
115
+ end
116
+
117
+ def compute_rel(target, rel)
118
+ return rel if rel.present?
119
+ return "noopener noreferrer" if target == "_blank"
120
+ nil
121
+ end
122
+
123
+ def base_classes
124
+ ring_class = case @variant
125
+ when :primary then "focus:ring-primary-500"
126
+ when :secondary then "focus:ring-secondary-500"
127
+ when :accent then "focus:ring-accent-500"
128
+ when :success then "focus:ring-success-500"
129
+ when :danger then "focus:ring-danger-500"
130
+ when :warning then "focus:ring-warning-500"
131
+ when :info then "focus:ring-info-500"
132
+ when :light then "focus:ring-grayscale-400"
133
+ when :dark then "focus:ring-grayscale-600"
134
+ end
135
+
136
+ [
137
+ "inline-flex items-center justify-center",
138
+ "font-medium rounded-lg",
139
+ "transition-all duration-200",
140
+ "focus:outline-none focus:ring-2 focus:ring-offset-2",
141
+ ring_class
142
+ ]
143
+ end
144
+
145
+ def style_classes
146
+ case @style
147
+ when :solid then solid_classes
148
+ when :outline then outline_classes
149
+ when :ghost then ghost_classes
150
+ when :soft then soft_classes
151
+ end
152
+ end
153
+
154
+ def solid_classes
155
+ bg_classes = case @variant
156
+ when :primary
157
+ [ "bg-primary-600", "hover:bg-primary-700", "active:bg-primary-800" ]
158
+ when :secondary
159
+ [ "bg-secondary-600", "hover:bg-secondary-700", "active:bg-secondary-800" ]
160
+ when :accent
161
+ [ "bg-accent-600", "hover:bg-accent-700", "active:bg-accent-800" ]
162
+ when :success
163
+ [ "bg-success-600", "hover:bg-success-700", "active:bg-success-800" ]
164
+ when :danger
165
+ [ "bg-danger-600", "hover:bg-danger-700", "active:bg-danger-800" ]
166
+ when :warning
167
+ [ "bg-warning-600", "hover:bg-warning-700", "active:bg-warning-800" ]
168
+ when :info
169
+ [ "bg-info-600", "hover:bg-info-700", "active:bg-info-800" ]
170
+ when :light
171
+ [ "bg-grayscale-100", "hover:bg-grayscale-200", "active:bg-grayscale-300" ]
172
+ when :dark
173
+ [ "bg-grayscale-900", "hover:bg-grayscale-800", "active:bg-grayscale-700" ]
174
+ end
175
+
176
+ bg_classes + [ text_color_for_solid ]
177
+ end
178
+
179
+ def outline_classes
180
+ color_classes = case @variant
181
+ when :primary
182
+ [ "border-primary-600", "hover:border-primary-700", "hover:bg-primary-50", "text-primary-600" ]
183
+ when :secondary
184
+ [ "border-secondary-600", "hover:border-secondary-700", "hover:bg-secondary-50", "text-secondary-600" ]
185
+ when :accent
186
+ [ "border-accent-600", "hover:border-accent-700", "hover:bg-accent-50", "text-accent-600" ]
187
+ when :success
188
+ [ "border-success-600", "hover:border-success-700", "hover:bg-success-50", "text-success-600" ]
189
+ when :danger
190
+ [ "border-danger-600", "hover:border-danger-700", "hover:bg-danger-50", "text-danger-600" ]
191
+ when :warning
192
+ [ "border-warning-600", "hover:border-warning-700", "hover:bg-warning-50", "text-warning-600" ]
193
+ when :info
194
+ [ "border-info-600", "hover:border-info-700", "hover:bg-info-50", "text-info-600" ]
195
+ when :light
196
+ [ "border-grayscale-400", "hover:border-grayscale-500", "hover:bg-grayscale-50", "text-grayscale-400", "hover:text-grayscale-500" ]
197
+ when :dark
198
+ [ "border-grayscale-700", "hover:border-grayscale-600", "hover:bg-grayscale-600", "text-grayscale-700", "hover:text-grayscale-50" ]
199
+ end
200
+
201
+ [ "bg-transparent", "border-2" ] + color_classes
202
+ end
203
+
204
+ def ghost_classes
205
+ color_classes = case @variant
206
+ when :primary
207
+ [ "hover:bg-primary-50", "active:bg-primary-100", "text-primary-600" ]
208
+ when :secondary
209
+ [ "hover:bg-secondary-50", "active:bg-secondary-100", "text-secondary-600" ]
210
+ when :accent
211
+ [ "hover:bg-accent-50", "active:bg-accent-100", "text-accent-600" ]
212
+ when :success
213
+ [ "hover:bg-success-50", "active:bg-success-100", "text-success-600" ]
214
+ when :danger
215
+ [ "hover:bg-danger-50", "active:bg-danger-100", "text-danger-600" ]
216
+ when :warning
217
+ [ "hover:bg-warning-50", "active:bg-warning-100", "text-warning-600" ]
218
+ when :info
219
+ [ "hover:bg-info-50", "active:bg-info-100", "text-info-600" ]
220
+ when :light
221
+ [ "hover:bg-grayscale-100", "active:bg-grayscale-200", "text-grayscale-700" ]
222
+ when :dark
223
+ [ "hover:bg-grayscale-800", "active:bg-grayscale-700", "text-grayscale-700", "hover:text-grayscale-50" ]
224
+ end
225
+
226
+ [ "bg-transparent" ] + color_classes
227
+ end
228
+
229
+ def soft_classes
230
+ case @variant
231
+ when :primary
232
+ [ "bg-primary-100", "hover:bg-primary-200", "active:bg-primary-300", "text-primary-700" ]
233
+ when :secondary
234
+ [ "bg-secondary-100", "hover:bg-secondary-200", "active:bg-secondary-300", "text-secondary-700" ]
235
+ when :accent
236
+ [ "bg-accent-100", "hover:bg-accent-200", "active:bg-accent-300", "text-accent-700" ]
237
+ when :success
238
+ [ "bg-success-100", "hover:bg-success-200", "active:bg-success-300", "text-success-700" ]
239
+ when :danger
240
+ [ "bg-danger-100", "hover:bg-danger-200", "active:bg-danger-300", "text-danger-700" ]
241
+ when :warning
242
+ [ "bg-warning-100", "hover:bg-warning-200", "active:bg-warning-300", "text-warning-700" ]
243
+ when :info
244
+ [ "bg-info-100", "hover:bg-info-200", "active:bg-info-300", "text-info-700" ]
245
+ when :light
246
+ [ "bg-grayscale-100", "hover:bg-grayscale-200", "active:bg-grayscale-300", "text-grayscale-700" ]
247
+ when :dark
248
+ [ "bg-grayscale-800", "hover:bg-grayscale-700", "active:bg-grayscale-600", "text-grayscale-100" ]
249
+ end
250
+ end
251
+
252
+ def text_color_for_solid
253
+ @variant == :light ? "text-grayscale-900" : "text-grayscale-50"
254
+ end
255
+
256
+ def size_classes
257
+ size_config = SIZES[@size]
258
+ [
259
+ size_config[:padding],
260
+ size_config[:text],
261
+ size_config[:gap]
262
+ ]
263
+ end
264
+
265
+ def state_classes
266
+ classes = []
267
+ if @disabled && !@show_loader
268
+ classes << "opacity-50 cursor-not-allowed"
269
+ classes << "pointer-events-none" if link?
270
+ elsif @show_loader
271
+ classes << "cursor-wait"
272
+ classes << "pointer-events-none" if link?
273
+ else
274
+ classes << "cursor-pointer"
275
+ end
276
+ classes
277
+ end
278
+
279
+ def validate_variant(variant)
280
+ unless BetterUi::ApplicationComponent::VARIANTS.key?(variant)
281
+ raise ArgumentError, "Invalid variant: #{variant}. Must be one of: #{BetterUi::ApplicationComponent::VARIANTS.keys.join(", ")}"
282
+ end
283
+ variant
284
+ end
285
+
286
+ def validate_style(style)
287
+ unless STYLES.include?(style)
288
+ raise ArgumentError, "Invalid style: #{style}. Must be one of: #{STYLES.join(", ")}"
289
+ end
290
+ style
291
+ end
292
+
293
+ def validate_size(size)
294
+ unless SIZES.key?(size)
295
+ raise ArgumentError, "Invalid size: #{size}. Must be one of: #{SIZES.keys.join(", ")}"
296
+ end
297
+ size
298
+ end
299
+
300
+ def validate_type(type)
301
+ unless TYPES.include?(type)
302
+ raise ArgumentError, "Invalid type: #{type}. Must be one of: #{TYPES.join(", ")}"
303
+ end
304
+ type
305
+ end
306
+ end
307
+ end
@@ -0,0 +1,17 @@
1
+ <div class="<%= component_classes %>" <%= tag.attributes(html_attributes) %>>
2
+ <% if header? %>
3
+ <div class="<%= header_wrapper_classes %>">
4
+ <%= header %>
5
+ </div>
6
+ <% end %>
7
+
8
+ <div class="<%= body_wrapper_classes %>">
9
+ <%= body? ? body : content %>
10
+ </div>
11
+
12
+ <% if footer? %>
13
+ <div class="<%= footer_wrapper_classes %>">
14
+ <%= footer %>
15
+ </div>
16
+ <% end %>
17
+ </div>