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,34 @@
1
+ <div class="p-4">
2
+ <h3 class="text-lg font-semibold mb-4">Default Dialog</h3>
3
+
4
+ <%= render BetterUi::Dialog::DialogComponent.new(size: :md) do |d| %>
5
+ <% d.with_trigger do %>
6
+ <%= render(BetterUi::ButtonComponent.new(variant: :primary)) do %>Open Dialog<% end %>
7
+ <% end %>
8
+
9
+ <%= render BetterUi::CardComponent.new(style: :bordered, shadow: true, size: :md) do |card| %>
10
+ <% card.with_header do %>
11
+ <h3 class="text-lg font-semibold text-grayscale-900">Dialog Title</h3>
12
+ <% end %>
13
+
14
+ <% card.with_body do %>
15
+ <p class="text-grayscale-600">This is a basic dialog with a card inside. Click the X button or the backdrop to close it.</p>
16
+ <% end %>
17
+
18
+ <% card.with_footer do %>
19
+ <div class="flex flex-col-reverse sm:flex-row sm:justify-end gap-3">
20
+ <%= render(BetterUi::ButtonComponent.new(
21
+ variant: :secondary,
22
+ style: :outline,
23
+ data: { action: "click->better-ui--dialog--dialog#close" }
24
+ )) do %>Cancel<% end %>
25
+ <%= render(BetterUi::ButtonComponent.new(
26
+ variant: :primary,
27
+ style: :solid,
28
+ data: { action: "click->better-ui--dialog--dialog#close" }
29
+ )) do %>Save<% end %>
30
+ </div>
31
+ <% end %>
32
+ <% end %>
33
+ <% end %>
34
+ </div>
@@ -0,0 +1,28 @@
1
+ <div class="p-4">
2
+ <h3 class="text-lg font-semibold mb-4">No Close Button</h3>
3
+
4
+ <%= render BetterUi::Dialog::DialogComponent.new(size: :sm, show_close_button: false) do |d| %>
5
+ <% d.with_trigger do %>
6
+ <%= render(BetterUi::ButtonComponent.new(variant: :warning)) do %>Open (No X Button)<% end %>
7
+ <% end %>
8
+
9
+ <%= render BetterUi::CardComponent.new(style: :bordered, shadow: true, size: :md) do |card| %>
10
+ <% card.with_header do %>
11
+ <h3 class="text-lg font-semibold text-grayscale-900">No Close Button</h3>
12
+ <% end %>
13
+
14
+ <% card.with_body do %>
15
+ <p class="text-grayscale-600">This dialog has no X button. You can still close it by clicking the backdrop or pressing Escape, or use the button below.</p>
16
+ <% end %>
17
+
18
+ <% card.with_footer do %>
19
+ <div class="flex justify-end">
20
+ <%= render(BetterUi::ButtonComponent.new(
21
+ variant: :primary,
22
+ data: { action: "click->better-ui--dialog--dialog#close" }
23
+ )) do %>Close<% end %>
24
+ </div>
25
+ <% end %>
26
+ <% end %>
27
+ <% end %>
28
+ </div>
@@ -0,0 +1,39 @@
1
+ <div class="p-4">
2
+ <h3 class="text-lg font-semibold mb-4">Playground</h3>
3
+
4
+ <%= render BetterUi::Dialog::DialogComponent.new(
5
+ size: @size,
6
+ close_on_backdrop: @close_on_backdrop,
7
+ close_on_escape: @close_on_escape,
8
+ show_close_button: @show_close_button
9
+ ) do |d| %>
10
+ <% d.with_trigger do %>
11
+ <%= render(BetterUi::ButtonComponent.new(variant: :primary)) do %>Open Dialog<% end %>
12
+ <% end %>
13
+
14
+ <%= render BetterUi::CardComponent.new(style: :bordered, shadow: true, size: :md) do |card| %>
15
+ <% card.with_header do %>
16
+ <h3 class="text-lg font-semibold text-grayscale-900">Dialog Title</h3>
17
+ <% end %>
18
+
19
+ <% card.with_body do %>
20
+ <p class="text-grayscale-600">This is the dialog body content. You can put any content here.</p>
21
+ <% end %>
22
+
23
+ <% card.with_footer do %>
24
+ <div class="flex flex-col-reverse sm:flex-row sm:justify-end gap-3">
25
+ <%= render(BetterUi::ButtonComponent.new(
26
+ variant: :secondary,
27
+ style: :outline,
28
+ data: { action: "click->better-ui--dialog--dialog#close" }
29
+ )) do %>Cancel<% end %>
30
+ <%= render(BetterUi::ButtonComponent.new(
31
+ variant: :primary,
32
+ style: :solid,
33
+ data: { action: "click->better-ui--dialog--dialog#close" }
34
+ )) do %>Save Changes<% end %>
35
+ </div>
36
+ <% end %>
37
+ <% end %>
38
+ <% end %>
39
+ </div>
@@ -0,0 +1,52 @@
1
+ <div class="p-4">
2
+ <h3 class="text-lg font-semibold mb-4">With Card Content</h3>
3
+
4
+ <%= render BetterUi::Dialog::DialogComponent.new(size: :lg) do |d| %>
5
+ <% d.with_trigger do %>
6
+ <%= render(BetterUi::ButtonComponent.new(variant: :success)) do %>Open Full Dialog<% end %>
7
+ <% end %>
8
+
9
+ <%= render BetterUi::CardComponent.new(style: :bordered, shadow: true, size: :md) do |card| %>
10
+ <% card.with_header do %>
11
+ <div class="flex items-center gap-2">
12
+ <svg class="h-5 w-5 text-success-600" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
13
+ <path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
14
+ </svg>
15
+ <h3 class="text-lg font-semibold text-grayscale-900">Edit Profile</h3>
16
+ </div>
17
+ <% end %>
18
+
19
+ <% card.with_body do %>
20
+ <div class="space-y-4">
21
+ <div>
22
+ <label class="block text-sm font-medium text-grayscale-700 mb-1">Name</label>
23
+ <input type="text" value="John Doe" class="w-full rounded-md border-grayscale-300 shadow-sm focus:border-primary-500 focus:ring-primary-500 px-3 py-2 border" />
24
+ </div>
25
+ <div>
26
+ <label class="block text-sm font-medium text-grayscale-700 mb-1">Email</label>
27
+ <input type="email" value="john@example.com" class="w-full rounded-md border-grayscale-300 shadow-sm focus:border-primary-500 focus:ring-primary-500 px-3 py-2 border" />
28
+ </div>
29
+ <div>
30
+ <label class="block text-sm font-medium text-grayscale-700 mb-1">Bio</label>
31
+ <textarea rows="3" class="w-full rounded-md border-grayscale-300 shadow-sm focus:border-primary-500 focus:ring-primary-500 px-3 py-2 border">Software developer and coffee enthusiast.</textarea>
32
+ </div>
33
+ </div>
34
+ <% end %>
35
+
36
+ <% card.with_footer do %>
37
+ <div class="flex flex-col-reverse sm:flex-row sm:justify-end gap-3">
38
+ <%= render(BetterUi::ButtonComponent.new(
39
+ variant: :secondary,
40
+ style: :outline,
41
+ data: { action: "click->better-ui--dialog--dialog#close" }
42
+ )) do %>Cancel<% end %>
43
+ <%= render(BetterUi::ButtonComponent.new(
44
+ variant: :success,
45
+ style: :solid,
46
+ data: { action: "click->better-ui--dialog--dialog#close" }
47
+ )) do %>Save Changes<% end %>
48
+ </div>
49
+ <% end %>
50
+ <% end %>
51
+ <% end %>
52
+ </div>
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterUi
4
+ module Dialog
5
+ # @label Dialog
6
+ class DialogComponentPreview < ViewComponent::Preview
7
+ # @label Default
8
+ # @display max_height 600px
9
+ def default
10
+ render_with_template
11
+ end
12
+
13
+ # @label All Sizes
14
+ # @display max_height 600px
15
+ def all_sizes
16
+ render_with_template
17
+ end
18
+
19
+ # @label With All Slots
20
+ # @display max_height 600px
21
+ def with_all_slots
22
+ render_with_template
23
+ end
24
+
25
+ # @label No Close Button
26
+ # @display max_height 600px
27
+ def no_close_button
28
+ render_with_template
29
+ end
30
+
31
+ # @label Playground
32
+ # @display max_height 600px
33
+ # @param size select { choices: [sm, md, lg, xl, xxl, full] }
34
+ # @param close_on_backdrop toggle
35
+ # @param close_on_escape toggle
36
+ # @param show_close_button toggle
37
+ def playground(
38
+ size: :md,
39
+ close_on_backdrop: true,
40
+ close_on_escape: true,
41
+ show_close_button: true
42
+ )
43
+ @size = size.presence&.to_sym || :md
44
+ @close_on_backdrop = close_on_backdrop
45
+ @close_on_escape = close_on_escape
46
+ @show_close_button = show_close_button
47
+ render_with_template
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,58 @@
1
+ <div class="space-y-8 p-4">
2
+ <div>
3
+ <h3 class="text-sm font-semibold text-grayscale-700 mb-2">Solid (default)</h3>
4
+ <%= render BetterUi::DividerComponent.new(style: :solid) %>
5
+ </div>
6
+
7
+ <div>
8
+ <h3 class="text-sm font-semibold text-grayscale-700 mb-2">Dashed</h3>
9
+ <%= render BetterUi::DividerComponent.new(style: :dashed) %>
10
+ </div>
11
+
12
+ <div>
13
+ <h3 class="text-sm font-semibold text-grayscale-700 mb-2">Dotted</h3>
14
+ <%= render BetterUi::DividerComponent.new(style: :dotted) %>
15
+ </div>
16
+
17
+ <hr class="my-8 border-grayscale-200">
18
+
19
+ <h3 class="text-sm font-semibold text-grayscale-700 mb-4">Sizes</h3>
20
+
21
+ <div>
22
+ <p class="text-xs text-grayscale-500 mb-1">Extra Small (xs)</p>
23
+ <%= render BetterUi::DividerComponent.new(size: :xs) %>
24
+ </div>
25
+
26
+ <div>
27
+ <p class="text-xs text-grayscale-500 mb-1">Small (sm)</p>
28
+ <%= render BetterUi::DividerComponent.new(size: :sm) %>
29
+ </div>
30
+
31
+ <div>
32
+ <p class="text-xs text-grayscale-500 mb-1">Medium (md)</p>
33
+ <%= render BetterUi::DividerComponent.new(size: :md) %>
34
+ </div>
35
+
36
+ <hr class="my-8 border-grayscale-200">
37
+
38
+ <h3 class="text-sm font-semibold text-grayscale-700 mb-4">Variants</h3>
39
+
40
+ <% [nil, :primary, :secondary, :accent, :success, :danger, :warning, :info, :light, :dark].each do |variant| %>
41
+ <div>
42
+ <p class="text-xs text-grayscale-500 mb-1"><%= variant ? variant.to_s.capitalize : "Default (nil)" %></p>
43
+ <%= render BetterUi::DividerComponent.new(variant: variant, size: :sm) %>
44
+ </div>
45
+ <% end %>
46
+
47
+ <hr class="my-8 border-grayscale-200">
48
+
49
+ <h3 class="text-sm font-semibold text-grayscale-700 mb-4">Spacing</h3>
50
+
51
+ <% BetterUi::DividerComponent::SPACINGS.each do |spacing| %>
52
+ <div class="bg-grayscale-100 rounded">
53
+ <p class="text-xs text-grayscale-500 px-2 pt-1"><%= spacing %> spacing</p>
54
+ <%= render BetterUi::DividerComponent.new(spacing: spacing, variant: :primary) %>
55
+ <p class="text-xs text-grayscale-500 px-2 pb-1">Content below</p>
56
+ </div>
57
+ <% end %>
58
+ </div>
@@ -0,0 +1,67 @@
1
+ <div class="space-y-8 p-4">
2
+ <div>
3
+ <h3 class="text-sm font-semibold text-grayscale-700 mb-2">Center Label (default)</h3>
4
+ <%= render BetterUi::DividerComponent.new(label: "OR") %>
5
+ </div>
6
+
7
+ <div>
8
+ <h3 class="text-sm font-semibold text-grayscale-700 mb-2">Left Label</h3>
9
+ <%= render BetterUi::DividerComponent.new(label: "Section 1", label_position: :left) %>
10
+ </div>
11
+
12
+ <div>
13
+ <h3 class="text-sm font-semibold text-grayscale-700 mb-2">Right Label</h3>
14
+ <%= render BetterUi::DividerComponent.new(label: "Continue", label_position: :right) %>
15
+ </div>
16
+
17
+ <hr class="my-8 border-grayscale-200">
18
+
19
+ <h3 class="text-sm font-semibold text-grayscale-700 mb-4">Labels with Variants</h3>
20
+
21
+ <% [nil, :primary, :secondary, :accent, :success, :danger, :warning, :info, :light, :dark].each do |variant| %>
22
+ <div>
23
+ <%= render BetterUi::DividerComponent.new(
24
+ label: variant ? variant.to_s.capitalize : "Default",
25
+ variant: variant
26
+ ) %>
27
+ </div>
28
+ <% end %>
29
+
30
+ <hr class="my-8 border-grayscale-200">
31
+
32
+ <h3 class="text-sm font-semibold text-grayscale-700 mb-4">Labels with Styles</h3>
33
+
34
+ <div>
35
+ <p class="text-xs text-grayscale-500 mb-1">Solid</p>
36
+ <%= render BetterUi::DividerComponent.new(label: "Solid", style: :solid, variant: :primary) %>
37
+ </div>
38
+
39
+ <div>
40
+ <p class="text-xs text-grayscale-500 mb-1">Dashed</p>
41
+ <%= render BetterUi::DividerComponent.new(label: "Dashed", style: :dashed, variant: :primary) %>
42
+ </div>
43
+
44
+ <div>
45
+ <p class="text-xs text-grayscale-500 mb-1">Dotted</p>
46
+ <%= render BetterUi::DividerComponent.new(label: "Dotted", style: :dotted, variant: :primary) %>
47
+ </div>
48
+
49
+ <hr class="my-8 border-grayscale-200">
50
+
51
+ <h3 class="text-sm font-semibold text-grayscale-700 mb-4">Labels with Sizes</h3>
52
+
53
+ <div>
54
+ <p class="text-xs text-grayscale-500 mb-1">Extra Small (xs)</p>
55
+ <%= render BetterUi::DividerComponent.new(label: "XS", size: :xs, variant: :primary) %>
56
+ </div>
57
+
58
+ <div>
59
+ <p class="text-xs text-grayscale-500 mb-1">Small (sm)</p>
60
+ <%= render BetterUi::DividerComponent.new(label: "SM", size: :sm, variant: :primary) %>
61
+ </div>
62
+
63
+ <div>
64
+ <p class="text-xs text-grayscale-500 mb-1">Medium (md)</p>
65
+ <%= render BetterUi::DividerComponent.new(label: "MD", size: :md, variant: :primary) %>
66
+ </div>
67
+ </div>
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterUi
4
+ # @label Divider
5
+ class DividerComponentPreview < ViewComponent::Preview
6
+ # @label Default
7
+ # @display bg_color #f5f5f5
8
+ def default
9
+ render BetterUi::DividerComponent.new
10
+ end
11
+
12
+ # @label All Styles
13
+ # @display bg_color #f5f5f5
14
+ def all_styles
15
+ render_with_template
16
+ end
17
+
18
+ # @label With Labels
19
+ # @display bg_color #f5f5f5
20
+ def with_labels
21
+ render_with_template
22
+ end
23
+
24
+ # @label Vertical
25
+ # @display bg_color #f5f5f5
26
+ def vertical
27
+ render BetterUi::DividerComponent.new(orientation: :vertical)
28
+ end
29
+
30
+ # @label Playground
31
+ # @display bg_color #f5f5f5
32
+ # @param orientation select { choices: [horizontal, vertical] }
33
+ # @param style select { choices: [solid, dashed, dotted] }
34
+ # @param variant select { choices: [~, primary, secondary, accent, success, danger, warning, info, light, dark] }
35
+ # @param size select { choices: [xs, sm, md] }
36
+ # @param spacing select { choices: [xs, sm, md, lg, xl] }
37
+ # @param label text
38
+ # @param label_position select { choices: [left, center, right] }
39
+ def playground(
40
+ orientation: :horizontal,
41
+ style: :solid,
42
+ variant: nil,
43
+ size: :md,
44
+ spacing: :md,
45
+ label: nil,
46
+ label_position: :center
47
+ )
48
+ variant_sym = variant.present? && variant != "~" ? variant.to_sym : nil
49
+ label_value = label.present? ? label : nil
50
+
51
+ render BetterUi::DividerComponent.new(
52
+ orientation: orientation.to_sym,
53
+ style: style.to_sym,
54
+ variant: variant_sym,
55
+ size: size.to_sym,
56
+ spacing: spacing.to_sym,
57
+ label: label_value,
58
+ label_position: label_position.to_sym
59
+ )
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,169 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterUi
4
+ module Drawer
5
+ # @label Header
6
+ class HeaderComponentPreview < ViewComponent::Preview
7
+ # @label Default
8
+ def default
9
+ render BetterUi::Drawer::HeaderComponent.new do |header|
10
+ header.with_logo { "BetterUI" }
11
+ end
12
+ end
13
+
14
+ # @label With Navigation
15
+ def with_navigation
16
+ render BetterUi::Drawer::HeaderComponent.new do |header|
17
+ header.with_logo { "Brand" }
18
+ header.with_navigation do
19
+ "<nav class='flex gap-6'>
20
+ <a href='#' class='text-grayscale-600 hover:text-grayscale-900'>Home</a>
21
+ <a href='#' class='text-grayscale-600 hover:text-grayscale-900'>Products</a>
22
+ <a href='#' class='text-grayscale-600 hover:text-grayscale-900'>About</a>
23
+ <a href='#' class='text-grayscale-600 hover:text-grayscale-900'>Contact</a>
24
+ </nav>".html_safe
25
+ end
26
+ end
27
+ end
28
+
29
+ # @label With Actions
30
+ def with_actions
31
+ render BetterUi::Drawer::HeaderComponent.new do |header|
32
+ header.with_logo { "Brand" }
33
+ header.with_actions do
34
+ "<div class='flex items-center gap-4'>
35
+ <button class='text-grayscale-600 hover:text-grayscale-900'>
36
+ <svg class='w-6 h-6' fill='none' stroke='currentColor' viewBox='0 0 24 24'><path stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9'></path></svg>
37
+ </button>
38
+ <div class='w-8 h-8 bg-primary-500 rounded-full'></div>
39
+ </div>".html_safe
40
+ end
41
+ end
42
+ end
43
+
44
+ # @label With Mobile Menu Button
45
+ def with_mobile_menu_button
46
+ render BetterUi::Drawer::HeaderComponent.new do |header|
47
+ header.with_mobile_menu_button do
48
+ "<button class='p-2 text-grayscale-600 hover:text-grayscale-900 hover:bg-grayscale-100 rounded-md'>
49
+ <svg class='w-6 h-6' fill='none' stroke='currentColor' viewBox='0 0 24 24'><path stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 6h16M4 12h16M4 18h16'></path></svg>
50
+ </button>".html_safe
51
+ end
52
+ header.with_logo { "Brand" }
53
+ header.with_actions do
54
+ "<div class='w-8 h-8 bg-primary-500 rounded-full'></div>".html_safe
55
+ end
56
+ end
57
+ end
58
+
59
+ # @label Complete Header
60
+ def complete_header
61
+ render BetterUi::Drawer::HeaderComponent.new do |header|
62
+ header.with_mobile_menu_button do
63
+ "<button class='p-2 text-grayscale-600 hover:text-grayscale-900 hover:bg-grayscale-100 rounded-md lg:hidden'>
64
+ <svg class='w-6 h-6' fill='none' stroke='currentColor' viewBox='0 0 24 24'><path stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 6h16M4 12h16M4 18h16'></path></svg>
65
+ </button>".html_safe
66
+ end
67
+ header.with_logo do
68
+ "<div class='flex items-center'>
69
+ <div class='w-8 h-8 bg-primary-600 rounded-lg flex items-center justify-center text-white font-bold'>B</div>
70
+ <span class='ml-2 font-semibold text-lg'>BetterUI</span>
71
+ </div>".html_safe
72
+ end
73
+ header.with_navigation do
74
+ "<nav class='flex gap-6'>
75
+ <a href='#' class='text-primary-600 font-medium'>Dashboard</a>
76
+ <a href='#' class='text-grayscale-600 hover:text-grayscale-900'>Projects</a>
77
+ <a href='#' class='text-grayscale-600 hover:text-grayscale-900'>Team</a>
78
+ <a href='#' class='text-grayscale-600 hover:text-grayscale-900'>Settings</a>
79
+ </nav>".html_safe
80
+ end
81
+ header.with_actions do
82
+ "<div class='flex items-center gap-4'>
83
+ <button class='text-grayscale-600 hover:text-grayscale-900'>
84
+ <svg class='w-6 h-6' fill='none' stroke='currentColor' viewBox='0 0 24 24'><path stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z'></path></svg>
85
+ </button>
86
+ <button class='text-grayscale-600 hover:text-grayscale-900 relative'>
87
+ <svg class='w-6 h-6' fill='none' stroke='currentColor' viewBox='0 0 24 24'><path stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9'></path></svg>
88
+ <span class='absolute -top-1 -right-1 w-2 h-2 bg-danger-500 rounded-full'></span>
89
+ </button>
90
+ <div class='w-8 h-8 bg-primary-500 rounded-full'></div>
91
+ </div>".html_safe
92
+ end
93
+ end
94
+ end
95
+
96
+ # @label Light Variant
97
+ def light_variant
98
+ render BetterUi::Drawer::HeaderComponent.new(variant: :light) do |header|
99
+ header.with_logo { "Light Header" }
100
+ end
101
+ end
102
+
103
+ # @label Dark Variant
104
+ # @display bg_color #1f2937
105
+ def dark_variant
106
+ render BetterUi::Drawer::HeaderComponent.new(variant: :dark) do |header|
107
+ header.with_logo { "Dark Header" }
108
+ end
109
+ end
110
+
111
+ # @label Primary Variant
112
+ def primary_variant
113
+ render BetterUi::Drawer::HeaderComponent.new(variant: :primary) do |header|
114
+ header.with_logo { "Primary Header" }
115
+ end
116
+ end
117
+
118
+ # @label Transparent Variant
119
+ # @display bg_color #e0e7ff
120
+ def transparent_variant
121
+ render BetterUi::Drawer::HeaderComponent.new(variant: :transparent) do |header|
122
+ header.with_logo { "Transparent Header" }
123
+ end
124
+ end
125
+
126
+ # @label Small Height
127
+ def small_height
128
+ render BetterUi::Drawer::HeaderComponent.new(height: :sm) do |header|
129
+ header.with_logo { "Small Header" }
130
+ end
131
+ end
132
+
133
+ # @label Large Height
134
+ def large_height
135
+ render BetterUi::Drawer::HeaderComponent.new(height: :lg) do |header|
136
+ header.with_logo { "Large Header" }
137
+ end
138
+ end
139
+
140
+ # @label Non-Sticky
141
+ def non_sticky
142
+ render BetterUi::Drawer::HeaderComponent.new(sticky: false) do |header|
143
+ header.with_logo { "Non-Sticky Header" }
144
+ end
145
+ end
146
+
147
+ # @label Playground
148
+ # @param variant select { choices: [light, dark, transparent, primary] }
149
+ # @param height select { choices: [sm, md, lg] }
150
+ # @param sticky toggle
151
+ def playground(variant: :light, height: :md, sticky: true)
152
+ render BetterUi::Drawer::HeaderComponent.new(
153
+ variant: variant.to_sym,
154
+ height: height.to_sym,
155
+ sticky: sticky
156
+ ) do |header|
157
+ header.with_mobile_menu_button do
158
+ "<button class='p-2 rounded-md'>Menu</button>".html_safe
159
+ end
160
+ header.with_logo { "Playground Header" }
161
+ header.with_navigation do
162
+ "<nav>Navigation</nav>".html_safe
163
+ end
164
+ header.with_actions { "Actions" }
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,87 @@
1
+ <%= render BetterUi::Drawer::LayoutComponent.new do |layout| %>
2
+ <% layout.with_header do |header| %>
3
+ <% header.with_mobile_menu_button do %>
4
+ <button class="p-2 text-grayscale-600 hover:text-grayscale-900 hover:bg-grayscale-100 rounded-md lg:hidden" data-action="click->better-ui--drawer--layout#toggle">
5
+ <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path></svg>
6
+ </button>
7
+ <% end %>
8
+ <% header.with_logo do %>
9
+ <div class="flex items-center">
10
+ <div class="w-8 h-8 bg-primary-600 rounded-lg flex items-center justify-center text-white font-bold">B</div>
11
+ <span class="ml-2 font-semibold text-lg">BetterUI</span>
12
+ </div>
13
+ <% end %>
14
+ <% header.with_navigation do %>
15
+ <nav class="flex gap-6">
16
+ <a href="#" class="text-primary-600 font-medium">Dashboard</a>
17
+ <a href="#" class="text-grayscale-600 hover:text-grayscale-900">Projects</a>
18
+ <a href="#" class="text-grayscale-600 hover:text-grayscale-900">Team</a>
19
+ </nav>
20
+ <% end %>
21
+ <% header.with_actions do %>
22
+ <div class="flex items-center gap-4">
23
+ <button class="text-grayscale-600 hover:text-grayscale-900 relative">
24
+ <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"></path></svg>
25
+ <span class="absolute -top-1 -right-1 w-2 h-2 bg-danger-500 rounded-full"></span>
26
+ </button>
27
+ <div class="w-8 h-8 bg-primary-500 rounded-full"></div>
28
+ </div>
29
+ <% end %>
30
+ <% end %>
31
+
32
+ <% layout.with_sidebar do |sidebar| %>
33
+ <% sidebar.with_header do %>
34
+ <div class="text-sm font-medium text-grayscale-500 uppercase">Navigation</div>
35
+ <% end %>
36
+ <% sidebar.with_navigation do %>
37
+ <nav class="space-y-1">
38
+ <a href="#" class="flex items-center px-4 py-2 rounded-md bg-primary-50 text-primary-700">
39
+ <svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"></path></svg>
40
+ Dashboard
41
+ </a>
42
+ <a href="#" class="flex items-center px-4 py-2 rounded-md hover:bg-grayscale-100">
43
+ <svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"></path></svg>
44
+ Projects
45
+ </a>
46
+ <a href="#" class="flex items-center px-4 py-2 rounded-md hover:bg-grayscale-100">
47
+ <svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197m12 5.198H9"></path></svg>
48
+ Team
49
+ </a>
50
+ <a href="#" class="flex items-center px-4 py-2 rounded-md hover:bg-grayscale-100">
51
+ <svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path></svg>
52
+ Settings
53
+ </a>
54
+ </nav>
55
+ <% end %>
56
+ <% sidebar.with_footer do %>
57
+ <div class="flex items-center">
58
+ <div class="w-10 h-10 bg-grayscale-300 rounded-full"></div>
59
+ <div class="ml-3">
60
+ <div class="text-sm font-medium">John Doe</div>
61
+ <div class="text-xs text-grayscale-500">john@example.com</div>
62
+ </div>
63
+ </div>
64
+ <% end %>
65
+ <% end %>
66
+
67
+ <% layout.with_main do %>
68
+ <div class="p-6">
69
+ <h1 class="text-2xl font-bold mb-4">Complete Layout</h1>
70
+ <p class="text-grayscale-600 mb-4">This demonstrates a complete drawer layout with header, sidebar, and main content area. On mobile, click the menu button to toggle the sidebar drawer.</p>
71
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
72
+ <div class="bg-white p-4 rounded-lg border border-grayscale-200">
73
+ <div class="text-2xl font-bold">24</div>
74
+ <div class="text-grayscale-500">Active Projects</div>
75
+ </div>
76
+ <div class="bg-white p-4 rounded-lg border border-grayscale-200">
77
+ <div class="text-2xl font-bold">8</div>
78
+ <div class="text-grayscale-500">Team Members</div>
79
+ </div>
80
+ <div class="bg-white p-4 rounded-lg border border-grayscale-200">
81
+ <div class="text-2xl font-bold">98%</div>
82
+ <div class="text-grayscale-500">Completion Rate</div>
83
+ </div>
84
+ </div>
85
+ </div>
86
+ <% end %>
87
+ <% end %>