m9sh 0.2.1 → 0.2.2

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 (125) hide show
  1. checksums.yaml +4 -4
  2. data/.idea/hotcdn.iml +30 -0
  3. data/.mise.toml +2 -2
  4. data/app/assets/config/manifest.js +4 -0
  5. data/app/assets/images/icons/activity.svg +3 -0
  6. data/app/assets/images/icons/bell.svg +4 -0
  7. data/app/assets/images/icons/book.svg +4 -0
  8. data/app/assets/images/icons/chevron-down.svg +3 -0
  9. data/app/assets/images/icons/chevron-left.svg +3 -0
  10. data/app/assets/images/icons/chevron-right.svg +3 -0
  11. data/app/assets/images/icons/credit-card.svg +4 -0
  12. data/app/assets/images/icons/dollar-sign.svg +3 -0
  13. data/app/assets/images/icons/edit.svg +4 -0
  14. data/app/assets/images/icons/github.svg +3 -0
  15. data/app/assets/images/icons/home.svg +4 -0
  16. data/app/assets/images/icons/info.svg +5 -0
  17. data/app/assets/images/icons/layout.svg +6 -0
  18. data/app/assets/images/icons/logout.svg +5 -0
  19. data/app/assets/images/icons/menu.svg +5 -0
  20. data/app/assets/images/icons/moon.svg +3 -0
  21. data/app/assets/images/icons/paintbrush.svg +6 -0
  22. data/app/assets/images/icons/search.svg +4 -0
  23. data/app/assets/images/icons/settings.svg +4 -0
  24. data/app/assets/images/icons/sun.svg +11 -0
  25. data/app/assets/images/icons/user.svg +4 -0
  26. data/app/assets/images/icons/users.svg +5 -0
  27. data/app/assets/stylesheets/tailwind.css +1180 -0
  28. data/app/components/backdrop_component.rb +103 -0
  29. data/app/components/docs/code_block_component.rb +56 -0
  30. data/app/components/docs/component_api_component.rb +16 -0
  31. data/app/components/docs/component_examples_component.rb +16 -0
  32. data/app/components/docs/component_header_component.html.erb +8 -0
  33. data/app/components/docs/component_header_component.rb +14 -0
  34. data/app/components/docs/component_installation_component.html.erb +15 -0
  35. data/app/components/docs/component_installation_component.rb +13 -0
  36. data/app/components/docs/component_page_component.html.erb +9 -0
  37. data/app/components/docs/component_page_component.rb +19 -0
  38. data/app/components/docs/component_preview_component.rb +318 -0
  39. data/app/components/docs/component_usage_component.rb +18 -0
  40. data/app/components/docs/prop_table_component.rb +64 -0
  41. data/app/controllers/application_controller.rb +3 -0
  42. data/app/controllers/blocks_controller.rb +51 -0
  43. data/app/controllers/docs_controller.rb +162 -0
  44. data/app/controllers/showcase_controller.rb +42 -0
  45. data/app/helpers/blocks_helper.rb +343 -0
  46. data/app/helpers/docs_helper.rb +3807 -0
  47. data/app/helpers/m9sh/toast_helper.rb +46 -0
  48. data/app/helpers/m9sh_helper.rb +343 -0
  49. data/app/javascript/application.js +3 -0
  50. data/app/javascript/controllers/application.js +9 -0
  51. data/app/javascript/controllers/backdrop_controller.js +137 -0
  52. data/app/javascript/controllers/color_customizer_controller.js +569 -0
  53. data/app/javascript/controllers/color_theme_controller.js +120 -0
  54. data/app/javascript/controllers/docs/component_preview_controller.js +149 -0
  55. data/app/javascript/controllers/docs/copy_button_controller.js +20 -0
  56. data/app/javascript/controllers/index.js +6 -0
  57. data/app/javascript/controllers/theme_controller.js +23 -0
  58. data/app/views/blocks/_sidebar.html.erb +31 -0
  59. data/app/views/blocks/_toc.html.erb +29 -0
  60. data/app/views/blocks/examples/dashboard-01.html.erb +180 -0
  61. data/app/views/blocks/examples/dashboard-02.html.erb +190 -0
  62. data/app/views/blocks/examples/dashboard-03.html.erb +210 -0
  63. data/app/views/blocks/examples/settings-01.html.erb +220 -0
  64. data/app/views/blocks/examples/settings-02.html.erb +231 -0
  65. data/app/views/blocks/examples/settings-03.html.erb +340 -0
  66. data/app/views/blocks/index.html.erb +65 -0
  67. data/app/views/docs/_sidebar.html.erb +47 -0
  68. data/app/views/docs/_toc.html.erb +19 -0
  69. data/app/views/docs/about.html.erb +68 -0
  70. data/app/views/docs/components/accordion.html.erb +196 -0
  71. data/app/views/docs/components/alert.html.erb +272 -0
  72. data/app/views/docs/components/alert_dialog.html.erb +232 -0
  73. data/app/views/docs/components/avatar.html.erb +207 -0
  74. data/app/views/docs/components/badge.html.erb +145 -0
  75. data/app/views/docs/components/breadcrumb.html.erb +264 -0
  76. data/app/views/docs/components/button.html.erb +229 -0
  77. data/app/views/docs/components/card.html.erb +378 -0
  78. data/app/views/docs/components/checkbox.html.erb +212 -0
  79. data/app/views/docs/components/collapsible.html.erb +252 -0
  80. data/app/views/docs/components/dialog.html.erb +323 -0
  81. data/app/views/docs/components/dropdown_menu.html.erb +289 -0
  82. data/app/views/docs/components/hover_card.html.erb +220 -0
  83. data/app/views/docs/components/input.html.erb +254 -0
  84. data/app/views/docs/components/label.html.erb +128 -0
  85. data/app/views/docs/components/main.html.erb +352 -0
  86. data/app/views/docs/components/navbar.html.erb +394 -0
  87. data/app/views/docs/components/navigation_menu.html.erb +226 -0
  88. data/app/views/docs/components/popover.html.erb +267 -0
  89. data/app/views/docs/components/progress.html.erb +107 -0
  90. data/app/views/docs/components/radio_group.html.erb +209 -0
  91. data/app/views/docs/components/select.html.erb +260 -0
  92. data/app/views/docs/components/separator.html.erb +162 -0
  93. data/app/views/docs/components/sheet.html.erb +270 -0
  94. data/app/views/docs/components/sidebar.html.erb +597 -0
  95. data/app/views/docs/components/skeleton.html.erb +150 -0
  96. data/app/views/docs/components/slider.html.erb +218 -0
  97. data/app/views/docs/components/spinner.html.erb +132 -0
  98. data/app/views/docs/components/switch.html.erb +148 -0
  99. data/app/views/docs/components/table.html.erb +259 -0
  100. data/app/views/docs/components/tabs.html.erb +225 -0
  101. data/app/views/docs/components/textarea.html.erb +239 -0
  102. data/app/views/docs/components/theme_toggle.html.erb +135 -0
  103. data/app/views/docs/components/toast.html.erb +205 -0
  104. data/app/views/docs/components/toaster.html.erb +227 -0
  105. data/app/views/docs/components/toggle.html.erb +154 -0
  106. data/app/views/docs/components/tooltip.html.erb +216 -0
  107. data/app/views/docs/components/typography.html.erb +180 -0
  108. data/app/views/docs/index.html.erb +143 -0
  109. data/app/views/docs/installation.html.erb +155 -0
  110. data/app/views/docs/simple_test.html.erb +13 -0
  111. data/app/views/docs/test_accordion.html.erb +14 -0
  112. data/app/views/docs/usage.html.erb +272 -0
  113. data/app/views/layouts/application.html.erb +107 -0
  114. data/app/views/layouts/backdrop.html.erb +77 -0
  115. data/app/views/shared/_app_navbar.html.erb +240 -0
  116. data/app/views/shared/_navbar.html.erb +69 -0
  117. data/app/views/showcase/v2/_components_grid.html.erb +38 -0
  118. data/app/views/showcase/v2/_features.html.erb +59 -0
  119. data/app/views/showcase/v2/_forms.html.erb +195 -0
  120. data/app/views/showcase/v2/_hero.html.erb +55 -0
  121. data/app/views/showcase/v2/_metrics.html.erb +107 -0
  122. data/app/views/showcase/v2.html.erb +18 -0
  123. data/lib/m9sh/version.rb +1 -1
  124. data/m9sh.gemspec +1 -1
  125. metadata +120 -1
@@ -0,0 +1,3807 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DocsHelper
4
+ def accordion_usage_code
5
+ <<~'CODE'
6
+ <%= render M9sh::AccordionComponent.new(type: "single", collapsible: true) do |c| %>
7
+ <% c.with_item(value: "item-1") do |item| %>
8
+ <% item.with_trigger do %>
9
+ Is it accessible?
10
+ <% end %>
11
+ <% item.with_body do %>
12
+ Yes. It adheres to the WAI-ARIA design pattern.
13
+ <% end %>
14
+ <% end %>
15
+ <% end %>
16
+ CODE
17
+ end
18
+
19
+ def accordion_example_code
20
+ <<~'CODE'
21
+ <%= render M9sh::AccordionComponent.new(type: "single", collapsible: true) do |accordion| %>
22
+ <% accordion.with_item(value: "item-1") do |item| %>
23
+ <% item.with_trigger do %>
24
+ Is it accessible?
25
+ <% end %>
26
+ <% item.with_body do %>
27
+ Yes. It adheres to the WAI-ARIA design pattern.
28
+ <% end %>
29
+ <% end %>
30
+
31
+ <% accordion.with_item(value: "item-2") do |item| %>
32
+ <% item.with_trigger do %>
33
+ Is it styled?
34
+ <% end %>
35
+ <% item.with_body do %>
36
+ Yes. It comes with default styles that matches the other components' aesthetic.
37
+ <% end %>
38
+ <% end %>
39
+
40
+ <% accordion.with_item(value: "item-3") do |item| %>
41
+ <% item.with_trigger do %>
42
+ Is it animated?
43
+ <% end %>
44
+ <% item.with_body do %>
45
+ Yes. It's animated by default with smooth height transitions.
46
+ <% end %>
47
+ <% end %>
48
+ <% end %>
49
+ CODE
50
+ end
51
+
52
+ def accordion_multiple_code
53
+ <<~'CODE'
54
+ <%= render M9sh::AccordionComponent.new(type: "multiple") do |accordion| %>
55
+ <% accordion.with_item(value: "item-1") do |item| %>
56
+ <% item.with_trigger do %>
57
+ First Question
58
+ <% end %>
59
+ <% item.with_body do %>
60
+ This accordion allows multiple items to be open at the same time.
61
+ <% end %>
62
+ <% end %>
63
+ <% end %>
64
+ CODE
65
+ end
66
+
67
+ def accordion_default_value_code
68
+ <<~'CODE'
69
+ <%= render M9sh::AccordionComponent.new(type: "single", default_value: "item-2") do |accordion| %>
70
+ <!-- Items here -->
71
+ <% end %>
72
+ CODE
73
+ end
74
+
75
+ def accordion_caption_code
76
+ <<~'CODE'
77
+ <%= render M9sh::AccordionComponent.new(type: "single", collapsible: true) do |accordion| %>
78
+ <%= render M9sh::AccordionComponent::CaptionComponent.new do %>
79
+ A list of your recent invoices.
80
+ <% end %>
81
+ <!-- Accordion content -->
82
+ <% end %>
83
+ CODE
84
+ end
85
+
86
+ # Button component helpers
87
+ def button_usage_code
88
+ <<~'CODE'
89
+ <%= render M9sh::ButtonComponent.new do %>
90
+ Button
91
+ <% end %>
92
+ CODE
93
+ end
94
+
95
+ def button_default_code
96
+ <<~'CODE'
97
+ <%= render M9sh::ButtonComponent.new do %>
98
+ Button
99
+ <% end %>
100
+ CODE
101
+ end
102
+
103
+ def button_variants_code
104
+ <<~'CODE'
105
+ <%= render M9sh::ButtonComponent.new(variant: :default) do %>
106
+ Default
107
+ <% end %>
108
+
109
+ <%= render M9sh::ButtonComponent.new(variant: :secondary) do %>
110
+ Secondary
111
+ <% end %>
112
+
113
+ <%= render M9sh::ButtonComponent.new(variant: :destructive) do %>
114
+ Destructive
115
+ <% end %>
116
+
117
+ <%= render M9sh::ButtonComponent.new(variant: :outline) do %>
118
+ Outline
119
+ <% end %>
120
+
121
+ <%= render M9sh::ButtonComponent.new(variant: :ghost) do %>
122
+ Ghost
123
+ <% end %>
124
+
125
+ <%= render M9sh::ButtonComponent.new(variant: :link) do %>
126
+ Link
127
+ <% end %>
128
+ CODE
129
+ end
130
+
131
+ def button_sizes_code
132
+ <<~'CODE'
133
+ <%= render M9sh::ButtonComponent.new(size: :sm) do %>
134
+ Small
135
+ <% end %>
136
+
137
+ <%= render M9sh::ButtonComponent.new(size: :md) do %>
138
+ Medium
139
+ <% end %>
140
+
141
+ <%= render M9sh::ButtonComponent.new(size: :lg) do %>
142
+ Large
143
+ <% end %>
144
+ CODE
145
+ end
146
+
147
+ def button_disabled_code
148
+ <<~'CODE'
149
+ <%= render M9sh::ButtonComponent.new(disabled: true) do %>
150
+ Disabled Button
151
+ <% end %>
152
+ CODE
153
+ end
154
+
155
+ def button_icon_code
156
+ <<~'CODE'
157
+ <%= render M9sh::ButtonComponent.new(variant: :outline, size: :icon) do %>
158
+ <!-- SVG icon -->
159
+ <% end %>
160
+ CODE
161
+ end
162
+
163
+ # Breadcrumb component helpers
164
+ def breadcrumb_usage_code
165
+ <<~'CODE'
166
+ <%= render M9sh::BreadcrumbComponent.new do |breadcrumb| %>
167
+ <% breadcrumb.with_item do |item| %>
168
+ <% item.with_link do %>
169
+ <%= link_to "Home", root_path %>
170
+ <% end %>
171
+ <% end %>
172
+
173
+ <% breadcrumb.with_item(current: true) do |item| %>
174
+ <% item.with_page do %>
175
+ Current Page
176
+ <% end %>
177
+ <% end %>
178
+ <% end %>
179
+ CODE
180
+ end
181
+
182
+ def breadcrumb_default_code
183
+ <<~'CODE'
184
+ <%= render M9sh::BreadcrumbComponent.new do |breadcrumb| %>
185
+ <% breadcrumb.with_item do |item| %>
186
+ <% item.with_link do %>
187
+ <%= link_to "Home", "#" %>
188
+ <% end %>
189
+ <% end %>
190
+
191
+ <% breadcrumb.with_item do |item| %>
192
+ <% item.with_link do %>
193
+ <%= link_to "Components", "#" %>
194
+ <% end %>
195
+ <% end %>
196
+
197
+ <% breadcrumb.with_item(current: true) do |item| %>
198
+ <% item.with_page do %>
199
+ Breadcrumb
200
+ <% end %>
201
+ <% end %>
202
+ <% end %>
203
+ CODE
204
+ end
205
+
206
+ def breadcrumb_with_icons_code
207
+ <<~'CODE'
208
+ <%= render M9sh::BreadcrumbComponent.new do |breadcrumb| %>
209
+ <% breadcrumb.with_item do |item| %>
210
+ <% item.with_link do %>
211
+ <%= link_to "#", class: "flex items-center gap-1" do %>
212
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
213
+ <path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>
214
+ <polyline points="9 22 9 12 15 12 15 22"/>
215
+ </svg>
216
+ Home
217
+ <% end %>
218
+ <% end %>
219
+ <% end %>
220
+
221
+ <% breadcrumb.with_item do |item| %>
222
+ <% item.with_link do %>
223
+ <%= link_to "Documents", "#" %>
224
+ <% end %>
225
+ <% end %>
226
+
227
+ <% breadcrumb.with_item(current: true) do |item| %>
228
+ <% item.with_page do %>
229
+ README.md
230
+ <% end %>
231
+ <% end %>
232
+ <% end %>
233
+ CODE
234
+ end
235
+
236
+ def breadcrumb_custom_separator_code
237
+ <<~'CODE'
238
+ <%= render M9sh::BreadcrumbComponent.new(class_name: "custom-breadcrumb") do |breadcrumb| %>
239
+ <% breadcrumb.with_item do |item| %>
240
+ <% item.with_link do %>
241
+ <%= link_to "Home", "#" %>
242
+ <% end %>
243
+ <% end %>
244
+
245
+ <% breadcrumb.with_item do |item| %>
246
+ <% item.with_link do %>
247
+ <%= link_to "Library", "#" %>
248
+ <% end %>
249
+ <% end %>
250
+
251
+ <% breadcrumb.with_item(current: true) do |item| %>
252
+ <% item.with_page do %>
253
+ Data
254
+ <% end %>
255
+ <% end %>
256
+ <% end %>
257
+ CODE
258
+ end
259
+
260
+ def breadcrumb_dropdown_code
261
+ <<~'CODE'
262
+ <%= render M9sh::BreadcrumbComponent.new do |breadcrumb| %>
263
+ <% breadcrumb.with_item do |item| %>
264
+ <% item.with_link do %>
265
+ <%= link_to "Home", "#" %>
266
+ <% end %>
267
+ <% end %>
268
+
269
+ <% breadcrumb.with_item do |item| %>
270
+ <button type="button" class="flex items-center gap-1 hover:text-foreground transition-colors">
271
+ <span>...</span>
272
+ <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
273
+ <polyline points="6 9 12 15 18 9"/>
274
+ </svg>
275
+ </button>
276
+ <% end %>
277
+
278
+ <% breadcrumb.with_item do |item| %>
279
+ <% item.with_link do %>
280
+ <%= link_to "Components", "#" %>
281
+ <% end %>
282
+ <% end %>
283
+
284
+ <% breadcrumb.with_item(current: true) do |item| %>
285
+ <% item.with_page do %>
286
+ Breadcrumb
287
+ <% end %>
288
+ <% end %>
289
+ <% end %>
290
+ CODE
291
+ end
292
+
293
+ # Table component helpers
294
+ def table_usage_code
295
+ <<~'CODE'
296
+ <%= render M9sh::TableComponent.new do %>
297
+ <%= render M9sh::TableComponent::HeaderComponent.new do %>
298
+ <%= render M9sh::TableComponent::RowComponent.new do %>
299
+ <%= render M9sh::TableComponent::HeadComponent.new do %>
300
+ Name
301
+ <% end %>
302
+ <% end %>
303
+ <% end %>
304
+ <%= render M9sh::TableComponent::BodyComponent.new do %>
305
+ <%= render M9sh::TableComponent::RowComponent.new do %>
306
+ <%= render M9sh::TableComponent::CellComponent.new do %>
307
+ John Doe
308
+ <% end %>
309
+ <% end %>
310
+ <% end %>
311
+ <% end %>
312
+ CODE
313
+ end
314
+
315
+ def table_default_code
316
+ <<~'CODE'
317
+ <%= render M9sh::TableComponent.new do %>
318
+ <%= render M9sh::TableComponent::HeaderComponent.new do %>
319
+ <%= render M9sh::TableComponent::RowComponent.new do %>
320
+ <%= render M9sh::TableComponent::HeadComponent.new do %>
321
+ Name
322
+ <% end %>
323
+ <%= render M9sh::TableComponent::HeadComponent.new do %>
324
+ Email
325
+ <% end %>
326
+ <%= render M9sh::TableComponent::HeadComponent.new do %>
327
+ Role
328
+ <% end %>
329
+ <% end %>
330
+ <% end %>
331
+
332
+ <%= render M9sh::TableComponent::BodyComponent.new do %>
333
+ <%= render M9sh::TableComponent::RowComponent.new do %>
334
+ <%= render M9sh::TableComponent::CellComponent.new do %>
335
+ John Doe
336
+ <% end %>
337
+ <%= render M9sh::TableComponent::CellComponent.new do %>
338
+ john@example.com
339
+ <% end %>
340
+ <%= render M9sh::TableComponent::CellComponent.new do %>
341
+ Admin
342
+ <% end %>
343
+ <% end %>
344
+ <% end %>
345
+ <% end %>
346
+ CODE
347
+ end
348
+
349
+ def table_caption_code
350
+ <<~'CODE'
351
+ <%= render M9sh::TableComponent.new do %>
352
+ <%= render M9sh::TableComponent::CaptionComponent.new do %>
353
+ A list of your recent invoices.
354
+ <% end %>
355
+ <!-- Table content -->
356
+ <% end %>
357
+ CODE
358
+ end
359
+
360
+ def table_footer_code
361
+ <<~'CODE'
362
+ <%= render M9sh::TableComponent.new do %>
363
+ <!-- Header and Body -->
364
+ <%= render M9sh::TableComponent::FooterComponent.new do %>
365
+ <%= render M9sh::TableComponent::RowComponent.new do %>
366
+ <%= render M9sh::TableComponent::CellComponent.new do %>
367
+ Total
368
+ <% end %>
369
+ <% end %>
370
+ <% end %>
371
+ <% end %>
372
+ CODE
373
+ end
374
+
375
+ # Alert component helpers
376
+ def alert_usage_code
377
+ <<~'CODE'
378
+ <%= render M9sh::AlertComponent.new do |alert| %>
379
+ <% alert.with_title do %>
380
+ Alert Title
381
+ <% end %>
382
+ <% alert.with_description do %>
383
+ This is an alert description.
384
+ <% end %>
385
+ <% end %>
386
+ CODE
387
+ end
388
+
389
+ def alert_default_code
390
+ <<~'CODE'
391
+ <%= render M9sh::AlertComponent.new do |alert| %>
392
+ <% alert.with_title do %>
393
+ Heads up!
394
+ <% end %>
395
+ <% alert.with_description do %>
396
+ You can add components to your app using the CLI.
397
+ <% end %>
398
+ <% end %>
399
+ CODE
400
+ end
401
+
402
+ def alert_destructive_code
403
+ <<~'CODE'
404
+ <%= render M9sh::AlertComponent.new(variant: :destructive) do |alert| %>
405
+ <% alert.with_title do %>
406
+ Error
407
+ <% end %>
408
+ <% alert.with_description do %>
409
+ Your session has expired. Please log in again.
410
+ <% end %>
411
+ <% end %>
412
+ CODE
413
+ end
414
+
415
+ def alert_with_icon_code
416
+ <<~'CODE'
417
+ <%= render M9sh::AlertComponent.new do |alert| %>
418
+ <% alert.with_icon do %>
419
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
420
+ <circle cx="12" cy="12" r="10"/>
421
+ <line x1="12" y1="16" x2="12" y2="12"/>
422
+ <line x1="12" y1="8" x2="12.01" y2="8"/>
423
+ </svg>
424
+ <% end %>
425
+ <% alert.with_title do %>
426
+ Important Notice
427
+ <% end %>
428
+ <% alert.with_description do %>
429
+ This is an alert with an icon for better visual communication.
430
+ <% end %>
431
+ <% end %>
432
+ CODE
433
+ end
434
+
435
+ # Badge component helpers
436
+ def badge_usage_code
437
+ <<~'CODE'
438
+ <%= render M9sh::BadgeComponent.new do %>
439
+ Badge
440
+ <% end %>
441
+ CODE
442
+ end
443
+
444
+ def badge_variants_code
445
+ <<~'CODE'
446
+ <%= render M9sh::BadgeComponent.new(variant: :default) do %>
447
+ Default
448
+ <% end %>
449
+
450
+ <%= render M9sh::BadgeComponent.new(variant: :secondary) do %>
451
+ Secondary
452
+ <% end %>
453
+
454
+ <%= render M9sh::BadgeComponent.new(variant: :destructive) do %>
455
+ Destructive
456
+ <% end %>
457
+
458
+ <%= render M9sh::BadgeComponent.new(variant: :outline) do %>
459
+ Outline
460
+ <% end %>
461
+
462
+ <%= render M9sh::BadgeComponent.new(variant: :success) do %>
463
+ Success
464
+ <% end %>
465
+
466
+ <%= render M9sh::BadgeComponent.new(variant: :warning) do %>
467
+ Warning
468
+ <% end %>
469
+ CODE
470
+ end
471
+
472
+ def badge_secondary_code
473
+ <<~'CODE'
474
+ <%= render M9sh::BadgeComponent.new(variant: :secondary) do %>
475
+ Secondary
476
+ <% end %>
477
+ CODE
478
+ end
479
+
480
+ def badge_destructive_code
481
+ <<~'CODE'
482
+ <%= render M9sh::BadgeComponent.new(variant: :destructive) do %>
483
+ Destructive
484
+ <% end %>
485
+ CODE
486
+ end
487
+
488
+ def badge_outline_code
489
+ <<~'CODE'
490
+ <%= render M9sh::BadgeComponent.new(variant: :outline) do %>
491
+ Outline
492
+ <% end %>
493
+ CODE
494
+ end
495
+
496
+ def badge_success_code
497
+ <<~'CODE'
498
+ <%= render M9sh::BadgeComponent.new(variant: :success) do %>
499
+ Success
500
+ <% end %>
501
+ CODE
502
+ end
503
+
504
+ def badge_warning_code
505
+ <<~'CODE'
506
+ <%= render M9sh::BadgeComponent.new(variant: :warning) do %>
507
+ Warning
508
+ <% end %>
509
+ CODE
510
+ end
511
+
512
+ # Separator component helpers
513
+ def separator_usage_code
514
+ <<~'CODE'
515
+ <%= render M9sh::SeparatorComponent.new %>
516
+ CODE
517
+ end
518
+
519
+ def separator_vertical_code
520
+ <<~'CODE'
521
+ <%= render M9sh::SeparatorComponent.new(orientation: :vertical) %>
522
+ CODE
523
+ end
524
+
525
+ def separator_horizontal_code
526
+ <<~'CODE'
527
+ <div>
528
+ <div class="space-y-1">
529
+ <h4 class="text-sm font-medium leading-none">Radix Primitives</h4>
530
+ <p class="text-sm text-muted-foreground">
531
+ An open-source UI component library.
532
+ </p>
533
+ </div>
534
+ <%= render M9sh::SeparatorComponent.new(class: "my-4") %>
535
+ <div class="flex h-5 items-center space-x-4 text-sm">
536
+ <div>Blog</div>
537
+ <%= render M9sh::SeparatorComponent.new(orientation: :vertical) %>
538
+ <div>Docs</div>
539
+ <%= render M9sh::SeparatorComponent.new(orientation: :vertical) %>
540
+ <div>Source</div>
541
+ </div>
542
+ </div>
543
+ CODE
544
+ end
545
+
546
+ def separator_text_sections_code
547
+ <<~'CODE'
548
+ <div>
549
+ <div class="space-y-1">
550
+ <h4 class="text-sm font-medium leading-none">Introduction</h4>
551
+ <p class="text-sm text-muted-foreground">
552
+ An introduction to the product and its features.
553
+ </p>
554
+ </div>
555
+ <%= render M9sh::SeparatorComponent.new(class: "my-4") %>
556
+ <div class="space-y-1">
557
+ <h4 class="text-sm font-medium leading-none">Getting Started</h4>
558
+ <p class="text-sm text-muted-foreground">
559
+ Learn how to install and configure the components.
560
+ </p>
561
+ </div>
562
+ </div>
563
+ CODE
564
+ end
565
+
566
+ def separator_breadcrumb_code
567
+ <<~'CODE'
568
+ <div class="flex items-center text-sm text-muted-foreground">
569
+ <a href="#" class="hover:text-foreground transition-colors">Home</a>
570
+ <%= render M9sh::SeparatorComponent.new(orientation: :vertical, class: "mx-2 h-4") %>
571
+ <a href="#" class="hover:text-foreground transition-colors">Components</a>
572
+ <%= render M9sh::SeparatorComponent.new(orientation: :vertical, class: "mx-2 h-4") %>
573
+ <span class="text-foreground font-medium">Separator</span>
574
+ </div>
575
+ CODE
576
+ end
577
+
578
+ def separator_in_card_code
579
+ <<~'CODE'
580
+ <%= render M9sh::CardComponent.new do |card| %>
581
+ <% card.with_header do |header| %>
582
+ <% header.with_title { "Account Settings" } %>
583
+ <% header.with_description { "Manage your account preferences and settings." } %>
584
+ <% end %>
585
+ <% card.with_body do %>
586
+ <div class="space-y-4">
587
+ <div class="space-y-2">
588
+ <label class="text-sm font-medium leading-none">Email</label>
589
+ <p class="text-sm text-muted-foreground">m@example.com</p>
590
+ </div>
591
+ <%= render M9sh::SeparatorComponent.new %>
592
+ <div class="space-y-2">
593
+ <label class="text-sm font-medium leading-none">Plan</label>
594
+ <p class="text-sm text-muted-foreground">Pro</p>
595
+ </div>
596
+ </div>
597
+ <% end %>
598
+ <% card.with_footer do %>
599
+ <%= render M9sh::ButtonComponent.new(variant: :outline, class: "w-full") { "Manage Account" } %>
600
+ <% end %>
601
+ <% end %>
602
+ CODE
603
+ end
604
+
605
+ # Avatar component helpers
606
+ def avatar_usage_code
607
+ <<~'CODE'
608
+ <%= render M9sh::AvatarComponent.new(
609
+ src: "https://github.com/shadcn.png",
610
+ alt: "User Avatar"
611
+ ) %>
612
+ CODE
613
+ end
614
+
615
+ def avatar_with_fallback_code
616
+ <<~'CODE'
617
+ <%= render M9sh::AvatarComponent.new(
618
+ fallback: "JD"
619
+ ) %>
620
+ CODE
621
+ end
622
+
623
+ def avatar_sizes_code
624
+ <<~'CODE'
625
+ <%= render M9sh::AvatarComponent.new(
626
+ src: "https://github.com/shadcn.png",
627
+ alt: "User Avatar",
628
+ size: :sm
629
+ ) %>
630
+
631
+ <%= render M9sh::AvatarComponent.new(
632
+ src: "https://github.com/shadcn.png",
633
+ alt: "User Avatar",
634
+ size: :md
635
+ ) %>
636
+
637
+ <%= render M9sh::AvatarComponent.new(
638
+ src: "https://github.com/shadcn.png",
639
+ alt: "User Avatar",
640
+ size: :lg
641
+ ) %>
642
+
643
+ <%= render M9sh::AvatarComponent.new(
644
+ src: "https://github.com/shadcn.png",
645
+ alt: "User Avatar",
646
+ size: :xl
647
+ ) %>
648
+ CODE
649
+ end
650
+
651
+ def avatar_with_fallback_example_code
652
+ <<~'CODE'
653
+ <%= render M9sh::AvatarComponent.new(
654
+ src: "https://github.com/shadcn.png",
655
+ alt: "User Avatar",
656
+ fallback: "CN"
657
+ ) %>
658
+
659
+ <%= render M9sh::AvatarComponent.new(
660
+ src: "https://invalid-image-url.png",
661
+ alt: "Invalid Avatar",
662
+ fallback: "AB"
663
+ ) %>
664
+ CODE
665
+ end
666
+
667
+ def avatar_fallback_sizes_code
668
+ <<~'CODE'
669
+ <%= render M9sh::AvatarComponent.new(
670
+ fallback: "SM",
671
+ size: :sm
672
+ ) %>
673
+
674
+ <%= render M9sh::AvatarComponent.new(
675
+ fallback: "MD",
676
+ size: :md
677
+ ) %>
678
+
679
+ <%= render M9sh::AvatarComponent.new(
680
+ fallback: "LG",
681
+ size: :lg
682
+ ) %>
683
+
684
+ <%= render M9sh::AvatarComponent.new(
685
+ fallback: "XL",
686
+ size: :xl
687
+ ) %>
688
+ CODE
689
+ end
690
+
691
+ def avatar_stack_code
692
+ <<~'CODE'
693
+ <div class="flex -space-x-2">
694
+ <%= render M9sh::AvatarComponent.new(
695
+ src: "https://github.com/shadcn.png",
696
+ alt: "Avatar 1",
697
+ class: "border-2 border-background"
698
+ ) %>
699
+ <%= render M9sh::AvatarComponent.new(
700
+ fallback: "JD",
701
+ class: "border-2 border-background"
702
+ ) %>
703
+ <%= render M9sh::AvatarComponent.new(
704
+ fallback: "AB",
705
+ class: "border-2 border-background"
706
+ ) %>
707
+ <%= render M9sh::AvatarComponent.new(
708
+ fallback: "CD",
709
+ class: "border-2 border-background"
710
+ ) %>
711
+ <%= render M9sh::AvatarComponent.new(
712
+ fallback: "+3",
713
+ class: "border-2 border-background"
714
+ ) %>
715
+ </div>
716
+ CODE
717
+ end
718
+
719
+ # Label component helpers
720
+ def label_usage_code
721
+ <<~'CODE'
722
+ <%= render M9sh::LabelComponent.new(for_id: "email") do %>
723
+ Email
724
+ <% end %>
725
+ CODE
726
+ end
727
+
728
+ def label_with_input_code
729
+ <<~'CODE'
730
+ <div class="space-y-2">
731
+ <%= render M9sh::LabelComponent.new(for_id: "email") do %>
732
+ Email
733
+ <% end %>
734
+ <input
735
+ id="email"
736
+ type="email"
737
+ placeholder="Enter your email"
738
+ class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
739
+ />
740
+ </div>
741
+ CODE
742
+ end
743
+
744
+ def label_with_required_code
745
+ <<~'CODE'
746
+ <div class="space-y-2">
747
+ <%= render M9sh::LabelComponent.new(for_id: "username") do %>
748
+ Username <span class="text-destructive">*</span>
749
+ <% end %>
750
+ <input
751
+ id="username"
752
+ type="text"
753
+ placeholder="Enter your username"
754
+ required
755
+ class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
756
+ />
757
+ </div>
758
+ CODE
759
+ end
760
+
761
+ def label_with_disabled_code
762
+ <<~'CODE'
763
+ <div class="space-y-2 group" data-disabled="true">
764
+ <%= render M9sh::LabelComponent.new(for_id: "disabled-input") do %>
765
+ Disabled Field
766
+ <% end %>
767
+ <input
768
+ id="disabled-input"
769
+ type="text"
770
+ placeholder="This field is disabled"
771
+ disabled
772
+ class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
773
+ />
774
+ </div>
775
+ CODE
776
+ end
777
+
778
+ # Skeleton component helpers
779
+ def skeleton_usage_code
780
+ <<~'CODE'
781
+ <%= render M9sh::SkeletonComponent.new(class: "w-full h-12") %>
782
+ CODE
783
+ end
784
+
785
+ def skeleton_default_code
786
+ <<~'CODE'
787
+ <div class="space-y-2">
788
+ <%= render M9sh::SkeletonComponent.new(class: "w-full h-12") %>
789
+ <%= render M9sh::SkeletonComponent.new(class: "w-full h-12") %>
790
+ <%= render M9sh::SkeletonComponent.new(class: "w-full h-12") %>
791
+ </div>
792
+ CODE
793
+ end
794
+
795
+ def skeleton_variants_code
796
+ <<~'CODE'
797
+ <%= render M9sh::SkeletonComponent.new(variant: :default, class: "w-full h-12") %>
798
+
799
+ <%= render M9sh::SkeletonComponent.new(variant: :pulse, class: "w-full h-12") %>
800
+
801
+ <%= render M9sh::SkeletonComponent.new(variant: :shimmer, class: "w-full h-12") %>
802
+
803
+ <%= render M9sh::SkeletonComponent.new(variant: :none, class: "w-full h-12") %>
804
+ CODE
805
+ end
806
+
807
+ def skeleton_rounded_code
808
+ <<~'CODE'
809
+ <%= render M9sh::SkeletonComponent.new(rounded: :none, class: "w-full h-12") %>
810
+
811
+ <%= render M9sh::SkeletonComponent.new(rounded: :sm, class: "w-full h-12") %>
812
+
813
+ <%= render M9sh::SkeletonComponent.new(rounded: :md, class: "w-full h-12") %>
814
+
815
+ <%= render M9sh::SkeletonComponent.new(rounded: :lg, class: "w-full h-12") %>
816
+
817
+ <%= render M9sh::SkeletonComponent.new(rounded: :xl, class: "w-full h-12") %>
818
+
819
+ <%= render M9sh::SkeletonComponent.new(rounded: :full, class: "w-24 h-24") %>
820
+ CODE
821
+ end
822
+
823
+ def skeleton_card_code
824
+ <<~'CODE'
825
+ <div class="border rounded-lg p-6 space-y-4">
826
+ <div class="flex items-center space-x-4">
827
+ <%= render M9sh::SkeletonComponent.new(rounded: :full, class: "w-12 h-12") %>
828
+ <div class="flex-1 space-y-2">
829
+ <%= render M9sh::SkeletonComponent.new(class: "w-3/4 h-4") %>
830
+ <%= render M9sh::SkeletonComponent.new(class: "w-1/2 h-4") %>
831
+ </div>
832
+ </div>
833
+ <%= render M9sh::SkeletonComponent.new(class: "w-full h-32") %>
834
+ <div class="space-y-2">
835
+ <%= render M9sh::SkeletonComponent.new(class: "w-full h-4") %>
836
+ <%= render M9sh::SkeletonComponent.new(class: "w-5/6 h-4") %>
837
+ </div>
838
+ </div>
839
+ CODE
840
+ end
841
+
842
+ def skeleton_list_code
843
+ <<~'CODE'
844
+ <div class="space-y-4">
845
+ <% 3.times do %>
846
+ <div class="flex items-center space-x-4">
847
+ <%= render M9sh::SkeletonComponent.new(rounded: :full, class: "w-10 h-10") %>
848
+ <div class="flex-1 space-y-2">
849
+ <%= render M9sh::SkeletonComponent.new(class: "w-3/4 h-4") %>
850
+ <%= render M9sh::SkeletonComponent.new(class: "w-1/2 h-3") %>
851
+ </div>
852
+ </div>
853
+ <% end %>
854
+ </div>
855
+ CODE
856
+ end
857
+
858
+ def skeleton_table_code
859
+ <<~'CODE'
860
+ <div class="border rounded-lg overflow-hidden">
861
+ <div class="border-b p-4 space-y-2">
862
+ <%= render M9sh::SkeletonComponent.new(class: "w-1/4 h-6") %>
863
+ </div>
864
+ <% 5.times do %>
865
+ <div class="border-b last:border-b-0 p-4">
866
+ <div class="grid grid-cols-3 gap-4">
867
+ <%= render M9sh::SkeletonComponent.new(class: "w-full h-4") %>
868
+ <%= render M9sh::SkeletonComponent.new(class: "w-full h-4") %>
869
+ <%= render M9sh::SkeletonComponent.new(class: "w-full h-4") %>
870
+ </div>
871
+ </div>
872
+ <% end %>
873
+ </div>
874
+ CODE
875
+ end
876
+
877
+ # Textarea component helpers
878
+ def textarea_usage_code
879
+ <<~'CODE'
880
+ <%= render M9sh::TextareaComponent.new(
881
+ name: "message",
882
+ placeholder: "Type your message here."
883
+ ) %>
884
+ CODE
885
+ end
886
+
887
+ def textarea_with_label_code
888
+ <<~'CODE'
889
+ <div class="space-y-2">
890
+ <%= render M9sh::LabelComponent.new(for_id: "message") do %>
891
+ Your message
892
+ <% end %>
893
+ <%= render M9sh::TextareaComponent.new(
894
+ id: "message",
895
+ name: "message",
896
+ placeholder: "Type your message here."
897
+ ) %>
898
+ </div>
899
+ CODE
900
+ end
901
+
902
+ def textarea_disabled_code
903
+ <<~'CODE'
904
+ <%= render M9sh::TextareaComponent.new(
905
+ name: "disabled-textarea",
906
+ placeholder: "This textarea is disabled",
907
+ disabled: true
908
+ ) %>
909
+ CODE
910
+ end
911
+
912
+ def textarea_with_placeholder_code
913
+ <<~'CODE'
914
+ <%= render M9sh::TextareaComponent.new(
915
+ name: "bio",
916
+ placeholder: "Tell us a little bit about yourself"
917
+ ) %>
918
+ CODE
919
+ end
920
+
921
+ def textarea_sizes_code
922
+ <<~'CODE'
923
+ <!-- Small -->
924
+ <%= render M9sh::TextareaComponent.new(
925
+ name: "small",
926
+ placeholder: "Smaller textarea",
927
+ rows: 2
928
+ ) %>
929
+
930
+ <!-- Medium (default) -->
931
+ <%= render M9sh::TextareaComponent.new(
932
+ name: "medium",
933
+ placeholder: "Default textarea",
934
+ rows: 3
935
+ ) %>
936
+
937
+ <!-- Large -->
938
+ <%= render M9sh::TextareaComponent.new(
939
+ name: "large",
940
+ placeholder: "Larger textarea",
941
+ rows: 6
942
+ ) %>
943
+ CODE
944
+ end
945
+
946
+ def textarea_with_value_code
947
+ <<~'CODE'
948
+ <%= render M9sh::TextareaComponent.new(
949
+ name: "content",
950
+ value: "This textarea has pre-filled content that can be edited.",
951
+ placeholder: "Enter content"
952
+ ) %>
953
+ CODE
954
+ end
955
+
956
+ def textarea_readonly_code
957
+ <<~'CODE'
958
+ <%= render M9sh::TextareaComponent.new(
959
+ name: "readonly-textarea",
960
+ value: "This textarea is read-only and cannot be edited.",
961
+ readonly: true
962
+ ) %>
963
+ CODE
964
+ end
965
+
966
+ # Switch component helpers
967
+ def switch_usage_code
968
+ <<~'CODE'
969
+ <%= render M9sh::SwitchComponent.new %>
970
+ CODE
971
+ end
972
+
973
+ def switch_with_label_code
974
+ <<~'CODE'
975
+ <div class="flex items-center space-x-2">
976
+ <%= render M9sh::SwitchComponent.new(name: "notifications") %>
977
+ <%= render M9sh::LabelComponent.new(for_id: "notifications") do %>
978
+ Enable notifications
979
+ <% end %>
980
+ </div>
981
+ CODE
982
+ end
983
+
984
+ def switch_disabled_code
985
+ <<~'CODE'
986
+ <%= render M9sh::SwitchComponent.new(disabled: true) %>
987
+ CODE
988
+ end
989
+
990
+ def switch_checked_code
991
+ <<~'CODE'
992
+ <%= render M9sh::SwitchComponent.new(checked: true) %>
993
+ CODE
994
+ end
995
+
996
+ def switch_disabled_states_code
997
+ <<~'CODE'
998
+ <!-- Disabled unchecked -->
999
+ <%= render M9sh::SwitchComponent.new(disabled: true) %>
1000
+
1001
+ <!-- Disabled checked -->
1002
+ <%= render M9sh::SwitchComponent.new(checked: true, disabled: true) %>
1003
+ CODE
1004
+ end
1005
+
1006
+ def switch_form_code
1007
+ <<~'CODE'
1008
+ <div class="space-y-4">
1009
+ <div class="flex items-center justify-between">
1010
+ <div class="space-y-0.5">
1011
+ <div class="font-medium">Marketing emails</div>
1012
+ <div class="text-sm text-muted-foreground">
1013
+ Receive emails about new products and features.
1014
+ </div>
1015
+ </div>
1016
+ <%= render M9sh::SwitchComponent.new(name: "marketing_emails", checked: true) %>
1017
+ </div>
1018
+
1019
+ <div class="flex items-center justify-between">
1020
+ <div class="space-y-0.5">
1021
+ <div class="font-medium">Security emails</div>
1022
+ <div class="text-sm text-muted-foreground">
1023
+ Receive emails about your account security.
1024
+ </div>
1025
+ </div>
1026
+ <%= render M9sh::SwitchComponent.new(name: "security_emails", checked: true, disabled: true) %>
1027
+ </div>
1028
+ </div>
1029
+ CODE
1030
+ end
1031
+
1032
+ # Input component helpers
1033
+ def input_usage_code
1034
+ <<~'CODE'
1035
+ <%= render M9sh::InputComponent.new(
1036
+ type: "text",
1037
+ placeholder: "Enter text..."
1038
+ ) %>
1039
+ CODE
1040
+ end
1041
+
1042
+ def input_types_code
1043
+ <<~'CODE'
1044
+ <%= render M9sh::InputComponent.new(
1045
+ type: "text",
1046
+ placeholder: "Text input"
1047
+ ) %>
1048
+
1049
+ <%= render M9sh::InputComponent.new(
1050
+ type: "email",
1051
+ placeholder: "Email input"
1052
+ ) %>
1053
+
1054
+ <%= render M9sh::InputComponent.new(
1055
+ type: "password",
1056
+ placeholder: "Password input"
1057
+ ) %>
1058
+
1059
+ <%= render M9sh::InputComponent.new(
1060
+ type: "number",
1061
+ placeholder: "Number input"
1062
+ ) %>
1063
+ CODE
1064
+ end
1065
+
1066
+ def input_with_label_code
1067
+ <<~'CODE'
1068
+ <div class="space-y-2">
1069
+ <%= render M9sh::LabelComponent.new(for_id: "email") do %>
1070
+ Email
1071
+ <% end %>
1072
+ <%= render M9sh::InputComponent.new(
1073
+ id: "email",
1074
+ type: "email",
1075
+ placeholder: "Enter your email"
1076
+ ) %>
1077
+ </div>
1078
+ CODE
1079
+ end
1080
+
1081
+ def input_disabled_code
1082
+ <<~'CODE'
1083
+ <%= render M9sh::InputComponent.new(
1084
+ type: "text",
1085
+ placeholder: "Disabled input",
1086
+ disabled: true
1087
+ ) %>
1088
+ CODE
1089
+ end
1090
+
1091
+ def input_placeholder_code
1092
+ <<~'CODE'
1093
+ <%= render M9sh::InputComponent.new(
1094
+ type: "text",
1095
+ placeholder: "This is a placeholder..."
1096
+ ) %>
1097
+ CODE
1098
+ end
1099
+
1100
+ def input_value_code
1101
+ <<~'CODE'
1102
+ <%= render M9sh::InputComponent.new(
1103
+ type: "text",
1104
+ value: "Pre-filled value",
1105
+ placeholder: "Enter text..."
1106
+ ) %>
1107
+ CODE
1108
+ end
1109
+
1110
+ def input_file_code
1111
+ <<~'CODE'
1112
+ <%= render M9sh::InputComponent.new(
1113
+ type: "file"
1114
+ ) %>
1115
+ CODE
1116
+ end
1117
+
1118
+ # Checkbox component helpers
1119
+ def checkbox_usage_code
1120
+ <<~'CODE'
1121
+ <%= render M9sh::CheckboxComponent.new(name: "terms") %>
1122
+ CODE
1123
+ end
1124
+
1125
+ def checkbox_with_label_code
1126
+ <<~'CODE'
1127
+ <div class="flex items-center space-x-2">
1128
+ <%= render M9sh::CheckboxComponent.new(name: "terms", id: "terms") %>
1129
+ <%= render M9sh::LabelComponent.new(for_id: "terms") do %>
1130
+ Accept terms and conditions
1131
+ <% end %>
1132
+ </div>
1133
+ CODE
1134
+ end
1135
+
1136
+ def checkbox_checked_code
1137
+ <<~'CODE'
1138
+ <div class="flex items-center space-x-2">
1139
+ <%= render M9sh::CheckboxComponent.new(name: "checked", id: "checked", checked: true) %>
1140
+ <%= render M9sh::LabelComponent.new(for_id: "checked") do %>
1141
+ This checkbox is checked by default
1142
+ <% end %>
1143
+ </div>
1144
+ CODE
1145
+ end
1146
+
1147
+ def checkbox_disabled_code
1148
+ <<~'CODE'
1149
+ <%= render M9sh::CheckboxComponent.new(name: "disabled", disabled: true) %>
1150
+
1151
+ <%= render M9sh::CheckboxComponent.new(
1152
+ name: "disabled_checked",
1153
+ checked: true,
1154
+ disabled: true
1155
+ ) %>
1156
+ CODE
1157
+ end
1158
+
1159
+ def checkbox_multiple_code
1160
+ <<~'CODE'
1161
+ <div class="space-y-3">
1162
+ <div class="flex items-center space-x-2">
1163
+ <%= render M9sh::CheckboxComponent.new(name: "preferences[]", value: "email", id: "email_notifications") %>
1164
+ <%= render M9sh::LabelComponent.new(for_id: "email_notifications") do %>
1165
+ Email notifications
1166
+ <% end %>
1167
+ </div>
1168
+ <div class="flex items-center space-x-2">
1169
+ <%= render M9sh::CheckboxComponent.new(name: "preferences[]", value: "sms", id: "sms_notifications", checked: true) %>
1170
+ <%= render M9sh::LabelComponent.new(for_id: "sms_notifications") do %>
1171
+ SMS notifications
1172
+ <% end %>
1173
+ </div>
1174
+ <div class="flex items-center space-x-2">
1175
+ <%= render M9sh::CheckboxComponent.new(name: "preferences[]", value: "push", id: "push_notifications") %>
1176
+ <%= render M9sh::LabelComponent.new(for_id: "push_notifications") do %>
1177
+ Push notifications
1178
+ <% end %>
1179
+ </div>
1180
+ <div class="flex items-center space-x-2">
1181
+ <%= render M9sh::CheckboxComponent.new(name: "preferences[]", value: "newsletter", id: "newsletter", checked: true) %>
1182
+ <%= render M9sh::LabelComponent.new(for_id: "newsletter") do %>
1183
+ Weekly newsletter
1184
+ <% end %>
1185
+ </div>
1186
+ </div>
1187
+ CODE
1188
+ end
1189
+
1190
+ def checkbox_form_code
1191
+ <<~'CODE'
1192
+ <div class="border rounded-lg p-6 max-w-md">
1193
+ <h3 class="text-lg font-semibold mb-4">Account Settings</h3>
1194
+ <div class="space-y-4">
1195
+ <div class="flex items-start space-x-2">
1196
+ <%= render M9sh::CheckboxComponent.new(name: "account[two_factor]", id: "two_factor", checked: true) %>
1197
+ <div class="grid gap-1.5 leading-none">
1198
+ <%= render M9sh::LabelComponent.new(for_id: "two_factor", class: "font-medium") do %>
1199
+ Enable two-factor authentication
1200
+ <% end %>
1201
+ <p class="text-sm text-muted-foreground">
1202
+ Add an extra layer of security to your account.
1203
+ </p>
1204
+ </div>
1205
+ </div>
1206
+ <!-- More checkbox items... -->
1207
+ </div>
1208
+ </div>
1209
+ CODE
1210
+ end
1211
+
1212
+ # Tabs component helpers
1213
+ def tabs_usage_code
1214
+ <<~'CODE'
1215
+ <%= render M9sh::TabsComponent.new(default_value: "tab1") do |tabs| %>
1216
+ <% tabs.with_tabs_list do |list| %>
1217
+ <%= render list.tabs_trigger(value: "tab1") { "Account" } %>
1218
+ <%= render list.tabs_trigger(value: "tab2") { "Password" } %>
1219
+ <% end %>
1220
+
1221
+ <% tabs.with_tabs_content(value: "tab1") do %>
1222
+ <p>Make changes to your account here.</p>
1223
+ <% end %>
1224
+
1225
+ <% tabs.with_tabs_content(value: "tab2") do %>
1226
+ <p>Change your password here.</p>
1227
+ <% end %>
1228
+ <% end %>
1229
+ CODE
1230
+ end
1231
+
1232
+ def tabs_default_code
1233
+ <<~'CODE'
1234
+ <%= render M9sh::TabsComponent.new(default_value: "account") do |tabs| %>
1235
+ <% tabs.with_tabs_list do |list| %>
1236
+ <%= render list.tabs_trigger(value: "account") { "Account" } %>
1237
+ <%= render list.tabs_trigger(value: "password") { "Password" } %>
1238
+ <% end %>
1239
+
1240
+ <% tabs.with_tabs_content(value: "account") do %>
1241
+ <div class="space-y-4">
1242
+ <div class="space-y-2">
1243
+ <h3 class="text-lg font-medium">Account Settings</h3>
1244
+ <p class="text-sm text-muted-foreground">
1245
+ Make changes to your account here. Click save when you're done.
1246
+ </p>
1247
+ </div>
1248
+ <div class="space-y-2">
1249
+ <label class="text-sm font-medium">Name</label>
1250
+ <input type="text" placeholder="Enter your name" class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm" />
1251
+ </div>
1252
+ <div class="space-y-2">
1253
+ <label class="text-sm font-medium">Email</label>
1254
+ <input type="email" placeholder="Enter your email" class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm" />
1255
+ </div>
1256
+ </div>
1257
+ <% end %>
1258
+
1259
+ <% tabs.with_tabs_content(value: "password") do %>
1260
+ <div class="space-y-4">
1261
+ <div class="space-y-2">
1262
+ <h3 class="text-lg font-medium">Password Settings</h3>
1263
+ <p class="text-sm text-muted-foreground">
1264
+ Change your password here. After saving, you'll be logged out.
1265
+ </p>
1266
+ </div>
1267
+ <div class="space-y-2">
1268
+ <label class="text-sm font-medium">Current Password</label>
1269
+ <input type="password" placeholder="Enter current password" class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm" />
1270
+ </div>
1271
+ <div class="space-y-2">
1272
+ <label class="text-sm font-medium">New Password</label>
1273
+ <input type="password" placeholder="Enter new password" class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm" />
1274
+ </div>
1275
+ </div>
1276
+ <% end %>
1277
+ <% end %>
1278
+ CODE
1279
+ end
1280
+
1281
+ def tabs_multiple_groups_code
1282
+ <<~'CODE'
1283
+ <div class="space-y-8">
1284
+ <div>
1285
+ <h3 class="text-lg font-semibold mb-4">User Settings</h3>
1286
+ <%= render M9sh::TabsComponent.new(default_value: "profile") do |tabs| %>
1287
+ <% tabs.with_tabs_list do |list| %>
1288
+ <%= render list.tabs_trigger(value: "profile") { "Profile" } %>
1289
+ <%= render list.tabs_trigger(value: "preferences") { "Preferences" } %>
1290
+ <% end %>
1291
+
1292
+ <% tabs.with_tabs_content(value: "profile") do %>
1293
+ <p class="text-sm">Profile settings content</p>
1294
+ <% end %>
1295
+
1296
+ <% tabs.with_tabs_content(value: "preferences") do %>
1297
+ <p class="text-sm">Preferences content</p>
1298
+ <% end %>
1299
+ <% end %>
1300
+ </div>
1301
+
1302
+ <div>
1303
+ <h3 class="text-lg font-semibold mb-4">System Settings</h3>
1304
+ <%= render M9sh::TabsComponent.new(default_value: "general") do |tabs| %>
1305
+ <% tabs.with_tabs_list do |list| %>
1306
+ <%= render list.tabs_trigger(value: "general") { "General" } %>
1307
+ <%= render list.tabs_trigger(value: "advanced") { "Advanced" } %>
1308
+ <% end %>
1309
+
1310
+ <% tabs.with_tabs_content(value: "general") do %>
1311
+ <p class="text-sm">General settings content</p>
1312
+ <% end %>
1313
+
1314
+ <% tabs.with_tabs_content(value: "advanced") do %>
1315
+ <p class="text-sm">Advanced settings content</p>
1316
+ <% end %>
1317
+ <% end %>
1318
+ </div>
1319
+ </div>
1320
+ CODE
1321
+ end
1322
+
1323
+ def tabs_simple_code
1324
+ <<~'CODE'
1325
+ <%= render M9sh::TabsComponent.new(default_value: "tab1") do |tabs| %>
1326
+ <% tabs.with_tabs_list do |list| %>
1327
+ <%= render list.tabs_trigger(value: "tab1") { "Tab 1" } %>
1328
+ <%= render list.tabs_trigger(value: "tab2") { "Tab 2" } %>
1329
+ <%= render list.tabs_trigger(value: "tab3") { "Tab 3" } %>
1330
+ <% end %>
1331
+
1332
+ <% tabs.with_tabs_content(value: "tab1") do %>
1333
+ <p>Content for tab 1</p>
1334
+ <% end %>
1335
+
1336
+ <% tabs.with_tabs_content(value: "tab2") do %>
1337
+ <p>Content for tab 2</p>
1338
+ <% end %>
1339
+
1340
+ <% tabs.with_tabs_content(value: "tab3") do %>
1341
+ <p>Content for tab 3</p>
1342
+ <% end %>
1343
+ <% end %>
1344
+ CODE
1345
+ end
1346
+
1347
+ # Radio Group component helpers
1348
+ def radio_group_usage_code
1349
+ <<~'CODE'
1350
+ <%= render M9sh::RadioGroupComponent.new(name: "option") do |radio_group| %>
1351
+ <% radio_group.with_item(value: "option1", label: "Option 1") %>
1352
+ <% end %>
1353
+ CODE
1354
+ end
1355
+
1356
+ def radio_group_with_label_code
1357
+ <<~'CODE'
1358
+ <%= render M9sh::RadioGroupComponent.new(name: "option") do |radio_group| %>
1359
+ <% radio_group.with_item(value: "default", label: "Default", checked: true) %>
1360
+ <% radio_group.with_item(value: "comfortable", label: "Comfortable") %>
1361
+ <% radio_group.with_item(value: "compact", label: "Compact") %>
1362
+ <% end %>
1363
+ CODE
1364
+ end
1365
+
1366
+ def radio_group_default_code
1367
+ <<~'CODE'
1368
+ <%= render M9sh::RadioGroupComponent.new(name: "default") do |radio_group| %>
1369
+ <% radio_group.with_item(value: "option1", label: "Option 1", checked: true) %>
1370
+ <% radio_group.with_item(value: "option2", label: "Option 2") %>
1371
+ <% radio_group.with_item(value: "option3", label: "Option 3") %>
1372
+ <% end %>
1373
+ CODE
1374
+ end
1375
+
1376
+ def radio_group_with_description_code
1377
+ <<~'CODE'
1378
+ <%= render M9sh::RadioGroupComponent.new(name: "plan") do |radio_group| %>
1379
+ <% radio_group.with_item(
1380
+ value: "free",
1381
+ label: "Free",
1382
+ description: "Perfect for personal use",
1383
+ checked: true
1384
+ ) %>
1385
+ <% radio_group.with_item(
1386
+ value: "pro",
1387
+ label: "Pro",
1388
+ description: "Best for professionals"
1389
+ ) %>
1390
+ <% radio_group.with_item(
1391
+ value: "enterprise",
1392
+ label: "Enterprise",
1393
+ description: "For large organizations"
1394
+ ) %>
1395
+ <% end %>
1396
+ CODE
1397
+ end
1398
+
1399
+ def radio_group_disabled_code
1400
+ <<~'CODE'
1401
+ <%= render M9sh::RadioGroupComponent.new(name: "disabled-group") do |radio_group| %>
1402
+ <% radio_group.with_item(value: "option1", label: "Available option", checked: true) %>
1403
+ <% radio_group.with_item(value: "option2", label: "Disabled option", disabled: true) %>
1404
+ <% radio_group.with_item(value: "option3", label: "Another available option") %>
1405
+ <% end %>
1406
+ CODE
1407
+ end
1408
+
1409
+ def radio_group_horizontal_code
1410
+ <<~'CODE'
1411
+ <%= render M9sh::RadioGroupComponent.new(name: "horizontal", class: "flex flex-row space-x-4") do |radio_group| %>
1412
+ <% radio_group.with_item(value: "yes", label: "Yes", checked: true) %>
1413
+ <% radio_group.with_item(value: "no", label: "No") %>
1414
+ <% radio_group.with_item(value: "maybe", label: "Maybe") %>
1415
+ <% end %>
1416
+ CODE
1417
+ end
1418
+
1419
+ def radio_group_form_integration_code
1420
+ <<~'CODE'
1421
+ <div class="border rounded-lg p-6 max-w-md">
1422
+ <h3 class="text-lg font-semibold mb-4">Notification Settings</h3>
1423
+ <div class="space-y-6">
1424
+ <div class="space-y-3">
1425
+ <div class="font-medium">Email frequency</div>
1426
+ <%= render M9sh::RadioGroupComponent.new(name: "email_frequency") do |radio_group| %>
1427
+ <% radio_group.with_item(
1428
+ value: "realtime",
1429
+ label: "Realtime",
1430
+ description: "Get notified immediately",
1431
+ checked: true
1432
+ ) %>
1433
+ <% radio_group.with_item(
1434
+ value: "daily",
1435
+ label: "Daily digest",
1436
+ description: "Once per day at 9 AM"
1437
+ ) %>
1438
+ <% radio_group.with_item(
1439
+ value: "weekly",
1440
+ label: "Weekly digest",
1441
+ description: "Every Monday morning"
1442
+ ) %>
1443
+ <% radio_group.with_item(
1444
+ value: "never",
1445
+ label: "Never",
1446
+ description: "Disable email notifications"
1447
+ ) %>
1448
+ <% end %>
1449
+ </div>
1450
+ </div>
1451
+ </div>
1452
+ CODE
1453
+ end
1454
+
1455
+ # Select component helpers
1456
+ def select_usage_code
1457
+ <<~'CODE'
1458
+ <%= render M9sh::SelectComponent.new(
1459
+ name: "country",
1460
+ options: ["USA", "Canada", "Mexico"]
1461
+ ) %>
1462
+ CODE
1463
+ end
1464
+
1465
+ def select_with_label_code
1466
+ <<~'CODE'
1467
+ <div class="space-y-2">
1468
+ <%= render M9sh::LabelComponent.new(for_id: "country") do %>
1469
+ Select your country
1470
+ <% end %>
1471
+ <%= render M9sh::SelectComponent.new(
1472
+ name: "country",
1473
+ options: ["USA", "Canada", "Mexico"]
1474
+ ) %>
1475
+ </div>
1476
+ CODE
1477
+ end
1478
+
1479
+ def select_disabled_code
1480
+ <<~'CODE'
1481
+ <%= render M9sh::SelectComponent.new(
1482
+ name: "disabled",
1483
+ options: ["Option 1", "Option 2"],
1484
+ disabled: true
1485
+ ) %>
1486
+ CODE
1487
+ end
1488
+
1489
+ def select_with_placeholder_code
1490
+ <<~'CODE'
1491
+ <%= render M9sh::SelectComponent.new(
1492
+ name: "fruit",
1493
+ options: ["Apple", "Banana", "Orange", "Strawberry"],
1494
+ placeholder: "Select a fruit"
1495
+ ) %>
1496
+ CODE
1497
+ end
1498
+
1499
+ def select_custom_options_code
1500
+ <<~'CODE'
1501
+ <%= render M9sh::SelectComponent.new(
1502
+ name: "country_code",
1503
+ options: [
1504
+ ["United States", "us"],
1505
+ ["Canada", "ca"],
1506
+ ["Mexico", "mx"],
1507
+ ["United Kingdom", "uk"]
1508
+ ]
1509
+ ) %>
1510
+ CODE
1511
+ end
1512
+
1513
+ def select_with_selected_code
1514
+ <<~'CODE'
1515
+ <%= render M9sh::SelectComponent.new(
1516
+ name: "language",
1517
+ options: [
1518
+ ["English", "en"],
1519
+ ["Spanish", "es"],
1520
+ ["French", "fr"],
1521
+ ["German", "de"]
1522
+ ],
1523
+ selected: "es"
1524
+ ) %>
1525
+ CODE
1526
+ end
1527
+
1528
+ def select_form_integration_code
1529
+ <<~'CODE'
1530
+ <div class="border rounded-lg p-6 max-w-md">
1531
+ <h3 class="text-lg font-semibold mb-4">User Information</h3>
1532
+ <div class="space-y-4">
1533
+ <div class="space-y-2">
1534
+ <%= render M9sh::LabelComponent.new(for_id: "country") do %>
1535
+ Country
1536
+ <% end %>
1537
+ <%= render M9sh::SelectComponent.new(
1538
+ name: "user[country]",
1539
+ options: [
1540
+ ["United States", "us"],
1541
+ ["Canada", "ca"],
1542
+ ["Mexico", "mx"],
1543
+ ["United Kingdom", "uk"]
1544
+ ],
1545
+ placeholder: "Select your country"
1546
+ ) %>
1547
+ </div>
1548
+ <div class="space-y-2">
1549
+ <%= render M9sh::LabelComponent.new(for_id: "timezone") do %>
1550
+ Timezone
1551
+ <% end %>
1552
+ <%= render M9sh::SelectComponent.new(
1553
+ name: "user[timezone]",
1554
+ options: [
1555
+ ["Eastern Time (ET)", "est"],
1556
+ ["Central Time (CT)", "cst"],
1557
+ ["Mountain Time (MT)", "mst"],
1558
+ ["Pacific Time (PT)", "pst"]
1559
+ ],
1560
+ selected: "est"
1561
+ ) %>
1562
+ </div>
1563
+ </div>
1564
+ </div>
1565
+ CODE
1566
+ end
1567
+
1568
+ # Collapsible component helpers
1569
+ def collapsible_usage_code
1570
+ <<~'CODE'
1571
+ <%= render M9sh::CollapsibleComponent.new do |c| %>
1572
+ <% c.with_trigger do %>
1573
+ Click to toggle
1574
+ <% end %>
1575
+ <% c.with_collapsible_content do %>
1576
+ Content that can be collapsed
1577
+ <% end %>
1578
+ <% end %>
1579
+ CODE
1580
+ end
1581
+
1582
+ def collapsible_default_code
1583
+ <<~'CODE'
1584
+ <%= render M9sh::CollapsibleComponent.new(class: "space-y-2") do |c| %>
1585
+ <% c.with_trigger do %>
1586
+ <button class="flex w-full items-center justify-between rounded-md bg-muted px-4 py-2 text-sm font-medium">
1587
+ <span>@peduarte starred 3 repositories</span>
1588
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1589
+ <polyline points="6 9 12 15 18 9"/>
1590
+ </svg>
1591
+ </button>
1592
+ <% end %>
1593
+ <% c.with_collapsible_content do %>
1594
+ <div class="space-y-2 pt-2">
1595
+ <div class="rounded-md border px-4 py-3 text-sm">
1596
+ @radix-ui/primitives
1597
+ </div>
1598
+ <div class="rounded-md border px-4 py-3 text-sm">
1599
+ @radix-ui/colors
1600
+ </div>
1601
+ <div class="rounded-md border px-4 py-3 text-sm">
1602
+ @stitches/react
1603
+ </div>
1604
+ </div>
1605
+ <% end %>
1606
+ <% end %>
1607
+ CODE
1608
+ end
1609
+
1610
+ def collapsible_open_code
1611
+ <<~'CODE'
1612
+ <%= render M9sh::CollapsibleComponent.new(open: true, class: "space-y-2") do |c| %>
1613
+ <% c.with_trigger do %>
1614
+ <button class="flex w-full items-center justify-between rounded-md bg-muted px-4 py-2 text-sm font-medium">
1615
+ <span>Project Information</span>
1616
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1617
+ <polyline points="6 9 12 15 18 9"/>
1618
+ </svg>
1619
+ </button>
1620
+ <% end %>
1621
+ <% c.with_collapsible_content do %>
1622
+ <div class="space-y-2 pt-2">
1623
+ <div class="rounded-md border px-4 py-3 text-sm">
1624
+ <strong>Name:</strong> m9sh Components
1625
+ </div>
1626
+ <div class="rounded-md border px-4 py-3 text-sm">
1627
+ <strong>Status:</strong> Active Development
1628
+ </div>
1629
+ <div class="rounded-md border px-4 py-3 text-sm">
1630
+ <strong>Version:</strong> 1.0.0
1631
+ </div>
1632
+ </div>
1633
+ <% end %>
1634
+ <% end %>
1635
+ CODE
1636
+ end
1637
+
1638
+ def collapsible_button_code
1639
+ <<~'CODE'
1640
+ <%= render M9sh::CollapsibleComponent.new(class: "space-y-2") do |c| %>
1641
+ <% c.with_trigger do %>
1642
+ <%= render M9sh::ButtonComponent.new(variant: :outline, class: "w-full justify-between") do %>
1643
+ <span>Show more details</span>
1644
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1645
+ <polyline points="6 9 12 15 18 9"/>
1646
+ </svg>
1647
+ <% end %>
1648
+ <% end %>
1649
+ <% c.with_collapsible_content do %>
1650
+ <div class="rounded-md border p-4 text-sm">
1651
+ <p class="text-muted-foreground">
1652
+ This is additional content that can be toggled.
1653
+ </p>
1654
+ </div>
1655
+ <% end %>
1656
+ <% end %>
1657
+ CODE
1658
+ end
1659
+
1660
+ def collapsible_faq_code
1661
+ <<~'CODE'
1662
+ <div class="space-y-4">
1663
+ <%= render M9sh::CollapsibleComponent.new(class: "space-y-2") do |c| %>
1664
+ <% c.with_trigger do %>
1665
+ <button class="flex w-full items-center justify-between rounded-md border px-4 py-2 text-sm font-medium">
1666
+ <span>What is m9sh Components?</span>
1667
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1668
+ <polyline points="6 9 12 15 18 9"/>
1669
+ </svg>
1670
+ </button>
1671
+ <% end %>
1672
+ <% c.with_collapsible_content do %>
1673
+ <div class="border-x border-b rounded-b-md px-4 py-3 text-sm text-muted-foreground">
1674
+ m9sh Components is a collection of reusable UI components.
1675
+ </div>
1676
+ <% end %>
1677
+ <% end %>
1678
+
1679
+ <%= render M9sh::CollapsibleComponent.new(class: "space-y-2") do |c| %>
1680
+ <% c.with_trigger do %>
1681
+ <button class="flex w-full items-center justify-between rounded-md border px-4 py-2 text-sm font-medium">
1682
+ <span>How do I install it?</span>
1683
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1684
+ <polyline points="6 9 12 15 18 9"/>
1685
+ </svg>
1686
+ </button>
1687
+ <% end %>
1688
+ <% c.with_collapsible_content do %>
1689
+ <div class="border-x border-b rounded-b-md px-4 py-3 text-sm text-muted-foreground">
1690
+ Simply copy the component files into your Rails application.
1691
+ </div>
1692
+ <% end %>
1693
+ <% end %>
1694
+ </div>
1695
+ CODE
1696
+ end
1697
+
1698
+ # Card component helpers
1699
+ def card_usage_code
1700
+ <<~'CODE'
1701
+ <%= render M9sh::CardComponent.new do |card| %>
1702
+ <% card.with_body do %>
1703
+ Card content goes here
1704
+ <% end %>
1705
+ <% end %>
1706
+ CODE
1707
+ end
1708
+
1709
+ def card_with_header_code
1710
+ <<~'CODE'
1711
+ <%= render M9sh::CardComponent.new do |card| %>
1712
+ <% card.with_header do |header| %>
1713
+ <% header.with_title do %>
1714
+ Card Title
1715
+ <% end %>
1716
+ <% header.with_description do %>
1717
+ Card description
1718
+ <% end %>
1719
+ <% end %>
1720
+ <% card.with_body do %>
1721
+ Card content goes here
1722
+ <% end %>
1723
+ <% end %>
1724
+ CODE
1725
+ end
1726
+
1727
+ def card_with_footer_code
1728
+ <<~'CODE'
1729
+ <%= render M9sh::CardComponent.new do |card| %>
1730
+ <% card.with_body do %>
1731
+ Card content goes here
1732
+ <% end %>
1733
+ <% card.with_footer do %>
1734
+ <p class="text-sm text-muted-foreground">Card footer content</p>
1735
+ <% end %>
1736
+ <% end %>
1737
+ CODE
1738
+ end
1739
+
1740
+ def card_complete_code
1741
+ <<~'CODE'
1742
+ <%= render M9sh::CardComponent.new do |card| %>
1743
+ <% card.with_header do |header| %>
1744
+ <% header.with_title do %>
1745
+ Create Project
1746
+ <% end %>
1747
+ <% header.with_description do %>
1748
+ Deploy your new project in one-click.
1749
+ <% end %>
1750
+ <% end %>
1751
+ <% card.with_body do %>
1752
+ <div class="space-y-4">
1753
+ <div class="space-y-2">
1754
+ <label class="text-sm font-medium">Name</label>
1755
+ <input type="text" placeholder="Name of your project" class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm" />
1756
+ </div>
1757
+ <div class="space-y-2">
1758
+ <label class="text-sm font-medium">Framework</label>
1759
+ <select class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm">
1760
+ <option>Next.js</option>
1761
+ <option>SvelteKit</option>
1762
+ <option>Astro</option>
1763
+ <option>Nuxt.js</option>
1764
+ </select>
1765
+ </div>
1766
+ </div>
1767
+ <% end %>
1768
+ <% card.with_footer do %>
1769
+ <div class="flex justify-between w-full">
1770
+ <button class="px-4 py-2 rounded-md text-sm">Cancel</button>
1771
+ <button class="px-4 py-2 bg-primary text-primary-foreground rounded-md text-sm">Deploy</button>
1772
+ </div>
1773
+ <% end %>
1774
+ <% end %>
1775
+ CODE
1776
+ end
1777
+
1778
+ def card_with_action_code
1779
+ <<~'CODE'
1780
+ <%= render M9sh::CardComponent.new do |card| %>
1781
+ <% card.with_header do |header| %>
1782
+ <% header.with_title do %>
1783
+ Notifications
1784
+ <% end %>
1785
+ <% header.with_description do %>
1786
+ You have 3 unread messages.
1787
+ <% end %>
1788
+ <% header.with_action do %>
1789
+ <button class="text-sm text-primary hover:underline">
1790
+ Mark all as read
1791
+ </button>
1792
+ <% end %>
1793
+ <% end %>
1794
+ <% card.with_body do %>
1795
+ Card content goes here
1796
+ <% end %>
1797
+ <% end %>
1798
+ CODE
1799
+ end
1800
+
1801
+ # Progress component helpers
1802
+ def progress_usage_code
1803
+ <<~'CODE'
1804
+ <%= render M9sh::ProgressComponent.new(value: 60) %>
1805
+ CODE
1806
+ end
1807
+
1808
+ def progress_values_code
1809
+ <<~'CODE'
1810
+ <%= render M9sh::ProgressComponent.new(value: 25) %>
1811
+
1812
+ <%= render M9sh::ProgressComponent.new(value: 50) %>
1813
+
1814
+ <%= render M9sh::ProgressComponent.new(value: 75) %>
1815
+
1816
+ <%= render M9sh::ProgressComponent.new(value: 100) %>
1817
+ CODE
1818
+ end
1819
+
1820
+ def progress_indeterminate_code
1821
+ <<~'CODE'
1822
+ <%= render M9sh::ProgressComponent.new(value: 0) %>
1823
+ CODE
1824
+ end
1825
+
1826
+ # Slider component helpers
1827
+ def slider_usage_code
1828
+ <<~'CODE'
1829
+ <%= render M9sh::SliderComponent.new %>
1830
+ CODE
1831
+ end
1832
+
1833
+ def slider_range_code
1834
+ <<~'CODE'
1835
+ <%= render M9sh::SliderComponent.new(
1836
+ min: 0,
1837
+ max: 100,
1838
+ step: 5,
1839
+ value: 50
1840
+ ) %>
1841
+ CODE
1842
+ end
1843
+
1844
+ def slider_with_label_code
1845
+ <<~'CODE'
1846
+ <div class="space-y-2">
1847
+ <%= render M9sh::LabelComponent.new(for_id: "volume") do %>
1848
+ Volume
1849
+ <% end %>
1850
+ <%= render M9sh::SliderComponent.new(
1851
+ name: "volume",
1852
+ min: 0,
1853
+ max: 100,
1854
+ value: 75
1855
+ ) %>
1856
+ </div>
1857
+ CODE
1858
+ end
1859
+
1860
+ def slider_disabled_code
1861
+ <<~'CODE'
1862
+ <%= render M9sh::SliderComponent.new(
1863
+ value: 50,
1864
+ disabled: true
1865
+ ) %>
1866
+ CODE
1867
+ end
1868
+
1869
+ def slider_form_integration_code
1870
+ <<~'CODE'
1871
+ <div class="space-y-2">
1872
+ <div class="flex items-center justify-between">
1873
+ <%= render M9sh::LabelComponent.new(for_id: "price-range") do %>
1874
+ Price Range
1875
+ <% end %>
1876
+ <span class="text-sm text-muted-foreground">$50</span>
1877
+ </div>
1878
+ <%= render M9sh::SliderComponent.new(
1879
+ name: "price",
1880
+ min: 0,
1881
+ max: 100,
1882
+ step: 1,
1883
+ value: 50
1884
+ ) %>
1885
+ </div>
1886
+ CODE
1887
+ end
1888
+
1889
+ # Toggle component helpers
1890
+ def toggle_usage_code
1891
+ <<~'CODE'
1892
+ <%= render M9sh::ToggleComponent.new do %>
1893
+ Toggle
1894
+ <% end %>
1895
+ CODE
1896
+ end
1897
+
1898
+ def toggle_default_code
1899
+ <<~'CODE'
1900
+ <%= render M9sh::ToggleComponent.new do %>
1901
+ Toggle
1902
+ <% end %>
1903
+ CODE
1904
+ end
1905
+
1906
+ def toggle_with_text_code
1907
+ <<~'CODE'
1908
+ <%= render M9sh::ToggleComponent.new do %>
1909
+ Toggle with text
1910
+ <% end %>
1911
+ CODE
1912
+ end
1913
+
1914
+ def toggle_with_icon_code
1915
+ <<~'CODE'
1916
+ <%= render M9sh::ToggleComponent.new do %>
1917
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1918
+ <path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/>
1919
+ <path d="m15 5 4 4"/>
1920
+ </svg>
1921
+ <% end %>
1922
+ CODE
1923
+ end
1924
+
1925
+ def toggle_disabled_code
1926
+ <<~'CODE'
1927
+ <%= render M9sh::ToggleComponent.new(disabled: true) do %>
1928
+ Disabled
1929
+ <% end %>
1930
+
1931
+ <%= render M9sh::ToggleComponent.new(pressed: true, disabled: true) do %>
1932
+ Disabled Pressed
1933
+ <% end %>
1934
+ CODE
1935
+ end
1936
+
1937
+ def toggle_variants_code
1938
+ <<~'CODE'
1939
+ <%= render M9sh::ToggleComponent.new(variant: :default) do %>
1940
+ Default
1941
+ <% end %>
1942
+
1943
+ <%= render M9sh::ToggleComponent.new(variant: :outline) do %>
1944
+ Outline
1945
+ <% end %>
1946
+ CODE
1947
+ end
1948
+
1949
+ def toggle_sizes_code
1950
+ <<~'CODE'
1951
+ <%= render M9sh::ToggleComponent.new(size: :sm) do %>
1952
+ Small
1953
+ <% end %>
1954
+
1955
+ <%= render M9sh::ToggleComponent.new(size: :default) do %>
1956
+ Default
1957
+ <% end %>
1958
+
1959
+ <%= render M9sh::ToggleComponent.new(size: :lg) do %>
1960
+ Large
1961
+ <% end %>
1962
+ CODE
1963
+ end
1964
+
1965
+ # ThemeToggle component helpers
1966
+ def theme_toggle_usage_code
1967
+ <<~'CODE'
1968
+ <%= render M9sh::ThemeToggleComponent.new %>
1969
+ CODE
1970
+ end
1971
+
1972
+ def theme_toggle_default_code
1973
+ <<~'CODE'
1974
+ <%= render M9sh::ThemeToggleComponent.new %>
1975
+ CODE
1976
+ end
1977
+
1978
+ def theme_toggle_with_label_code
1979
+ <<~'CODE'
1980
+ <div class="flex items-center gap-3">
1981
+ <span class="text-sm text-muted-foreground">Theme:</span>
1982
+ <%= render M9sh::ThemeToggleComponent.new %>
1983
+ </div>
1984
+ CODE
1985
+ end
1986
+
1987
+ def theme_toggle_in_header_code
1988
+ <<~'CODE'
1989
+ <div class="flex items-center justify-between border rounded-lg p-4 bg-card">
1990
+ <div>
1991
+ <h3 class="text-lg font-semibold">Settings</h3>
1992
+ <p class="text-sm text-muted-foreground">Manage your preferences</p>
1993
+ </div>
1994
+ <%= render M9sh::ThemeToggleComponent.new %>
1995
+ </div>
1996
+ CODE
1997
+ end
1998
+
1999
+ def theme_toggle_in_nav_code
2000
+ <<~'CODE'
2001
+ <nav class="flex items-center justify-between border rounded-lg p-4 bg-card">
2002
+ <div class="flex items-center gap-4">
2003
+ <span class="font-semibold">My App</span>
2004
+ <a href="#" class="text-sm">Home</a>
2005
+ <a href="#" class="text-sm">About</a>
2006
+ <a href="#" class="text-sm">Contact</a>
2007
+ </div>
2008
+ <%= render M9sh::ThemeToggleComponent.new %>
2009
+ </nav>
2010
+ CODE
2011
+ end
2012
+
2013
+ # Sheet component helpers
2014
+ def sheet_usage_code
2015
+ <<~'CODE'
2016
+ <%= render M9sh::SheetComponent.new do |sheet| %>
2017
+ <% sheet.with_trigger do %>
2018
+ <%= render M9sh::ButtonComponent.new do %>
2019
+ Open Sheet
2020
+ <% end %>
2021
+ <% end %>
2022
+ <% sheet.with_title do %>
2023
+ Sheet Title
2024
+ <% end %>
2025
+ <% sheet.with_description do %>
2026
+ Sheet description goes here.
2027
+ <% end %>
2028
+ <% sheet.with_sheet_content do %>
2029
+ Sheet content goes here.
2030
+ <% end %>
2031
+ <% end %>
2032
+ CODE
2033
+ end
2034
+
2035
+ def sheet_side_code
2036
+ <<~'CODE'
2037
+ <%= render M9sh::SheetComponent.new(side: "left") do |sheet| %>
2038
+ <% sheet.with_trigger do %>
2039
+ <%= render M9sh::ButtonComponent.new(variant: :outline) do %>
2040
+ Open Left
2041
+ <% end %>
2042
+ <% end %>
2043
+ <% sheet.with_title do %>Left Sheet<% end %>
2044
+ <% sheet.with_sheet_content do %>
2045
+ Content from the left side.
2046
+ <% end %>
2047
+ <% end %>
2048
+
2049
+ <%= render M9sh::SheetComponent.new(side: "right") do |sheet| %>
2050
+ <% sheet.with_trigger do %>
2051
+ <%= render M9sh::ButtonComponent.new(variant: :outline) do %>
2052
+ Open Right
2053
+ <% end %>
2054
+ <% end %>
2055
+ <% sheet.with_title do %>Right Sheet<% end %>
2056
+ <% sheet.with_sheet_content do %>
2057
+ Content from the right side.
2058
+ <% end %>
2059
+ <% end %>
2060
+
2061
+ <%= render M9sh::SheetComponent.new(side: "top") do |sheet| %>
2062
+ <% sheet.with_trigger do %>
2063
+ <%= render M9sh::ButtonComponent.new(variant: :outline) do %>
2064
+ Open Top
2065
+ <% end %>
2066
+ <% end %>
2067
+ <% sheet.with_title do %>Top Sheet<% end %>
2068
+ <% sheet.with_sheet_content do %>
2069
+ Content from the top.
2070
+ <% end %>
2071
+ <% end %>
2072
+
2073
+ <%= render M9sh::SheetComponent.new(side: "bottom") do |sheet| %>
2074
+ <% sheet.with_trigger do %>
2075
+ <%= render M9sh::ButtonComponent.new(variant: :outline) do %>
2076
+ Open Bottom
2077
+ <% end %>
2078
+ <% end %>
2079
+ <% sheet.with_title do %>Bottom Sheet<% end %>
2080
+ <% sheet.with_sheet_content do %>
2081
+ Content from the bottom.
2082
+ <% end %>
2083
+ <% end %>
2084
+ CODE
2085
+ end
2086
+
2087
+ def sheet_with_form_code
2088
+ <<~'CODE'
2089
+ <%= render M9sh::SheetComponent.new do |sheet| %>
2090
+ <% sheet.with_trigger do %>
2091
+ <%= render M9sh::ButtonComponent.new do %>
2092
+ Edit Profile
2093
+ <% end %>
2094
+ <% end %>
2095
+ <% sheet.with_title do %>
2096
+ Edit Profile
2097
+ <% end %>
2098
+ <% sheet.with_description do %>
2099
+ Make changes to your profile here. Click save when you're done.
2100
+ <% end %>
2101
+ <% sheet.with_sheet_content do %>
2102
+ <div class="space-y-4 py-4">
2103
+ <div class="space-y-2">
2104
+ <%= render M9sh::LabelComponent.new(for_id: "name") do %>
2105
+ Name
2106
+ <% end %>
2107
+ <%= render M9sh::InputComponent.new(
2108
+ id: "name",
2109
+ type: "text",
2110
+ placeholder: "Enter your name"
2111
+ ) %>
2112
+ </div>
2113
+ <div class="space-y-2">
2114
+ <%= render M9sh::LabelComponent.new(for_id: "email") do %>
2115
+ Email
2116
+ <% end %>
2117
+ <%= render M9sh::InputComponent.new(
2118
+ id: "email",
2119
+ type: "email",
2120
+ placeholder: "Enter your email"
2121
+ ) %>
2122
+ </div>
2123
+ <div class="flex justify-end gap-2 pt-4">
2124
+ <%= render M9sh::ButtonComponent.new(variant: :outline) do %>
2125
+ Cancel
2126
+ <% end %>
2127
+ <%= render M9sh::ButtonComponent.new do %>
2128
+ Save Changes
2129
+ <% end %>
2130
+ </div>
2131
+ </div>
2132
+ <% end %>
2133
+ <% end %>
2134
+ CODE
2135
+ end
2136
+
2137
+ # Popover component helpers
2138
+ def popover_usage_code
2139
+ <<~'CODE'
2140
+ <%= render M9sh::PopoverComponent.new do |popover| %>
2141
+ <% popover.with_trigger do %>
2142
+ <%= render M9sh::ButtonComponent.new(variant: :outline) do %>
2143
+ Open Popover
2144
+ <% end %>
2145
+ <% end %>
2146
+ <% popover.with_popover_content do %>
2147
+ <p class="text-sm">Popover content goes here.</p>
2148
+ <% end %>
2149
+ <% end %>
2150
+ CODE
2151
+ end
2152
+
2153
+ def popover_with_form_code
2154
+ <<~'CODE'
2155
+ <%= render M9sh::PopoverComponent.new do |popover| %>
2156
+ <% popover.with_trigger do %>
2157
+ <%= render M9sh::ButtonComponent.new(variant: :outline) do %>
2158
+ Settings
2159
+ <% end %>
2160
+ <% end %>
2161
+ <% popover.with_popover_content do %>
2162
+ <div class="space-y-4">
2163
+ <h4 class="font-medium text-sm">Dimensions</h4>
2164
+ <div class="space-y-2">
2165
+ <%= render M9sh::LabelComponent.new(for_id: "width") do %>
2166
+ Width
2167
+ <% end %>
2168
+ <%= render M9sh::InputComponent.new(
2169
+ id: "width",
2170
+ type: "number",
2171
+ placeholder: "100"
2172
+ ) %>
2173
+ </div>
2174
+ <div class="space-y-2">
2175
+ <%= render M9sh::LabelComponent.new(for_id: "height") do %>
2176
+ Height
2177
+ <% end %>
2178
+ <%= render M9sh::InputComponent.new(
2179
+ id: "height",
2180
+ type: "number",
2181
+ placeholder: "100"
2182
+ ) %>
2183
+ </div>
2184
+ <%= render M9sh::ButtonComponent.new(class: "w-full") do %>
2185
+ Save
2186
+ <% end %>
2187
+ </div>
2188
+ <% end %>
2189
+ <% end %>
2190
+ CODE
2191
+ end
2192
+
2193
+ def popover_rich_content_code
2194
+ <<~'CODE'
2195
+ <%= render M9sh::PopoverComponent.new do |popover| %>
2196
+ <% popover.with_trigger do %>
2197
+ <%= render M9sh::ButtonComponent.new(variant: :outline) do %>
2198
+ User Info
2199
+ <% end %>
2200
+ <% end %>
2201
+ <% popover.with_popover_content do %>
2202
+ <div class="space-y-3">
2203
+ <div class="flex items-center gap-3">
2204
+ <div class="w-12 h-12 rounded-full bg-primary/10 flex items-center justify-center font-semibold text-primary">
2205
+ JD
2206
+ </div>
2207
+ <div>
2208
+ <h4 class="font-semibold text-sm">John Doe</h4>
2209
+ <p class="text-xs text-muted-foreground">john@example.com</p>
2210
+ </div>
2211
+ </div>
2212
+ <div class="border-t pt-3">
2213
+ <p class="text-xs text-muted-foreground mb-2">Bio</p>
2214
+ <p class="text-sm">Software developer passionate about building great user experiences.</p>
2215
+ </div>
2216
+ <div class="flex gap-2 pt-2">
2217
+ <%= render M9sh::ButtonComponent.new(variant: :outline, size: :sm, class: "flex-1") do %>
2218
+ View Profile
2219
+ <% end %>
2220
+ <%= render M9sh::ButtonComponent.new(size: :sm, class: "flex-1") do %>
2221
+ Message
2222
+ <% end %>
2223
+ </div>
2224
+ </div>
2225
+ <% end %>
2226
+ <% end %>
2227
+ CODE
2228
+ end
2229
+
2230
+ # Toast component helpers
2231
+ def toast_usage_code
2232
+ <<~'CODE'
2233
+ <%= render M9sh::ToastComponent.new(
2234
+ title: "Notification",
2235
+ description: "Your changes have been saved."
2236
+ ) %>
2237
+ CODE
2238
+ end
2239
+
2240
+ def toast_variants_code
2241
+ <<~'CODE'
2242
+ <%= render M9sh::ToastComponent.new(
2243
+ title: "Default",
2244
+ description: "This is a default toast.",
2245
+ variant: :default
2246
+ ) %>
2247
+
2248
+ <%= render M9sh::ToastComponent.new(
2249
+ title: "Success",
2250
+ description: "Your action was successful.",
2251
+ variant: :success
2252
+ ) %>
2253
+
2254
+ <%= render M9sh::ToastComponent.new(
2255
+ title: "Error",
2256
+ description: "An error occurred.",
2257
+ variant: :error
2258
+ ) %>
2259
+
2260
+ <%= render M9sh::ToastComponent.new(
2261
+ title: "Warning",
2262
+ description: "Please review your changes.",
2263
+ variant: :warning
2264
+ ) %>
2265
+
2266
+ <%= render M9sh::ToastComponent.new(
2267
+ title: "Info",
2268
+ description: "Here's some information.",
2269
+ variant: :info
2270
+ ) %>
2271
+ CODE
2272
+ end
2273
+
2274
+ def toast_default_code
2275
+ <<~'CODE'
2276
+ <%= render M9sh::ToastComponent.new(
2277
+ title: "Notification",
2278
+ description: "Your changes have been saved successfully."
2279
+ ) %>
2280
+ CODE
2281
+ end
2282
+
2283
+ def toast_success_code
2284
+ <<~'CODE'
2285
+ <%= render M9sh::ToastComponent.new(
2286
+ title: "Success",
2287
+ description: "Your profile has been updated.",
2288
+ variant: :success
2289
+ ) %>
2290
+ CODE
2291
+ end
2292
+
2293
+ def toast_error_code
2294
+ <<~'CODE'
2295
+ <%= render M9sh::ToastComponent.new(
2296
+ title: "Error",
2297
+ description: "Unable to save changes. Please try again.",
2298
+ variant: :error
2299
+ ) %>
2300
+ CODE
2301
+ end
2302
+
2303
+ def toast_warning_code
2304
+ <<~'CODE'
2305
+ <%= render M9sh::ToastComponent.new(
2306
+ title: "Warning",
2307
+ description: "Your session will expire in 5 minutes.",
2308
+ variant: :warning
2309
+ ) %>
2310
+ CODE
2311
+ end
2312
+
2313
+ def toast_title_only_code
2314
+ <<~'CODE'
2315
+ <%= render M9sh::ToastComponent.new(
2316
+ title: "Message sent successfully!",
2317
+ variant: :success
2318
+ ) %>
2319
+ CODE
2320
+ end
2321
+
2322
+ def toast_custom_duration_code
2323
+ <<~'CODE'
2324
+ <%= render M9sh::ToastComponent.new(
2325
+ title: "Quick notification",
2326
+ description: "This will disappear in 2 seconds.",
2327
+ duration: 2000
2328
+ ) %>
2329
+ CODE
2330
+ end
2331
+
2332
+ # Toaster component helpers
2333
+ def toaster_usage_code
2334
+ <<~'CODE'
2335
+ <%= render M9sh::ToasterComponent.new %>
2336
+ CODE
2337
+ end
2338
+
2339
+ def toaster_javascript_code
2340
+ <<~'CODE'
2341
+ // Dispatch a toast event
2342
+ window.dispatchEvent(new CustomEvent('hotcdn:toast', {
2343
+ detail: {
2344
+ title: 'Notification',
2345
+ description: 'Your changes have been saved.',
2346
+ variant: 'success',
2347
+ duration: 5000
2348
+ }
2349
+ }));
2350
+ CODE
2351
+ end
2352
+
2353
+ def toaster_example_code
2354
+ <<~'CODE'
2355
+ <!-- Add this to your layout -->
2356
+ <%= render M9sh::ToasterComponent.new %>
2357
+
2358
+ <!-- Then trigger toasts from JavaScript -->
2359
+ <button
2360
+ onclick="window.dispatchEvent(new CustomEvent('hotcdn:toast', {
2361
+ detail: {
2362
+ title: 'Success',
2363
+ description: 'Operation completed successfully.',
2364
+ variant: 'success'
2365
+ }
2366
+ }))"
2367
+ class="px-4 py-2 bg-primary text-primary-foreground rounded-md"
2368
+ >
2369
+ Show Toast
2370
+ </button>
2371
+ CODE
2372
+ end
2373
+
2374
+ def toaster_turbo_stream_code
2375
+ <<~'CODE'
2376
+ <!-- In your turbo stream template -->
2377
+ <%= turbo_stream.append "notifications" do %>
2378
+ <script>
2379
+ window.dispatchEvent(new CustomEvent('hotcdn:toast', {
2380
+ detail: {
2381
+ title: 'Record created',
2382
+ description: 'The record has been successfully created.',
2383
+ variant: 'success'
2384
+ }
2385
+ }));
2386
+ </script>
2387
+ <% end %>
2388
+ CODE
2389
+ end
2390
+
2391
+ # Dialog component helpers
2392
+ def dialog_usage_code
2393
+ <<~'CODE'
2394
+ <%= render M9sh::DialogComponent.new do |dialog| %>
2395
+ <% dialog.with_dialog_trigger do %>
2396
+ <%= render M9sh::ButtonComponent.new { "Open Dialog" } %>
2397
+ <% end %>
2398
+ <% dialog.with_dialog_content do |content| %>
2399
+ <% content.with_dialog_header do |header| %>
2400
+ <% header.with_dialog_title { "Dialog Title" } %>
2401
+ <% header.with_dialog_description { "Dialog description goes here." } %>
2402
+ <% end %>
2403
+ <p>Dialog content goes here.</p>
2404
+ <% end %>
2405
+ <% end %>
2406
+ CODE
2407
+ end
2408
+
2409
+ def dialog_default_code
2410
+ <<~'CODE'
2411
+ <%= render M9sh::DialogComponent.new do |dialog| %>
2412
+ <% dialog.with_dialog_trigger do %>
2413
+ <%= render M9sh::ButtonComponent.new { "Open Dialog" } %>
2414
+ <% end %>
2415
+ <% dialog.with_dialog_content do |content| %>
2416
+ <% content.with_dialog_header do |header| %>
2417
+ <% header.with_dialog_title { "Are you absolutely sure?" } %>
2418
+ <% header.with_dialog_description do %>
2419
+ This action cannot be undone. This will permanently delete your account
2420
+ and remove your data from our servers.
2421
+ <% end %>
2422
+ <% end %>
2423
+ <% end %>
2424
+ <% end %>
2425
+ CODE
2426
+ end
2427
+
2428
+ def dialog_with_header_code
2429
+ <<~'CODE'
2430
+ <%= render M9sh::DialogComponent.new do |dialog| %>
2431
+ <% dialog.with_dialog_trigger do %>
2432
+ <%= render M9sh::ButtonComponent.new(variant: :outline) { "Edit Profile" } %>
2433
+ <% end %>
2434
+ <% dialog.with_dialog_content do |content| %>
2435
+ <% content.with_dialog_header do |header| %>
2436
+ <% header.with_dialog_title { "Edit profile" } %>
2437
+ <% header.with_dialog_description do %>
2438
+ Make changes to your profile here. Click save when you're done.
2439
+ <% end %>
2440
+ <% end %>
2441
+ <div class="space-y-4">
2442
+ <div class="space-y-2">
2443
+ <%= render M9sh::LabelComponent.new(text: "Name") %>
2444
+ <%= render M9sh::InputComponent.new(type: "text", placeholder: "Pedro Duarte") %>
2445
+ </div>
2446
+ <div class="space-y-2">
2447
+ <%= render M9sh::LabelComponent.new(text: "Username") %>
2448
+ <%= render M9sh::InputComponent.new(type: "text", placeholder: "@peduarte") %>
2449
+ </div>
2450
+ </div>
2451
+ <% content.with_dialog_footer do %>
2452
+ <%= render M9sh::ButtonComponent.new(type: "submit") { "Save changes" } %>
2453
+ <% end %>
2454
+ <% end %>
2455
+ <% end %>
2456
+ CODE
2457
+ end
2458
+
2459
+ def dialog_with_footer_code
2460
+ <<~'CODE'
2461
+ <%= render M9sh::DialogComponent.new do |dialog| %>
2462
+ <% dialog.with_dialog_trigger do %>
2463
+ <%= render M9sh::ButtonComponent.new { "Open Dialog" } %>
2464
+ <% end %>
2465
+ <% dialog.with_dialog_content do |content| %>
2466
+ <% content.with_dialog_header do |header| %>
2467
+ <% header.with_dialog_title { "Confirm Action" } %>
2468
+ <% header.with_dialog_description do %>
2469
+ This is a dialog with a footer containing action buttons.
2470
+ <% end %>
2471
+ <% end %>
2472
+ <p class="text-sm">Are you sure you want to proceed with this action?</p>
2473
+ <% content.with_dialog_footer do %>
2474
+ <%= render M9sh::DialogCloseComponent.new(as_child: true) do %>
2475
+ <%= render M9sh::ButtonComponent.new(variant: :outline) { "Cancel" } %>
2476
+ <% end %>
2477
+ <%= render M9sh::ButtonComponent.new { "Continue" } %>
2478
+ <% end %>
2479
+ <% end %>
2480
+ <% end %>
2481
+ CODE
2482
+ end
2483
+
2484
+ def dialog_form_code
2485
+ <<~'CODE'
2486
+ <%= render M9sh::DialogComponent.new do |dialog| %>
2487
+ <% dialog.with_dialog_trigger do %>
2488
+ <%= render M9sh::ButtonComponent.new(variant: :outline) { "Share" } %>
2489
+ <% end %>
2490
+ <% dialog.with_dialog_content do |content| %>
2491
+ <% content.with_dialog_header do |header| %>
2492
+ <% header.with_dialog_title { "Share link" } %>
2493
+ <% header.with_dialog_description do %>
2494
+ Anyone who has this link will be able to view this.
2495
+ <% end %>
2496
+ <% end %>
2497
+ <div class="flex items-center space-x-2">
2498
+ <%= render M9sh::InputComponent.new(
2499
+ value: "https://ui.shadcn.com/docs/installation",
2500
+ readonly: true,
2501
+ class: "flex-1"
2502
+ ) %>
2503
+ <%= render M9sh::ButtonComponent.new(type: "button", variant: :secondary, size: :sm) { "Copy" } %>
2504
+ </div>
2505
+ <% content.with_dialog_footer do %>
2506
+ <%= render M9sh::DialogCloseComponent.new %>
2507
+ <% end %>
2508
+ <% end %>
2509
+ <% end %>
2510
+ CODE
2511
+ end
2512
+
2513
+ def dialog_scrollable_code
2514
+ <<~'CODE'
2515
+ <%= render M9sh::DialogComponent.new do |dialog| %>
2516
+ <% dialog.with_dialog_trigger do %>
2517
+ <%= render M9sh::ButtonComponent.new { "View Terms" } %>
2518
+ <% end %>
2519
+ <% dialog.with_dialog_content do |content| %>
2520
+ <% content.with_dialog_header do |header| %>
2521
+ <% header.with_dialog_title { "Terms and Conditions" } %>
2522
+ <% header.with_dialog_description do %>
2523
+ Please read and accept our terms and conditions.
2524
+ <% end %>
2525
+ <% end %>
2526
+ <div class="max-h-[300px] overflow-y-auto space-y-4">
2527
+ <p class="text-sm">Lorem ipsum dolor sit amet.</p>
2528
+ <p class="text-sm">Ut enim ad minim veniam.</p>
2529
+ <p class="text-sm">Duis aute irure dolor.</p>
2530
+ </div>
2531
+ <% content.with_dialog_footer do %>
2532
+ <%= render M9sh::DialogCloseComponent.new(as_child: true) do %>
2533
+ <%= render M9sh::ButtonComponent.new(variant: :outline) { "Decline" } %>
2534
+ <% end %>
2535
+ <%= render M9sh::ButtonComponent.new { "Accept" } %>
2536
+ <% end %>
2537
+ <% end %>
2538
+ <% end %>
2539
+ CODE
2540
+ end
2541
+
2542
+ # AlertDialog component helpers
2543
+ def alert_dialog_usage_code
2544
+ <<~'CODE'
2545
+ <%= render M9sh::AlertDialogComponent.new do |alert| %>
2546
+ <% alert.with_trigger do %>
2547
+ <%= render M9sh::ButtonComponent.new(variant: :outline) do %>
2548
+ Show Dialog
2549
+ <% end %>
2550
+ <% end %>
2551
+ <% alert.with_title do %>
2552
+ Are you sure?
2553
+ <% end %>
2554
+ <% alert.with_description do %>
2555
+ This action cannot be undone.
2556
+ <% end %>
2557
+ <% alert.with_footer do %>
2558
+ <%= render M9sh::ButtonComponent.new(variant: :outline) do %>
2559
+ Cancel
2560
+ <% end %>
2561
+ <%= render M9sh::ButtonComponent.new do %>
2562
+ Continue
2563
+ <% end %>
2564
+ <% end %>
2565
+ <% end %>
2566
+ CODE
2567
+ end
2568
+
2569
+ def alert_dialog_default_code
2570
+ <<~'CODE'
2571
+ <%= render M9sh::AlertDialogComponent.new do |alert| %>
2572
+ <% alert.with_trigger do %>
2573
+ <%= render M9sh::ButtonComponent.new(variant: :outline) do %>
2574
+ Show Dialog
2575
+ <% end %>
2576
+ <% end %>
2577
+ <% alert.with_title do %>
2578
+ Are you absolutely sure?
2579
+ <% end %>
2580
+ <% alert.with_description do %>
2581
+ This action cannot be undone. This will permanently delete your account
2582
+ and remove your data from our servers.
2583
+ <% end %>
2584
+ <% alert.with_footer do %>
2585
+ <%= render M9sh::ButtonComponent.new(variant: :outline) do %>
2586
+ Cancel
2587
+ <% end %>
2588
+ <%= render M9sh::ButtonComponent.new do %>
2589
+ Continue
2590
+ <% end %>
2591
+ <% end %>
2592
+ <% end %>
2593
+ CODE
2594
+ end
2595
+
2596
+ def alert_dialog_destructive_code
2597
+ <<~'CODE'
2598
+ <%= render M9sh::AlertDialogComponent.new do |alert| %>
2599
+ <% alert.with_trigger do %>
2600
+ <%= render M9sh::ButtonComponent.new(variant: :destructive) do %>
2601
+ Delete Account
2602
+ <% end %>
2603
+ <% end %>
2604
+ <% alert.with_title do %>
2605
+ Delete Account
2606
+ <% end %>
2607
+ <% alert.with_description do %>
2608
+ This action cannot be undone. This will permanently delete your account
2609
+ and all associated data.
2610
+ <% end %>
2611
+ <% alert.with_footer do %>
2612
+ <%= render M9sh::ButtonComponent.new(variant: :outline) do %>
2613
+ Cancel
2614
+ <% end %>
2615
+ <%= render M9sh::ButtonComponent.new(variant: :destructive) do %>
2616
+ Delete
2617
+ <% end %>
2618
+ <% end %>
2619
+ <% end %>
2620
+ CODE
2621
+ end
2622
+
2623
+ def alert_dialog_with_description_code
2624
+ <<~'CODE'
2625
+ <%= render M9sh::AlertDialogComponent.new do |alert| %>
2626
+ <% alert.with_trigger do %>
2627
+ <%= render M9sh::ButtonComponent.new do %>
2628
+ Continue
2629
+ <% end %>
2630
+ <% end %>
2631
+ <% alert.with_title do %>
2632
+ Confirm your action
2633
+ <% end %>
2634
+ <% alert.with_description do %>
2635
+ This will submit your form data. Please review your information before
2636
+ continuing. You can still go back and make changes if needed.
2637
+ <% end %>
2638
+ <% alert.with_footer do %>
2639
+ <%= render M9sh::ButtonComponent.new(variant: :outline) do %>
2640
+ Go Back
2641
+ <% end %>
2642
+ <%= render M9sh::ButtonComponent.new do %>
2643
+ Submit
2644
+ <% end %>
2645
+ <% end %>
2646
+ <% end %>
2647
+ CODE
2648
+ end
2649
+
2650
+ def typography_usage_code
2651
+ <<~'CODE'
2652
+ <%= render M9sh::TypographyComponent.new(variant: :h1) do %>
2653
+ Your Heading Here
2654
+ <% end %>
2655
+ CODE
2656
+ end
2657
+
2658
+ def typography_headings_code
2659
+ <<~'CODE'
2660
+ <%= render M9sh::TypographyComponent.new(variant: :h1) do %>
2661
+ Taxing Laughter: The Joke Tax Chronicles
2662
+ <% end %>
2663
+
2664
+ <%= render M9sh::TypographyComponent.new(variant: :h2) do %>
2665
+ The People of the Kingdom
2666
+ <% end %>
2667
+
2668
+ <%= render M9sh::TypographyComponent.new(variant: :h3) do %>
2669
+ The Joke Tax
2670
+ <% end %>
2671
+
2672
+ <%= render M9sh::TypographyComponent.new(variant: :h4) do %>
2673
+ People stopped telling jokes
2674
+ <% end %>
2675
+ CODE
2676
+ end
2677
+
2678
+ def typography_paragraph_code
2679
+ <<~'CODE'
2680
+ <%= render M9sh::TypographyComponent.new(variant: :p) do %>
2681
+ The king, seeing how much happier his subjects were, realized the error of his ways
2682
+ and repealed the joke tax.
2683
+ <% end %>
2684
+ CODE
2685
+ end
2686
+
2687
+ def typography_blockquote_code
2688
+ <<~'CODE'
2689
+ <%= render M9sh::TypographyComponent.new(variant: :blockquote) do %>
2690
+ "After all," he said, "everyone enjoys a good joke, so it's only fair that they should
2691
+ pay for the privilege."
2692
+ <% end %>
2693
+ CODE
2694
+ end
2695
+
2696
+ def typography_list_code
2697
+ <<~'CODE'
2698
+ <%= render M9sh::TypographyComponent.new(variant: :list) do %>
2699
+ <li>1st level of puns: 5 gold coins</li>
2700
+ <li>2nd level of jokes: 10 gold coins</li>
2701
+ <li>3rd level of one-liners: 20 gold coins</li>
2702
+ <% end %>
2703
+ CODE
2704
+ end
2705
+
2706
+ def typography_inline_code_code
2707
+ <<~'CODE'
2708
+ <%= render M9sh::TypographyComponent.new(variant: :inline_code) do %>
2709
+ @radix-ui/react-alert-dialog
2710
+ <% end %>
2711
+ CODE
2712
+ end
2713
+
2714
+ def typography_lead_code
2715
+ <<~'CODE'
2716
+ <%= render M9sh::TypographyComponent.new(variant: :lead) do %>
2717
+ A modal dialog that interrupts the user with important content and expects a response.
2718
+ <% end %>
2719
+ CODE
2720
+ end
2721
+
2722
+ def typography_variants_code
2723
+ <<~'CODE'
2724
+ <%= render M9sh::TypographyComponent.new(variant: :large) do %>
2725
+ Are you absolutely sure?
2726
+ <% end %>
2727
+
2728
+ <%= render M9sh::TypographyComponent.new(variant: :small) do %>
2729
+ Email address
2730
+ <% end %>
2731
+
2732
+ <%= render M9sh::TypographyComponent.new(variant: :muted) do %>
2733
+ Enter your email address.
2734
+ <% end %>
2735
+ CODE
2736
+ end
2737
+
2738
+ # Navigation Menu component helpers
2739
+ def navigation_menu_usage_code
2740
+ <<~'CODE'
2741
+ <%= render M9sh::NavigationMenuComponent.new do |nav| %>
2742
+ <% nav.with_item do |item| %>
2743
+ <% item.with_trigger do %>
2744
+ Components
2745
+ <% end %>
2746
+ <% item.with_menu_content do %>
2747
+ <!-- Menu content -->
2748
+ <% end %>
2749
+ <% end %>
2750
+ <% end %>
2751
+ CODE
2752
+ end
2753
+
2754
+ def navigation_menu_default_code
2755
+ <<~'CODE'
2756
+ <%= render M9sh::NavigationMenuComponent.new do |nav| %>
2757
+ <% nav.with_item do |item| %>
2758
+ <% item.with_trigger do %>
2759
+ Getting started
2760
+ <% end %>
2761
+ <% item.with_menu_content do %>
2762
+ <ul class="grid gap-3 p-4 md:w-[400px] lg:w-[500px] lg:grid-cols-[.75fr_1fr]">
2763
+ <li class="row-span-3">
2764
+ <div class="flex h-full w-full select-none flex-col justify-end rounded-md bg-gradient-to-b from-muted/50 to-muted p-6 no-underline outline-none focus:shadow-md">
2765
+ <div class="mb-2 mt-4 text-lg font-medium">
2766
+ shadcn/ui
2767
+ </div>
2768
+ <p class="text-sm leading-tight text-muted-foreground">
2769
+ Beautifully designed components built with Radix UI and Tailwind CSS.
2770
+ </p>
2771
+ </div>
2772
+ </li>
2773
+ <li>
2774
+ <a href="#" class="block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground">
2775
+ <div class="text-sm font-medium leading-none">Introduction</div>
2776
+ <p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
2777
+ Re-usable components built using Radix UI and Tailwind CSS.
2778
+ </p>
2779
+ </a>
2780
+ </li>
2781
+ <li>
2782
+ <a href="#" class="block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground">
2783
+ <div class="text-sm font-medium leading-none">Installation</div>
2784
+ <p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
2785
+ How to install dependencies and structure your app.
2786
+ </p>
2787
+ </a>
2788
+ </li>
2789
+ <li>
2790
+ <a href="#" class="block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground">
2791
+ <div class="text-sm font-medium leading-none">Typography</div>
2792
+ <p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
2793
+ Styles for headings, paragraphs, lists...etc
2794
+ </p>
2795
+ </a>
2796
+ </li>
2797
+ </ul>
2798
+ <% end %>
2799
+ <% end %>
2800
+
2801
+ <% nav.with_item do |item| %>
2802
+ <% item.with_trigger do %>
2803
+ Components
2804
+ <% end %>
2805
+ <% item.with_menu_content do %>
2806
+ <ul class="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px]">
2807
+ <li>
2808
+ <a href="#" class="block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground">
2809
+ <div class="text-sm font-medium leading-none">Alert Dialog</div>
2810
+ <p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
2811
+ A modal dialog that interrupts the user with important content.
2812
+ </p>
2813
+ </a>
2814
+ </li>
2815
+ <li>
2816
+ <a href="#" class="block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground">
2817
+ <div class="text-sm font-medium leading-none">Hover Card</div>
2818
+ <p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
2819
+ For sighted users to preview content available behind a link.
2820
+ </p>
2821
+ </a>
2822
+ </li>
2823
+ <li>
2824
+ <a href="#" class="block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground">
2825
+ <div class="text-sm font-medium leading-none">Progress</div>
2826
+ <p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
2827
+ Displays an indicator showing the completion progress.
2828
+ </p>
2829
+ </a>
2830
+ </li>
2831
+ <li>
2832
+ <a href="#" class="block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground">
2833
+ <div class="text-sm font-medium leading-none">Scroll-area</div>
2834
+ <p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
2835
+ Visually or semantically separates content.
2836
+ </p>
2837
+ </a>
2838
+ </li>
2839
+ <li>
2840
+ <a href="#" class="block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground">
2841
+ <div class="text-sm font-medium leading-none">Tabs</div>
2842
+ <p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
2843
+ A set of layered sections of content.
2844
+ </p>
2845
+ </a>
2846
+ </li>
2847
+ <li>
2848
+ <a href="#" class="block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground">
2849
+ <div class="text-sm font-medium leading-none">Tooltip</div>
2850
+ <p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
2851
+ A popup that displays information related to an element.
2852
+ </p>
2853
+ </a>
2854
+ </li>
2855
+ </ul>
2856
+ <% end %>
2857
+ <% end %>
2858
+ <% end %>
2859
+ CODE
2860
+ end
2861
+
2862
+ def navigation_menu_simple_links_code
2863
+ <<~'CODE'
2864
+ <%= render M9sh::NavigationMenuComponent.new do |nav| %>
2865
+ <% nav.with_item do |item| %>
2866
+ <% item.with_link(href: "#docs") do %>
2867
+ Documentation
2868
+ <% end %>
2869
+ <% end %>
2870
+
2871
+ <% nav.with_item do |item| %>
2872
+ <% item.with_link(href: "#components") do %>
2873
+ Components
2874
+ <% end %>
2875
+ <% end %>
2876
+
2877
+ <% nav.with_item do |item| %>
2878
+ <% item.with_link(href: "#examples") do %>
2879
+ Examples
2880
+ <% end %>
2881
+ <% end %>
2882
+ <% end %>
2883
+ CODE
2884
+ end
2885
+
2886
+ # Navbar component helpers
2887
+ def navbar_usage_code
2888
+ <<~'CODE'
2889
+ <%= render M9sh::NavbarComponent.new do |navbar| %>
2890
+ <% navbar.with_brand do %>
2891
+ <a href="/" class="font-bold text-xl">Brand</a>
2892
+ <% end %>
2893
+
2894
+ <% navbar.with_navigation do %>
2895
+ <nav class="flex items-center gap-6">
2896
+ <a href="#">Link 1</a>
2897
+ <a href="#">Link 2</a>
2898
+ </nav>
2899
+ <% end %>
2900
+
2901
+ <% navbar.with_actions do %>
2902
+ <%= render M9sh::ButtonComponent.new do %>
2903
+ Action
2904
+ <% end %>
2905
+ <% end %>
2906
+ <% end %>
2907
+ CODE
2908
+ end
2909
+
2910
+ def navbar_simple_code
2911
+ <<~'CODE'
2912
+ <%= render M9sh::NavbarComponent.new do |navbar| %>
2913
+ <% navbar.with_brand do %>
2914
+ <a href="/" class="flex items-center space-x-2">
2915
+ <span class="font-bold text-xl text-foreground">Brand</span>
2916
+ </a>
2917
+ <% end %>
2918
+
2919
+ <% navbar.with_navigation do %>
2920
+ <nav class="hidden md:flex items-center gap-6">
2921
+ <a href="#" class="text-sm font-medium text-foreground hover:text-foreground/80 transition-colors">Features</a>
2922
+ <a href="#" class="text-sm font-medium text-foreground hover:text-foreground/80 transition-colors">Pricing</a>
2923
+ <a href="#" class="text-sm font-medium text-foreground hover:text-foreground/80 transition-colors">About</a>
2924
+ <a href="#" class="text-sm font-medium text-foreground hover:text-foreground/80 transition-colors">Contact</a>
2925
+ </nav>
2926
+ <% end %>
2927
+
2928
+ <% navbar.with_actions do %>
2929
+ <%= render M9sh::ButtonComponent.new(variant: :ghost, size: :sm) do %>
2930
+ Sign In
2931
+ <% end %>
2932
+ <% end %>
2933
+
2934
+ <% navbar.with_actions do %>
2935
+ <%= render M9sh::ButtonComponent.new(size: :sm) do %>
2936
+ Sign Up
2937
+ <% end %>
2938
+ <% end %>
2939
+ <% end %>
2940
+ CODE
2941
+ end
2942
+
2943
+ def navbar_with_menu_code
2944
+ <<~'CODE'
2945
+ <%= render M9sh::NavbarComponent.new do |navbar| %>
2946
+ <% navbar.with_brand do %>
2947
+ <a href="/" class="flex items-center space-x-2">
2948
+ <span class="font-bold text-xl text-foreground">m9sh/ui</span>
2949
+ </a>
2950
+ <% end %>
2951
+
2952
+ <% navbar.with_navigation do %>
2953
+ <div class="hidden md:block">
2954
+ <%= render M9sh::NavigationMenuComponent.new do |nav| %>
2955
+ <% nav.with_item do |item| %>
2956
+ <% item.with_trigger do %>
2957
+ Products
2958
+ <% end %>
2959
+ <% item.with_menu_content do %>
2960
+ <ul class="grid gap-3 p-4 w-[400px]">
2961
+ <li>
2962
+ <a href="#" class="block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground">
2963
+ <div class="text-sm font-medium leading-none">Product 1</div>
2964
+ <p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
2965
+ Description of product 1
2966
+ </p>
2967
+ </a>
2968
+ </li>
2969
+ <li>
2970
+ <a href="#" class="block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground">
2971
+ <div class="text-sm font-medium leading-none">Product 2</div>
2972
+ <p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
2973
+ Description of product 2
2974
+ </p>
2975
+ </a>
2976
+ </li>
2977
+ </ul>
2978
+ <% end %>
2979
+ <% end %>
2980
+
2981
+ <% nav.with_item do |item| %>
2982
+ <% item.with_link(href: "#pricing") do %>
2983
+ Pricing
2984
+ <% end %>
2985
+ <% end %>
2986
+
2987
+ <% nav.with_item do |item| %>
2988
+ <% item.with_link(href: "#docs") do %>
2989
+ Docs
2990
+ <% end %>
2991
+ <% end %>
2992
+ <% end %>
2993
+ </div>
2994
+ <% end %>
2995
+
2996
+ <% navbar.with_actions do %>
2997
+ <%= render M9sh::ButtonComponent.new(variant: :outline, size: :sm) do %>
2998
+ Login
2999
+ <% end %>
3000
+ <% end %>
3001
+ <% end %>
3002
+ CODE
3003
+ end
3004
+
3005
+ def navbar_transparent_code
3006
+ <<~'CODE'
3007
+ <%= render M9sh::NavbarComponent.new(transparent: true) do |navbar| %>
3008
+ <% navbar.with_brand do %>
3009
+ <a href="/" class="flex items-center space-x-2">
3010
+ <span class="font-bold text-xl text-foreground">Brand</span>
3011
+ </a>
3012
+ <% end %>
3013
+
3014
+ <% navbar.with_navigation do %>
3015
+ <nav class="hidden md:flex items-center gap-6">
3016
+ <a href="#" class="text-sm font-medium text-foreground hover:text-foreground/80 transition-colors">Home</a>
3017
+ <a href="#" class="text-sm font-medium text-foreground hover:text-foreground/80 transition-colors">About</a>
3018
+ <a href="#" class="text-sm font-medium text-foreground hover:text-foreground/80 transition-colors">Services</a>
3019
+ </nav>
3020
+ <% end %>
3021
+
3022
+ <% navbar.with_actions do %>
3023
+ <%= render M9sh::ButtonComponent.new(variant: :ghost, size: :sm) do %>
3024
+ Get Started
3025
+ <% end %>
3026
+ <% end %>
3027
+ <% end %>
3028
+ CODE
3029
+ end
3030
+
3031
+ def navbar_full_width_code
3032
+ <<~'CODE'
3033
+ <%= render M9sh::NavbarComponent.new(container: false) do |navbar| %>
3034
+ <% navbar.with_brand do %>
3035
+ <a href="/" class="font-bold text-xl">Full Width</a>
3036
+ <% end %>
3037
+
3038
+ <% navbar.with_navigation do %>
3039
+ <nav class="flex items-center gap-6">
3040
+ <a href="#" class="text-sm font-medium">Features</a>
3041
+ <a href="#" class="text-sm font-medium">Docs</a>
3042
+ </nav>
3043
+ <% end %>
3044
+
3045
+ <% navbar.with_actions do %>
3046
+ <%= render M9sh::ButtonComponent.new(size: :sm) do %>
3047
+ Sign Up
3048
+ <% end %>
3049
+ <% end %>
3050
+ <% end %>
3051
+ CODE
3052
+ end
3053
+
3054
+ def navbar_sizes_code
3055
+ <<~'CODE'
3056
+ <!-- Small navbar -->
3057
+ <%= render M9sh::NavbarComponent.new(size: :sm) do |navbar| %>
3058
+ <% navbar.with_brand do %>
3059
+ <a href="/" class="font-bold">Small</a>
3060
+ <% end %>
3061
+ <% navbar.with_actions do %>
3062
+ <%= render M9sh::ButtonComponent.new(size: :sm) do %>
3063
+ Action
3064
+ <% end %>
3065
+ <% end %>
3066
+ <% end %>
3067
+
3068
+ <!-- Default navbar -->
3069
+ <%= render M9sh::NavbarComponent.new do |navbar| %>
3070
+ <% navbar.with_brand do %>
3071
+ <a href="/" class="font-bold text-xl">Default</a>
3072
+ <% end %>
3073
+ <% navbar.with_actions do %>
3074
+ <%= render M9sh::ButtonComponent.new(size: :sm) do %>
3075
+ Action
3076
+ <% end %>
3077
+ <% end %>
3078
+ <% end %>
3079
+
3080
+ <!-- Large navbar -->
3081
+ <%= render M9sh::NavbarComponent.new(size: :lg) do |navbar| %>
3082
+ <% navbar.with_brand do %>
3083
+ <a href="/" class="font-bold text-2xl">Large</a>
3084
+ <% end %>
3085
+ <% navbar.with_actions do %>
3086
+ <%= render M9sh::ButtonComponent.new do %>
3087
+ Action
3088
+ <% end %>
3089
+ <% end %>
3090
+ <% end %>
3091
+ CODE
3092
+ end
3093
+
3094
+ def navbar_blur_code
3095
+ <<~'CODE'
3096
+ <%= render M9sh::NavbarComponent.new(blur: true) do |navbar| %>
3097
+ <% navbar.with_brand do %>
3098
+ <a href="/" class="font-bold text-xl">Blur Effect</a>
3099
+ <% end %>
3100
+
3101
+ <% navbar.with_navigation do %>
3102
+ <nav class="flex items-center gap-6">
3103
+ <a href="#" class="text-sm font-medium">Home</a>
3104
+ <a href="#" class="text-sm font-medium">Products</a>
3105
+ </nav>
3106
+ <% end %>
3107
+
3108
+ <% navbar.with_actions do %>
3109
+ <%= render M9sh::ButtonComponent.new(variant: :outline, size: :sm) do %>
3110
+ Contact
3111
+ <% end %>
3112
+ <% end %>
3113
+ <% end %>
3114
+ CODE
3115
+ end
3116
+
3117
+ def navbar_no_border_code
3118
+ <<~'CODE'
3119
+ <%= render M9sh::NavbarComponent.new(border: false) do |navbar| %>
3120
+ <% navbar.with_brand do %>
3121
+ <a href="/" class="font-bold text-xl">No Border</a>
3122
+ <% end %>
3123
+
3124
+ <% navbar.with_navigation do %>
3125
+ <nav class="flex items-center gap-4">
3126
+ <a href="#" class="text-sm">Link 1</a>
3127
+ <a href="#" class="text-sm">Link 2</a>
3128
+ </nav>
3129
+ <% end %>
3130
+ <% end %>
3131
+ CODE
3132
+ end
3133
+
3134
+ def navbar_combined_options_code
3135
+ <<~'CODE'
3136
+ <%= render M9sh::NavbarComponent.new(
3137
+ sticky: true,
3138
+ transparent: true,
3139
+ container: false,
3140
+ size: :lg,
3141
+ border: false
3142
+ ) do |navbar| %>
3143
+ <% navbar.with_brand do %>
3144
+ <a href="/" class="flex items-center space-x-2">
3145
+ <span class="font-bold text-2xl">Custom</span>
3146
+ </a>
3147
+ <% end %>
3148
+
3149
+ <% navbar.with_navigation do %>
3150
+ <nav class="flex items-center gap-6">
3151
+ <a href="#" class="text-sm font-medium hover:text-primary transition-colors">Home</a>
3152
+ <a href="#" class="text-sm font-medium hover:text-primary transition-colors">Features</a>
3153
+ <a href="#" class="text-sm font-medium hover:text-primary transition-colors">Pricing</a>
3154
+ <a href="#" class="text-sm font-medium hover:text-primary transition-colors">Contact</a>
3155
+ </nav>
3156
+ <% end %>
3157
+
3158
+ <% navbar.with_actions do %>
3159
+ <%= render M9sh::ButtonComponent.new(variant: :ghost) do %>
3160
+ Login
3161
+ <% end %>
3162
+ <% end %>
3163
+
3164
+ <% navbar.with_actions do %>
3165
+ <%= render M9sh::ButtonComponent.new do %>
3166
+ Get Started
3167
+ <% end %>
3168
+ <% end %>
3169
+ <% end %>
3170
+ CODE
3171
+ end
3172
+
3173
+ def navbar_mobile_menu_code
3174
+ <<~'CODE'
3175
+ <%= render M9sh::NavbarComponent.new do |navbar| %>
3176
+ <% navbar.with_brand do %>
3177
+ <a href="/" class="font-bold text-xl">Brand</a>
3178
+ <% end %>
3179
+
3180
+ <% navbar.with_navigation do %>
3181
+ <nav class="flex items-center gap-6">
3182
+ <a href="#" class="text-sm font-medium">Home</a>
3183
+ <a href="#" class="text-sm font-medium">About</a>
3184
+ <a href="#" class="text-sm font-medium">Services</a>
3185
+ </nav>
3186
+ <% end %>
3187
+
3188
+ <% navbar.with_actions do %>
3189
+ <%= render M9sh::ButtonComponent.new(variant: :ghost, size: :sm) do %>
3190
+ Login
3191
+ <% end %>
3192
+ <% end %>
3193
+
3194
+ <% navbar.with_actions do %>
3195
+ <%= render M9sh::ButtonComponent.new(size: :sm) do %>
3196
+ Sign Up
3197
+ <% end %>
3198
+ <% end %>
3199
+
3200
+ <% navbar.with_mobile_menu do %>
3201
+ <%= render M9sh::DropdownMenuItemComponent.new(href: "#") do %>
3202
+ Home
3203
+ <% end %>
3204
+ <%= render M9sh::DropdownMenuItemComponent.new(href: "#") do %>
3205
+ About
3206
+ <% end %>
3207
+ <%= render M9sh::DropdownMenuItemComponent.new(href: "#") do %>
3208
+ Services
3209
+ <% end %>
3210
+ <%= render M9sh::DropdownMenuSeparatorComponent.new %>
3211
+ <%= render M9sh::DropdownMenuItemComponent.new(href: "#") do %>
3212
+ Login
3213
+ <% end %>
3214
+ <%= render M9sh::DropdownMenuItemComponent.new(href: "#") do %>
3215
+ Sign Up
3216
+ <% end %>
3217
+ <% end %>
3218
+ <% end %>
3219
+ CODE
3220
+ end
3221
+
3222
+ # Spinner component helpers
3223
+ def spinner_usage_code
3224
+ <<~'CODE'
3225
+ <%= render M9sh::SpinnerComponent.new %>
3226
+ CODE
3227
+ end
3228
+
3229
+ def spinner_sizes_code
3230
+ <<~'CODE'
3231
+ <%= render M9sh::SpinnerComponent.new(size: :sm) %>
3232
+ <%= render M9sh::SpinnerComponent.new %>
3233
+ <%= render M9sh::SpinnerComponent.new(size: :md) %>
3234
+ <%= render M9sh::SpinnerComponent.new(size: :lg) %>
3235
+ CODE
3236
+ end
3237
+
3238
+ def spinner_colors_code
3239
+ <<~'CODE'
3240
+ <%= render M9sh::SpinnerComponent.new(class: "text-primary") %>
3241
+ <%= render M9sh::SpinnerComponent.new(class: "text-destructive") %>
3242
+ <%= render M9sh::SpinnerComponent.new(class: "text-green-500") %>
3243
+ <%= render M9sh::SpinnerComponent.new(class: "text-blue-500") %>
3244
+ CODE
3245
+ end
3246
+
3247
+ def spinner_button_code
3248
+ <<~'CODE'
3249
+ <%= render M9sh::ButtonComponent.new(disabled: true) do %>
3250
+ <div class="flex items-center gap-2">
3251
+ <%= render M9sh::SpinnerComponent.new(size: :sm) %>
3252
+ <span>Please wait</span>
3253
+ </div>
3254
+ <% end %>
3255
+ CODE
3256
+ end
3257
+
3258
+ # Sidebar
3259
+ def sidebar_usage_code
3260
+ <<~'CODE'
3261
+ <%= render M9sh::SidebarProviderComponent.new do %>
3262
+ <%= render M9sh::SidebarComponent.new do |sidebar| %>
3263
+ <% sidebar.with_sidebar_content do %>
3264
+ <%= render M9sh::SidebarGroupComponent.new do |group| %>
3265
+ <% group.with_group_content do %>
3266
+ <%= render M9sh::SidebarMenuComponent.new do %>
3267
+ <%= render M9sh::SidebarMenuItemComponent.new do %>
3268
+ <%= render M9sh::SidebarMenuButtonComponent.new(href: "#") do %>
3269
+ Home
3270
+ <% end %>
3271
+ <% end %>
3272
+ <% end %>
3273
+ <% end %>
3274
+ <% end %>
3275
+ <% end %>
3276
+ <% end %>
3277
+ <%= render M9sh::SidebarInsetComponent.new do %>
3278
+ <header>
3279
+ <%= render M9sh::SidebarTriggerComponent.new %>
3280
+ </header>
3281
+ <div class="p-4">
3282
+ Main content
3283
+ </div>
3284
+ <% end %>
3285
+ <% end %>
3286
+ CODE
3287
+ end
3288
+
3289
+ def sidebar_with_header_code
3290
+ <<~'CODE'
3291
+ <%= render M9sh::SidebarComponent.new do |sidebar| %>
3292
+ <% sidebar.with_header do %>
3293
+ <h2 class="font-bold text-lg">My App</h2>
3294
+ <% end %>
3295
+ <% sidebar.with_sidebar_content do %>
3296
+ Navigation items...
3297
+ <% end %>
3298
+ <% end %>
3299
+ CODE
3300
+ end
3301
+
3302
+ def sidebar_with_groups_code
3303
+ <<~'CODE'
3304
+ <%= render M9sh::SidebarComponent.new do |sidebar| %>
3305
+ <% sidebar.with_sidebar_content do %>
3306
+ <%= render M9sh::SidebarGroupComponent.new do |group| %>
3307
+ <% group.with_label do %>
3308
+ Application
3309
+ <% end %>
3310
+ <% group.with_group_content do %>
3311
+ <%= render M9sh::SidebarMenuComponent.new do %>
3312
+ <%= render M9sh::SidebarMenuItemComponent.new do %>
3313
+ <%= render M9sh::SidebarMenuButtonComponent.new(href: "#", active: true) do %>
3314
+ Dashboard
3315
+ <% end %>
3316
+ <% end %>
3317
+ <%= render M9sh::SidebarMenuItemComponent.new do %>
3318
+ <%= render M9sh::SidebarMenuButtonComponent.new(href: "#") do %>
3319
+ Settings
3320
+ <% end %>
3321
+ <% end %>
3322
+ <% end %>
3323
+ <% end %>
3324
+ <% end %>
3325
+ <% end %>
3326
+ <% end %>
3327
+ CODE
3328
+ end
3329
+
3330
+ def sidebar_collapsible_code
3331
+ <<~'CODE'
3332
+ <%= render M9sh::SidebarComponent.new(collapsible: :icon) do |sidebar| %>
3333
+ <% sidebar.with_sidebar_content do %>
3334
+ Navigation items...
3335
+ <% end %>
3336
+ <% end %>
3337
+ CODE
3338
+ end
3339
+
3340
+ def sidebar_app_code
3341
+ <<~'CODE'
3342
+ <%= render M9sh::SidebarProviderComponent.new do %>
3343
+ <%= render M9sh::SidebarComponent.new(collapsible: :none) do |sidebar| %>
3344
+ <% sidebar.with_header do %>
3345
+ <div class="flex items-center gap-2 px-2 py-2">
3346
+ <div class="h-8 w-8 rounded-lg bg-sidebar-primary text-sidebar-primary-foreground flex items-center justify-center font-semibold text-sm">
3347
+ A
3348
+ </div>
3349
+ <span class="text-sm font-semibold">Acme Inc.</span>
3350
+ </div>
3351
+ <% end %>
3352
+ <% sidebar.with_sidebar_content do %>
3353
+ <div class="px-3 py-2">
3354
+ <%= render M9sh::ButtonComponent.new(variant: :default, class: "w-full justify-start gap-2 rounded-lg shadow-sm") do %>
3355
+ Quick Create
3356
+ <% end %>
3357
+ </div>
3358
+ <!-- Navigation groups -->
3359
+ <% end %>
3360
+ <% sidebar.with_footer do %>
3361
+ <div class="border-t border-sidebar-border px-1 py-3">
3362
+ <!-- Footer content -->
3363
+ </div>
3364
+ <% end %>
3365
+ <% end %>
3366
+ <%= render M9sh::SidebarInsetComponent.new do %>
3367
+ <header class="flex h-16 items-center gap-2 border-b px-4">
3368
+ <%= render M9sh::SidebarTriggerComponent.new %>
3369
+ <h1 class="text-lg font-semibold">Documents</h1>
3370
+ </header>
3371
+ <div class="flex-1 p-6">
3372
+ <div class="rounded-xl border border-border bg-card p-6 shadow-sm">
3373
+ Main content
3374
+ </div>
3375
+ </div>
3376
+ <% end %>
3377
+ <% end %>
3378
+ CODE
3379
+ end
3380
+ end
3381
+
3382
+ # Tooltip component helpers
3383
+ def tooltip_usage_code
3384
+ <<~'CODE'
3385
+ <%= render M9sh::TooltipComponent.new do |tooltip| %>
3386
+ <% tooltip.with_trigger do %>
3387
+ Hover me
3388
+ <% end %>
3389
+ <% tooltip.with_tooltip_content do %>
3390
+ Tooltip content
3391
+ <% end %>
3392
+ <% end %>
3393
+ CODE
3394
+ end
3395
+
3396
+ def tooltip_default_code
3397
+ <<~'CODE'
3398
+ <%= render M9sh::TooltipComponent.new do |tooltip| %>
3399
+ <% tooltip.with_trigger do %>
3400
+ <button class="px-4 py-2 rounded-md border">Hover me</button>
3401
+ <% end %>
3402
+ <% tooltip.with_tooltip_content do %>
3403
+ This is a tooltip
3404
+ <% end %>
3405
+ <% end %>
3406
+ CODE
3407
+ end
3408
+
3409
+ def tooltip_positions_code
3410
+ <<~'CODE'
3411
+ <%= render M9sh::TooltipComponent.new(side: "top") do |tooltip| %>
3412
+ <% tooltip.with_trigger do %>
3413
+ <button class="px-4 py-2 rounded-md border">Top</button>
3414
+ <% end %>
3415
+ <% tooltip.with_tooltip_content do %>
3416
+ Tooltip on top
3417
+ <% end %>
3418
+ <% end %>
3419
+
3420
+ <%= render M9sh::TooltipComponent.new(side: "right") do |tooltip| %>
3421
+ <% tooltip.with_trigger do %>
3422
+ <button class="px-4 py-2 rounded-md border">Right</button>
3423
+ <% end %>
3424
+ <% tooltip.with_tooltip_content do %>
3425
+ Tooltip on right
3426
+ <% end %>
3427
+ <% end %>
3428
+
3429
+ <%= render M9sh::TooltipComponent.new(side: "bottom") do |tooltip| %>
3430
+ <% tooltip.with_trigger do %>
3431
+ <button class="px-4 py-2 rounded-md border">Bottom</button>
3432
+ <% end %>
3433
+ <% tooltip.with_tooltip_content do %>
3434
+ Tooltip on bottom
3435
+ <% end %>
3436
+ <% end %>
3437
+
3438
+ <%= render M9sh::TooltipComponent.new(side: "left") do |tooltip| %>
3439
+ <% tooltip.with_trigger do %>
3440
+ <button class="px-4 py-2 rounded-md border">Left</button>
3441
+ <% end %>
3442
+ <% tooltip.with_tooltip_content do %>
3443
+ Tooltip on left
3444
+ <% end %>
3445
+ <% end %>
3446
+ CODE
3447
+ end
3448
+
3449
+ def tooltip_rich_content_code
3450
+ <<~'CODE'
3451
+ <%= render M9sh::TooltipComponent.new do |tooltip| %>
3452
+ <% tooltip.with_trigger do %>
3453
+ <button class="px-4 py-2 rounded-md border">Hover for info</button>
3454
+ <% end %>
3455
+ <% tooltip.with_tooltip_content do %>
3456
+ <div class="space-y-1">
3457
+ <p class="font-semibold">Pro Tip</p>
3458
+ <p class="text-xs">You can use rich content in tooltips</p>
3459
+ </div>
3460
+ <% end %>
3461
+ <% end %>
3462
+ CODE
3463
+ end
3464
+
3465
+ # HoverCard component helpers
3466
+ def hover_card_usage_code
3467
+ <<~'CODE'
3468
+ <%= render M9sh::HoverCardComponent.new do |card| %>
3469
+ <% card.with_trigger do %>
3470
+ Hover me
3471
+ <% end %>
3472
+ <% card.with_hover_content do %>
3473
+ Hover card content
3474
+ <% end %>
3475
+ <% end %>
3476
+ CODE
3477
+ end
3478
+
3479
+ def hover_card_default_code
3480
+ <<~'CODE'
3481
+ <%= render M9sh::HoverCardComponent.new do |card| %>
3482
+ <% card.with_trigger do %>
3483
+ <span class="underline cursor-pointer">@username</span>
3484
+ <% end %>
3485
+ <% card.with_hover_content do %>
3486
+ <div class="space-y-2">
3487
+ <h4 class="text-sm font-semibold">@username</h4>
3488
+ <p class="text-sm text-muted-foreground">
3489
+ The hover card component is a rich preview that appears when hovering over a trigger element.
3490
+ </p>
3491
+ </div>
3492
+ <% end %>
3493
+ <% end %>
3494
+ CODE
3495
+ end
3496
+
3497
+ def hover_card_with_avatar_code
3498
+ <<~'CODE'
3499
+ <%= render M9sh::HoverCardComponent.new do |card| %>
3500
+ <% card.with_trigger do %>
3501
+ <span class="underline cursor-pointer">@nextjs</span>
3502
+ <% end %>
3503
+ <% card.with_hover_content do %>
3504
+ <div class="flex gap-4">
3505
+ <%= render M9sh::AvatarComponent.new(
3506
+ src: "https://github.com/vercel.png",
3507
+ fallback: "VC"
3508
+ ) %>
3509
+ <div class="space-y-1">
3510
+ <h4 class="text-sm font-semibold">@nextjs</h4>
3511
+ <p class="text-sm text-muted-foreground">
3512
+ The React Framework - created and maintained by @vercel.
3513
+ </p>
3514
+ <div class="flex items-center pt-2">
3515
+ <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="mr-1">
3516
+ <rect x="2" y="7" width="20" height="14" rx="2" ry="2"/>
3517
+ <path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"/>
3518
+ </svg>
3519
+ <span class="text-xs text-muted-foreground">Joined December 2021</span>
3520
+ </div>
3521
+ </div>
3522
+ </div>
3523
+ <% end %>
3524
+ <% end %>
3525
+ CODE
3526
+ end
3527
+
3528
+ def hover_card_complex_code
3529
+ <<~'CODE'
3530
+ <%= render M9sh::HoverCardComponent.new(open_delay: 300, close_delay: 400) do |card| %>
3531
+ <% card.with_trigger do %>
3532
+ <span class="underline cursor-pointer text-sm font-medium">View Details</span>
3533
+ <% end %>
3534
+ <% card.with_hover_content do %>
3535
+ <div class="space-y-3">
3536
+ <div>
3537
+ <h4 class="text-sm font-semibold mb-1">Product Information</h4>
3538
+ <p class="text-xs text-muted-foreground">
3539
+ Detailed information about the product.
3540
+ </p>
3541
+ </div>
3542
+ <div class="border-t pt-3 space-y-2">
3543
+ <div class="flex justify-between text-xs">
3544
+ <span class="text-muted-foreground">Price:</span>
3545
+ <span class="font-medium">$29.99</span>
3546
+ </div>
3547
+ </div>
3548
+ </div>
3549
+ <% end %>
3550
+ <% end %>
3551
+ CODE
3552
+ end
3553
+
3554
+ # DropdownMenu component helpers
3555
+ # Main component helpers
3556
+ def main_usage_code
3557
+ <<~'CODE'
3558
+ <%= render M9sh::MainComponent.new do %>
3559
+ <header class="flex h-14 shrink-0 items-center gap-2 px-4 border-b">
3560
+ <h1 class="text-base font-semibold">Page Title</h1>
3561
+ </header>
3562
+ <div class="flex-1 overflow-auto p-6">
3563
+ <p>Your content here</p>
3564
+ </div>
3565
+ <% end %>
3566
+ CODE
3567
+ end
3568
+
3569
+ def main_with_cards_code
3570
+ <<~'CODE'
3571
+ <%= render M9sh::MainComponent.new do %>
3572
+ <header class="flex h-14 shrink-0 items-center gap-2 px-4 border-b">
3573
+ <h1 class="text-base font-semibold">Dashboard</h1>
3574
+ </header>
3575
+ <div class="flex-1 overflow-auto p-6">
3576
+ <div class="space-y-6">
3577
+ <div class="rounded-3xl bg-card border border-border/50 p-8 shadow-xl">
3578
+ <h3 class="text-sm font-medium text-muted-foreground mb-3">Total Revenue</h3>
3579
+ <p class="text-4xl font-bold mb-2">$1,250.00</p>
3580
+ <p class="text-sm text-muted-foreground">+20.1% from last month</p>
3581
+ </div>
3582
+ </div>
3583
+ </div>
3584
+ <% end %>
3585
+ CODE
3586
+ end
3587
+
3588
+ def main_with_sidebar_code
3589
+ <<~'CODE'
3590
+ <%= render M9sh::SidebarProviderComponent.new(background: :sidebar) do %>
3591
+ <%= render M9sh::SidebarComponent.new(collapsible: :none, show_border: false) do |sidebar| %>
3592
+ <% sidebar.with_header do %>
3593
+ <div class="flex items-center gap-2">
3594
+ <span class="font-semibold">My App</span>
3595
+ </div>
3596
+ <% end %>
3597
+ <% sidebar.with_sidebar_content do %>
3598
+ <!-- Sidebar navigation -->
3599
+ <% end %>
3600
+ <% end %>
3601
+ <%= render M9sh::SidebarInsetComponent.new do %>
3602
+ <%= render M9sh::MainComponent.new do %>
3603
+ <header class="flex h-14 shrink-0 items-center gap-2 px-4 border-b">
3604
+ <h1 class="text-base font-semibold">Welcome</h1>
3605
+ </header>
3606
+ <div class="flex-1 overflow-auto p-6">
3607
+ <p>Main content area</p>
3608
+ </div>
3609
+ <% end %>
3610
+ <% end %>
3611
+ <% end %>
3612
+ CODE
3613
+ end
3614
+
3615
+ def main_with_navbar_code
3616
+ <<~'CODE'
3617
+ <div class="h-screen flex flex-col bg-sidebar">
3618
+ <!-- Top Navbar -->
3619
+ <header class="h-14 bg-sidebar flex items-center justify-between px-4">
3620
+ <div class="flex items-center gap-4">
3621
+ <div class="h-8 w-8 rounded-lg bg-sidebar-primary text-sidebar-primary-foreground flex items-center justify-center font-bold">
3622
+ A
3623
+ </div>
3624
+ <span class="text-base font-semibold text-sidebar-foreground">Acme Inc.</span>
3625
+ </div>
3626
+ <div class="flex items-center gap-2">
3627
+ <button class="p-2 rounded-lg hover:bg-sidebar-accent transition-colors">
3628
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
3629
+ <circle cx="11" cy="11" r="8"/>
3630
+ <path d="m21 21-4.35-4.35"/>
3631
+ </svg>
3632
+ </button>
3633
+ <button class="p-2 rounded-lg hover:bg-sidebar-accent transition-colors">
3634
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
3635
+ <path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/>
3636
+ <path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/>
3637
+ </svg>
3638
+ </button>
3639
+ <button class="p-2 rounded-lg hover:bg-sidebar-accent transition-colors">
3640
+ <img src="https://github.com/shadcn.png" alt="User" class="h-7 w-7 rounded-lg object-cover" />
3641
+ </button>
3642
+ </div>
3643
+ </header>
3644
+
3645
+ <!-- Content Area with Sidebar -->
3646
+ <div class="flex-1 flex overflow-hidden">
3647
+ <%= render M9sh::SidebarProviderComponent.new(background: :sidebar) do %>
3648
+ <%= render M9sh::SidebarComponent.new(collapsible: :none, show_border: false) do |sidebar| %>
3649
+ <% sidebar.with_sidebar_content do %>
3650
+ <div class="px-2 py-2">
3651
+ <div class="space-y-1">
3652
+ <a href="#" class="flex items-center gap-3 px-3 py-2 text-sm font-medium rounded-lg bg-sidebar-accent">
3653
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
3654
+ <rect width="7" height="9" x="3" y="3" rx="1"/>
3655
+ <rect width="7" height="5" x="14" y="3" rx="1"/>
3656
+ <rect width="7" height="9" x="14" y="12" rx="1"/>
3657
+ <rect width="7" height="5" x="3" y="16" rx="1"/>
3658
+ </svg>
3659
+ <span>Dashboard</span>
3660
+ </a>
3661
+ <!-- More navigation items -->
3662
+ </div>
3663
+ </div>
3664
+ <% end %>
3665
+ <% end %>
3666
+ <%= render M9sh::SidebarInsetComponent.new do %>
3667
+ <%= render M9sh::MainComponent.new do %>
3668
+ <header class="flex h-14 shrink-0 items-center gap-2 px-4 border-b">
3669
+ <h1 class="text-lg font-semibold">Dashboard Overview</h1>
3670
+ </header>
3671
+ <div class="flex-1 overflow-auto p-6">
3672
+ <!-- Your content here -->
3673
+ </div>
3674
+ <% end %>
3675
+ <% end %>
3676
+ <% end %>
3677
+ </div>
3678
+ </div>
3679
+ CODE
3680
+ end
3681
+
3682
+ def dropdown_menu_usage_code
3683
+ <<~'CODE'
3684
+ <%= render M9sh::DropdownMenuComponent.new do %>
3685
+ <%= render M9sh::DropdownMenuTriggerComponent.new do %>
3686
+ Open Menu
3687
+ <% end %>
3688
+ <%= render M9sh::DropdownMenuContentComponent.new do %>
3689
+ <%= render M9sh::DropdownMenuItemComponent.new do %>
3690
+ Menu Item
3691
+ <% end %>
3692
+ <% end %>
3693
+ <% end %>
3694
+ CODE
3695
+ end
3696
+
3697
+ def dropdown_menu_default_code
3698
+ <<~'CODE'
3699
+ <%= render M9sh::DropdownMenuComponent.new do %>
3700
+ <%= render M9sh::DropdownMenuTriggerComponent.new(class: "px-4 py-2 rounded-md border") do %>
3701
+ Open
3702
+ <% end %>
3703
+ <%= render M9sh::DropdownMenuContentComponent.new do %>
3704
+ <%= render M9sh::DropdownMenuItemComponent.new do %>
3705
+ Profile
3706
+ <% end %>
3707
+ <%= render M9sh::DropdownMenuItemComponent.new do %>
3708
+ Settings
3709
+ <% end %>
3710
+ <%= render M9sh::DropdownMenuSeparatorComponent.new %>
3711
+ <%= render M9sh::DropdownMenuItemComponent.new do %>
3712
+ Logout
3713
+ <% end %>
3714
+ <% end %>
3715
+ <% end %>
3716
+ CODE
3717
+ end
3718
+
3719
+ def dropdown_menu_with_icons_code
3720
+ <<~'CODE'
3721
+ <%= render M9sh::DropdownMenuComponent.new do %>
3722
+ <%= render M9sh::DropdownMenuTriggerComponent.new(class: "px-4 py-2 rounded-md border") do %>
3723
+ Open Menu
3724
+ <% end %>
3725
+ <%= render M9sh::DropdownMenuContentComponent.new do %>
3726
+ <%= render M9sh::DropdownMenuItemComponent.new do %>
3727
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="mr-2">
3728
+ <path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/>
3729
+ <circle cx="12" cy="7" r="4"/>
3730
+ </svg>
3731
+ Profile
3732
+ <% end %>
3733
+ <%= render M9sh::DropdownMenuItemComponent.new do %>
3734
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="mr-2">
3735
+ <path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/>
3736
+ <circle cx="12" cy="12" r="3"/>
3737
+ </svg>
3738
+ Settings
3739
+ <% end %>
3740
+ <%= render M9sh::DropdownMenuSeparatorComponent.new %>
3741
+ <%= render M9sh::DropdownMenuItemComponent.new do %>
3742
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="mr-2">
3743
+ <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/>
3744
+ <polyline points="16 17 21 12 16 7"/>
3745
+ <line x1="21" y1="12" x2="9" y2="12"/>
3746
+ </svg>
3747
+ Logout
3748
+ <% end %>
3749
+ <% end %>
3750
+ <% end %>
3751
+ CODE
3752
+ end
3753
+
3754
+ def dropdown_menu_with_separators_code
3755
+ <<~'CODE'
3756
+ <%= render M9sh::DropdownMenuComponent.new do %>
3757
+ <%= render M9sh::DropdownMenuTriggerComponent.new(class: "px-4 py-2 rounded-md border") do %>
3758
+ Options
3759
+ <% end %>
3760
+ <%= render M9sh::DropdownMenuContentComponent.new do %>
3761
+ <%= render M9sh::DropdownMenuItemComponent.new do %>
3762
+ New Tab
3763
+ <% end %>
3764
+ <%= render M9sh::DropdownMenuItemComponent.new do %>
3765
+ New Window
3766
+ <% end %>
3767
+ <%= render M9sh::DropdownMenuSeparatorComponent.new %>
3768
+ <%= render M9sh::DropdownMenuItemComponent.new do %>
3769
+ History
3770
+ <% end %>
3771
+ <%= render M9sh::DropdownMenuItemComponent.new do %>
3772
+ Downloads
3773
+ <% end %>
3774
+ <%= render M9sh::DropdownMenuSeparatorComponent.new %>
3775
+ <%= render M9sh::DropdownMenuItemComponent.new do %>
3776
+ Settings
3777
+ <% end %>
3778
+ <% end %>
3779
+ <% end %>
3780
+ CODE
3781
+ end
3782
+
3783
+ def dropdown_menu_alignment_code
3784
+ <<~'CODE'
3785
+ <%= render M9sh::DropdownMenuComponent.new(align: "start") do %>
3786
+ <%= render M9sh::DropdownMenuTriggerComponent.new(class: "px-4 py-2 rounded-md border") do %>
3787
+ Align Start
3788
+ <% end %>
3789
+ <%= render M9sh::DropdownMenuContentComponent.new do %>
3790
+ <%= render M9sh::DropdownMenuItemComponent.new do %>
3791
+ Item 1
3792
+ <% end %>
3793
+ <% end %>
3794
+ <% end %>
3795
+
3796
+ <%= render M9sh::DropdownMenuComponent.new(align: "end") do %>
3797
+ <%= render M9sh::DropdownMenuTriggerComponent.new(class: "px-4 py-2 rounded-md border") do %>
3798
+ Align End
3799
+ <% end %>
3800
+ <%= render M9sh::DropdownMenuContentComponent.new do %>
3801
+ <%= render M9sh::DropdownMenuItemComponent.new do %>
3802
+ Item 1
3803
+ <% end %>
3804
+ <% end %>
3805
+ <% end %>
3806
+ CODE
3807
+ end