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,378 @@
|
|
1
|
+
<%= render Docs::ComponentPageComponent.new(title: "Card") do |page| %>
|
2
|
+
<% page.with_header(
|
3
|
+
name: "Card",
|
4
|
+
description: "Displays a flexible container component with optional header, body, and footer sections for organizing content."
|
5
|
+
) %>
|
6
|
+
|
7
|
+
<% page.with_installation(component_name: "card") %>
|
8
|
+
|
9
|
+
<% page.with_usage do %>
|
10
|
+
<%= render Docs::CodeBlockComponent.new(
|
11
|
+
code: card_usage_code,
|
12
|
+
language: "erb"
|
13
|
+
) %>
|
14
|
+
<% end %>
|
15
|
+
|
16
|
+
<% page.with_examples do %>
|
17
|
+
<!-- Default Card Example -->
|
18
|
+
<% default_card_html = capture do %>
|
19
|
+
<%= render M9sh::CardComponent.new do |card| %>
|
20
|
+
<% card.with_body do %>
|
21
|
+
<p class="text-sm">
|
22
|
+
This is a simple card with just body content. Cards provide a clean container with subtle borders and shadows.
|
23
|
+
</p>
|
24
|
+
<% end %>
|
25
|
+
<% end %>
|
26
|
+
<% end %>
|
27
|
+
|
28
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
29
|
+
title: "Default",
|
30
|
+
preview_content: default_card_html,
|
31
|
+
code: card_usage_code,
|
32
|
+
ai_command: card_usage_code
|
33
|
+
) %>
|
34
|
+
|
35
|
+
<!-- Card with Header -->
|
36
|
+
<% card_with_header_html = capture do %>
|
37
|
+
<%= render M9sh::CardComponent.new do |card| %>
|
38
|
+
<% card.with_header do |header| %>
|
39
|
+
<% header.with_title do %>
|
40
|
+
Card Title
|
41
|
+
<% end %>
|
42
|
+
<% header.with_description do %>
|
43
|
+
Card description provides additional context
|
44
|
+
<% end %>
|
45
|
+
<% end %>
|
46
|
+
<% card.with_body do %>
|
47
|
+
<p class="text-sm">
|
48
|
+
This card includes a header with a title and description. The header is automatically styled with appropriate spacing and typography.
|
49
|
+
</p>
|
50
|
+
<% end %>
|
51
|
+
<% end %>
|
52
|
+
<% end %>
|
53
|
+
|
54
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
55
|
+
title: "With Header",
|
56
|
+
preview_content: card_with_header_html,
|
57
|
+
code: card_with_header_code,
|
58
|
+
ai_command: card_with_header_code
|
59
|
+
) %>
|
60
|
+
|
61
|
+
<!-- Card with Footer -->
|
62
|
+
<% card_with_footer_html = capture do %>
|
63
|
+
<%= render M9sh::CardComponent.new do |card| %>
|
64
|
+
<% card.with_body do %>
|
65
|
+
<p class="text-sm">
|
66
|
+
This card includes a footer section below the main content, perfect for action buttons or metadata.
|
67
|
+
</p>
|
68
|
+
<% end %>
|
69
|
+
<% card.with_footer do %>
|
70
|
+
<p class="text-sm text-muted-foreground">Last updated: 2 hours ago</p>
|
71
|
+
<% end %>
|
72
|
+
<% end %>
|
73
|
+
<% end %>
|
74
|
+
|
75
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
76
|
+
title: "With Footer",
|
77
|
+
preview_content: card_with_footer_html,
|
78
|
+
code: card_with_footer_code,
|
79
|
+
ai_command: card_with_footer_code
|
80
|
+
) %>
|
81
|
+
|
82
|
+
<!-- Complete Card Example -->
|
83
|
+
<% complete_card_html = capture do %>
|
84
|
+
<%= render M9sh::CardComponent.new do |card| %>
|
85
|
+
<% card.with_header do |header| %>
|
86
|
+
<% header.with_title do %>
|
87
|
+
Create Project
|
88
|
+
<% end %>
|
89
|
+
<% header.with_description do %>
|
90
|
+
Deploy your new project in one-click.
|
91
|
+
<% end %>
|
92
|
+
<% end %>
|
93
|
+
<% card.with_body do %>
|
94
|
+
<div class="space-y-4">
|
95
|
+
<div class="space-y-2">
|
96
|
+
<%= render M9sh::LabelComponent.new(for_id: "project-name") do %>
|
97
|
+
Name
|
98
|
+
<% end %>
|
99
|
+
<%= render M9sh::InputComponent.new(
|
100
|
+
id: "project-name",
|
101
|
+
type: "text",
|
102
|
+
placeholder: "Name of your project"
|
103
|
+
) %>
|
104
|
+
</div>
|
105
|
+
<div class="space-y-2">
|
106
|
+
<%= render M9sh::LabelComponent.new(for_id: "framework") do %>
|
107
|
+
Framework
|
108
|
+
<% end %>
|
109
|
+
<%= render M9sh::SelectComponent.new(
|
110
|
+
name: "framework",
|
111
|
+
options: ["Next.js", "SvelteKit", "Astro", "Nuxt.js"]
|
112
|
+
) %>
|
113
|
+
</div>
|
114
|
+
</div>
|
115
|
+
<% end %>
|
116
|
+
<% card.with_footer do %>
|
117
|
+
<div class="flex justify-between w-full">
|
118
|
+
<%= render M9sh::ButtonComponent.new(variant: :outline) do %>
|
119
|
+
Cancel
|
120
|
+
<% end %>
|
121
|
+
<%= render M9sh::ButtonComponent.new do %>
|
122
|
+
Deploy
|
123
|
+
<% end %>
|
124
|
+
</div>
|
125
|
+
<% end %>
|
126
|
+
<% end %>
|
127
|
+
<% end %>
|
128
|
+
|
129
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
130
|
+
title: "Complete Card",
|
131
|
+
preview_content: complete_card_html,
|
132
|
+
code: card_complete_code,
|
133
|
+
ai_command: card_complete_code
|
134
|
+
) %>
|
135
|
+
|
136
|
+
<!-- Card with Header Action -->
|
137
|
+
<% card_with_action_html = capture do %>
|
138
|
+
<%= render M9sh::CardComponent.new(class: "max-w-md") do |card| %>
|
139
|
+
<% card.with_header do |header| %>
|
140
|
+
<% header.with_title do %>
|
141
|
+
Notifications
|
142
|
+
<% end %>
|
143
|
+
<% header.with_description do %>
|
144
|
+
You have 3 unread messages.
|
145
|
+
<% end %>
|
146
|
+
<% header.with_action do %>
|
147
|
+
<%= render M9sh::ButtonComponent.new(variant: :ghost, size: :sm) do %>
|
148
|
+
Mark all as read
|
149
|
+
<% end %>
|
150
|
+
<% end %>
|
151
|
+
<% end %>
|
152
|
+
<% card.with_body do %>
|
153
|
+
<div class="space-y-3">
|
154
|
+
<div class="flex items-start gap-3 p-3 rounded-md hover:bg-muted transition-colors border border-transparent hover:border-border">
|
155
|
+
<div class="flex-shrink-0 w-2 h-2 rounded-full bg-primary mt-2"></div>
|
156
|
+
<div class="flex-1 space-y-1">
|
157
|
+
<p class="text-sm font-medium">Your call has been confirmed.</p>
|
158
|
+
<p class="text-xs text-muted-foreground">5 minutes ago</p>
|
159
|
+
</div>
|
160
|
+
</div>
|
161
|
+
<div class="flex items-start gap-3 p-3 rounded-md hover:bg-muted transition-colors border border-transparent hover:border-border">
|
162
|
+
<div class="flex-shrink-0 w-2 h-2 rounded-full bg-primary mt-2"></div>
|
163
|
+
<div class="flex-1 space-y-1">
|
164
|
+
<p class="text-sm font-medium">You have a new message!</p>
|
165
|
+
<p class="text-xs text-muted-foreground">10 minutes ago</p>
|
166
|
+
</div>
|
167
|
+
</div>
|
168
|
+
<div class="flex items-start gap-3 p-3 rounded-md hover:bg-muted transition-colors border border-transparent hover:border-border">
|
169
|
+
<div class="flex-shrink-0 w-2 h-2 rounded-full bg-primary mt-2"></div>
|
170
|
+
<div class="flex-1 space-y-1">
|
171
|
+
<p class="text-sm font-medium">Your subscription is expiring soon!</p>
|
172
|
+
<p class="text-xs text-muted-foreground">2 hours ago</p>
|
173
|
+
</div>
|
174
|
+
</div>
|
175
|
+
</div>
|
176
|
+
<% end %>
|
177
|
+
<% end %>
|
178
|
+
<% end %>
|
179
|
+
|
180
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
181
|
+
title: "With Header Action",
|
182
|
+
preview_content: card_with_action_html,
|
183
|
+
code: card_with_action_code,
|
184
|
+
ai_command: card_with_action_code
|
185
|
+
) %>
|
186
|
+
|
187
|
+
<!-- Multiple Cards in a Grid -->
|
188
|
+
<% multiple_cards_html = capture do %>
|
189
|
+
<div class="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
190
|
+
<%= render M9sh::CardComponent.new do |card| %>
|
191
|
+
<% card.with_header do |header| %>
|
192
|
+
<% header.with_title do %>
|
193
|
+
Total Revenue
|
194
|
+
<% end %>
|
195
|
+
<% header.with_description do %>
|
196
|
+
Monthly earnings
|
197
|
+
<% end %>
|
198
|
+
<% end %>
|
199
|
+
<% card.with_body do %>
|
200
|
+
<div class="text-2xl font-bold">$45,231.89</div>
|
201
|
+
<p class="text-xs text-muted-foreground mt-1">+20.1% from last month</p>
|
202
|
+
<% end %>
|
203
|
+
<% end %>
|
204
|
+
|
205
|
+
<%= render M9sh::CardComponent.new do |card| %>
|
206
|
+
<% card.with_header do |header| %>
|
207
|
+
<% header.with_title do %>
|
208
|
+
Subscriptions
|
209
|
+
<% end %>
|
210
|
+
<% header.with_description do %>
|
211
|
+
Active subscribers
|
212
|
+
<% end %>
|
213
|
+
<% end %>
|
214
|
+
<% card.with_body do %>
|
215
|
+
<div class="text-2xl font-bold">+2,350</div>
|
216
|
+
<p class="text-xs text-muted-foreground mt-1">+180.1% from last month</p>
|
217
|
+
<% end %>
|
218
|
+
<% end %>
|
219
|
+
|
220
|
+
<%= render M9sh::CardComponent.new do |card| %>
|
221
|
+
<% card.with_header do |header| %>
|
222
|
+
<% header.with_title do %>
|
223
|
+
Active Now
|
224
|
+
<% end %>
|
225
|
+
<% header.with_description do %>
|
226
|
+
Current online users
|
227
|
+
<% end %>
|
228
|
+
<% end %>
|
229
|
+
<% card.with_body do %>
|
230
|
+
<div class="text-2xl font-bold">+573</div>
|
231
|
+
<p class="text-xs text-muted-foreground mt-1">+201 since last hour</p>
|
232
|
+
<% end %>
|
233
|
+
<% end %>
|
234
|
+
</div>
|
235
|
+
<% end %>
|
236
|
+
|
237
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
238
|
+
title: "Multiple Cards",
|
239
|
+
preview_content: multiple_cards_html,
|
240
|
+
code: nil,
|
241
|
+
ai_command: nil
|
242
|
+
) %>
|
243
|
+
|
244
|
+
<!-- Card with Custom Content -->
|
245
|
+
<% custom_content_card_html = capture do %>
|
246
|
+
<%= render M9sh::CardComponent.new(class: "max-w-md") do |card| %>
|
247
|
+
<% card.with_header do |header| %>
|
248
|
+
<% header.with_title do %>
|
249
|
+
Team Members
|
250
|
+
<% end %>
|
251
|
+
<% header.with_description do %>
|
252
|
+
Invite your team members to collaborate.
|
253
|
+
<% end %>
|
254
|
+
<% end %>
|
255
|
+
<% card.with_body do %>
|
256
|
+
<div class="space-y-4">
|
257
|
+
<div class="flex items-center justify-between p-2 rounded-md hover:bg-muted transition-colors">
|
258
|
+
<div class="flex items-center gap-3">
|
259
|
+
<%= render M9sh::AvatarComponent.new(fallback: "JD", class: "h-10 w-10") %>
|
260
|
+
<div>
|
261
|
+
<p class="text-sm font-medium">John Doe</p>
|
262
|
+
<p class="text-xs text-muted-foreground">john@example.com</p>
|
263
|
+
</div>
|
264
|
+
</div>
|
265
|
+
<%= render M9sh::BadgeComponent.new(variant: :secondary) do %>
|
266
|
+
Owner
|
267
|
+
<% end %>
|
268
|
+
</div>
|
269
|
+
<div class="flex items-center justify-between p-2 rounded-md hover:bg-muted transition-colors">
|
270
|
+
<div class="flex items-center gap-3">
|
271
|
+
<%= render M9sh::AvatarComponent.new(fallback: "JS", class: "h-10 w-10") %>
|
272
|
+
<div>
|
273
|
+
<p class="text-sm font-medium">Jane Smith</p>
|
274
|
+
<p class="text-xs text-muted-foreground">jane@example.com</p>
|
275
|
+
</div>
|
276
|
+
</div>
|
277
|
+
<%= render M9sh::BadgeComponent.new(variant: :secondary) do %>
|
278
|
+
Admin
|
279
|
+
<% end %>
|
280
|
+
</div>
|
281
|
+
<div class="flex items-center justify-between p-2 rounded-md hover:bg-muted transition-colors">
|
282
|
+
<div class="flex items-center gap-3">
|
283
|
+
<%= render M9sh::AvatarComponent.new(fallback: "BJ", class: "h-10 w-10") %>
|
284
|
+
<div>
|
285
|
+
<p class="text-sm font-medium">Bob Johnson</p>
|
286
|
+
<p class="text-xs text-muted-foreground">bob@example.com</p>
|
287
|
+
</div>
|
288
|
+
</div>
|
289
|
+
<%= render M9sh::BadgeComponent.new(variant: :secondary) do %>
|
290
|
+
Member
|
291
|
+
<% end %>
|
292
|
+
</div>
|
293
|
+
</div>
|
294
|
+
<% end %>
|
295
|
+
<% card.with_footer do %>
|
296
|
+
<%= render M9sh::ButtonComponent.new(class: "w-full") do %>
|
297
|
+
Invite Team Member
|
298
|
+
<% end %>
|
299
|
+
<% end %>
|
300
|
+
<% end %>
|
301
|
+
<% end %>
|
302
|
+
|
303
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
304
|
+
title: "Custom Content",
|
305
|
+
preview_content: custom_content_card_html,
|
306
|
+
code: nil,
|
307
|
+
ai_command: nil
|
308
|
+
) %>
|
309
|
+
<% end %>
|
310
|
+
|
311
|
+
<% page.with_api do %>
|
312
|
+
<h3 class="text-lg font-semibold">Card Component</h3>
|
313
|
+
<p class="text-sm text-muted-foreground mb-4">
|
314
|
+
The Card component accepts all standard HTML attributes which are passed through to the root div element.
|
315
|
+
</p>
|
316
|
+
|
317
|
+
<h3 class="text-lg font-semibold mt-6">Card Slots</h3>
|
318
|
+
<%= render Docs::PropTableComponent.new(
|
319
|
+
props: [
|
320
|
+
{
|
321
|
+
name: "header",
|
322
|
+
type: "HeaderComponent",
|
323
|
+
default: nil,
|
324
|
+
description: "Optional header section. Supports title, description, and action slots"
|
325
|
+
},
|
326
|
+
{
|
327
|
+
name: "body",
|
328
|
+
type: "Slot",
|
329
|
+
default: nil,
|
330
|
+
description: "Main content area of the card"
|
331
|
+
},
|
332
|
+
{
|
333
|
+
name: "footer",
|
334
|
+
type: "Slot",
|
335
|
+
default: nil,
|
336
|
+
description: "Optional footer section for actions or metadata"
|
337
|
+
}
|
338
|
+
]
|
339
|
+
) %>
|
340
|
+
|
341
|
+
<h3 class="text-lg font-semibold mt-6">Header Component Slots</h3>
|
342
|
+
<%= render Docs::PropTableComponent.new(
|
343
|
+
props: [
|
344
|
+
{
|
345
|
+
name: "title",
|
346
|
+
type: "Slot",
|
347
|
+
default: nil,
|
348
|
+
description: "The title/heading text displayed in the header"
|
349
|
+
},
|
350
|
+
{
|
351
|
+
name: "description",
|
352
|
+
type: "Slot",
|
353
|
+
default: nil,
|
354
|
+
description: "Optional description text displayed below the title"
|
355
|
+
},
|
356
|
+
{
|
357
|
+
name: "action",
|
358
|
+
type: "Slot",
|
359
|
+
default: nil,
|
360
|
+
description: "Optional action element (e.g., button, link) displayed in the top-right corner of the header"
|
361
|
+
}
|
362
|
+
]
|
363
|
+
) %>
|
364
|
+
|
365
|
+
<div class="mt-6 space-y-2">
|
366
|
+
<h3 class="text-lg font-semibold">Notes</h3>
|
367
|
+
<ul class="list-disc list-inside text-sm text-muted-foreground space-y-1">
|
368
|
+
<li>All slots (header, body, footer) are optional and can be used in any combination</li>
|
369
|
+
<li>The card includes hover effects that enhance the border and shadow on mouse over</li>
|
370
|
+
<li>The header component supports a grid layout when an action slot is provided</li>
|
371
|
+
<li>The header title and description are automatically styled with appropriate typography</li>
|
372
|
+
<li>The body content is wrapped in a container with horizontal padding for consistent spacing</li>
|
373
|
+
<li>The footer automatically aligns items with proper spacing</li>
|
374
|
+
<li>Cards are responsive and work well in grid layouts (as shown in the Multiple Cards example)</li>
|
375
|
+
</ul>
|
376
|
+
</div>
|
377
|
+
<% end %>
|
378
|
+
<% end %>
|
@@ -0,0 +1,212 @@
|
|
1
|
+
<%= render Docs::ComponentPageComponent.new(title: "Checkbox") do |page| %>
|
2
|
+
<% page.with_header(name: "Checkbox", description: "A control that allows the user to toggle between checked and not checked.") %>
|
3
|
+
<% page.with_installation(component_name: "checkbox") %>
|
4
|
+
<% page.with_usage do %>
|
5
|
+
<%= render Docs::CodeBlockComponent.new(code: checkbox_usage_code, language: "erb") %>
|
6
|
+
<% end %>
|
7
|
+
<% page.with_examples do %>
|
8
|
+
<!-- Default Example -->
|
9
|
+
<% default_html = capture do %>
|
10
|
+
<%= render M9sh::CheckboxComponent.new(name: "default") %>
|
11
|
+
<% end %>
|
12
|
+
|
13
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
14
|
+
title: "Default",
|
15
|
+
preview_content: default_html,
|
16
|
+
code: checkbox_usage_code,
|
17
|
+
ai_command: checkbox_usage_code
|
18
|
+
) %>
|
19
|
+
|
20
|
+
<!-- With Label Example -->
|
21
|
+
<% with_label_html = capture do %>
|
22
|
+
<div class="flex items-center space-x-2">
|
23
|
+
<%= render M9sh::CheckboxComponent.new(name: "terms", id: "terms") %>
|
24
|
+
<%= render M9sh::LabelComponent.new(for_id: "terms") do %>
|
25
|
+
Accept terms and conditions
|
26
|
+
<% end %>
|
27
|
+
</div>
|
28
|
+
<% end %>
|
29
|
+
|
30
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
31
|
+
title: "With Label",
|
32
|
+
preview_content: with_label_html,
|
33
|
+
code: checkbox_with_label_code,
|
34
|
+
ai_command: checkbox_with_label_code
|
35
|
+
) %>
|
36
|
+
|
37
|
+
<!-- Checked State Example -->
|
38
|
+
<% checked_html = capture do %>
|
39
|
+
<div class="flex items-center space-x-2">
|
40
|
+
<%= render M9sh::CheckboxComponent.new(name: "checked", id: "checked", checked: true) %>
|
41
|
+
<%= render M9sh::LabelComponent.new(for_id: "checked") do %>
|
42
|
+
This checkbox is checked by default
|
43
|
+
<% end %>
|
44
|
+
</div>
|
45
|
+
<% end %>
|
46
|
+
|
47
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
48
|
+
title: "Checked State",
|
49
|
+
preview_content: checked_html,
|
50
|
+
code: checkbox_checked_code,
|
51
|
+
ai_command: checkbox_checked_code
|
52
|
+
) %>
|
53
|
+
|
54
|
+
<!-- Disabled State Example -->
|
55
|
+
<% disabled_html = capture do %>
|
56
|
+
<div class="flex flex-col space-y-4">
|
57
|
+
<div class="flex items-center space-x-2">
|
58
|
+
<%= render M9sh::CheckboxComponent.new(name: "disabled", id: "disabled", disabled: true) %>
|
59
|
+
<%= render M9sh::LabelComponent.new(for_id: "disabled") do %>
|
60
|
+
Disabled unchecked
|
61
|
+
<% end %>
|
62
|
+
</div>
|
63
|
+
<div class="flex items-center space-x-2">
|
64
|
+
<%= render M9sh::CheckboxComponent.new(name: "disabled_checked", id: "disabled_checked", checked: true, disabled: true) %>
|
65
|
+
<%= render M9sh::LabelComponent.new(for_id: "disabled_checked") do %>
|
66
|
+
Disabled checked
|
67
|
+
<% end %>
|
68
|
+
</div>
|
69
|
+
</div>
|
70
|
+
<% end %>
|
71
|
+
|
72
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
73
|
+
title: "Disabled State",
|
74
|
+
preview_content: disabled_html,
|
75
|
+
code: checkbox_disabled_code,
|
76
|
+
ai_command: checkbox_disabled_code
|
77
|
+
) %>
|
78
|
+
|
79
|
+
<!-- Multiple Checkboxes Example -->
|
80
|
+
<% multiple_html = capture do %>
|
81
|
+
<div class="space-y-3">
|
82
|
+
<div class="flex items-center space-x-2">
|
83
|
+
<%= render M9sh::CheckboxComponent.new(name: "preferences[]", value: "email", id: "email_notifications") %>
|
84
|
+
<%= render M9sh::LabelComponent.new(for_id: "email_notifications") do %>
|
85
|
+
Email notifications
|
86
|
+
<% end %>
|
87
|
+
</div>
|
88
|
+
<div class="flex items-center space-x-2">
|
89
|
+
<%= render M9sh::CheckboxComponent.new(name: "preferences[]", value: "sms", id: "sms_notifications", checked: true) %>
|
90
|
+
<%= render M9sh::LabelComponent.new(for_id: "sms_notifications") do %>
|
91
|
+
SMS notifications
|
92
|
+
<% end %>
|
93
|
+
</div>
|
94
|
+
<div class="flex items-center space-x-2">
|
95
|
+
<%= render M9sh::CheckboxComponent.new(name: "preferences[]", value: "push", id: "push_notifications") %>
|
96
|
+
<%= render M9sh::LabelComponent.new(for_id: "push_notifications") do %>
|
97
|
+
Push notifications
|
98
|
+
<% end %>
|
99
|
+
</div>
|
100
|
+
<div class="flex items-center space-x-2">
|
101
|
+
<%= render M9sh::CheckboxComponent.new(name: "preferences[]", value: "newsletter", id: "newsletter", checked: true) %>
|
102
|
+
<%= render M9sh::LabelComponent.new(for_id: "newsletter") do %>
|
103
|
+
Weekly newsletter
|
104
|
+
<% end %>
|
105
|
+
</div>
|
106
|
+
</div>
|
107
|
+
<% end %>
|
108
|
+
|
109
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
110
|
+
title: "Multiple Checkboxes",
|
111
|
+
preview_content: multiple_html,
|
112
|
+
code: checkbox_multiple_code,
|
113
|
+
ai_command: checkbox_multiple_code
|
114
|
+
) %>
|
115
|
+
|
116
|
+
<!-- Form Integration Example -->
|
117
|
+
<% form_html = capture do %>
|
118
|
+
<div class="border rounded-lg p-6 max-w-md">
|
119
|
+
<h3 class="text-lg font-semibold mb-4">Account Settings</h3>
|
120
|
+
<div class="space-y-4">
|
121
|
+
<div class="flex items-start space-x-2">
|
122
|
+
<%= render M9sh::CheckboxComponent.new(name: "account[two_factor]", id: "two_factor", checked: true) %>
|
123
|
+
<div class="grid gap-1.5 leading-none">
|
124
|
+
<%= render M9sh::LabelComponent.new(for_id: "two_factor", class: "font-medium") do %>
|
125
|
+
Enable two-factor authentication
|
126
|
+
<% end %>
|
127
|
+
<p class="text-sm text-muted-foreground">
|
128
|
+
Add an extra layer of security to your account.
|
129
|
+
</p>
|
130
|
+
</div>
|
131
|
+
</div>
|
132
|
+
<div class="flex items-start space-x-2">
|
133
|
+
<%= render M9sh::CheckboxComponent.new(name: "account[public_profile]", id: "public_profile") %>
|
134
|
+
<div class="grid gap-1.5 leading-none">
|
135
|
+
<%= render M9sh::LabelComponent.new(for_id: "public_profile", class: "font-medium") do %>
|
136
|
+
Public profile
|
137
|
+
<% end %>
|
138
|
+
<p class="text-sm text-muted-foreground">
|
139
|
+
Make your profile visible to everyone.
|
140
|
+
</p>
|
141
|
+
</div>
|
142
|
+
</div>
|
143
|
+
<div class="flex items-start space-x-2">
|
144
|
+
<%= render M9sh::CheckboxComponent.new(name: "account[marketing]", id: "marketing") %>
|
145
|
+
<div class="grid gap-1.5 leading-none">
|
146
|
+
<%= render M9sh::LabelComponent.new(for_id: "marketing", class: "font-medium") do %>
|
147
|
+
Marketing emails
|
148
|
+
<% end %>
|
149
|
+
<p class="text-sm text-muted-foreground">
|
150
|
+
Receive emails about new products and features.
|
151
|
+
</p>
|
152
|
+
</div>
|
153
|
+
</div>
|
154
|
+
</div>
|
155
|
+
</div>
|
156
|
+
<% end %>
|
157
|
+
|
158
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
159
|
+
title: "Form Integration",
|
160
|
+
preview_content: form_html,
|
161
|
+
code: checkbox_form_code,
|
162
|
+
ai_command: checkbox_form_code
|
163
|
+
) %>
|
164
|
+
<% end %>
|
165
|
+
<% page.with_api do %>
|
166
|
+
<%= render Docs::PropTableComponent.new(
|
167
|
+
props: [
|
168
|
+
{
|
169
|
+
name: "name",
|
170
|
+
type: "String",
|
171
|
+
default: "nil",
|
172
|
+
description: "The name attribute for the checkbox input element"
|
173
|
+
},
|
174
|
+
{
|
175
|
+
name: "checked",
|
176
|
+
type: "Boolean",
|
177
|
+
default: "false",
|
178
|
+
description: "Whether the checkbox is checked by default"
|
179
|
+
},
|
180
|
+
{
|
181
|
+
name: "value",
|
182
|
+
type: "String",
|
183
|
+
default: '"1"',
|
184
|
+
description: "The value attribute for the checkbox input element"
|
185
|
+
},
|
186
|
+
{
|
187
|
+
name: "disabled",
|
188
|
+
type: "Boolean",
|
189
|
+
default: "false",
|
190
|
+
description: "Whether the checkbox is disabled"
|
191
|
+
},
|
192
|
+
{
|
193
|
+
name: "id",
|
194
|
+
type: "String",
|
195
|
+
default: "nil",
|
196
|
+
description: "The id attribute for the checkbox input element (useful for associating with labels)"
|
197
|
+
}
|
198
|
+
]
|
199
|
+
) %>
|
200
|
+
|
201
|
+
<div class="mt-6 space-y-2">
|
202
|
+
<h3 class="text-lg font-semibold">Additional Notes</h3>
|
203
|
+
<ul class="list-disc list-inside space-y-2 text-sm text-muted-foreground">
|
204
|
+
<li>The checkbox component includes a Stimulus controller (m9sh--checkbox) for enhanced interactivity</li>
|
205
|
+
<li>The component automatically manages the data-state attribute for checked/unchecked states</li>
|
206
|
+
<li>All additional HTML attributes can be passed via extra_attrs and will be applied to the input element</li>
|
207
|
+
<li>The checkbox follows the WAI-ARIA design pattern for accessibility</li>
|
208
|
+
<li>For multiple checkboxes with the same name, use array notation (e.g., name: "preferences[]")</li>
|
209
|
+
</ul>
|
210
|
+
</div>
|
211
|
+
<% end %>
|
212
|
+
<% end %>
|