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.
- checksums.yaml +4 -4
- data/.idea/hotcdn.iml +30 -0
- data/.mise.toml +2 -2
- data/app/assets/config/manifest.js +4 -0
- data/app/assets/images/icons/activity.svg +3 -0
- data/app/assets/images/icons/bell.svg +4 -0
- data/app/assets/images/icons/book.svg +4 -0
- data/app/assets/images/icons/chevron-down.svg +3 -0
- data/app/assets/images/icons/chevron-left.svg +3 -0
- data/app/assets/images/icons/chevron-right.svg +3 -0
- data/app/assets/images/icons/credit-card.svg +4 -0
- data/app/assets/images/icons/dollar-sign.svg +3 -0
- data/app/assets/images/icons/edit.svg +4 -0
- data/app/assets/images/icons/github.svg +3 -0
- data/app/assets/images/icons/home.svg +4 -0
- data/app/assets/images/icons/info.svg +5 -0
- data/app/assets/images/icons/layout.svg +6 -0
- data/app/assets/images/icons/logout.svg +5 -0
- data/app/assets/images/icons/menu.svg +5 -0
- data/app/assets/images/icons/moon.svg +3 -0
- data/app/assets/images/icons/paintbrush.svg +6 -0
- data/app/assets/images/icons/search.svg +4 -0
- data/app/assets/images/icons/settings.svg +4 -0
- data/app/assets/images/icons/sun.svg +11 -0
- data/app/assets/images/icons/user.svg +4 -0
- data/app/assets/images/icons/users.svg +5 -0
- data/app/assets/stylesheets/tailwind.css +1180 -0
- data/app/components/backdrop_component.rb +103 -0
- data/app/components/docs/code_block_component.rb +56 -0
- data/app/components/docs/component_api_component.rb +16 -0
- data/app/components/docs/component_examples_component.rb +16 -0
- data/app/components/docs/component_header_component.html.erb +8 -0
- data/app/components/docs/component_header_component.rb +14 -0
- data/app/components/docs/component_installation_component.html.erb +15 -0
- data/app/components/docs/component_installation_component.rb +13 -0
- data/app/components/docs/component_page_component.html.erb +9 -0
- data/app/components/docs/component_page_component.rb +19 -0
- data/app/components/docs/component_preview_component.rb +318 -0
- data/app/components/docs/component_usage_component.rb +18 -0
- data/app/components/docs/prop_table_component.rb +64 -0
- data/app/controllers/application_controller.rb +3 -0
- data/app/controllers/blocks_controller.rb +51 -0
- data/app/controllers/docs_controller.rb +162 -0
- data/app/controllers/showcase_controller.rb +42 -0
- data/app/helpers/blocks_helper.rb +343 -0
- data/app/helpers/docs_helper.rb +3807 -0
- data/app/helpers/m9sh/toast_helper.rb +46 -0
- data/app/helpers/m9sh_helper.rb +343 -0
- data/app/javascript/application.js +3 -0
- data/app/javascript/controllers/application.js +9 -0
- data/app/javascript/controllers/backdrop_controller.js +137 -0
- data/app/javascript/controllers/color_customizer_controller.js +569 -0
- data/app/javascript/controllers/color_theme_controller.js +120 -0
- data/app/javascript/controllers/docs/component_preview_controller.js +149 -0
- data/app/javascript/controllers/docs/copy_button_controller.js +20 -0
- data/app/javascript/controllers/index.js +6 -0
- data/app/javascript/controllers/theme_controller.js +23 -0
- data/app/views/blocks/_sidebar.html.erb +31 -0
- data/app/views/blocks/_toc.html.erb +29 -0
- data/app/views/blocks/examples/dashboard-01.html.erb +180 -0
- data/app/views/blocks/examples/dashboard-02.html.erb +190 -0
- data/app/views/blocks/examples/dashboard-03.html.erb +210 -0
- data/app/views/blocks/examples/settings-01.html.erb +220 -0
- data/app/views/blocks/examples/settings-02.html.erb +231 -0
- data/app/views/blocks/examples/settings-03.html.erb +340 -0
- data/app/views/blocks/index.html.erb +65 -0
- data/app/views/docs/_sidebar.html.erb +47 -0
- data/app/views/docs/_toc.html.erb +19 -0
- data/app/views/docs/about.html.erb +68 -0
- data/app/views/docs/components/accordion.html.erb +196 -0
- data/app/views/docs/components/alert.html.erb +272 -0
- data/app/views/docs/components/alert_dialog.html.erb +232 -0
- data/app/views/docs/components/avatar.html.erb +207 -0
- data/app/views/docs/components/badge.html.erb +145 -0
- data/app/views/docs/components/breadcrumb.html.erb +264 -0
- data/app/views/docs/components/button.html.erb +229 -0
- data/app/views/docs/components/card.html.erb +378 -0
- data/app/views/docs/components/checkbox.html.erb +212 -0
- data/app/views/docs/components/collapsible.html.erb +252 -0
- data/app/views/docs/components/dialog.html.erb +323 -0
- data/app/views/docs/components/dropdown_menu.html.erb +289 -0
- data/app/views/docs/components/hover_card.html.erb +220 -0
- data/app/views/docs/components/input.html.erb +254 -0
- data/app/views/docs/components/label.html.erb +128 -0
- data/app/views/docs/components/main.html.erb +352 -0
- data/app/views/docs/components/navbar.html.erb +394 -0
- data/app/views/docs/components/navigation_menu.html.erb +226 -0
- data/app/views/docs/components/popover.html.erb +267 -0
- data/app/views/docs/components/progress.html.erb +107 -0
- data/app/views/docs/components/radio_group.html.erb +209 -0
- data/app/views/docs/components/select.html.erb +260 -0
- data/app/views/docs/components/separator.html.erb +162 -0
- data/app/views/docs/components/sheet.html.erb +270 -0
- data/app/views/docs/components/sidebar.html.erb +597 -0
- data/app/views/docs/components/skeleton.html.erb +150 -0
- data/app/views/docs/components/slider.html.erb +218 -0
- data/app/views/docs/components/spinner.html.erb +132 -0
- data/app/views/docs/components/switch.html.erb +148 -0
- data/app/views/docs/components/table.html.erb +259 -0
- data/app/views/docs/components/tabs.html.erb +225 -0
- data/app/views/docs/components/textarea.html.erb +239 -0
- data/app/views/docs/components/theme_toggle.html.erb +135 -0
- data/app/views/docs/components/toast.html.erb +205 -0
- data/app/views/docs/components/toaster.html.erb +227 -0
- data/app/views/docs/components/toggle.html.erb +154 -0
- data/app/views/docs/components/tooltip.html.erb +216 -0
- data/app/views/docs/components/typography.html.erb +180 -0
- data/app/views/docs/index.html.erb +143 -0
- data/app/views/docs/installation.html.erb +155 -0
- data/app/views/docs/simple_test.html.erb +13 -0
- data/app/views/docs/test_accordion.html.erb +14 -0
- data/app/views/docs/usage.html.erb +272 -0
- data/app/views/layouts/application.html.erb +107 -0
- data/app/views/layouts/backdrop.html.erb +77 -0
- data/app/views/shared/_app_navbar.html.erb +240 -0
- data/app/views/shared/_navbar.html.erb +69 -0
- data/app/views/showcase/v2/_components_grid.html.erb +38 -0
- data/app/views/showcase/v2/_features.html.erb +59 -0
- data/app/views/showcase/v2/_forms.html.erb +195 -0
- data/app/views/showcase/v2/_hero.html.erb +55 -0
- data/app/views/showcase/v2/_metrics.html.erb +107 -0
- data/app/views/showcase/v2.html.erb +18 -0
- data/lib/m9sh/version.rb +1 -1
- data/m9sh.gemspec +1 -1
- 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
|