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,232 @@
1
+ <%= render Docs::ComponentPageComponent.new(title: "Alert Dialog") do |page| %>
2
+ <% page.with_header(
3
+ name: "Alert Dialog",
4
+ description: "A modal dialog that interrupts the user with important content and expects a response. Similar to Dialog but specifically for alerts and confirmations."
5
+ ) %>
6
+
7
+ <% page.with_installation(component_name: "alert_dialog") %>
8
+
9
+ <% page.with_usage do %>
10
+ <%= render Docs::CodeBlockComponent.new(
11
+ code: alert_dialog_usage_code,
12
+ language: "erb"
13
+ ) %>
14
+ <% end %>
15
+
16
+ <% page.with_examples do %>
17
+ <!-- Default Confirmation Example -->
18
+ <% default_alert_dialog_html = capture do %>
19
+ <%= render M9sh::AlertDialogComponent.new do |alert| %>
20
+ <% alert.with_trigger do %>
21
+ <%= render M9sh::ButtonComponent.new(variant: :outline) do %>
22
+ Show Dialog
23
+ <% end %>
24
+ <% end %>
25
+ <% alert.with_title do %>
26
+ Are you absolutely sure?
27
+ <% end %>
28
+ <% alert.with_description do %>
29
+ This action cannot be undone. This will permanently delete your account
30
+ and remove your data from our servers.
31
+ <% end %>
32
+ <% alert.with_footer do %>
33
+ <%= render M9sh::ButtonComponent.new(variant: :outline, data: { action: "click->m9sh--alert-dialog#close" }) do %>
34
+ Cancel
35
+ <% end %>
36
+ <%= render M9sh::ButtonComponent.new(data: { action: "click->m9sh--alert-dialog#close" }) do %>
37
+ Continue
38
+ <% end %>
39
+ <% end %>
40
+ <% end %>
41
+ <% end %>
42
+
43
+ <%= render Docs::ComponentPreviewComponent.new(
44
+ title: "Default Confirmation",
45
+ preview_content: default_alert_dialog_html,
46
+ code: alert_dialog_default_code,
47
+ ai_command: alert_dialog_default_code
48
+ ) %>
49
+
50
+ <!-- Destructive Action Example -->
51
+ <% destructive_alert_dialog_html = capture do %>
52
+ <%= render M9sh::AlertDialogComponent.new do |alert| %>
53
+ <% alert.with_trigger do %>
54
+ <%= render M9sh::ButtonComponent.new(variant: :destructive) do %>
55
+ Delete Account
56
+ <% end %>
57
+ <% end %>
58
+ <% alert.with_title do %>
59
+ Delete Account
60
+ <% end %>
61
+ <% alert.with_description do %>
62
+ This action cannot be undone. This will permanently delete your account
63
+ and all associated data.
64
+ <% end %>
65
+ <% alert.with_footer do %>
66
+ <%= render M9sh::ButtonComponent.new(variant: :outline, data: { action: "click->m9sh--alert-dialog#close" }) do %>
67
+ Cancel
68
+ <% end %>
69
+ <%= render M9sh::ButtonComponent.new(variant: :destructive, data: { action: "click->m9sh--alert-dialog#close" }) do %>
70
+ Delete
71
+ <% end %>
72
+ <% end %>
73
+ <% end %>
74
+ <% end %>
75
+
76
+ <%= render Docs::ComponentPreviewComponent.new(
77
+ title: "Destructive Action",
78
+ preview_content: destructive_alert_dialog_html,
79
+ code: alert_dialog_destructive_code,
80
+ ai_command: alert_dialog_destructive_code
81
+ ) %>
82
+
83
+ <!-- With Description Example -->
84
+ <% with_description_alert_dialog_html = capture do %>
85
+ <%= render M9sh::AlertDialogComponent.new do |alert| %>
86
+ <% alert.with_trigger do %>
87
+ <%= render M9sh::ButtonComponent.new do %>
88
+ Continue
89
+ <% end %>
90
+ <% end %>
91
+ <% alert.with_title do %>
92
+ Confirm your action
93
+ <% end %>
94
+ <% alert.with_description do %>
95
+ This will submit your form data. Please review your information before
96
+ continuing. You can still go back and make changes if needed.
97
+ <% end %>
98
+ <% alert.with_footer do %>
99
+ <%= render M9sh::ButtonComponent.new(variant: :outline, data: { action: "click->m9sh--alert-dialog#close" }) do %>
100
+ Go Back
101
+ <% end %>
102
+ <%= render M9sh::ButtonComponent.new(data: { action: "click->m9sh--alert-dialog#close" }) do %>
103
+ Submit
104
+ <% end %>
105
+ <% end %>
106
+ <% end %>
107
+ <% end %>
108
+
109
+ <%= render Docs::ComponentPreviewComponent.new(
110
+ title: "With Description",
111
+ preview_content: with_description_alert_dialog_html,
112
+ code: alert_dialog_with_description_code,
113
+ ai_command: alert_dialog_with_description_code
114
+ ) %>
115
+
116
+ <!-- Custom Content Example -->
117
+ <% custom_content_alert_dialog_html = capture do %>
118
+ <%= render M9sh::AlertDialogComponent.new do |alert| %>
119
+ <% alert.with_trigger do %>
120
+ <%= render M9sh::ButtonComponent.new(variant: :outline) do %>
121
+ Delete Items
122
+ <% end %>
123
+ <% end %>
124
+ <% alert.with_title do %>
125
+ Delete Multiple Items
126
+ <% end %>
127
+ <% alert.with_description do %>
128
+ You are about to delete 5 items. This action cannot be undone.
129
+ <% end %>
130
+ <% alert.with_alert_content do %>
131
+ <div class="rounded-md border p-3 mt-4 space-y-2">
132
+ <p class="text-sm font-medium">Items to be deleted:</p>
133
+ <ul class="text-sm text-muted-foreground space-y-1">
134
+ <li>- Document.pdf</li>
135
+ <li>- Image.jpg</li>
136
+ <li>- Spreadsheet.xlsx</li>
137
+ <li>- Presentation.pptx</li>
138
+ <li>- Notes.txt</li>
139
+ </ul>
140
+ </div>
141
+ <% end %>
142
+ <% alert.with_footer do %>
143
+ <%= render M9sh::ButtonComponent.new(variant: :outline, data: { action: "click->m9sh--alert-dialog#close" }) do %>
144
+ Cancel
145
+ <% end %>
146
+ <%= render M9sh::ButtonComponent.new(variant: :destructive, data: { action: "click->m9sh--alert-dialog#close" }) do %>
147
+ Delete All
148
+ <% end %>
149
+ <% end %>
150
+ <% end %>
151
+ <% end %>
152
+
153
+ <%= render Docs::ComponentPreviewComponent.new(
154
+ title: "Custom Content",
155
+ preview_content: custom_content_alert_dialog_html,
156
+ code: nil,
157
+ ai_command: nil
158
+ ) %>
159
+ <% end %>
160
+
161
+ <% page.with_api do %>
162
+ <h3 class="text-lg font-semibold">Alert Dialog Slots</h3>
163
+ <%= render Docs::PropTableComponent.new(
164
+ props: [
165
+ {
166
+ name: "trigger",
167
+ type: "Slot",
168
+ default: nil,
169
+ description: "The element that triggers the alert dialog to open (usually a button)"
170
+ },
171
+ {
172
+ name: "title",
173
+ type: "Slot",
174
+ default: nil,
175
+ description: "The title/heading of the alert dialog"
176
+ },
177
+ {
178
+ name: "description",
179
+ type: "Slot",
180
+ default: nil,
181
+ description: "The description text that appears below the title"
182
+ },
183
+ {
184
+ name: "alert_content",
185
+ type: "Slot",
186
+ default: nil,
187
+ description: "Optional additional content to display in the body of the alert"
188
+ },
189
+ {
190
+ name: "footer",
191
+ type: "Slot",
192
+ default: nil,
193
+ description: "Footer content for action buttons (typically Cancel and Confirm)"
194
+ }
195
+ ]
196
+ ) %>
197
+
198
+ <div class="mt-6 space-y-2">
199
+ <h3 class="text-lg font-semibold">JavaScript Actions</h3>
200
+ <ul class="list-disc list-inside text-sm text-muted-foreground space-y-1">
201
+ <li><code>data-action="click->m9sh--alert-dialog#open"</code> - Opens the alert dialog</li>
202
+ <li><code>data-action="click->m9sh--alert-dialog#close"</code> - Closes the alert dialog</li>
203
+ <li>The alert dialog automatically closes when an action button is clicked</li>
204
+ <li>Unlike regular dialogs, clicking the overlay does not close the alert dialog (by design)</li>
205
+ </ul>
206
+ </div>
207
+
208
+ <div class="mt-6 space-y-2">
209
+ <h3 class="text-lg font-semibold">Differences from Dialog</h3>
210
+ <ul class="list-disc list-inside text-sm text-muted-foreground space-y-1">
211
+ <li>Alert Dialog is specifically for critical confirmations and alerts</li>
212
+ <li>Does not have a close button (X) - users must choose an action</li>
213
+ <li>Cannot be dismissed by clicking the backdrop</li>
214
+ <li>Uses <code>role="alertdialog"</code> for proper accessibility</li>
215
+ <li>Typically requires explicit user action before closing</li>
216
+ <li>Best used for destructive actions or important confirmations</li>
217
+ </ul>
218
+ </div>
219
+
220
+ <div class="mt-6 space-y-2">
221
+ <h3 class="text-lg font-semibold">Notes</h3>
222
+ <ul class="list-disc list-inside text-sm text-muted-foreground space-y-1">
223
+ <li>The alert dialog is centered on the screen with a dark overlay backdrop</li>
224
+ <li>Includes smooth animations for opening and closing</li>
225
+ <li>Automatically manages focus and accessibility with proper ARIA attributes</li>
226
+ <li>Always include at least two action buttons (e.g., Cancel and Confirm)</li>
227
+ <li>Use the destructive variant for delete or dangerous actions</li>
228
+ <li>The title and description help users understand the consequences of their action</li>
229
+ </ul>
230
+ </div>
231
+ <% end %>
232
+ <% end %>
@@ -0,0 +1,207 @@
1
+ <%= render Docs::ComponentPageComponent.new(title: "Avatar") do |page| %>
2
+ <% page.with_header(
3
+ name: "Avatar",
4
+ description: "Displays an image that represents a user or entity with fallback support for initials."
5
+ ) %>
6
+
7
+ <% page.with_installation(component_name: "avatar") %>
8
+
9
+ <% page.with_usage do %>
10
+ <%= render Docs::CodeBlockComponent.new(
11
+ code: avatar_usage_code,
12
+ language: "erb"
13
+ ) %>
14
+ <% end %>
15
+
16
+ <% page.with_examples do %>
17
+ <!-- Default Example with Image -->
18
+ <% default_avatar_html = capture do %>
19
+ <%= render M9sh::AvatarComponent.new(
20
+ src: "https://github.com/shadcn.png",
21
+ alt: "User Avatar"
22
+ ) %>
23
+ <% end %>
24
+
25
+ <%= render Docs::ComponentPreviewComponent.new(
26
+ title: "Default",
27
+ preview_content: default_avatar_html,
28
+ code: avatar_usage_code,
29
+ ai_command: avatar_usage_code
30
+ ) %>
31
+
32
+ <!-- With Fallback Initials -->
33
+ <% fallback_avatar_html = capture do %>
34
+ <%= render M9sh::AvatarComponent.new(
35
+ fallback: "JD"
36
+ ) %>
37
+ <% end %>
38
+
39
+ <%= render Docs::ComponentPreviewComponent.new(
40
+ title: "With Fallback Initials",
41
+ preview_content: fallback_avatar_html,
42
+ code: avatar_with_fallback_code,
43
+ ai_command: avatar_with_fallback_code
44
+ ) %>
45
+
46
+ <!-- Image with Fallback -->
47
+ <% image_with_fallback_html = capture do %>
48
+ <div class="flex items-center gap-4">
49
+ <%= render M9sh::AvatarComponent.new(
50
+ src: "https://github.com/shadcn.png",
51
+ alt: "User Avatar",
52
+ fallback: "CN"
53
+ ) %>
54
+ <%= render M9sh::AvatarComponent.new(
55
+ src: "https://invalid-image-url.png",
56
+ alt: "Invalid Avatar",
57
+ fallback: "AB"
58
+ ) %>
59
+ </div>
60
+ <% end %>
61
+
62
+ <%= render Docs::ComponentPreviewComponent.new(
63
+ title: "Image with Fallback",
64
+ preview_content: image_with_fallback_html,
65
+ code: avatar_with_fallback_example_code,
66
+ ai_command: avatar_with_fallback_example_code
67
+ ) %>
68
+
69
+ <!-- Different Sizes -->
70
+ <% sizes_avatar_html = capture do %>
71
+ <div class="flex items-center gap-4">
72
+ <%= render M9sh::AvatarComponent.new(
73
+ src: "https://github.com/shadcn.png",
74
+ alt: "Small Avatar",
75
+ size: :sm
76
+ ) %>
77
+ <%= render M9sh::AvatarComponent.new(
78
+ src: "https://github.com/shadcn.png",
79
+ alt: "Medium Avatar",
80
+ size: :md
81
+ ) %>
82
+ <%= render M9sh::AvatarComponent.new(
83
+ src: "https://github.com/shadcn.png",
84
+ alt: "Large Avatar",
85
+ size: :lg
86
+ ) %>
87
+ <%= render M9sh::AvatarComponent.new(
88
+ src: "https://github.com/shadcn.png",
89
+ alt: "Extra Large Avatar",
90
+ size: :xl
91
+ ) %>
92
+ </div>
93
+ <% end %>
94
+
95
+ <%= render Docs::ComponentPreviewComponent.new(
96
+ title: "Sizes",
97
+ preview_content: sizes_avatar_html,
98
+ code: avatar_sizes_code,
99
+ ai_command: avatar_sizes_code
100
+ ) %>
101
+
102
+ <!-- Fallback Sizes -->
103
+ <% fallback_sizes_html = capture do %>
104
+ <div class="flex items-center gap-4">
105
+ <%= render M9sh::AvatarComponent.new(
106
+ fallback: "SM",
107
+ size: :sm
108
+ ) %>
109
+ <%= render M9sh::AvatarComponent.new(
110
+ fallback: "MD",
111
+ size: :md
112
+ ) %>
113
+ <%= render M9sh::AvatarComponent.new(
114
+ fallback: "LG",
115
+ size: :lg
116
+ ) %>
117
+ <%= render M9sh::AvatarComponent.new(
118
+ fallback: "XL",
119
+ size: :xl
120
+ ) %>
121
+ </div>
122
+ <% end %>
123
+
124
+ <%= render Docs::ComponentPreviewComponent.new(
125
+ title: "Fallback Sizes",
126
+ preview_content: fallback_sizes_html,
127
+ code: avatar_fallback_sizes_code,
128
+ ai_command: avatar_fallback_sizes_code
129
+ ) %>
130
+
131
+ <!-- Multiple Avatars -->
132
+ <% multiple_avatars_html = capture do %>
133
+ <div class="flex -space-x-2">
134
+ <%= render M9sh::AvatarComponent.new(
135
+ src: "https://github.com/shadcn.png",
136
+ alt: "Avatar 1",
137
+ class: "border-2 border-background"
138
+ ) %>
139
+ <%= render M9sh::AvatarComponent.new(
140
+ fallback: "JD",
141
+ class: "border-2 border-background"
142
+ ) %>
143
+ <%= render M9sh::AvatarComponent.new(
144
+ fallback: "AB",
145
+ class: "border-2 border-background"
146
+ ) %>
147
+ <%= render M9sh::AvatarComponent.new(
148
+ fallback: "CD",
149
+ class: "border-2 border-background"
150
+ ) %>
151
+ <%= render M9sh::AvatarComponent.new(
152
+ fallback: "+3",
153
+ class: "border-2 border-background"
154
+ ) %>
155
+ </div>
156
+ <% end %>
157
+
158
+ <%= render Docs::ComponentPreviewComponent.new(
159
+ title: "Avatar Stack",
160
+ preview_content: multiple_avatars_html,
161
+ code: avatar_stack_code,
162
+ ai_command: avatar_stack_code
163
+ ) %>
164
+ <% end %>
165
+
166
+ <% page.with_api do %>
167
+ <%= render Docs::PropTableComponent.new(
168
+ props: [
169
+ {
170
+ name: "src",
171
+ type: "String",
172
+ default: "nil",
173
+ description: "The image source URL for the avatar"
174
+ },
175
+ {
176
+ name: "alt",
177
+ type: "String",
178
+ default: "nil",
179
+ description: "Alternative text for the avatar image"
180
+ },
181
+ {
182
+ name: "fallback",
183
+ type: "String",
184
+ default: "nil",
185
+ description: "Text to display when image is not available (typically initials)"
186
+ },
187
+ {
188
+ name: "size",
189
+ type: "Symbol",
190
+ default: ":md",
191
+ description: "Size of the avatar. Options: :sm (24px), :md (32px), :lg (40px), :xl (48px)"
192
+ }
193
+ ]
194
+ ) %>
195
+
196
+ <div class="mt-6 space-y-2">
197
+ <h3 class="text-lg font-semibold">Notes</h3>
198
+ <ul class="list-disc list-inside text-sm text-muted-foreground space-y-1">
199
+ <li>When both src and fallback are provided, the image will be displayed if it loads successfully, otherwise the fallback text will be shown</li>
200
+ <li>The avatar is always rendered as a circular element with rounded-full styling</li>
201
+ <li>The fallback background uses the muted color scheme for consistency</li>
202
+ <li>Images are automatically sized to fill the avatar container with proper aspect ratio</li>
203
+ <li>Use the class parameter to add custom styling like borders for avatar stacks</li>
204
+ </ul>
205
+ </div>
206
+ <% end %>
207
+ <% end %>
@@ -0,0 +1,145 @@
1
+ <%= render Docs::ComponentPageComponent.new(title: "Badge") do |page| %>
2
+ <% page.with_header(
3
+ name: "Badge",
4
+ description: "Displays a badge for labels, tags, and status indicators."
5
+ ) %>
6
+
7
+ <% page.with_installation(component_name: "badge") %>
8
+
9
+ <% page.with_usage do %>
10
+ <%= render Docs::CodeBlockComponent.new(
11
+ code: badge_usage_code,
12
+ language: "erb"
13
+ ) %>
14
+ <% end %>
15
+
16
+ <% page.with_examples do %>
17
+ <!-- Default Example -->
18
+ <% default_html = capture do %>
19
+ <%= render M9sh::BadgeComponent.new do %>
20
+ Badge
21
+ <% end %>
22
+ <% end %>
23
+
24
+ <%= render Docs::ComponentPreviewComponent.new(
25
+ title: "Default",
26
+ preview_content: default_html,
27
+ code: badge_usage_code,
28
+ ai_command: badge_usage_code
29
+ ) %>
30
+
31
+ <!-- Variants Example -->
32
+ <% variants_html = capture do %>
33
+ <div class="flex flex-wrap gap-2">
34
+ <%= render M9sh::BadgeComponent.new(variant: :default) do %>
35
+ Default
36
+ <% end %>
37
+ <%= render M9sh::BadgeComponent.new(variant: :secondary) do %>
38
+ Secondary
39
+ <% end %>
40
+ <%= render M9sh::BadgeComponent.new(variant: :destructive) do %>
41
+ Destructive
42
+ <% end %>
43
+ <%= render M9sh::BadgeComponent.new(variant: :outline) do %>
44
+ Outline
45
+ <% end %>
46
+ <%= render M9sh::BadgeComponent.new(variant: :success) do %>
47
+ Success
48
+ <% end %>
49
+ <%= render M9sh::BadgeComponent.new(variant: :warning) do %>
50
+ Warning
51
+ <% end %>
52
+ </div>
53
+ <% end %>
54
+
55
+ <%= render Docs::ComponentPreviewComponent.new(
56
+ title: "Variants",
57
+ preview_content: variants_html,
58
+ code: badge_variants_code,
59
+ ai_command: badge_variants_code
60
+ ) %>
61
+
62
+ <!-- Secondary Example -->
63
+ <% secondary_html = capture do %>
64
+ <%= render M9sh::BadgeComponent.new(variant: :secondary) do %>
65
+ Secondary
66
+ <% end %>
67
+ <% end %>
68
+
69
+ <%= render Docs::ComponentPreviewComponent.new(
70
+ title: "Secondary",
71
+ preview_content: secondary_html,
72
+ code: badge_secondary_code,
73
+ ai_command: badge_secondary_code
74
+ ) %>
75
+
76
+ <!-- Destructive Example -->
77
+ <% destructive_html = capture do %>
78
+ <%= render M9sh::BadgeComponent.new(variant: :destructive) do %>
79
+ Destructive
80
+ <% end %>
81
+ <% end %>
82
+
83
+ <%= render Docs::ComponentPreviewComponent.new(
84
+ title: "Destructive",
85
+ preview_content: destructive_html,
86
+ code: badge_destructive_code,
87
+ ai_command: badge_destructive_code
88
+ ) %>
89
+
90
+ <!-- Outline Example -->
91
+ <% outline_html = capture do %>
92
+ <%= render M9sh::BadgeComponent.new(variant: :outline) do %>
93
+ Outline
94
+ <% end %>
95
+ <% end %>
96
+
97
+ <%= render Docs::ComponentPreviewComponent.new(
98
+ title: "Outline",
99
+ preview_content: outline_html,
100
+ code: badge_outline_code,
101
+ ai_command: badge_outline_code
102
+ ) %>
103
+
104
+ <!-- Success Example -->
105
+ <% success_html = capture do %>
106
+ <%= render M9sh::BadgeComponent.new(variant: :success) do %>
107
+ Success
108
+ <% end %>
109
+ <% end %>
110
+
111
+ <%= render Docs::ComponentPreviewComponent.new(
112
+ title: "Success",
113
+ preview_content: success_html,
114
+ code: badge_success_code,
115
+ ai_command: badge_success_code
116
+ ) %>
117
+
118
+ <!-- Warning Example -->
119
+ <% warning_html = capture do %>
120
+ <%= render M9sh::BadgeComponent.new(variant: :warning) do %>
121
+ Warning
122
+ <% end %>
123
+ <% end %>
124
+
125
+ <%= render Docs::ComponentPreviewComponent.new(
126
+ title: "Warning",
127
+ preview_content: warning_html,
128
+ code: badge_warning_code,
129
+ ai_command: badge_warning_code
130
+ ) %>
131
+ <% end %>
132
+
133
+ <% page.with_api do %>
134
+ <%= render Docs::PropTableComponent.new(
135
+ props: [
136
+ {
137
+ name: "variant",
138
+ type: "Symbol",
139
+ default: ":default",
140
+ description: "The visual style variant. Options: :default, :secondary, :destructive, :outline, :success, :warning"
141
+ }
142
+ ]
143
+ ) %>
144
+ <% end %>
145
+ <% end %>