better_ui 0.9.0 → 0.9.1

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 (166) hide show
  1. checksums.yaml +4 -4
  2. data/lib/better_ui/version.rb +1 -1
  3. data/spec/components/previews/better_ui/action_messages_component_preview/all_styles.html.erb +17 -0
  4. data/spec/components/previews/better_ui/action_messages_component_preview/all_variants.html.erb +19 -0
  5. data/spec/components/previews/better_ui/action_messages_component_preview/auto_dismiss.html.erb +51 -0
  6. data/spec/components/previews/better_ui/action_messages_component_preview/dismissible.html.erb +19 -0
  7. data/spec/components/previews/better_ui/action_messages_component_preview/with_title.html.erb +17 -0
  8. data/spec/components/previews/better_ui/action_messages_component_preview.rb +224 -0
  9. data/spec/components/previews/better_ui/avatar_component_preview/all_shapes.html.erb +26 -0
  10. data/spec/components/previews/better_ui/avatar_component_preview/all_sizes.html.erb +24 -0
  11. data/spec/components/previews/better_ui/avatar_component_preview/all_variants.html.erb +12 -0
  12. data/spec/components/previews/better_ui/avatar_component_preview/with_initials.html.erb +22 -0
  13. data/spec/components/previews/better_ui/avatar_component_preview/with_status.html.erb +26 -0
  14. data/spec/components/previews/better_ui/avatar_component_preview.rb +73 -0
  15. data/spec/components/previews/better_ui/badge_component_preview/all_sizes.html.erb +29 -0
  16. data/spec/components/previews/better_ui/badge_component_preview/all_styles.html.erb +26 -0
  17. data/spec/components/previews/better_ui/badge_component_preview/all_variants.html.erb +14 -0
  18. data/spec/components/previews/better_ui/badge_component_preview/counter_badges.html.erb +39 -0
  19. data/spec/components/previews/better_ui/badge_component_preview/dot_badges.html.erb +28 -0
  20. data/spec/components/previews/better_ui/badge_component_preview.rb +69 -0
  21. data/spec/components/previews/better_ui/breadcrumb/breadcrumb_component_preview/all_separators.html.erb +47 -0
  22. data/spec/components/previews/better_ui/breadcrumb/breadcrumb_component_preview/default.html.erb +23 -0
  23. data/spec/components/previews/better_ui/breadcrumb/breadcrumb_component_preview/with_icons.html.erb +43 -0
  24. data/spec/components/previews/better_ui/breadcrumb/breadcrumb_component_preview.rb +38 -0
  25. data/spec/components/previews/better_ui/button_component_preview/all_sizes.html.erb +25 -0
  26. data/spec/components/previews/better_ui/button_component_preview/all_variants.html.erb +14 -0
  27. data/spec/components/previews/better_ui/button_component_preview/as_links.html.erb +18 -0
  28. data/spec/components/previews/better_ui/button_component_preview/auto_loading_submit.html.erb +112 -0
  29. data/spec/components/previews/better_ui/button_component_preview/external_links.html.erb +61 -0
  30. data/spec/components/previews/better_ui/button_component_preview/form_integration.html.erb +102 -0
  31. data/spec/components/previews/better_ui/button_component_preview/interactive.html.erb +149 -0
  32. data/spec/components/previews/better_ui/button_component_preview/link_states.html.erb +36 -0
  33. data/spec/components/previews/better_ui/button_component_preview/loading_states.html.erb +62 -0
  34. data/spec/components/previews/better_ui/button_component_preview/turbo_method_links.html.erb +98 -0
  35. data/spec/components/previews/better_ui/button_component_preview/with_icons.html.erb +123 -0
  36. data/spec/components/previews/better_ui/button_component_preview.rb +155 -0
  37. data/spec/components/previews/better_ui/card_component_preview/all_sizes.html.erb +10 -0
  38. data/spec/components/previews/better_ui/card_component_preview/all_styles.html.erb +22 -0
  39. data/spec/components/previews/better_ui/card_component_preview/all_variants.html.erb +10 -0
  40. data/spec/components/previews/better_ui/card_component_preview.rb +269 -0
  41. data/spec/components/previews/better_ui/container_component_preview/all_sizes.html.erb +13 -0
  42. data/spec/components/previews/better_ui/container_component_preview.rb +59 -0
  43. data/spec/components/previews/better_ui/dialog/alert_component_preview/all_variants.html.erb +17 -0
  44. data/spec/components/previews/better_ui/dialog/alert_component_preview/custom_button_label.html.erb +14 -0
  45. data/spec/components/previews/better_ui/dialog/alert_component_preview/default.html.erb +13 -0
  46. data/spec/components/previews/better_ui/dialog/alert_component_preview/playground.html.erb +16 -0
  47. data/spec/components/previews/better_ui/dialog/alert_component_preview/without_icon.html.erb +14 -0
  48. data/spec/components/previews/better_ui/dialog/alert_component_preview.rb +57 -0
  49. data/spec/components/previews/better_ui/dialog/confirm_component_preview/all_variants.html.erb +17 -0
  50. data/spec/components/previews/better_ui/dialog/confirm_component_preview/custom_labels.html.erb +15 -0
  51. data/spec/components/previews/better_ui/dialog/confirm_component_preview/danger_confirm.html.erb +15 -0
  52. data/spec/components/previews/better_ui/dialog/confirm_component_preview/default.html.erb +13 -0
  53. data/spec/components/previews/better_ui/dialog/confirm_component_preview/playground.html.erb +17 -0
  54. data/spec/components/previews/better_ui/dialog/confirm_component_preview.rb +60 -0
  55. data/spec/components/previews/better_ui/dialog/dialog_component_preview/all_sizes.html.erb +32 -0
  56. data/spec/components/previews/better_ui/dialog/dialog_component_preview/default.html.erb +34 -0
  57. data/spec/components/previews/better_ui/dialog/dialog_component_preview/no_close_button.html.erb +28 -0
  58. data/spec/components/previews/better_ui/dialog/dialog_component_preview/playground.html.erb +39 -0
  59. data/spec/components/previews/better_ui/dialog/dialog_component_preview/with_all_slots.html.erb +52 -0
  60. data/spec/components/previews/better_ui/dialog/dialog_component_preview.rb +51 -0
  61. data/spec/components/previews/better_ui/divider_component_preview/all_styles.html.erb +58 -0
  62. data/spec/components/previews/better_ui/divider_component_preview/with_labels.html.erb +67 -0
  63. data/spec/components/previews/better_ui/divider_component_preview.rb +62 -0
  64. data/spec/components/previews/better_ui/drawer/header_component_preview.rb +169 -0
  65. data/spec/components/previews/better_ui/drawer/layout_component_preview/complete_layout.html.erb +87 -0
  66. data/spec/components/previews/better_ui/drawer/layout_component_preview/dark_theme.html.erb +36 -0
  67. data/spec/components/previews/better_ui/drawer/layout_component_preview/dashboard_example.html.erb +188 -0
  68. data/spec/components/previews/better_ui/drawer/layout_component_preview/default.html.erb +22 -0
  69. data/spec/components/previews/better_ui/drawer/layout_component_preview/primary_theme.html.erb +36 -0
  70. data/spec/components/previews/better_ui/drawer/layout_component_preview/right_sidebar.html.erb +44 -0
  71. data/spec/components/previews/better_ui/drawer/layout_component_preview/with_header_only.html.erb +20 -0
  72. data/spec/components/previews/better_ui/drawer/layout_component_preview/with_sidebar_only.html.erb +21 -0
  73. data/spec/components/previews/better_ui/drawer/layout_component_preview.rb +91 -0
  74. data/spec/components/previews/better_ui/drawer/nav_group_component_preview/complete_navigation.html.erb +55 -0
  75. data/spec/components/previews/better_ui/drawer/nav_group_component_preview.rb +163 -0
  76. data/spec/components/previews/better_ui/drawer/nav_item_component_preview.rb +104 -0
  77. data/spec/components/previews/better_ui/drawer/sidebar_component_preview.rb +212 -0
  78. data/spec/components/previews/better_ui/dropdown/dropdown_component_preview/all_sizes.html.erb +19 -0
  79. data/spec/components/previews/better_ui/dropdown/dropdown_component_preview/default.html.erb +12 -0
  80. data/spec/components/previews/better_ui/dropdown/dropdown_component_preview/disabled_items.html.erb +14 -0
  81. data/spec/components/previews/better_ui/dropdown/dropdown_component_preview/placement_options.html.erb +16 -0
  82. data/spec/components/previews/better_ui/dropdown/dropdown_component_preview/playground.html.erb +35 -0
  83. data/spec/components/previews/better_ui/dropdown/dropdown_component_preview/with_dividers_and_headers.html.erb +18 -0
  84. data/spec/components/previews/better_ui/dropdown/dropdown_component_preview/with_icons.html.erb +34 -0
  85. data/spec/components/previews/better_ui/dropdown/dropdown_component_preview.rb +59 -0
  86. data/spec/components/previews/better_ui/fa_icon_component_preview/all_sizes.html.erb +17 -0
  87. data/spec/components/previews/better_ui/fa_icon_component_preview/all_styles.html.erb +19 -0
  88. data/spec/components/previews/better_ui/fa_icon_component_preview/all_variants.html.erb +26 -0
  89. data/spec/components/previews/better_ui/fa_icon_component_preview/animations.html.erb +26 -0
  90. data/spec/components/previews/better_ui/fa_icon_component_preview/transformations.html.erb +88 -0
  91. data/spec/components/previews/better_ui/fa_icon_component_preview.rb +85 -0
  92. data/spec/components/previews/better_ui/forms/checkbox_component_preview/all_sizes.html.erb +12 -0
  93. data/spec/components/previews/better_ui/forms/checkbox_component_preview/all_variants.html.erb +12 -0
  94. data/spec/components/previews/better_ui/forms/checkbox_component_preview/form_integration.html.erb +32 -0
  95. data/spec/components/previews/better_ui/forms/checkbox_component_preview.rb +143 -0
  96. data/spec/components/previews/better_ui/forms/checkbox_group_component_preview/all_variants.html.erb +14 -0
  97. data/spec/components/previews/better_ui/forms/checkbox_group_component_preview/form_integration.html.erb +47 -0
  98. data/spec/components/previews/better_ui/forms/checkbox_group_component_preview/orientations.html.erb +34 -0
  99. data/spec/components/previews/better_ui/forms/checkbox_group_component_preview.rb +150 -0
  100. data/spec/components/previews/better_ui/forms/number_input_component_preview/all_sizes.html.erb +14 -0
  101. data/spec/components/previews/better_ui/forms/number_input_component_preview/form_integration.html.erb +45 -0
  102. data/spec/components/previews/better_ui/forms/number_input_component_preview.rb +211 -0
  103. data/spec/components/previews/better_ui/forms/password_input_component_preview/all_sizes.html.erb +12 -0
  104. data/spec/components/previews/better_ui/forms/password_input_component_preview/confirm_password_example.html.erb +29 -0
  105. data/spec/components/previews/better_ui/forms/password_input_component_preview/form_integration.html.erb +34 -0
  106. data/spec/components/previews/better_ui/forms/password_input_component_preview.rb +181 -0
  107. data/spec/components/previews/better_ui/forms/select_component_preview/all_sizes.html.erb +13 -0
  108. data/spec/components/previews/better_ui/forms/select_component_preview/all_states.html.erb +64 -0
  109. data/spec/components/previews/better_ui/forms/select_component_preview.rb +167 -0
  110. data/spec/components/previews/better_ui/forms/text_input_component_preview/all_sizes.html.erb +12 -0
  111. data/spec/components/previews/better_ui/forms/text_input_component_preview/all_types.html.erb +12 -0
  112. data/spec/components/previews/better_ui/forms/text_input_component_preview/form_integration.html.erb +33 -0
  113. data/spec/components/previews/better_ui/forms/text_input_component_preview.rb +247 -0
  114. data/spec/components/previews/better_ui/forms/textarea_component_preview/all_resize_variants.html.erb +13 -0
  115. data/spec/components/previews/better_ui/forms/textarea_component_preview/all_sizes.html.erb +12 -0
  116. data/spec/components/previews/better_ui/forms/textarea_component_preview/form_integration.html.erb +36 -0
  117. data/spec/components/previews/better_ui/forms/textarea_component_preview.rb +239 -0
  118. data/spec/components/previews/better_ui/heading_component_preview/all_alignments.html.erb +12 -0
  119. data/spec/components/previews/better_ui/heading_component_preview/all_levels.html.erb +7 -0
  120. data/spec/components/previews/better_ui/heading_component_preview/all_variants.html.erb +14 -0
  121. data/spec/components/previews/better_ui/heading_component_preview.rb +113 -0
  122. data/spec/components/previews/better_ui/link_component_preview/all_sizes.html.erb +25 -0
  123. data/spec/components/previews/better_ui/link_component_preview/all_styles.html.erb +14 -0
  124. data/spec/components/previews/better_ui/link_component_preview/all_variants.html.erb +14 -0
  125. data/spec/components/previews/better_ui/link_component_preview/with_icons.html.erb +66 -0
  126. data/spec/components/previews/better_ui/link_component_preview.rb +66 -0
  127. data/spec/components/previews/better_ui/progress_component_preview/all_sizes.html.erb +15 -0
  128. data/spec/components/previews/better_ui/progress_component_preview/all_variants.html.erb +11 -0
  129. data/spec/components/previews/better_ui/progress_component_preview.rb +64 -0
  130. data/spec/components/previews/better_ui/spinner_component_preview/all_sizes.html.erb +17 -0
  131. data/spec/components/previews/better_ui/spinner_component_preview/all_variants.html.erb +11 -0
  132. data/spec/components/previews/better_ui/spinner_component_preview.rb +44 -0
  133. data/spec/components/previews/better_ui/table/table_component_preview/all_sizes.html.erb +28 -0
  134. data/spec/components/previews/better_ui/table/table_component_preview/all_variants.html.erb +34 -0
  135. data/spec/components/previews/better_ui/table/table_component_preview/bordered.html.erb +33 -0
  136. data/spec/components/previews/better_ui/table/table_component_preview/collection_mode.html.erb +31 -0
  137. data/spec/components/previews/better_ui/table/table_component_preview/default.html.erb +33 -0
  138. data/spec/components/previews/better_ui/table/table_component_preview/empty_state.html.erb +36 -0
  139. data/spec/components/previews/better_ui/table/table_component_preview/highlighted.html.erb +64 -0
  140. data/spec/components/previews/better_ui/table/table_component_preview/hoverable.html.erb +27 -0
  141. data/spec/components/previews/better_ui/table/table_component_preview/inside_card.html.erb +173 -0
  142. data/spec/components/previews/better_ui/table/table_component_preview/sortable.html.erb +44 -0
  143. data/spec/components/previews/better_ui/table/table_component_preview/striped.html.erb +31 -0
  144. data/spec/components/previews/better_ui/table/table_component_preview/with_footer.html.erb +40 -0
  145. data/spec/components/previews/better_ui/table/table_component_preview.rb +79 -0
  146. data/spec/components/previews/better_ui/tabs/container_component_preview/alignments.html.erb +24 -0
  147. data/spec/components/previews/better_ui/tabs/container_component_preview/all_sizes.html.erb +24 -0
  148. data/spec/components/previews/better_ui/tabs/container_component_preview/all_variants.html.erb +24 -0
  149. data/spec/components/previews/better_ui/tabs/container_component_preview/bordered_style.html.erb +30 -0
  150. data/spec/components/previews/better_ui/tabs/container_component_preview/default.html.erb +30 -0
  151. data/spec/components/previews/better_ui/tabs/container_component_preview/disabled_tab.html.erb +65 -0
  152. data/spec/components/previews/better_ui/tabs/container_component_preview/pills_style.html.erb +34 -0
  153. data/spec/components/previews/better_ui/tabs/container_component_preview/turbo_mode.html.erb +40 -0
  154. data/spec/components/previews/better_ui/tabs/container_component_preview/vertical_left.html.erb +38 -0
  155. data/spec/components/previews/better_ui/tabs/container_component_preview/vertical_right.html.erb +30 -0
  156. data/spec/components/previews/better_ui/tabs/container_component_preview/with_icons_and_badges.html.erb +71 -0
  157. data/spec/components/previews/better_ui/tabs/container_component_preview.rb +130 -0
  158. data/spec/components/previews/better_ui/tag_component_preview/all_styles.html.erb +14 -0
  159. data/spec/components/previews/better_ui/tag_component_preview/all_variants.html.erb +14 -0
  160. data/spec/components/previews/better_ui/tag_component_preview/as_links.html.erb +14 -0
  161. data/spec/components/previews/better_ui/tag_component_preview/dismissible.html.erb +34 -0
  162. data/spec/components/previews/better_ui/tag_component_preview.rb +56 -0
  163. data/spec/components/previews/better_ui/tooltip_component_preview/all_positions.html.erb +25 -0
  164. data/spec/components/previews/better_ui/tooltip_component_preview/variants.html.erb +37 -0
  165. data/spec/components/previews/better_ui/tooltip_component_preview.rb +40 -0
  166. metadata +164 -1
@@ -0,0 +1,150 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterUi
4
+ module Forms
5
+ # @label Checkbox Group
6
+ class CheckboxGroupComponentPreview < ViewComponent::Preview
7
+ # @label Default
8
+ # @display bg_color #f5f5f5
9
+ def default
10
+ render BetterUi::Forms::CheckboxGroupComponent.new(
11
+ name: "interests",
12
+ collection: [ "Sports", "Music", "Art", "Technology" ],
13
+ legend: "Interests"
14
+ )
15
+ end
16
+
17
+ # @label With Selection
18
+ # @display bg_color #f5f5f5
19
+ def with_selection
20
+ render BetterUi::Forms::CheckboxGroupComponent.new(
21
+ name: "roles",
22
+ collection: [
23
+ [ "Administrator", "admin" ],
24
+ [ "Editor", "editor" ],
25
+ [ "Viewer", "viewer" ]
26
+ ],
27
+ selected: [ "admin", "viewer" ],
28
+ legend: "User Roles"
29
+ )
30
+ end
31
+
32
+ # @label Horizontal Layout
33
+ # @display bg_color #f5f5f5
34
+ def horizontal
35
+ render BetterUi::Forms::CheckboxGroupComponent.new(
36
+ name: "days",
37
+ collection: [ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" ],
38
+ orientation: :horizontal,
39
+ legend: "Available Days"
40
+ )
41
+ end
42
+
43
+ # @label With Hint
44
+ # @display bg_color #f5f5f5
45
+ def with_hint
46
+ render BetterUi::Forms::CheckboxGroupComponent.new(
47
+ name: "notifications",
48
+ collection: [
49
+ [ "Email notifications", "email" ],
50
+ [ "Push notifications", "push" ],
51
+ [ "SMS notifications", "sms" ]
52
+ ],
53
+ legend: "Notification Preferences",
54
+ hint: "Select how you'd like to be notified"
55
+ )
56
+ end
57
+
58
+ # @label With Errors
59
+ # @display bg_color #f5f5f5
60
+ def with_errors
61
+ render BetterUi::Forms::CheckboxGroupComponent.new(
62
+ name: "terms",
63
+ collection: [
64
+ [ "Terms of Service", "tos" ],
65
+ [ "Privacy Policy", "privacy" ]
66
+ ],
67
+ legend: "Legal Agreements",
68
+ errors: [ "You must accept all agreements to continue" ]
69
+ )
70
+ end
71
+
72
+ # @label Required Field
73
+ # @display bg_color #f5f5f5
74
+ def required
75
+ render BetterUi::Forms::CheckboxGroupComponent.new(
76
+ name: "skills",
77
+ collection: [ "Ruby", "JavaScript", "Python", "Go" ],
78
+ legend: "Programming Skills",
79
+ required: true,
80
+ hint: "Select at least one skill"
81
+ )
82
+ end
83
+
84
+ # @label Disabled State
85
+ # @display bg_color #f5f5f5
86
+ def disabled
87
+ render BetterUi::Forms::CheckboxGroupComponent.new(
88
+ name: "permissions",
89
+ collection: [
90
+ [ "Read", "read" ],
91
+ [ "Write", "write" ],
92
+ [ "Delete", "delete" ]
93
+ ],
94
+ selected: [ "read" ],
95
+ legend: "Permissions (Disabled)",
96
+ disabled: true
97
+ )
98
+ end
99
+
100
+ # @label All Variants
101
+ # @display bg_color #f5f5f5
102
+ def all_variants
103
+ render_with_template
104
+ end
105
+
106
+ # @label Orientations
107
+ # @display bg_color #f5f5f5
108
+ def orientations
109
+ render_with_template
110
+ end
111
+
112
+ # @label Form Integration
113
+ # @display bg_color #f5f5f5
114
+ def form_integration
115
+ render_with_template
116
+ end
117
+
118
+ # @label Playground
119
+ # @param variant select { choices: [primary, secondary, accent, success, danger, warning, info, light, dark] }
120
+ # @param size select { choices: [xs, sm, md, lg, xl] }
121
+ # @param orientation select { choices: [vertical, horizontal] }
122
+ # @param disabled toggle
123
+ # @param required toggle
124
+ # @param with_hint toggle
125
+ # @param with_error toggle
126
+ def playground(
127
+ variant: :primary,
128
+ size: :md,
129
+ orientation: :vertical,
130
+ disabled: false,
131
+ required: false,
132
+ with_hint: false,
133
+ with_error: false
134
+ )
135
+ render BetterUi::Forms::CheckboxGroupComponent.new(
136
+ name: "playground",
137
+ collection: [ "Option A", "Option B", "Option C" ],
138
+ legend: "Playground Group",
139
+ variant: variant.to_sym,
140
+ size: size.to_sym,
141
+ orientation: orientation.to_sym,
142
+ disabled: disabled,
143
+ required: required,
144
+ hint: with_hint ? "Select one or more options" : nil,
145
+ errors: with_error ? [ "Please make a selection" ] : nil
146
+ )
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,14 @@
1
+ <div class="space-y-4 p-4">
2
+ <% BetterUi::Forms::BaseComponent::SIZES.each do |size| %>
3
+ <div>
4
+ <%= render BetterUi::Forms::NumberInputComponent.new(
5
+ name: "example_#{size}",
6
+ label: "Size: #{size}",
7
+ placeholder: "0",
8
+ size: size,
9
+ min: 0,
10
+ max: 100
11
+ ) %>
12
+ </div>
13
+ <% end %>
14
+ </div>
@@ -0,0 +1,45 @@
1
+ <div class="p-4 max-w-2xl">
2
+ <h3 class="text-lg font-semibold mb-4">Form Builder Integration Example</h3>
3
+
4
+ <%= form_with url: "#", method: :post, builder: BetterUi::UiFormBuilder, data: { turbo: false } do |f| %>
5
+ <div class="space-y-4">
6
+ <%= f.ui_number_input :age,
7
+ label: "Age",
8
+ hint: "Enter your age in years",
9
+ min: 0,
10
+ max: 120,
11
+ required: true,
12
+ size: :md
13
+ %>
14
+
15
+ <%= f.ui_number_input :price,
16
+ label: "Price",
17
+ placeholder: "0.00",
18
+ min: 0,
19
+ step: 0.01,
20
+ required: true
21
+ %>
22
+
23
+ <%= f.ui_number_input :quantity,
24
+ label: "Quantity",
25
+ hint: "How many items would you like?",
26
+ min: 1,
27
+ max: 100,
28
+ size: :lg
29
+ %>
30
+
31
+ <%= f.ui_number_input :weight,
32
+ label: "Weight (kg)",
33
+ placeholder: "0.0",
34
+ min: 0,
35
+ step: 0.1
36
+ %>
37
+
38
+ <div class="pt-2">
39
+ <%= render BetterUi::ButtonComponent.new(variant: :primary, type: :submit) do %>
40
+ Submit
41
+ <% end %>
42
+ </div>
43
+ </div>
44
+ <% end %>
45
+ </div>
@@ -0,0 +1,211 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterUi
4
+ module Forms
5
+ # @label Number Input
6
+ class NumberInputComponentPreview < ViewComponent::Preview
7
+ # @label Default
8
+ # @display bg_color #f5f5f5
9
+ def default
10
+ render BetterUi::Forms::NumberInputComponent.new(
11
+ name: "example",
12
+ label: "Example Number",
13
+ placeholder: "Enter a number"
14
+ )
15
+ end
16
+
17
+ # @label With Value
18
+ # @display bg_color #f5f5f5
19
+ def with_value
20
+ render BetterUi::Forms::NumberInputComponent.new(
21
+ name: "age",
22
+ label: "Age",
23
+ value: 25
24
+ )
25
+ end
26
+
27
+ # @label With Min, Max, and Step
28
+ # @display bg_color #f5f5f5
29
+ def with_constraints
30
+ render BetterUi::Forms::NumberInputComponent.new(
31
+ name: "price",
32
+ label: "Price",
33
+ placeholder: "0.00",
34
+ min: 0,
35
+ max: 10000,
36
+ step: 0.01,
37
+ hint: "Enter a price between $0 and $10,000"
38
+ )
39
+ end
40
+
41
+ # @label With Hint
42
+ # @display bg_color #f5f5f5
43
+ def with_hint
44
+ render BetterUi::Forms::NumberInputComponent.new(
45
+ name: "quantity",
46
+ label: "Quantity",
47
+ hint: "Enter the number of items you want to order",
48
+ min: 1,
49
+ max: 100
50
+ )
51
+ end
52
+
53
+ # @label With Errors
54
+ # @display bg_color #f5f5f5
55
+ def with_errors
56
+ render BetterUi::Forms::NumberInputComponent.new(
57
+ name: "age",
58
+ label: "Age",
59
+ value: -5,
60
+ min: 0,
61
+ max: 120,
62
+ errors: [
63
+ "Age must be positive",
64
+ "Age must be a valid number"
65
+ ]
66
+ )
67
+ end
68
+
69
+ # @label Required Field
70
+ # @display bg_color #f5f5f5
71
+ def required
72
+ render BetterUi::Forms::NumberInputComponent.new(
73
+ name: "employee_count",
74
+ label: "Number of Employees",
75
+ required: true,
76
+ min: 1,
77
+ placeholder: "Enter number"
78
+ )
79
+ end
80
+
81
+ # @label Disabled State
82
+ # @display bg_color #f5f5f5
83
+ def disabled
84
+ render BetterUi::Forms::NumberInputComponent.new(
85
+ name: "disabled_field",
86
+ label: "Disabled Field",
87
+ value: 42,
88
+ disabled: true
89
+ )
90
+ end
91
+
92
+ # @label Readonly State
93
+ # @display bg_color #f5f5f5
94
+ def readonly
95
+ render BetterUi::Forms::NumberInputComponent.new(
96
+ name: "readonly_field",
97
+ label: "Readonly Field",
98
+ value: 100,
99
+ readonly: true
100
+ )
101
+ end
102
+
103
+ # @label Without Spinners
104
+ # @display bg_color #f5f5f5
105
+ def without_spinners
106
+ render BetterUi::Forms::NumberInputComponent.new(
107
+ name: "price",
108
+ label: "Price (No Spinners)",
109
+ placeholder: "0.00",
110
+ min: 0,
111
+ step: 0.01,
112
+ show_spinner: false,
113
+ hint: "Clean input without up/down arrows"
114
+ )
115
+ end
116
+
117
+ # @label With Prefix Icon (Currency)
118
+ # @display bg_color #f5f5f5
119
+ def with_prefix_icon
120
+ render BetterUi::Forms::NumberInputComponent.new(
121
+ name: "price",
122
+ label: "Price",
123
+ placeholder: "0.00",
124
+ min: 0,
125
+ step: 0.01
126
+ ) do |component|
127
+ component.with_prefix_icon do
128
+ '<span class="text-gray-500 text-sm font-medium">$</span>'.html_safe
129
+ end
130
+ end
131
+ end
132
+
133
+ # @label With Suffix Icon (Unit)
134
+ # @display bg_color #f5f5f5
135
+ def with_suffix_icon
136
+ render BetterUi::Forms::NumberInputComponent.new(
137
+ name: "weight",
138
+ label: "Weight",
139
+ placeholder: "0",
140
+ min: 0,
141
+ step: 0.1
142
+ ) do |component|
143
+ component.with_suffix_icon do
144
+ '<span class="text-gray-500 text-sm font-medium">kg</span>'.html_safe
145
+ end
146
+ end
147
+ end
148
+
149
+ # @label With Both Icons
150
+ # @display bg_color #f5f5f5
151
+ def with_both_icons
152
+ render BetterUi::Forms::NumberInputComponent.new(
153
+ name: "temperature",
154
+ label: "Temperature",
155
+ placeholder: "0",
156
+ min: -100,
157
+ max: 100,
158
+ step: 0.5
159
+ ) do |component|
160
+ component.with_prefix_icon do
161
+ '<svg class="h-5 w-5 text-danger-500" fill="currentColor" viewBox="0 0 20 20">
162
+ <path fill-rule="evenodd" d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z" clip-rule="evenodd"/>
163
+ </svg>'.html_safe
164
+ end
165
+ component.with_suffix_icon do
166
+ '<span class="text-gray-500 text-sm font-medium">°C</span>'.html_safe
167
+ end
168
+ end
169
+ end
170
+
171
+ # @label All Sizes
172
+ # @display bg_color #f5f5f5
173
+ def all_sizes
174
+ render_with_template
175
+ end
176
+
177
+ # @label Form Integration
178
+ # @display bg_color #f5f5f5
179
+ def form_integration
180
+ render_with_template
181
+ end
182
+
183
+ # @label Playground
184
+ # @param size select { choices: [xs, sm, md, lg, xl] }
185
+ # @param disabled toggle
186
+ # @param readonly toggle
187
+ # @param required toggle
188
+ # @param show_spinner toggle
189
+ # @param with_hint toggle
190
+ # @param with_error toggle
191
+ # @param with_constraints toggle
192
+ def playground(size: :md, disabled: false, readonly: false, required: false, show_spinner: true, with_hint: false, with_error: false, with_constraints: false)
193
+ render BetterUi::Forms::NumberInputComponent.new(
194
+ name: "playground",
195
+ label: "Playground Number Input",
196
+ placeholder: "Enter a number...",
197
+ size: size.to_sym,
198
+ disabled: disabled,
199
+ readonly: readonly,
200
+ required: required,
201
+ show_spinner: show_spinner,
202
+ min: with_constraints ? 0 : nil,
203
+ max: with_constraints ? 100 : nil,
204
+ step: with_constraints ? 5 : nil,
205
+ hint: with_hint ? "This is a helpful hint" : nil,
206
+ errors: with_error ? [ "This field has an error" ] : nil
207
+ )
208
+ end
209
+ end
210
+ end
211
+ end
@@ -0,0 +1,12 @@
1
+ <div class="space-y-4 p-4">
2
+ <% BetterUi::Forms::BaseComponent::SIZES.each do |size| %>
3
+ <div>
4
+ <%= render BetterUi::Forms::PasswordInputComponent.new(
5
+ name: "password_#{size}",
6
+ label: "Size: #{size}",
7
+ placeholder: "#{size.to_s.upcase} password input",
8
+ size: size
9
+ ) %>
10
+ </div>
11
+ <% end %>
12
+ </div>
@@ -0,0 +1,29 @@
1
+ <div class="p-4 max-w-md space-y-4">
2
+ <%= render BetterUi::Forms::PasswordInputComponent.new(
3
+ name: "user[password]",
4
+ label: "New Password",
5
+ hint: "Must be at least 8 characters",
6
+ placeholder: "Enter new password",
7
+ required: true
8
+ ) do |component|
9
+ component.with_prefix_icon do
10
+ '<svg class="h-5 w-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
11
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/>
12
+ </svg>'.html_safe
13
+ end
14
+ end %>
15
+
16
+ <%= render BetterUi::Forms::PasswordInputComponent.new(
17
+ name: "user[password_confirmation]",
18
+ label: "Confirm Password",
19
+ hint: "Re-enter your password to confirm",
20
+ placeholder: "Confirm password",
21
+ required: true
22
+ ) do |component|
23
+ component.with_prefix_icon do
24
+ '<svg class="h-5 w-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
25
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
26
+ </svg>'.html_safe
27
+ end
28
+ end %>
29
+ </div>
@@ -0,0 +1,34 @@
1
+ <div class="p-4 max-w-2xl">
2
+ <h3 class="text-lg font-semibold mb-4">Form Builder Integration Example</h3>
3
+
4
+ <%= form_with url: "#", method: :post, builder: BetterUi::UiFormBuilder, data: { turbo: false } do |f| %>
5
+ <div class="space-y-4">
6
+ <%= f.ui_text_input :email,
7
+ label: "Email Address",
8
+ hint: "We'll never share your email",
9
+ placeholder: "you@example.com",
10
+ required: true,
11
+ size: :md
12
+ %>
13
+
14
+ <%= f.ui_password_input :password,
15
+ label: "Password",
16
+ hint: "Use 8 or more characters with a mix of letters, numbers & symbols",
17
+ placeholder: "Create a strong password",
18
+ required: true
19
+ %>
20
+
21
+ <%= f.ui_password_input :password_confirmation,
22
+ label: "Confirm Password",
23
+ placeholder: "Re-enter your password",
24
+ required: true
25
+ %>
26
+
27
+ <div class="pt-2">
28
+ <%= render BetterUi::ButtonComponent.new(variant: :primary, type: :submit) do %>
29
+ Create Account
30
+ <% end %>
31
+ </div>
32
+ </div>
33
+ <% end %>
34
+ </div>
@@ -0,0 +1,181 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterUi
4
+ module Forms
5
+ # @label Password Input
6
+ class PasswordInputComponentPreview < ViewComponent::Preview
7
+ # @label Default
8
+ # @display bg_color #f5f5f5
9
+ def default
10
+ render BetterUi::Forms::PasswordInputComponent.new(
11
+ name: "user[password]",
12
+ label: "Password",
13
+ placeholder: "Enter your password"
14
+ )
15
+ end
16
+
17
+ # @label With Value
18
+ # @display bg_color #f5f5f5
19
+ def with_value
20
+ render BetterUi::Forms::PasswordInputComponent.new(
21
+ name: "user[password]",
22
+ label: "Password",
23
+ value: "secret123"
24
+ )
25
+ end
26
+
27
+ # @label With Hint
28
+ # @display bg_color #f5f5f5
29
+ def with_hint
30
+ render BetterUi::Forms::PasswordInputComponent.new(
31
+ name: "user[password]",
32
+ label: "Password",
33
+ hint: "Must be at least 8 characters with 1 number and 1 special character",
34
+ placeholder: "Enter your password"
35
+ )
36
+ end
37
+
38
+ # @label With Errors
39
+ # @display bg_color #f5f5f5
40
+ def with_errors
41
+ render BetterUi::Forms::PasswordInputComponent.new(
42
+ name: "user[password]",
43
+ label: "Password",
44
+ value: "weak",
45
+ errors: [
46
+ "Password is too short (minimum is 8 characters)",
47
+ "Password must include at least one number",
48
+ "Password must include at least one special character"
49
+ ]
50
+ )
51
+ end
52
+
53
+ # @label Required Field
54
+ # @display bg_color #f5f5f5
55
+ def required
56
+ render BetterUi::Forms::PasswordInputComponent.new(
57
+ name: "user[password]",
58
+ label: "Password",
59
+ required: true,
60
+ placeholder: "Enter your password"
61
+ )
62
+ end
63
+
64
+ # @label Disabled State
65
+ # @display bg_color #f5f5f5
66
+ def disabled
67
+ render BetterUi::Forms::PasswordInputComponent.new(
68
+ name: "user[password]",
69
+ label: "Password",
70
+ value: "password123",
71
+ disabled: true
72
+ )
73
+ end
74
+
75
+ # @label Readonly State
76
+ # @display bg_color #f5f5f5
77
+ def readonly
78
+ render BetterUi::Forms::PasswordInputComponent.new(
79
+ name: "user[password]",
80
+ label: "Password",
81
+ value: "••••••••",
82
+ readonly: true
83
+ )
84
+ end
85
+
86
+ # @label With Prefix Icon (Lock)
87
+ # @display bg_color #f5f5f5
88
+ def with_prefix_icon
89
+ render BetterUi::Forms::PasswordInputComponent.new(
90
+ name: "user[password]",
91
+ label: "Password",
92
+ placeholder: "Enter your password"
93
+ ) do |component|
94
+ component.with_prefix_icon do
95
+ '<svg class="h-5 w-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
96
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/>
97
+ </svg>'.html_safe
98
+ end
99
+ end
100
+ end
101
+
102
+ # @label Complete Example
103
+ # @display bg_color #f5f5f5
104
+ def complete_example
105
+ render BetterUi::Forms::PasswordInputComponent.new(
106
+ name: "user[password]",
107
+ label: "Password",
108
+ hint: "Use 8 or more characters with a mix of letters, numbers & symbols",
109
+ placeholder: "Create a strong password",
110
+ required: true
111
+ ) do |component|
112
+ component.with_prefix_icon do
113
+ '<svg class="h-5 w-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
114
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/>
115
+ </svg>'.html_safe
116
+ end
117
+ end
118
+ end
119
+
120
+ # @label Confirm Password Example
121
+ # @display bg_color #f5f5f5
122
+ def confirm_password_example
123
+ render_with_template
124
+ end
125
+
126
+ # @label All Sizes
127
+ # @display bg_color #f5f5f5
128
+ def all_sizes
129
+ render_with_template
130
+ end
131
+
132
+ # @label Form Integration
133
+ # @display bg_color #f5f5f5
134
+ def form_integration
135
+ render_with_template
136
+ end
137
+
138
+ # @label Playground
139
+ # @param size select { choices: [xs, sm, md, lg, xl] }
140
+ # @param disabled toggle
141
+ # @param readonly toggle
142
+ # @param required toggle
143
+ # @param with_hint toggle
144
+ # @param with_error toggle
145
+ # @param with_prefix_icon toggle
146
+ def playground(
147
+ size: :md,
148
+ disabled: false,
149
+ readonly: false,
150
+ required: false,
151
+ with_hint: false,
152
+ with_error: false,
153
+ with_prefix_icon: false
154
+ )
155
+ component = BetterUi::Forms::PasswordInputComponent.new(
156
+ name: "user[password]",
157
+ label: "Password",
158
+ placeholder: "Enter your password",
159
+ size: size.to_sym,
160
+ disabled: disabled,
161
+ readonly: readonly,
162
+ required: required,
163
+ hint: with_hint ? "Must be at least 8 characters" : nil,
164
+ errors: with_error ? [ "Password is too weak" ] : nil
165
+ )
166
+
167
+ if with_prefix_icon
168
+ render component do |c|
169
+ c.with_prefix_icon do
170
+ '<svg class="h-5 w-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
171
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/>
172
+ </svg>'.html_safe
173
+ end
174
+ end
175
+ else
176
+ render component
177
+ end
178
+ end
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,13 @@
1
+ <div class="space-y-6 max-w-md">
2
+ <% countries = [["Italy", "it"], ["France", "fr"], ["Germany", "de"], ["Spain", "es"]] %>
3
+
4
+ <% BetterUi::Forms::BaseComponent::SIZES.each do |size| %>
5
+ <%= render BetterUi::Forms::SelectComponent.new(
6
+ name: "size_#{size}",
7
+ collection: countries,
8
+ label: "Size: #{size}",
9
+ placeholder: "Select a country...",
10
+ size: size
11
+ ) %>
12
+ <% end %>
13
+ </div>