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,28 @@
1
+ <div class="p-8 space-y-8">
2
+ <div>
3
+ <h3 class="text-lg font-semibold mb-4">Dot Badges (Solid)</h3>
4
+ <div class="flex flex-wrap gap-3 items-center">
5
+ <% BetterUi::ApplicationComponent::VARIANTS.each do |variant, _| %>
6
+ <%= render BetterUi::BadgeComponent.new(variant: variant, dot: true) %>
7
+ <% end %>
8
+ </div>
9
+ </div>
10
+
11
+ <div>
12
+ <h3 class="text-lg font-semibold mb-4">Dot Badges (Outline)</h3>
13
+ <div class="flex flex-wrap gap-3 items-center">
14
+ <% BetterUi::ApplicationComponent::VARIANTS.each do |variant, _| %>
15
+ <%= render BetterUi::BadgeComponent.new(variant: variant, style: :outline, dot: true) %>
16
+ <% end %>
17
+ </div>
18
+ </div>
19
+
20
+ <div>
21
+ <h3 class="text-lg font-semibold mb-4">Dot Badges (Soft)</h3>
22
+ <div class="flex flex-wrap gap-3 items-center">
23
+ <% BetterUi::ApplicationComponent::VARIANTS.each do |variant, _| %>
24
+ <%= render BetterUi::BadgeComponent.new(variant: variant, style: :soft, dot: true) %>
25
+ <% end %>
26
+ </div>
27
+ </div>
28
+ </div>
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterUi
4
+ class BadgeComponentPreview < ViewComponent::Preview
5
+ # @label Default
6
+ def default
7
+ render BetterUi::BadgeComponent.new do
8
+ "Badge"
9
+ end
10
+ end
11
+
12
+ # @label All Variants
13
+ # @display bg_color #f5f5f5
14
+ def all_variants
15
+ @variants = ApplicationComponent::VARIANTS.keys
16
+ @styles = [ :solid, :outline, :soft, :ghost ]
17
+ render_with_template
18
+ end
19
+
20
+ # @label All Styles
21
+ # @display bg_color #f5f5f5
22
+ def all_styles
23
+ @styles = [ :solid, :outline, :soft, :ghost ]
24
+ render_with_template
25
+ end
26
+
27
+ # @label All Sizes
28
+ def all_sizes
29
+ @sizes = [ :xs, :sm, :md, :lg ]
30
+ render_with_template
31
+ end
32
+
33
+ # @label Dot Badges
34
+ # @display bg_color #f5f5f5
35
+ def dot_badges
36
+ render_with_template
37
+ end
38
+
39
+ # @label Counter Badges
40
+ # @display bg_color #f5f5f5
41
+ def counter_badges
42
+ render_with_template
43
+ end
44
+
45
+ # @label Playground
46
+ # @param variant select { choices: [primary, secondary, accent, success, danger, warning, info, light, dark] }
47
+ # @param style select { choices: [solid, outline, soft, ghost] }
48
+ # @param size select { choices: [xs, sm, md, lg] }
49
+ # @param pill toggle
50
+ # @param dot toggle
51
+ # @param counter number
52
+ def playground(variant: :primary, style: :solid, size: :md, pill: true, dot: false, counter: nil)
53
+ pill_bool = ActiveModel::Type::Boolean.new.cast(pill)
54
+ dot_bool = ActiveModel::Type::Boolean.new.cast(dot)
55
+ counter_val = counter.present? ? counter.to_i : nil
56
+
57
+ render BetterUi::BadgeComponent.new(
58
+ variant: variant,
59
+ style: style,
60
+ size: size,
61
+ pill: pill_bool,
62
+ dot: dot_bool,
63
+ counter: counter_val
64
+ ) do
65
+ "Badge"
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,47 @@
1
+ <div class="p-6 space-y-8">
2
+ <div>
3
+ <h3 class="text-lg font-semibold text-grayscale-900 mb-2">Slash Separator (default)</h3>
4
+ <%= render BetterUi::Breadcrumb::BreadcrumbComponent.new(separator: :slash) do |breadcrumb| %>
5
+ <% breadcrumb.with_item(label: "Home", href: "#") %>
6
+ <% breadcrumb.with_item(label: "Products", href: "#") %>
7
+ <% breadcrumb.with_item(label: "Widget") %>
8
+ <% end %>
9
+ </div>
10
+
11
+ <div>
12
+ <h3 class="text-lg font-semibold text-grayscale-900 mb-2">Chevron Separator</h3>
13
+ <%= render BetterUi::Breadcrumb::BreadcrumbComponent.new(separator: :chevron) do |breadcrumb| %>
14
+ <% breadcrumb.with_item(label: "Home", href: "#") %>
15
+ <% breadcrumb.with_item(label: "Products", href: "#") %>
16
+ <% breadcrumb.with_item(label: "Widget") %>
17
+ <% end %>
18
+ </div>
19
+
20
+ <div>
21
+ <h3 class="text-lg font-semibold text-grayscale-900 mb-2">Dot Separator</h3>
22
+ <%= render BetterUi::Breadcrumb::BreadcrumbComponent.new(separator: :dot) do |breadcrumb| %>
23
+ <% breadcrumb.with_item(label: "Home", href: "#") %>
24
+ <% breadcrumb.with_item(label: "Products", href: "#") %>
25
+ <% breadcrumb.with_item(label: "Widget") %>
26
+ <% end %>
27
+ </div>
28
+
29
+ <hr class="border-grayscale-200">
30
+
31
+ <div>
32
+ <h3 class="text-lg font-semibold text-grayscale-900 mb-4">All Sizes</h3>
33
+
34
+ <div class="space-y-4">
35
+ <% BetterUi::Breadcrumb::BreadcrumbComponent::SIZES.each do |size| %>
36
+ <div>
37
+ <p class="text-sm text-grayscale-500 mb-1">Size: <%= size %></p>
38
+ <%= render BetterUi::Breadcrumb::BreadcrumbComponent.new(separator: :chevron, size: size) do |breadcrumb| %>
39
+ <% breadcrumb.with_item(label: "Home", href: "#") %>
40
+ <% breadcrumb.with_item(label: "Products", href: "#") %>
41
+ <% breadcrumb.with_item(label: "Widget") %>
42
+ <% end %>
43
+ </div>
44
+ <% end %>
45
+ </div>
46
+ </div>
47
+ </div>
@@ -0,0 +1,23 @@
1
+ <div class="p-6 space-y-6">
2
+ <h3 class="text-lg font-semibold text-grayscale-900">Default Breadcrumb</h3>
3
+
4
+ <%= render BetterUi::Breadcrumb::BreadcrumbComponent.new do |breadcrumb| %>
5
+ <% breadcrumb.with_item(label: "Home", href: "#") %>
6
+ <% breadcrumb.with_item(label: "Products", href: "#") %>
7
+ <% breadcrumb.with_item(label: "Categories", href: "#") %>
8
+ <% breadcrumb.with_item(label: "Electronics") %>
9
+ <% end %>
10
+
11
+ <h3 class="text-lg font-semibold text-grayscale-900 mt-8">Single Item</h3>
12
+
13
+ <%= render BetterUi::Breadcrumb::BreadcrumbComponent.new do |breadcrumb| %>
14
+ <% breadcrumb.with_item(label: "Home") %>
15
+ <% end %>
16
+
17
+ <h3 class="text-lg font-semibold text-grayscale-900 mt-8">Two Items</h3>
18
+
19
+ <%= render BetterUi::Breadcrumb::BreadcrumbComponent.new do |breadcrumb| %>
20
+ <% breadcrumb.with_item(label: "Home", href: "#") %>
21
+ <% breadcrumb.with_item(label: "Dashboard") %>
22
+ <% end %>
23
+ </div>
@@ -0,0 +1,43 @@
1
+ <div class="p-6 space-y-8">
2
+ <div>
3
+ <h3 class="text-lg font-semibold text-grayscale-900 mb-2">With Home Icon</h3>
4
+ <%= render BetterUi::Breadcrumb::BreadcrumbComponent.new(separator: :chevron) do |breadcrumb| %>
5
+ <% breadcrumb.with_item(label: "Home", href: "#") do |item| %>
6
+ <% item.with_icon_before do %>
7
+ <svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
8
+ <path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z" />
9
+ </svg>
10
+ <% end %>
11
+ <% end %>
12
+ <% breadcrumb.with_item(label: "Projects", href: "#") %>
13
+ <% breadcrumb.with_item(label: "Project Alpha") %>
14
+ <% end %>
15
+ </div>
16
+
17
+ <div>
18
+ <h3 class="text-lg font-semibold text-grayscale-900 mb-2">With Icons on Multiple Items</h3>
19
+ <%= render BetterUi::Breadcrumb::BreadcrumbComponent.new(separator: :slash, size: :lg) do |breadcrumb| %>
20
+ <% breadcrumb.with_item(label: "Home", href: "#") do |item| %>
21
+ <% item.with_icon_before do %>
22
+ <svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
23
+ <path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z" />
24
+ </svg>
25
+ <% end %>
26
+ <% end %>
27
+ <% breadcrumb.with_item(label: "Settings", href: "#") do |item| %>
28
+ <% item.with_icon_before do %>
29
+ <svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
30
+ <path fill-rule="evenodd" d="M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z" clip-rule="evenodd" />
31
+ </svg>
32
+ <% end %>
33
+ <% end %>
34
+ <% breadcrumb.with_item(label: "Profile") do |item| %>
35
+ <% item.with_icon_before do %>
36
+ <svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
37
+ <path fill-rule="evenodd" d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z" clip-rule="evenodd" />
38
+ </svg>
39
+ <% end %>
40
+ <% end %>
41
+ <% end %>
42
+ </div>
43
+ </div>
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterUi
4
+ module Breadcrumb
5
+ # @label Breadcrumb
6
+ class BreadcrumbComponentPreview < ViewComponent::Preview
7
+ # @label Default
8
+ def default
9
+ render_with_template
10
+ end
11
+
12
+ # @label All Separators
13
+ def all_separators
14
+ render_with_template
15
+ end
16
+
17
+ # @label With Icons
18
+ def with_icons
19
+ render_with_template
20
+ end
21
+
22
+ # @label Playground
23
+ # @param separator select { choices: [slash, chevron, dot] }
24
+ # @param size select { choices: [sm, md, lg] }
25
+ def playground(separator: :slash, size: :md)
26
+ render BetterUi::Breadcrumb::BreadcrumbComponent.new(
27
+ separator: separator.to_sym,
28
+ size: size.to_sym
29
+ ) do |breadcrumb|
30
+ breadcrumb.with_item(label: "Home", href: "#")
31
+ breadcrumb.with_item(label: "Library", href: "#")
32
+ breadcrumb.with_item(label: "Articles", href: "#")
33
+ breadcrumb.with_item(label: "Current Article")
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,25 @@
1
+ <div class="p-8">
2
+ <h3 class="text-lg font-semibold mb-6">Button Sizes</h3>
3
+
4
+ <div class="space-y-6">
5
+ <% (@sizes || [:xs, :sm, :md, :lg, :xl]).each do |size| %>
6
+ <div class="flex items-center gap-4">
7
+ <span class="w-20 text-sm font-medium text-gray-600 uppercase"><%= size %></span>
8
+
9
+ <div class="flex flex-wrap gap-3">
10
+ <%= render BetterUi::ButtonComponent.new(size: size, variant: :primary) do %>
11
+ Button <%= size.to_s.upcase %>
12
+ <% end %>
13
+
14
+ <%= render BetterUi::ButtonComponent.new(size: size, variant: :secondary, style: :outline) do %>
15
+ Outline <%= size.to_s.upcase %>
16
+ <% end %>
17
+
18
+ <%= render BetterUi::ButtonComponent.new(size: size, variant: :success, style: :ghost) do %>
19
+ Ghost <%= size.to_s.upcase %>
20
+ <% end %>
21
+ </div>
22
+ </div>
23
+ <% end %>
24
+ </div>
25
+ </div>
@@ -0,0 +1,14 @@
1
+ <div class="p-8 space-y-8">
2
+ <% (@styles || [:solid, :outline, :ghost, :soft]).each do |style| %>
3
+ <div>
4
+ <h3 class="text-lg font-semibold mb-4 capitalize"><%= style %> Buttons</h3>
5
+ <div class="flex flex-wrap gap-3">
6
+ <% (@variants || BetterUi::ApplicationComponent::VARIANTS.keys).each do |variant| %>
7
+ <%= render BetterUi::ButtonComponent.new(variant: variant, style: style) do %>
8
+ <%= variant.to_s.capitalize %>
9
+ <% end %>
10
+ <% end %>
11
+ </div>
12
+ </div>
13
+ <% end %>
14
+ </div>
@@ -0,0 +1,18 @@
1
+ <div class="p-8 space-y-8">
2
+ <% [:solid, :outline, :ghost, :soft].each do |style| %>
3
+ <div>
4
+ <h3 class="text-lg font-semibold mb-4 capitalize"><%= style %> Links</h3>
5
+ <div class="flex flex-wrap gap-3">
6
+ <% BetterUi::ApplicationComponent::VARIANTS.keys.each do |variant| %>
7
+ <%= render BetterUi::ButtonComponent.new(
8
+ variant: variant,
9
+ style: style,
10
+ href: "#"
11
+ ) do %>
12
+ <%= variant.to_s.capitalize %>
13
+ <% end %>
14
+ <% end %>
15
+ </div>
16
+ </div>
17
+ <% end %>
18
+ </div>
@@ -0,0 +1,112 @@
1
+ <div class="p-8 space-y-8">
2
+ <div>
3
+ <h3 class="text-lg font-semibold mb-4">Auto-Loading Submit Button Demo</h3>
4
+ <p class="text-sm text-gray-600 mb-4">
5
+ This button automatically shows a loading spinner when clicked (submit buttons only).
6
+ The loading state resets automatically when Turbo completes the request.
7
+ </p>
8
+
9
+ <%= turbo_frame_tag "demo-frame" do %>
10
+ <%= form_with url: "#", method: :post, data: { turbo_frame: "demo-frame" } do |f| %>
11
+ <div class="space-y-4">
12
+ <div>
13
+ <label class="block text-sm font-medium text-gray-700 mb-2">
14
+ Example Form Field
15
+ </label>
16
+ <input
17
+ type="text"
18
+ name="example"
19
+ class="px-3 py-2 border border-gray-300 rounded-md"
20
+ placeholder="Type something..."
21
+ />
22
+ </div>
23
+
24
+ <%= render BetterUi::ButtonComponent.new(
25
+ variant: :primary,
26
+ type: :submit,
27
+ show_loader_on_click: true
28
+ ) do %>
29
+ Submit Form
30
+ <% end %>
31
+ </div>
32
+ <% end %>
33
+
34
+ <div class="mt-4 p-4 bg-gray-50 rounded-md">
35
+ <p class="text-sm text-gray-600">
36
+ Click the submit button above to see the auto-loading behavior.
37
+ The spinner appears instantly on click and automatically resets.
38
+ </p>
39
+ </div>
40
+ <% end %>
41
+ </div>
42
+
43
+ <div>
44
+ <h3 class="text-lg font-semibold mb-4">Comparison: Regular Button vs Auto-Loading Submit</h3>
45
+ <div class="grid grid-cols-2 gap-4">
46
+ <div>
47
+ <p class="text-sm text-gray-600 mb-2">Regular Button (no auto-loading)</p>
48
+ <%= render BetterUi::ButtonComponent.new(variant: :secondary, type: :button) do %>
49
+ Regular Button
50
+ <% end %>
51
+ </div>
52
+ <div>
53
+ <p class="text-sm text-gray-600 mb-2">Submit with Auto-Loading</p>
54
+ <%= form_with url: "#", method: :post do |f| %>
55
+ <%= render BetterUi::ButtonComponent.new(
56
+ variant: :primary,
57
+ type: :submit,
58
+ show_loader_on_click: true
59
+ ) do %>
60
+ Auto-Loading Submit
61
+ <% end %>
62
+ <% end %>
63
+ </div>
64
+ </div>
65
+ </div>
66
+
67
+ <div>
68
+ <h3 class="text-lg font-semibold mb-4">Different Variants with Auto-Loading</h3>
69
+ <div class="flex flex-wrap gap-3">
70
+ <%= form_with url: "#", method: :post do |f| %>
71
+ <%= render BetterUi::ButtonComponent.new(
72
+ variant: :primary,
73
+ type: :submit,
74
+ show_loader_on_click: true
75
+ ) do %>
76
+ Primary
77
+ <% end %>
78
+ <% end %>
79
+
80
+ <%= form_with url: "#", method: :post do |f| %>
81
+ <%= render BetterUi::ButtonComponent.new(
82
+ variant: :success,
83
+ type: :submit,
84
+ show_loader_on_click: true
85
+ ) do %>
86
+ Success
87
+ <% end %>
88
+ <% end %>
89
+
90
+ <%= form_with url: "#", method: :post do |f| %>
91
+ <%= render BetterUi::ButtonComponent.new(
92
+ variant: :danger,
93
+ type: :submit,
94
+ show_loader_on_click: true
95
+ ) do %>
96
+ Danger
97
+ <% end %>
98
+ <% end %>
99
+
100
+ <%= form_with url: "#", method: :post do |f| %>
101
+ <%= render BetterUi::ButtonComponent.new(
102
+ variant: :warning,
103
+ style: :outline,
104
+ type: :submit,
105
+ show_loader_on_click: true
106
+ ) do %>
107
+ Warning Outline
108
+ <% end %>
109
+ <% end %>
110
+ </div>
111
+ </div>
112
+ </div>
@@ -0,0 +1,61 @@
1
+ <div class="p-8 space-y-6">
2
+ <div>
3
+ <h3 class="text-lg font-semibold mb-4">External Link (opens in new tab)</h3>
4
+ <p class="text-sm text-gray-600 mb-2">Automatically adds rel="noopener noreferrer" for security</p>
5
+ <%= render BetterUi::ButtonComponent.new(
6
+ href: "https://example.com",
7
+ target: "_blank"
8
+ ) do |c|
9
+ c.with_icon_after do %>
10
+ <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
11
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"></path>
12
+ </svg>
13
+ <% end
14
+ "Visit Example.com"
15
+ end %>
16
+ </div>
17
+
18
+ <div>
19
+ <h3 class="text-lg font-semibold mb-4">External Links with Different Styles</h3>
20
+ <div class="flex flex-wrap gap-3">
21
+ <%= render BetterUi::ButtonComponent.new(
22
+ href: "https://example.com",
23
+ target: "_blank",
24
+ variant: :info,
25
+ style: :outline
26
+ ) do |c|
27
+ c.with_icon_after do %>
28
+ <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
29
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"></path>
30
+ </svg>
31
+ <% end
32
+ "Documentation"
33
+ end %>
34
+
35
+ <%= render BetterUi::ButtonComponent.new(
36
+ href: "https://github.com",
37
+ target: "_blank",
38
+ variant: :dark,
39
+ style: :solid
40
+ ) do |c|
41
+ c.with_icon_before do %>
42
+ <svg class="w-4 h-4" fill="currentColor" viewBox="0 0 24 24">
43
+ <path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd"></path>
44
+ </svg>
45
+ <% end
46
+ "GitHub"
47
+ end %>
48
+ </div>
49
+ </div>
50
+
51
+ <div>
52
+ <h3 class="text-lg font-semibold mb-4">Link with Custom rel</h3>
53
+ <%= render BetterUi::ButtonComponent.new(
54
+ href: "https://example.com",
55
+ target: "_blank",
56
+ rel: "nofollow noopener",
57
+ variant: :secondary,
58
+ style: :ghost
59
+ ) { "Sponsored Link (nofollow)" } %>
60
+ </div>
61
+ </div>
@@ -0,0 +1,102 @@
1
+ <div class="p-8 space-y-8">
2
+ <div>
3
+ <h3 class="text-lg font-semibold mb-4">Form with Submit and Reset Buttons</h3>
4
+ <form class="max-w-md space-y-4">
5
+ <div>
6
+ <label for="name" class="block text-sm font-medium text-gray-700 mb-1">Name</label>
7
+ <input
8
+ type="text"
9
+ id="name"
10
+ name="name"
11
+ class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-primary-500"
12
+ placeholder="Enter your name"
13
+ />
14
+ </div>
15
+
16
+ <div>
17
+ <label for="email" class="block text-sm font-medium text-gray-700 mb-1">Email</label>
18
+ <input
19
+ type="email"
20
+ id="email"
21
+ name="email"
22
+ class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-primary-500"
23
+ placeholder="Enter your email"
24
+ />
25
+ </div>
26
+
27
+ <div class="flex gap-3">
28
+ <%= render BetterUi::ButtonComponent.new(type: :submit, variant: :primary) do %>
29
+ Submit Form
30
+ <% end %>
31
+
32
+ <%= render BetterUi::ButtonComponent.new(type: :reset, variant: :secondary, style: :outline) do %>
33
+ Reset Form
34
+ <% end %>
35
+
36
+ <%= render BetterUi::ButtonComponent.new(type: :button, variant: :secondary, style: :ghost) do %>
37
+ Cancel
38
+ <% end %>
39
+ </div>
40
+ </form>
41
+ </div>
42
+
43
+ <div>
44
+ <h3 class="text-lg font-semibold mb-4">Form Actions with Icons</h3>
45
+ <form class="max-w-md space-y-4">
46
+ <div>
47
+ <label for="title" class="block text-sm font-medium text-gray-700 mb-1">Title</label>
48
+ <input
49
+ type="text"
50
+ id="title"
51
+ name="title"
52
+ class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-primary-500"
53
+ placeholder="Enter title"
54
+ />
55
+ </div>
56
+
57
+ <div class="flex gap-3">
58
+ <%= render BetterUi::ButtonComponent.new(type: :submit, variant: :success) do |button| %>
59
+ <% button.with_icon_before do %>
60
+ <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
61
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
62
+ </svg>
63
+ <% end %>
64
+ Save Changes
65
+ <% end %>
66
+
67
+ <%= render BetterUi::ButtonComponent.new(type: :button, variant: :danger, style: :outline) do |button| %>
68
+ <% button.with_icon_before do %>
69
+ <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
70
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
71
+ </svg>
72
+ <% end %>
73
+ Cancel
74
+ <% end %>
75
+ </div>
76
+ </form>
77
+ </div>
78
+
79
+ <div>
80
+ <h3 class="text-lg font-semibold mb-4">Disabled Form Buttons</h3>
81
+ <div class="flex gap-3">
82
+ <%= render BetterUi::ButtonComponent.new(type: :submit, variant: :primary, disabled: true) do %>
83
+ Disabled Submit
84
+ <% end %>
85
+
86
+ <%= render BetterUi::ButtonComponent.new(type: :reset, variant: :secondary, style: :outline, disabled: true) do %>
87
+ Disabled Reset
88
+ <% end %>
89
+ </div>
90
+ </div>
91
+
92
+ <div>
93
+ <h3 class="text-lg font-semibold mb-4">Loading Form Button</h3>
94
+ <div class="flex gap-3">
95
+ <%= render BetterUi::ButtonComponent.new(type: :submit, variant: :primary, loading: true) do %>
96
+ Submitting...
97
+ <% end %>
98
+
99
+ <p class="text-sm text-gray-600 self-center">Button is disabled during loading state</p>
100
+ </div>
101
+ </div>
102
+ </div>