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,17 @@
1
+ <div class="p-8">
2
+ <h3 class="text-lg font-semibold mb-6">Spinner 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-6 items-center">
10
+ <%= render BetterUi::SpinnerComponent.new(size: size, variant: :primary) %>
11
+ <%= render BetterUi::SpinnerComponent.new(size: size, variant: :success) %>
12
+ <%= render BetterUi::SpinnerComponent.new(size: size, variant: :danger) %>
13
+ </div>
14
+ </div>
15
+ <% end %>
16
+ </div>
17
+ </div>
@@ -0,0 +1,11 @@
1
+ <div class="p-8 space-y-8">
2
+ <h3 class="text-lg font-semibold mb-4">Spinner Variants</h3>
3
+ <div class="flex flex-wrap gap-8 items-center">
4
+ <% (@variants || BetterUi::ApplicationComponent::VARIANTS.keys).each do |variant| %>
5
+ <div class="flex flex-col items-center gap-2">
6
+ <%= render BetterUi::SpinnerComponent.new(variant: variant, size: :lg) %>
7
+ <span class="text-sm font-medium text-gray-600 capitalize"><%= variant %></span>
8
+ </div>
9
+ <% end %>
10
+ </div>
11
+ </div>
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterUi
4
+ class SpinnerComponentPreview < ViewComponent::Preview
5
+ # @label Default
6
+ def default
7
+ render BetterUi::SpinnerComponent.new
8
+ end
9
+
10
+ # @label All Variants
11
+ # @display bg_color #f5f5f5
12
+ def all_variants
13
+ @variants = ApplicationComponent::VARIANTS.keys
14
+ render_with_template
15
+ end
16
+
17
+ # @label All Sizes
18
+ def all_sizes
19
+ @sizes = [ :xs, :sm, :md, :lg, :xl ]
20
+ render_with_template
21
+ end
22
+
23
+ # @label With Label
24
+ def with_label
25
+ render BetterUi::SpinnerComponent.new(
26
+ variant: :primary,
27
+ size: :lg,
28
+ label: "Loading content..."
29
+ )
30
+ end
31
+
32
+ # @label Playground
33
+ # @param variant select { choices: [primary, secondary, accent, success, danger, warning, info, light, dark] }
34
+ # @param size select { choices: [xs, sm, md, lg, xl] }
35
+ # @param label text
36
+ def playground(variant: :primary, size: :md, label: nil)
37
+ render BetterUi::SpinnerComponent.new(
38
+ variant: variant,
39
+ size: size,
40
+ label: label.presence
41
+ )
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,28 @@
1
+ <div class="max-w-4xl mx-auto p-6 space-y-8">
2
+ <h2 class="text-xl font-bold mb-4">All Sizes</h2>
3
+
4
+ <% [:xs, :sm, :md, :lg, :xl].each do |size| %>
5
+ <div>
6
+ <h3 class="text-lg font-semibold mb-2">Size: <%= size %></h3>
7
+ <%= render BetterUi::Table::TableComponent.new(variant: :primary, size: size) do |t| %>
8
+ <% t.with_header do |h| %>
9
+ <% h.with_cell(label: "Name") %>
10
+ <% h.with_cell(label: "Email") %>
11
+ <% h.with_cell(label: "Status", align: :center) %>
12
+ <% end %>
13
+
14
+ <% t.with_row do |r| %>
15
+ <% r.with_cell { "Alice Johnson" } %>
16
+ <% r.with_cell { "alice@example.com" } %>
17
+ <% r.with_cell(align: :center) { "Active" } %>
18
+ <% end %>
19
+
20
+ <% t.with_row do |r| %>
21
+ <% r.with_cell { "Bob Smith" } %>
22
+ <% r.with_cell { "bob@example.com" } %>
23
+ <% r.with_cell(align: :center) { "Inactive" } %>
24
+ <% end %>
25
+ <% end %>
26
+ </div>
27
+ <% end %>
28
+ </div>
@@ -0,0 +1,34 @@
1
+ <div class="max-w-4xl mx-auto p-6 space-y-8">
2
+ <h2 class="text-xl font-bold mb-4">All Variants</h2>
3
+
4
+ <% BetterUi::ApplicationComponent::VARIANTS.each_key do |variant| %>
5
+ <div>
6
+ <h3 class="text-lg font-semibold mb-2 capitalize"><%= variant %></h3>
7
+ <%= render BetterUi::Table::TableComponent.new(variant: variant, striped: true) do |t| %>
8
+ <% t.with_header do |h| %>
9
+ <% h.with_cell(label: "Name") %>
10
+ <% h.with_cell(label: "Email") %>
11
+ <% h.with_cell(label: "Role") %>
12
+ <% end %>
13
+
14
+ <% t.with_row do |r| %>
15
+ <% r.with_cell { "Alice Johnson" } %>
16
+ <% r.with_cell { "alice@example.com" } %>
17
+ <% r.with_cell { "Admin" } %>
18
+ <% end %>
19
+
20
+ <% t.with_row do |r| %>
21
+ <% r.with_cell { "Bob Smith" } %>
22
+ <% r.with_cell { "bob@example.com" } %>
23
+ <% r.with_cell { "Editor" } %>
24
+ <% end %>
25
+
26
+ <% t.with_row do |r| %>
27
+ <% r.with_cell { "Charlie Brown" } %>
28
+ <% r.with_cell { "charlie@example.com" } %>
29
+ <% r.with_cell { "Viewer" } %>
30
+ <% end %>
31
+ <% end %>
32
+ </div>
33
+ <% end %>
34
+ </div>
@@ -0,0 +1,33 @@
1
+ <div class="max-w-4xl mx-auto p-6">
2
+ <h2 class="text-xl font-bold mb-4">Bordered Table</h2>
3
+
4
+ <%= render BetterUi::Table::TableComponent.new(variant: :primary, style: :bordered) do |t| %>
5
+ <% t.with_header do |h| %>
6
+ <% h.with_cell(label: "Product") %>
7
+ <% h.with_cell(label: "Category") %>
8
+ <% h.with_cell(label: "Price", align: :right) %>
9
+ <% h.with_cell(label: "Stock", align: :center) %>
10
+ <% end %>
11
+
12
+ <% t.with_row do |r| %>
13
+ <% r.with_cell { "Widget A" } %>
14
+ <% r.with_cell { "Electronics" } %>
15
+ <% r.with_cell(align: :right) { "$29.99" } %>
16
+ <% r.with_cell(align: :center) { "150" } %>
17
+ <% end %>
18
+
19
+ <% t.with_row do |r| %>
20
+ <% r.with_cell { "Widget B" } %>
21
+ <% r.with_cell { "Hardware" } %>
22
+ <% r.with_cell(align: :right) { "$49.99" } %>
23
+ <% r.with_cell(align: :center) { "75" } %>
24
+ <% end %>
25
+
26
+ <% t.with_row do |r| %>
27
+ <% r.with_cell { "Widget C" } %>
28
+ <% r.with_cell { "Software" } %>
29
+ <% r.with_cell(align: :right) { "$9.99" } %>
30
+ <% r.with_cell(align: :center) { "∞" } %>
31
+ <% end %>
32
+ <% end %>
33
+ </div>
@@ -0,0 +1,31 @@
1
+ <%
2
+ users = [
3
+ OpenStruct.new(name: "Alice Johnson", email: "alice@example.com", role: "admin", active: true),
4
+ OpenStruct.new(name: "Bob Smith", email: "bob@example.com", role: "editor", active: true),
5
+ OpenStruct.new(name: "Charlie Brown", email: "charlie@example.com", role: "viewer", active: false),
6
+ OpenStruct.new(name: "Diana Prince", email: "diana@example.com", role: "admin", active: true)
7
+ ]
8
+ %>
9
+
10
+ <div class="max-w-4xl mx-auto p-6 space-y-8">
11
+ <h2 class="text-xl font-bold mb-4">Collection Mode</h2>
12
+
13
+ <div>
14
+ <h3 class="text-lg font-semibold mb-2">Basic Collection</h3>
15
+ <%= render BetterUi::Table::TableComponent.new(collection: users, variant: :primary, striped: true) do |t| %>
16
+ <% t.with_column(key: :name, label: "Name") %>
17
+ <% t.with_column(key: :email, label: "Email") %>
18
+ <% t.with_column(key: :role, label: "Role") { |user| user.role.capitalize } %>
19
+ <% t.with_column(key: :active, label: "Status", align: :center) { |user| user.active ? "Active" : "Inactive" } %>
20
+ <% end %>
21
+ </div>
22
+
23
+ <div>
24
+ <h3 class="text-lg font-semibold mb-2">Collection with Auto-humanized Labels</h3>
25
+ <%= render BetterUi::Table::TableComponent.new(collection: users, variant: :success) do |t| %>
26
+ <% t.with_column(key: :name) %>
27
+ <% t.with_column(key: :email) %>
28
+ <% t.with_column(key: :role) %>
29
+ <% end %>
30
+ </div>
31
+ </div>
@@ -0,0 +1,33 @@
1
+ <div class="max-w-4xl mx-auto p-6">
2
+ <h2 class="text-xl font-bold mb-4">Default Table</h2>
3
+
4
+ <%= render BetterUi::Table::TableComponent.new(variant: :primary) do |t| %>
5
+ <% t.with_header do |h| %>
6
+ <% h.with_cell(label: "Name") %>
7
+ <% h.with_cell(label: "Email") %>
8
+ <% h.with_cell(label: "Role") %>
9
+ <% h.with_cell(label: "Status", align: :center) %>
10
+ <% end %>
11
+
12
+ <% t.with_row do |r| %>
13
+ <% r.with_cell { "Alice Johnson" } %>
14
+ <% r.with_cell { "alice@example.com" } %>
15
+ <% r.with_cell { "Admin" } %>
16
+ <% r.with_cell(align: :center) { "Active" } %>
17
+ <% end %>
18
+
19
+ <% t.with_row do |r| %>
20
+ <% r.with_cell { "Bob Smith" } %>
21
+ <% r.with_cell { "bob@example.com" } %>
22
+ <% r.with_cell { "Editor" } %>
23
+ <% r.with_cell(align: :center) { "Active" } %>
24
+ <% end %>
25
+
26
+ <% t.with_row do |r| %>
27
+ <% r.with_cell { "Charlie Brown" } %>
28
+ <% r.with_cell { "charlie@example.com" } %>
29
+ <% r.with_cell { "Viewer" } %>
30
+ <% r.with_cell(align: :center) { "Inactive" } %>
31
+ <% end %>
32
+ <% end %>
33
+ </div>
@@ -0,0 +1,36 @@
1
+ <div class="max-w-4xl mx-auto p-6 space-y-8">
2
+ <h2 class="text-xl font-bold mb-4">Empty State</h2>
3
+
4
+ <div>
5
+ <h3 class="text-lg font-semibold mb-2">Slot Mode - Empty</h3>
6
+ <%= render BetterUi::Table::TableComponent.new(variant: :primary) do |t| %>
7
+ <% t.with_header do |h| %>
8
+ <% h.with_cell(label: "Name") %>
9
+ <% h.with_cell(label: "Email") %>
10
+ <% h.with_cell(label: "Role") %>
11
+ <% end %>
12
+
13
+ <% t.with_empty_state do %>
14
+ <div class="py-8 text-center text-grayscale-500">
15
+ <p class="text-lg font-medium">No users found</p>
16
+ <p class="text-sm mt-1">Try adjusting your search criteria.</p>
17
+ </div>
18
+ <% end %>
19
+ <% end %>
20
+ </div>
21
+
22
+ <div>
23
+ <h3 class="text-lg font-semibold mb-2">Collection Mode - Empty</h3>
24
+ <%= render BetterUi::Table::TableComponent.new(collection: [], variant: :info) do |t| %>
25
+ <% t.with_column(key: :name, label: "Name") %>
26
+ <% t.with_column(key: :email, label: "Email") %>
27
+
28
+ <% t.with_empty_state do %>
29
+ <div class="py-8 text-center text-grayscale-500">
30
+ <p class="text-lg font-medium">No records available</p>
31
+ <p class="text-sm mt-1">Data will appear here once added.</p>
32
+ </div>
33
+ <% end %>
34
+ <% end %>
35
+ </div>
36
+ </div>
@@ -0,0 +1,64 @@
1
+ <div class="max-w-4xl mx-auto p-6">
2
+ <h2 class="text-xl font-bold mb-4">Row Highlighting (Slot Mode)</h2>
3
+ <p class="text-sm text-grayscale-500 mb-4">Specific rows can be highlighted to draw attention.</p>
4
+
5
+ <%= render BetterUi::Table::TableComponent.new(variant: :primary) do |t| %>
6
+ <% t.with_header do |h| %>
7
+ <% h.with_cell(label: "Order #") %>
8
+ <% h.with_cell(label: "Customer") %>
9
+ <% h.with_cell(label: "Status") %>
10
+ <% h.with_cell(label: "Total", align: :right) %>
11
+ <% end %>
12
+
13
+ <% t.with_row do |r| %>
14
+ <% r.with_cell { "ORD-001" } %>
15
+ <% r.with_cell { "Alice Johnson" } %>
16
+ <% r.with_cell { "Shipped" } %>
17
+ <% r.with_cell(align: :right) { "$299.00" } %>
18
+ <% end %>
19
+
20
+ <% t.with_row(highlighted: true) do |r| %>
21
+ <% r.with_cell { "ORD-002" } %>
22
+ <% r.with_cell { "Bob Smith" } %>
23
+ <% r.with_cell { "Pending Review" } %>
24
+ <% r.with_cell(align: :right) { "$149.50" } %>
25
+ <% end %>
26
+
27
+ <% t.with_row do |r| %>
28
+ <% r.with_cell { "ORD-003" } %>
29
+ <% r.with_cell { "Charlie Brown" } %>
30
+ <% r.with_cell { "Delivered" } %>
31
+ <% r.with_cell(align: :right) { "$75.25" } %>
32
+ <% end %>
33
+
34
+ <% t.with_row(highlighted: true) do |r| %>
35
+ <% r.with_cell { "ORD-004" } %>
36
+ <% r.with_cell { "Diana Prince" } %>
37
+ <% r.with_cell { "Pending Review" } %>
38
+ <% r.with_cell(align: :right) { "$512.00" } %>
39
+ <% end %>
40
+ <% end %>
41
+
42
+ <h2 class="text-xl font-bold mb-4 mt-8">Row Highlighting (Collection Mode with Proc)</h2>
43
+ <p class="text-sm text-grayscale-500 mb-4">Highlighting applied dynamically based on item data.</p>
44
+
45
+ <%
46
+ orders = [
47
+ OpenStruct.new(number: "ORD-001", customer: "Alice Johnson", status: "Shipped", total: "$299.00", pending: false),
48
+ OpenStruct.new(number: "ORD-002", customer: "Bob Smith", status: "Pending Review", total: "$149.50", pending: true),
49
+ OpenStruct.new(number: "ORD-003", customer: "Charlie Brown", status: "Delivered", total: "$75.25", pending: false),
50
+ OpenStruct.new(number: "ORD-004", customer: "Diana Prince", status: "Pending Review", total: "$512.00", pending: true)
51
+ ]
52
+ %>
53
+
54
+ <%= render BetterUi::Table::TableComponent.new(
55
+ collection: orders,
56
+ variant: :warning,
57
+ row_highlighted: ->(item) { item.pending }
58
+ ) do |t| %>
59
+ <% t.with_column(key: :number, label: "Order #") %>
60
+ <% t.with_column(key: :customer, label: "Customer") %>
61
+ <% t.with_column(key: :status, label: "Status") %>
62
+ <% t.with_column(key: :total, label: "Total", align: :right) %>
63
+ <% end %>
64
+ </div>
@@ -0,0 +1,27 @@
1
+ <div class="max-w-4xl mx-auto p-6">
2
+ <h2 class="text-xl font-bold mb-4">Hoverable Table</h2>
3
+ <p class="text-sm text-grayscale-500 mb-4">Hover over the rows to see the highlight effect.</p>
4
+
5
+ <%= render BetterUi::Table::TableComponent.new(variant: :info, hoverable: true) do |t| %>
6
+ <% t.with_header do |h| %>
7
+ <% h.with_cell(label: "Order #") %>
8
+ <% h.with_cell(label: "Customer") %>
9
+ <% h.with_cell(label: "Date") %>
10
+ <% h.with_cell(label: "Total", align: :right) %>
11
+ <% end %>
12
+
13
+ <% [
14
+ ["ORD-001", "Alice Johnson", "2024-01-15", "$299.00"],
15
+ ["ORD-002", "Bob Smith", "2024-01-16", "$149.50"],
16
+ ["ORD-003", "Charlie Brown", "2024-01-17", "$75.25"],
17
+ ["ORD-004", "Diana Prince", "2024-01-18", "$512.00"]
18
+ ].each do |row_data| %>
19
+ <% t.with_row do |r| %>
20
+ <% r.with_cell { row_data[0] } %>
21
+ <% r.with_cell { row_data[1] } %>
22
+ <% r.with_cell { row_data[2] } %>
23
+ <% r.with_cell(align: :right) { row_data[3] } %>
24
+ <% end %>
25
+ <% end %>
26
+ <% end %>
27
+ </div>
@@ -0,0 +1,173 @@
1
+ <div class="max-w-4xl mx-auto p-6 space-y-10">
2
+
3
+ <%# ===== 1. Table inside a bordered Card ===== %>
4
+ <div>
5
+ <h2 class="text-xl font-bold mb-4">Table inside a Card (bordered)</h2>
6
+ <p class="text-sm text-grayscale-500 mb-4">
7
+ Use <code>body_padding: false</code> on the Card and
8
+ <code>container_classes: "shadow-none ring-0 rounded-none"</code> on the Table
9
+ to avoid double card styling.
10
+ </p>
11
+
12
+ <%= render BetterUi::CardComponent.new(
13
+ style: :bordered,
14
+ variant: :primary,
15
+ body_padding: false
16
+ ) do |card| %>
17
+ <% card.with_header { "Team Members" } %>
18
+ <% card.with_body do %>
19
+ <%= render BetterUi::Table::TableComponent.new(
20
+ variant: :primary,
21
+ container_classes: "shadow-none ring-0 rounded-none"
22
+ ) do |t| %>
23
+ <% t.with_header do |h| %>
24
+ <% h.with_cell(label: "Name") %>
25
+ <% h.with_cell(label: "Email") %>
26
+ <% h.with_cell(label: "Role") %>
27
+ <% h.with_cell(label: "Status", align: :center) %>
28
+ <% end %>
29
+
30
+ <% t.with_row do |r| %>
31
+ <% r.with_cell { "Alice Johnson" } %>
32
+ <% r.with_cell { "alice@example.com" } %>
33
+ <% r.with_cell { "Admin" } %>
34
+ <% r.with_cell(align: :center) { "Active" } %>
35
+ <% end %>
36
+ <% t.with_row do |r| %>
37
+ <% r.with_cell { "Bob Smith" } %>
38
+ <% r.with_cell { "bob@example.com" } %>
39
+ <% r.with_cell { "Editor" } %>
40
+ <% r.with_cell(align: :center) { "Active" } %>
41
+ <% end %>
42
+ <% t.with_row do |r| %>
43
+ <% r.with_cell { "Charlie Brown" } %>
44
+ <% r.with_cell { "charlie@example.com" } %>
45
+ <% r.with_cell { "Viewer" } %>
46
+ <% r.with_cell(align: :center) { "Inactive" } %>
47
+ <% end %>
48
+ <% end %>
49
+ <% end %>
50
+ <% card.with_footer do %>
51
+ <div class="flex justify-between items-center">
52
+ <span class="text-sm text-grayscale-500">3 members</span>
53
+ <button class="text-sm text-primary-600 font-medium hover:text-primary-800">Add member</button>
54
+ </div>
55
+ <% end %>
56
+ <% end %>
57
+ </div>
58
+
59
+ <%# ===== 2. Table inside an outline Card ===== %>
60
+ <div>
61
+ <h2 class="text-xl font-bold mb-4">Table inside a Card (outline, success variant)</h2>
62
+
63
+ <%= render BetterUi::CardComponent.new(
64
+ variant: :success,
65
+ style: :outline,
66
+ body_padding: false
67
+ ) do |card| %>
68
+ <% card.with_header do %>
69
+ <div class="flex justify-between items-center">
70
+ <span class="font-semibold">Recent Orders</span>
71
+ <span class="text-xs bg-success-100 text-success-700 px-2 py-1 rounded-full">Live</span>
72
+ </div>
73
+ <% end %>
74
+ <% card.with_body do %>
75
+ <%= render BetterUi::Table::TableComponent.new(
76
+ variant: :success,
77
+ striped: true,
78
+ hoverable: true,
79
+ container_classes: "shadow-none ring-0 rounded-none"
80
+ ) do |t| %>
81
+ <% t.with_header do |h| %>
82
+ <% h.with_cell(label: "Order #") %>
83
+ <% h.with_cell(label: "Customer") %>
84
+ <% h.with_cell(label: "Amount", align: :right) %>
85
+ <% end %>
86
+
87
+ <% t.with_row do |r| %>
88
+ <% r.with_cell { "#1001" } %>
89
+ <% r.with_cell { "Jane Cooper" } %>
90
+ <% r.with_cell(align: :right) { "$120.00" } %>
91
+ <% end %>
92
+ <% t.with_row do |r| %>
93
+ <% r.with_cell { "#1002" } %>
94
+ <% r.with_cell { "Wade Warren" } %>
95
+ <% r.with_cell(align: :right) { "$89.50" } %>
96
+ <% end %>
97
+ <% t.with_row do |r| %>
98
+ <% r.with_cell { "#1003" } %>
99
+ <% r.with_cell { "Esther Howard" } %>
100
+ <% r.with_cell(align: :right) { "$245.00" } %>
101
+ <% end %>
102
+ <% end %>
103
+ <% end %>
104
+ <% end %>
105
+ </div>
106
+
107
+ <%# ===== 3. Collection mode inside a soft Card ===== %>
108
+ <div>
109
+ <h2 class="text-xl font-bold mb-4">Collection mode inside a Card (soft, info variant)</h2>
110
+
111
+ <%
112
+ products = [
113
+ { name: "Widget A", sku: "WA-001", price: "$29.99", stock: 142 },
114
+ { name: "Widget B", sku: "WB-002", price: "$49.99", stock: 38 },
115
+ { name: "Gadget C", sku: "GC-003", price: "$99.99", stock: 7 },
116
+ ]
117
+ %>
118
+
119
+ <%= render BetterUi::CardComponent.new(
120
+ variant: :info,
121
+ style: :soft,
122
+ body_padding: false
123
+ ) do |card| %>
124
+ <% card.with_header do %>
125
+ <span class="font-semibold">Product Inventory</span>
126
+ <% end %>
127
+ <% card.with_body do %>
128
+ <%= render BetterUi::Table::TableComponent.new(
129
+ collection: products,
130
+ variant: :info,
131
+ size: :sm,
132
+ hoverable: true,
133
+ container_classes: "shadow-none ring-0 rounded-none"
134
+ ) do |t| %>
135
+ <% t.with_column(key: :name, label: "Product") %>
136
+ <% t.with_column(key: :sku, label: "SKU") %>
137
+ <% t.with_column(key: :price, label: "Price", align: :right) %>
138
+ <% t.with_column(key: :stock, label: "Stock", align: :center) { |p| p[:stock].to_s } %>
139
+ <% end %>
140
+ <% end %>
141
+ <% card.with_footer do %>
142
+ <span class="text-sm text-grayscale-500">Showing 3 of 3 products</span>
143
+ <% end %>
144
+ <% end %>
145
+ </div>
146
+
147
+ <%# ===== 4. Standalone table for comparison ===== %>
148
+ <div>
149
+ <h2 class="text-xl font-bold mb-4">Standalone table (for comparison)</h2>
150
+ <p class="text-sm text-grayscale-500 mb-4">
151
+ The table renders with its own card styling by default.
152
+ </p>
153
+
154
+ <%= render BetterUi::Table::TableComponent.new(variant: :primary, hoverable: true) do |t| %>
155
+ <% t.with_header do |h| %>
156
+ <% h.with_cell(label: "Name") %>
157
+ <% h.with_cell(label: "Email") %>
158
+ <% h.with_cell(label: "Role") %>
159
+ <% end %>
160
+ <% t.with_row do |r| %>
161
+ <% r.with_cell { "Alice Johnson" } %>
162
+ <% r.with_cell { "alice@example.com" } %>
163
+ <% r.with_cell { "Admin" } %>
164
+ <% end %>
165
+ <% t.with_row do |r| %>
166
+ <% r.with_cell { "Bob Smith" } %>
167
+ <% r.with_cell { "bob@example.com" } %>
168
+ <% r.with_cell { "Editor" } %>
169
+ <% end %>
170
+ <% end %>
171
+ </div>
172
+
173
+ </div>
@@ -0,0 +1,44 @@
1
+ <div class="max-w-4xl mx-auto p-6">
2
+ <h2 class="text-xl font-bold mb-4">Sortable Headers (Slot Mode)</h2>
3
+ <p class="text-sm text-grayscale-500 mb-4">Headers can indicate sort state with directional icons.</p>
4
+
5
+ <%= render BetterUi::Table::TableComponent.new(variant: :primary) do |t| %>
6
+ <% t.with_header do |h| %>
7
+ <% h.with_cell(label: "Name", sortable: true, sorted: true, sort_direction: :asc) %>
8
+ <% h.with_cell(label: "Email", sortable: true) %>
9
+ <% h.with_cell(label: "Role") %>
10
+ <% h.with_cell(label: "Joined", sortable: true, sorted: true, sort_direction: :desc) %>
11
+ <% end %>
12
+
13
+ <% [
14
+ ["Alice Johnson", "alice@example.com", "Admin", "2024-01-15"],
15
+ ["Bob Smith", "bob@example.com", "Editor", "2024-02-20"],
16
+ ["Charlie Brown", "charlie@example.com", "Viewer", "2024-03-10"]
17
+ ].each do |row_data| %>
18
+ <% t.with_row do |r| %>
19
+ <% r.with_cell { row_data[0] } %>
20
+ <% r.with_cell { row_data[1] } %>
21
+ <% r.with_cell { row_data[2] } %>
22
+ <% r.with_cell { row_data[3] } %>
23
+ <% end %>
24
+ <% end %>
25
+ <% end %>
26
+
27
+ <h2 class="text-xl font-bold mb-4 mt-8">Sortable Headers (Collection Mode)</h2>
28
+ <p class="text-sm text-grayscale-500 mb-4">Sort indicators in collection mode columns.</p>
29
+
30
+ <%
31
+ users = [
32
+ OpenStruct.new(name: "Alice Johnson", email: "alice@example.com", role: "Admin", joined: "2024-01-15"),
33
+ OpenStruct.new(name: "Bob Smith", email: "bob@example.com", role: "Editor", joined: "2024-02-20"),
34
+ OpenStruct.new(name: "Charlie Brown", email: "charlie@example.com", role: "Viewer", joined: "2024-03-10")
35
+ ]
36
+ %>
37
+
38
+ <%= render BetterUi::Table::TableComponent.new(collection: users, variant: :info) do |t| %>
39
+ <% t.with_column(key: :name, label: "Name", sortable: true, sorted: true, sort_direction: :asc) %>
40
+ <% t.with_column(key: :email, label: "Email", sortable: true) %>
41
+ <% t.with_column(key: :role, label: "Role") %>
42
+ <% t.with_column(key: :joined, label: "Joined", sortable: true, sorted: true, sort_direction: :desc) %>
43
+ <% end %>
44
+ </div>
@@ -0,0 +1,31 @@
1
+ <div class="max-w-4xl mx-auto p-6">
2
+ <h2 class="text-xl font-bold mb-4">Striped Table</h2>
3
+
4
+ <%= render BetterUi::Table::TableComponent.new(variant: :primary, striped: true) do |t| %>
5
+ <% t.with_header do |h| %>
6
+ <% h.with_cell(label: "#") %>
7
+ <% h.with_cell(label: "Name") %>
8
+ <% h.with_cell(label: "Department") %>
9
+ <% h.with_cell(label: "Salary", align: :right) %>
10
+ <% end %>
11
+
12
+ <% [
13
+ ["1", "Alice Johnson", "Engineering", "$120,000"],
14
+ ["2", "Bob Smith", "Marketing", "$95,000"],
15
+ ["3", "Charlie Brown", "Design", "$105,000"],
16
+ ["4", "Diana Prince", "Engineering", "$130,000"],
17
+ ["5", "Eve Wilson", "Sales", "$88,000"],
18
+ ["6", "Frank Castle", "Operations", "$92,000"]
19
+ ].each do |row_data| %>
20
+ <% t.with_row do |r| %>
21
+ <% row_data.each_with_index do |cell, i| %>
22
+ <% if i == 3 %>
23
+ <% r.with_cell(align: :right) { cell } %>
24
+ <% else %>
25
+ <% r.with_cell { cell } %>
26
+ <% end %>
27
+ <% end %>
28
+ <% end %>
29
+ <% end %>
30
+ <% end %>
31
+ </div>
@@ -0,0 +1,40 @@
1
+ <div class="max-w-4xl mx-auto p-6">
2
+ <h2 class="text-xl font-bold mb-4">Table with Footer</h2>
3
+
4
+ <%= render BetterUi::Table::TableComponent.new(variant: :primary, caption: "Quarterly Sales Report") do |t| %>
5
+ <% t.with_header do |h| %>
6
+ <% h.with_cell(label: "Quarter") %>
7
+ <% h.with_cell(label: "Revenue", align: :right) %>
8
+ <% h.with_cell(label: "Expenses", align: :right) %>
9
+ <% h.with_cell(label: "Profit", align: :right) %>
10
+ <% end %>
11
+
12
+ <% t.with_row do |r| %>
13
+ <% r.with_cell { "Q1 2024" } %>
14
+ <% r.with_cell(align: :right) { "$150,000" } %>
15
+ <% r.with_cell(align: :right) { "$90,000" } %>
16
+ <% r.with_cell(align: :right) { "$60,000" } %>
17
+ <% end %>
18
+
19
+ <% t.with_row do |r| %>
20
+ <% r.with_cell { "Q2 2024" } %>
21
+ <% r.with_cell(align: :right) { "$175,000" } %>
22
+ <% r.with_cell(align: :right) { "$95,000" } %>
23
+ <% r.with_cell(align: :right) { "$80,000" } %>
24
+ <% end %>
25
+
26
+ <% t.with_row do |r| %>
27
+ <% r.with_cell { "Q3 2024" } %>
28
+ <% r.with_cell(align: :right) { "$200,000" } %>
29
+ <% r.with_cell(align: :right) { "$110,000" } %>
30
+ <% r.with_cell(align: :right) { "$90,000" } %>
31
+ <% end %>
32
+
33
+ <% t.with_footer_row do |r| %>
34
+ <% r.with_cell { "Total" } %>
35
+ <% r.with_cell(align: :right) { "$525,000" } %>
36
+ <% r.with_cell(align: :right) { "$295,000" } %>
37
+ <% r.with_cell(align: :right) { "$230,000" } %>
38
+ <% end %>
39
+ <% end %>
40
+ </div>