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,254 @@
|
|
1
|
+
<%= render Docs::ComponentPageComponent.new(title: "Input") do |page| %>
|
2
|
+
<% page.with_header(
|
3
|
+
name: "Input",
|
4
|
+
description: "Displays a form input field with customizable types, placeholders, and states."
|
5
|
+
) %>
|
6
|
+
|
7
|
+
<% page.with_installation(component_name: "input") %>
|
8
|
+
|
9
|
+
<% page.with_usage do %>
|
10
|
+
<%= render Docs::CodeBlockComponent.new(
|
11
|
+
code: input_usage_code,
|
12
|
+
language: "erb"
|
13
|
+
) %>
|
14
|
+
<% end %>
|
15
|
+
|
16
|
+
<% page.with_examples do %>
|
17
|
+
<!-- Default Input Example -->
|
18
|
+
<% default_html = capture do %>
|
19
|
+
<div class="w-full max-w-sm">
|
20
|
+
<%= render M9sh::InputComponent.new(
|
21
|
+
type: "text",
|
22
|
+
placeholder: "Enter text..."
|
23
|
+
) %>
|
24
|
+
</div>
|
25
|
+
<% end %>
|
26
|
+
|
27
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
28
|
+
title: "Default Input",
|
29
|
+
preview_content: default_html,
|
30
|
+
code: input_usage_code,
|
31
|
+
ai_command: input_usage_code
|
32
|
+
) %>
|
33
|
+
|
34
|
+
<!-- Input Types Example -->
|
35
|
+
<% types_html = capture do %>
|
36
|
+
<div class="w-full max-w-sm space-y-4">
|
37
|
+
<%= render M9sh::InputComponent.new(
|
38
|
+
type: "text",
|
39
|
+
placeholder: "Text input"
|
40
|
+
) %>
|
41
|
+
|
42
|
+
<%= render M9sh::InputComponent.new(
|
43
|
+
type: "email",
|
44
|
+
placeholder: "Email input"
|
45
|
+
) %>
|
46
|
+
|
47
|
+
<%= render M9sh::InputComponent.new(
|
48
|
+
type: "password",
|
49
|
+
placeholder: "Password input"
|
50
|
+
) %>
|
51
|
+
|
52
|
+
<%= render M9sh::InputComponent.new(
|
53
|
+
type: "number",
|
54
|
+
placeholder: "Number input"
|
55
|
+
) %>
|
56
|
+
</div>
|
57
|
+
<% end %>
|
58
|
+
|
59
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
60
|
+
title: "Input Types",
|
61
|
+
preview_content: types_html,
|
62
|
+
code: input_types_code,
|
63
|
+
ai_command: input_types_code
|
64
|
+
) %>
|
65
|
+
|
66
|
+
<!-- Input with Label Example -->
|
67
|
+
<% with_label_html = capture do %>
|
68
|
+
<div class="w-full max-w-sm space-y-2">
|
69
|
+
<%= render M9sh::LabelComponent.new(for_id: "email") do %>
|
70
|
+
Email
|
71
|
+
<% end %>
|
72
|
+
<%= render M9sh::InputComponent.new(
|
73
|
+
id: "email",
|
74
|
+
type: "email",
|
75
|
+
placeholder: "Enter your email"
|
76
|
+
) %>
|
77
|
+
</div>
|
78
|
+
<% end %>
|
79
|
+
|
80
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
81
|
+
title: "Input with Label",
|
82
|
+
preview_content: with_label_html,
|
83
|
+
code: input_with_label_code,
|
84
|
+
ai_command: input_with_label_code
|
85
|
+
) %>
|
86
|
+
|
87
|
+
<!-- Disabled Input Example -->
|
88
|
+
<% disabled_html = capture do %>
|
89
|
+
<div class="w-full max-w-sm">
|
90
|
+
<%= render M9sh::InputComponent.new(
|
91
|
+
type: "text",
|
92
|
+
placeholder: "Disabled input",
|
93
|
+
disabled: true
|
94
|
+
) %>
|
95
|
+
</div>
|
96
|
+
<% end %>
|
97
|
+
|
98
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
99
|
+
title: "Disabled State",
|
100
|
+
preview_content: disabled_html,
|
101
|
+
code: input_disabled_code,
|
102
|
+
ai_command: input_disabled_code
|
103
|
+
) %>
|
104
|
+
|
105
|
+
<!-- Input with Placeholder Example -->
|
106
|
+
<% placeholder_html = capture do %>
|
107
|
+
<div class="w-full max-w-sm">
|
108
|
+
<%= render M9sh::InputComponent.new(
|
109
|
+
type: "text",
|
110
|
+
placeholder: "This is a placeholder..."
|
111
|
+
) %>
|
112
|
+
</div>
|
113
|
+
<% end %>
|
114
|
+
|
115
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
116
|
+
title: "With Placeholder",
|
117
|
+
preview_content: placeholder_html,
|
118
|
+
code: input_placeholder_code,
|
119
|
+
ai_command: input_placeholder_code
|
120
|
+
) %>
|
121
|
+
|
122
|
+
<!-- Input with Value Example -->
|
123
|
+
<% value_html = capture do %>
|
124
|
+
<div class="w-full max-w-sm">
|
125
|
+
<%= render M9sh::InputComponent.new(
|
126
|
+
type: "text",
|
127
|
+
value: "Pre-filled value",
|
128
|
+
placeholder: "Enter text..."
|
129
|
+
) %>
|
130
|
+
</div>
|
131
|
+
<% end %>
|
132
|
+
|
133
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
134
|
+
title: "With Default Value",
|
135
|
+
preview_content: value_html,
|
136
|
+
code: input_value_code,
|
137
|
+
ai_command: input_value_code
|
138
|
+
) %>
|
139
|
+
|
140
|
+
<!-- File Input Example -->
|
141
|
+
<% file_html = capture do %>
|
142
|
+
<div class="w-full max-w-sm">
|
143
|
+
<%= render M9sh::InputComponent.new(
|
144
|
+
type: "file"
|
145
|
+
) %>
|
146
|
+
</div>
|
147
|
+
<% end %>
|
148
|
+
|
149
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
150
|
+
title: "File Input",
|
151
|
+
preview_content: file_html,
|
152
|
+
code: input_file_code,
|
153
|
+
ai_command: input_file_code
|
154
|
+
) %>
|
155
|
+
<% end %>
|
156
|
+
|
157
|
+
<% page.with_api do %>
|
158
|
+
<%= render Docs::PropTableComponent.new(
|
159
|
+
props: [
|
160
|
+
{
|
161
|
+
name: "type",
|
162
|
+
type: "String",
|
163
|
+
default: '"text"',
|
164
|
+
description: "The input type (text, email, password, number, file, etc.). Accepts any valid HTML input type."
|
165
|
+
},
|
166
|
+
{
|
167
|
+
name: "name",
|
168
|
+
type: "String",
|
169
|
+
default: "nil",
|
170
|
+
description: "The name attribute for the input field, used when submitting forms."
|
171
|
+
},
|
172
|
+
{
|
173
|
+
name: "value",
|
174
|
+
type: "String",
|
175
|
+
default: "nil",
|
176
|
+
description: "The default value for the input field."
|
177
|
+
},
|
178
|
+
{
|
179
|
+
name: "placeholder",
|
180
|
+
type: "String",
|
181
|
+
default: "nil",
|
182
|
+
description: "Placeholder text displayed when the input is empty."
|
183
|
+
},
|
184
|
+
{
|
185
|
+
name: "disabled",
|
186
|
+
type: "Boolean",
|
187
|
+
default: "false",
|
188
|
+
description: "Whether the input is disabled. Disabled inputs cannot be edited or submitted."
|
189
|
+
},
|
190
|
+
{
|
191
|
+
name: "**extra_attrs",
|
192
|
+
type: "Hash",
|
193
|
+
default: "{}",
|
194
|
+
description: "Additional HTML attributes to apply to the input element (e.g., id, class, data attributes, required, readonly, etc.)."
|
195
|
+
}
|
196
|
+
]
|
197
|
+
) %>
|
198
|
+
|
199
|
+
<div class="mt-6 space-y-2">
|
200
|
+
<h3 class="text-lg font-semibold">Styling</h3>
|
201
|
+
<p class="text-sm text-muted-foreground">
|
202
|
+
The input component includes comprehensive styling with:
|
203
|
+
</p>
|
204
|
+
<ul class="list-disc list-inside space-y-1 text-sm text-muted-foreground">
|
205
|
+
<li>Rounded borders with <code class="text-xs bg-muted px-1.5 py-0.5 rounded">border-input</code> color</li>
|
206
|
+
<li>Transparent background that adapts to theme</li>
|
207
|
+
<li>Focus ring with <code class="text-xs bg-muted px-1.5 py-0.5 rounded">focus-visible:ring-1</code></li>
|
208
|
+
<li>Smooth transitions on color changes</li>
|
209
|
+
<li>File input styling with <code class="text-xs bg-muted px-1.5 py-0.5 rounded">file:</code> pseudo-element modifiers</li>
|
210
|
+
<li>Placeholder styling with muted foreground color</li>
|
211
|
+
<li>Disabled state with reduced opacity and not-allowed cursor</li>
|
212
|
+
</ul>
|
213
|
+
</div>
|
214
|
+
|
215
|
+
<div class="mt-6 space-y-2">
|
216
|
+
<h3 class="text-lg font-semibold">Accessibility</h3>
|
217
|
+
<ul class="list-disc list-inside space-y-1 text-sm text-muted-foreground">
|
218
|
+
<li>Supports all standard HTML input types for proper semantics</li>
|
219
|
+
<li>Use with <code class="text-xs bg-muted px-1.5 py-0.5 rounded">LabelComponent</code> to associate labels with inputs</li>
|
220
|
+
<li>Disabled state properly prevents interaction and updates cursor</li>
|
221
|
+
<li>Focus-visible ring ensures keyboard navigation visibility</li>
|
222
|
+
<li>Placeholder text uses muted color for better accessibility</li>
|
223
|
+
</ul>
|
224
|
+
</div>
|
225
|
+
|
226
|
+
<div class="mt-6 space-y-2">
|
227
|
+
<h3 class="text-lg font-semibold">Common Input Types</h3>
|
228
|
+
<div class="grid grid-cols-2 gap-4 text-sm">
|
229
|
+
<div>
|
230
|
+
<h4 class="font-semibold mb-2">Text Types</h4>
|
231
|
+
<ul class="list-disc list-inside space-y-1 text-muted-foreground">
|
232
|
+
<li><code class="text-xs bg-muted px-1.5 py-0.5 rounded">text</code> - Standard text input</li>
|
233
|
+
<li><code class="text-xs bg-muted px-1.5 py-0.5 rounded">email</code> - Email address input</li>
|
234
|
+
<li><code class="text-xs bg-muted px-1.5 py-0.5 rounded">password</code> - Password input (hidden)</li>
|
235
|
+
<li><code class="text-xs bg-muted px-1.5 py-0.5 rounded">tel</code> - Telephone number</li>
|
236
|
+
<li><code class="text-xs bg-muted px-1.5 py-0.5 rounded">url</code> - URL input</li>
|
237
|
+
<li><code class="text-xs bg-muted px-1.5 py-0.5 rounded">search</code> - Search input</li>
|
238
|
+
</ul>
|
239
|
+
</div>
|
240
|
+
<div>
|
241
|
+
<h4 class="font-semibold mb-2">Other Types</h4>
|
242
|
+
<ul class="list-disc list-inside space-y-1 text-muted-foreground">
|
243
|
+
<li><code class="text-xs bg-muted px-1.5 py-0.5 rounded">number</code> - Numeric input</li>
|
244
|
+
<li><code class="text-xs bg-muted px-1.5 py-0.5 rounded">date</code> - Date picker</li>
|
245
|
+
<li><code class="text-xs bg-muted px-1.5 py-0.5 rounded">time</code> - Time picker</li>
|
246
|
+
<li><code class="text-xs bg-muted px-1.5 py-0.5 rounded">datetime-local</code> - Date and time</li>
|
247
|
+
<li><code class="text-xs bg-muted px-1.5 py-0.5 rounded">file</code> - File upload</li>
|
248
|
+
<li><code class="text-xs bg-muted px-1.5 py-0.5 rounded">color</code> - Color picker</li>
|
249
|
+
</ul>
|
250
|
+
</div>
|
251
|
+
</div>
|
252
|
+
</div>
|
253
|
+
<% end %>
|
254
|
+
<% end %>
|
@@ -0,0 +1,128 @@
|
|
1
|
+
<%= render Docs::ComponentPageComponent.new(title: "Label") do |page| %>
|
2
|
+
<% page.with_header(
|
3
|
+
name: "Label",
|
4
|
+
description: "Renders an accessible label associated with form controls."
|
5
|
+
) %>
|
6
|
+
|
7
|
+
<% page.with_installation(component_name: "label") %>
|
8
|
+
|
9
|
+
<% page.with_usage do %>
|
10
|
+
<%= render Docs::CodeBlockComponent.new(
|
11
|
+
code: label_usage_code,
|
12
|
+
language: "erb"
|
13
|
+
) %>
|
14
|
+
<% end %>
|
15
|
+
|
16
|
+
<% page.with_examples do %>
|
17
|
+
<!-- Basic Label Example -->
|
18
|
+
<% basic_html = capture do %>
|
19
|
+
<%= render M9sh::LabelComponent.new(for_id: "email") do %>
|
20
|
+
Email
|
21
|
+
<% end %>
|
22
|
+
<% end %>
|
23
|
+
|
24
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
25
|
+
title: "Basic Label",
|
26
|
+
preview_content: basic_html,
|
27
|
+
code: label_usage_code,
|
28
|
+
ai_command: label_usage_code
|
29
|
+
) %>
|
30
|
+
|
31
|
+
<!-- Label with Input Field Example -->
|
32
|
+
<% with_input_html = capture do %>
|
33
|
+
<div class="space-y-2 w-full max-w-sm">
|
34
|
+
<%= render M9sh::LabelComponent.new(for_id: "email") do %>
|
35
|
+
Email
|
36
|
+
<% end %>
|
37
|
+
<input
|
38
|
+
id="email"
|
39
|
+
type="email"
|
40
|
+
placeholder="Enter your email"
|
41
|
+
class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
42
|
+
/>
|
43
|
+
</div>
|
44
|
+
<% end %>
|
45
|
+
|
46
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
47
|
+
title: "Label with Input Field",
|
48
|
+
preview_content: with_input_html,
|
49
|
+
code: label_with_input_code,
|
50
|
+
ai_command: label_with_input_code
|
51
|
+
) %>
|
52
|
+
|
53
|
+
<!-- Label with Required Indicator Example -->
|
54
|
+
<% required_html = capture do %>
|
55
|
+
<div class="space-y-2 w-full max-w-sm">
|
56
|
+
<%= render M9sh::LabelComponent.new(for_id: "username") do %>
|
57
|
+
Username <span class="text-destructive">*</span>
|
58
|
+
<% end %>
|
59
|
+
<input
|
60
|
+
id="username"
|
61
|
+
type="text"
|
62
|
+
placeholder="Enter your username"
|
63
|
+
required
|
64
|
+
class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
65
|
+
/>
|
66
|
+
</div>
|
67
|
+
<% end %>
|
68
|
+
|
69
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
70
|
+
title: "Label with Required Indicator",
|
71
|
+
preview_content: required_html,
|
72
|
+
code: label_with_required_code,
|
73
|
+
ai_command: label_with_required_code
|
74
|
+
) %>
|
75
|
+
|
76
|
+
<!-- Label with Disabled Input Example -->
|
77
|
+
<% disabled_html = capture do %>
|
78
|
+
<div class="space-y-2 w-full max-w-sm group" data-disabled="true">
|
79
|
+
<%= render M9sh::LabelComponent.new(for_id: "disabled-input") do %>
|
80
|
+
Disabled Field
|
81
|
+
<% end %>
|
82
|
+
<input
|
83
|
+
id="disabled-input"
|
84
|
+
type="text"
|
85
|
+
placeholder="This field is disabled"
|
86
|
+
disabled
|
87
|
+
class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
88
|
+
/>
|
89
|
+
</div>
|
90
|
+
<% end %>
|
91
|
+
|
92
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
93
|
+
title: "Label with Disabled Input",
|
94
|
+
preview_content: disabled_html,
|
95
|
+
code: label_with_disabled_code,
|
96
|
+
ai_command: label_with_disabled_code
|
97
|
+
) %>
|
98
|
+
<% end %>
|
99
|
+
|
100
|
+
<% page.with_api do %>
|
101
|
+
<%= render Docs::PropTableComponent.new(
|
102
|
+
props: [
|
103
|
+
{
|
104
|
+
name: "for_id",
|
105
|
+
type: "String",
|
106
|
+
default: "nil",
|
107
|
+
description: "The ID of the form control this label is associated with. Sets the HTML 'for' attribute."
|
108
|
+
},
|
109
|
+
{
|
110
|
+
name: "**extra_attrs",
|
111
|
+
type: "Hash",
|
112
|
+
default: "{}",
|
113
|
+
description: "Additional HTML attributes to apply to the label element (e.g., class, data attributes)."
|
114
|
+
}
|
115
|
+
]
|
116
|
+
) %>
|
117
|
+
|
118
|
+
<div class="mt-6 space-y-2">
|
119
|
+
<h3 class="text-lg font-semibold">Accessibility</h3>
|
120
|
+
<ul class="list-disc list-inside space-y-1 text-sm text-muted-foreground">
|
121
|
+
<li>The label uses the <code class="text-xs bg-muted px-1.5 py-0.5 rounded">for</code> attribute to associate with form controls</li>
|
122
|
+
<li>Labels are not selectable using the <code class="text-xs bg-muted px-1.5 py-0.5 rounded">select-none</code> class</li>
|
123
|
+
<li>Automatically responds to disabled state via <code class="text-xs bg-muted px-1.5 py-0.5 rounded">group-data-[disabled=true]</code> and <code class="text-xs bg-muted px-1.5 py-0.5 rounded">peer-disabled</code> selectors</li>
|
124
|
+
<li>Includes a <code class="text-xs bg-muted px-1.5 py-0.5 rounded">data-slot="label"</code> attribute for component composition</li>
|
125
|
+
</ul>
|
126
|
+
</div>
|
127
|
+
<% end %>
|
128
|
+
<% end %>
|