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,259 @@
|
|
1
|
+
<%= render Docs::ComponentPageComponent.new(title: "Table") do |page| %>
|
2
|
+
<% page.with_header(
|
3
|
+
name: "Table",
|
4
|
+
description: "A responsive table component for displaying data in rows and columns."
|
5
|
+
) %>
|
6
|
+
|
7
|
+
<% page.with_installation(component_name: "table") %>
|
8
|
+
|
9
|
+
<% page.with_usage do %>
|
10
|
+
<%= render Docs::CodeBlockComponent.new(
|
11
|
+
code: table_usage_code,
|
12
|
+
language: "erb"
|
13
|
+
) %>
|
14
|
+
<% end %>
|
15
|
+
|
16
|
+
<% page.with_examples do %>
|
17
|
+
<!-- Default Example -->
|
18
|
+
<% default_html = capture do %>
|
19
|
+
<%= render M9sh::TableComponent.new do %>
|
20
|
+
<%= render M9sh::TableComponent::HeaderComponent.new do %>
|
21
|
+
<%= render M9sh::TableComponent::RowComponent.new do %>
|
22
|
+
<%= render M9sh::TableComponent::HeadComponent.new do %>
|
23
|
+
Name
|
24
|
+
<% end %>
|
25
|
+
<%= render M9sh::TableComponent::HeadComponent.new do %>
|
26
|
+
Email
|
27
|
+
<% end %>
|
28
|
+
<%= render M9sh::TableComponent::HeadComponent.new do %>
|
29
|
+
Role
|
30
|
+
<% end %>
|
31
|
+
<% end %>
|
32
|
+
<% end %>
|
33
|
+
|
34
|
+
<%= render M9sh::TableComponent::BodyComponent.new do %>
|
35
|
+
<%= render M9sh::TableComponent::RowComponent.new do %>
|
36
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
37
|
+
John Doe
|
38
|
+
<% end %>
|
39
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
40
|
+
john@example.com
|
41
|
+
<% end %>
|
42
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
43
|
+
Admin
|
44
|
+
<% end %>
|
45
|
+
<% end %>
|
46
|
+
|
47
|
+
<%= render M9sh::TableComponent::RowComponent.new do %>
|
48
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
49
|
+
Jane Smith
|
50
|
+
<% end %>
|
51
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
52
|
+
jane@example.com
|
53
|
+
<% end %>
|
54
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
55
|
+
User
|
56
|
+
<% end %>
|
57
|
+
<% end %>
|
58
|
+
|
59
|
+
<%= render M9sh::TableComponent::RowComponent.new do %>
|
60
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
61
|
+
Bob Johnson
|
62
|
+
<% end %>
|
63
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
64
|
+
bob@example.com
|
65
|
+
<% end %>
|
66
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
67
|
+
User
|
68
|
+
<% end %>
|
69
|
+
<% end %>
|
70
|
+
<% end %>
|
71
|
+
<% end %>
|
72
|
+
<% end %>
|
73
|
+
|
74
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
75
|
+
title: "Default",
|
76
|
+
preview_content: default_html,
|
77
|
+
code: table_default_code,
|
78
|
+
ai_command: table_default_code
|
79
|
+
) %>
|
80
|
+
|
81
|
+
<!-- With Caption Example -->
|
82
|
+
<% caption_html = capture do %>
|
83
|
+
<%= render M9sh::TableComponent.new do %>
|
84
|
+
<%= render M9sh::TableComponent::CaptionComponent.new do %>
|
85
|
+
A list of your recent invoices.
|
86
|
+
<% end %>
|
87
|
+
|
88
|
+
<%= render M9sh::TableComponent::HeaderComponent.new do %>
|
89
|
+
<%= render M9sh::TableComponent::RowComponent.new do %>
|
90
|
+
<%= render M9sh::TableComponent::HeadComponent.new do %>
|
91
|
+
Invoice
|
92
|
+
<% end %>
|
93
|
+
<%= render M9sh::TableComponent::HeadComponent.new do %>
|
94
|
+
Status
|
95
|
+
<% end %>
|
96
|
+
<%= render M9sh::TableComponent::HeadComponent.new do %>
|
97
|
+
Amount
|
98
|
+
<% end %>
|
99
|
+
<% end %>
|
100
|
+
<% end %>
|
101
|
+
|
102
|
+
<%= render M9sh::TableComponent::BodyComponent.new do %>
|
103
|
+
<%= render M9sh::TableComponent::RowComponent.new do %>
|
104
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
105
|
+
INV001
|
106
|
+
<% end %>
|
107
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
108
|
+
Paid
|
109
|
+
<% end %>
|
110
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
111
|
+
$250.00
|
112
|
+
<% end %>
|
113
|
+
<% end %>
|
114
|
+
|
115
|
+
<%= render M9sh::TableComponent::RowComponent.new do %>
|
116
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
117
|
+
INV002
|
118
|
+
<% end %>
|
119
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
120
|
+
Pending
|
121
|
+
<% end %>
|
122
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
123
|
+
$150.00
|
124
|
+
<% end %>
|
125
|
+
<% end %>
|
126
|
+
<% end %>
|
127
|
+
<% end %>
|
128
|
+
<% end %>
|
129
|
+
|
130
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
131
|
+
title: "With Caption",
|
132
|
+
preview_content: caption_html,
|
133
|
+
code: table_caption_code,
|
134
|
+
ai_command: table_caption_code
|
135
|
+
) %>
|
136
|
+
|
137
|
+
<!-- With Footer Example -->
|
138
|
+
<% footer_html = capture do %>
|
139
|
+
<%= render M9sh::TableComponent.new do %>
|
140
|
+
<%= render M9sh::TableComponent::HeaderComponent.new do %>
|
141
|
+
<%= render M9sh::TableComponent::RowComponent.new do %>
|
142
|
+
<%= render M9sh::TableComponent::HeadComponent.new do %>
|
143
|
+
Product
|
144
|
+
<% end %>
|
145
|
+
<%= render M9sh::TableComponent::HeadComponent.new do %>
|
146
|
+
Quantity
|
147
|
+
<% end %>
|
148
|
+
<%= render M9sh::TableComponent::HeadComponent.new do %>
|
149
|
+
Price
|
150
|
+
<% end %>
|
151
|
+
<% end %>
|
152
|
+
<% end %>
|
153
|
+
|
154
|
+
<%= render M9sh::TableComponent::BodyComponent.new do %>
|
155
|
+
<%= render M9sh::TableComponent::RowComponent.new do %>
|
156
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
157
|
+
Widget A
|
158
|
+
<% end %>
|
159
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
160
|
+
5
|
161
|
+
<% end %>
|
162
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
163
|
+
$50.00
|
164
|
+
<% end %>
|
165
|
+
<% end %>
|
166
|
+
|
167
|
+
<%= render M9sh::TableComponent::RowComponent.new do %>
|
168
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
169
|
+
Widget B
|
170
|
+
<% end %>
|
171
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
172
|
+
3
|
173
|
+
<% end %>
|
174
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
175
|
+
$30.00
|
176
|
+
<% end %>
|
177
|
+
<% end %>
|
178
|
+
<% end %>
|
179
|
+
|
180
|
+
<%= render M9sh::TableComponent::FooterComponent.new do %>
|
181
|
+
<%= render M9sh::TableComponent::RowComponent.new do %>
|
182
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
183
|
+
Total
|
184
|
+
<% end %>
|
185
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
186
|
+
8
|
187
|
+
<% end %>
|
188
|
+
<%= render M9sh::TableComponent::CellComponent.new do %>
|
189
|
+
$80.00
|
190
|
+
<% end %>
|
191
|
+
<% end %>
|
192
|
+
<% end %>
|
193
|
+
<% end %>
|
194
|
+
<% end %>
|
195
|
+
|
196
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
197
|
+
title: "With Footer",
|
198
|
+
preview_content: footer_html,
|
199
|
+
code: table_footer_code,
|
200
|
+
ai_command: table_footer_code
|
201
|
+
) %>
|
202
|
+
<% end %>
|
203
|
+
|
204
|
+
<% page.with_api do %>
|
205
|
+
<h3 class="text-lg font-semibold">Sub-components</h3>
|
206
|
+
<%= render Docs::PropTableComponent.new(
|
207
|
+
props: [
|
208
|
+
{
|
209
|
+
name: "TableComponent",
|
210
|
+
type: "Component",
|
211
|
+
default: nil,
|
212
|
+
description: "The main table wrapper with overflow handling"
|
213
|
+
},
|
214
|
+
{
|
215
|
+
name: "HeaderComponent",
|
216
|
+
type: "Component",
|
217
|
+
default: nil,
|
218
|
+
description: "The table header (<thead>) section"
|
219
|
+
},
|
220
|
+
{
|
221
|
+
name: "BodyComponent",
|
222
|
+
type: "Component",
|
223
|
+
default: nil,
|
224
|
+
description: "The table body (<tbody>) section"
|
225
|
+
},
|
226
|
+
{
|
227
|
+
name: "FooterComponent",
|
228
|
+
type: "Component",
|
229
|
+
default: nil,
|
230
|
+
description: "The table footer (<tfoot>) section"
|
231
|
+
},
|
232
|
+
{
|
233
|
+
name: "RowComponent",
|
234
|
+
type: "Component",
|
235
|
+
default: nil,
|
236
|
+
description: "A table row (<tr>) with hover effects"
|
237
|
+
},
|
238
|
+
{
|
239
|
+
name: "HeadComponent",
|
240
|
+
type: "Component",
|
241
|
+
default: nil,
|
242
|
+
description: "A table header cell (<th>)"
|
243
|
+
},
|
244
|
+
{
|
245
|
+
name: "CellComponent",
|
246
|
+
type: "Component",
|
247
|
+
default: nil,
|
248
|
+
description: "A table data cell (<td>)"
|
249
|
+
},
|
250
|
+
{
|
251
|
+
name: "CaptionComponent",
|
252
|
+
type: "Component",
|
253
|
+
default: nil,
|
254
|
+
description: "A table caption describing the table content"
|
255
|
+
}
|
256
|
+
]
|
257
|
+
) %>
|
258
|
+
<% end %>
|
259
|
+
<% end %>
|
@@ -0,0 +1,225 @@
|
|
1
|
+
<%= render Docs::ComponentPageComponent.new(title: "Tabs") do |page| %>
|
2
|
+
<% page.with_header(
|
3
|
+
name: "Tabs",
|
4
|
+
description: "A set of layered sections of content—known as tab panels—that are displayed one at a time."
|
5
|
+
) %>
|
6
|
+
|
7
|
+
<% page.with_installation(component_name: "tabs") %>
|
8
|
+
|
9
|
+
<% page.with_usage do %>
|
10
|
+
<%= render Docs::CodeBlockComponent.new(
|
11
|
+
code: tabs_usage_code,
|
12
|
+
language: "erb"
|
13
|
+
) %>
|
14
|
+
<% end %>
|
15
|
+
|
16
|
+
<% page.with_examples do %>
|
17
|
+
<!-- Simple Example -->
|
18
|
+
<% simple_tabs_html = capture do %>
|
19
|
+
<div class="w-full max-w-md">
|
20
|
+
<%= render M9sh::TabsComponent.new(default_value: "tab1") do |tabs| %>
|
21
|
+
<% tabs.with_tabs_list do |list| %>
|
22
|
+
<%= render list.tabs_trigger(value: "tab1") { "Tab 1" } %>
|
23
|
+
<%= render list.tabs_trigger(value: "tab2") { "Tab 2" } %>
|
24
|
+
<%= render list.tabs_trigger(value: "tab3") { "Tab 3" } %>
|
25
|
+
<% end %>
|
26
|
+
|
27
|
+
<% tabs.with_tabs_content(value: "tab1") do %>
|
28
|
+
<p class="text-sm">Content for tab 1</p>
|
29
|
+
<% end %>
|
30
|
+
|
31
|
+
<% tabs.with_tabs_content(value: "tab2") do %>
|
32
|
+
<p class="text-sm">Content for tab 2</p>
|
33
|
+
<% end %>
|
34
|
+
|
35
|
+
<% tabs.with_tabs_content(value: "tab3") do %>
|
36
|
+
<p class="text-sm">Content for tab 3</p>
|
37
|
+
<% end %>
|
38
|
+
<% end %>
|
39
|
+
</div>
|
40
|
+
<% end %>
|
41
|
+
|
42
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
43
|
+
title: "Simple tabs",
|
44
|
+
preview_content: simple_tabs_html,
|
45
|
+
code: tabs_simple_code,
|
46
|
+
ai_command: tabs_simple_code
|
47
|
+
) %>
|
48
|
+
|
49
|
+
<!-- Default Example with Rich Content -->
|
50
|
+
<% default_tabs_html = capture do %>
|
51
|
+
<div class="w-full max-w-2xl">
|
52
|
+
<%= render M9sh::TabsComponent.new(default_value: "account") do |tabs| %>
|
53
|
+
<% tabs.with_tabs_list do |list| %>
|
54
|
+
<%= render list.tabs_trigger(value: "account") { "Account" } %>
|
55
|
+
<%= render list.tabs_trigger(value: "password") { "Password" } %>
|
56
|
+
<% end %>
|
57
|
+
|
58
|
+
<% tabs.with_tabs_content(value: "account") do %>
|
59
|
+
<div class="space-y-4">
|
60
|
+
<div class="space-y-2">
|
61
|
+
<h3 class="text-lg font-medium">Account Settings</h3>
|
62
|
+
<p class="text-sm text-muted-foreground">
|
63
|
+
Make changes to your account here. Click save when you're done.
|
64
|
+
</p>
|
65
|
+
</div>
|
66
|
+
<div class="space-y-2">
|
67
|
+
<label class="text-sm font-medium">Name</label>
|
68
|
+
<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" />
|
69
|
+
</div>
|
70
|
+
<div class="space-y-2">
|
71
|
+
<label class="text-sm font-medium">Email</label>
|
72
|
+
<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" />
|
73
|
+
</div>
|
74
|
+
</div>
|
75
|
+
<% end %>
|
76
|
+
|
77
|
+
<% tabs.with_tabs_content(value: "password") do %>
|
78
|
+
<div class="space-y-4">
|
79
|
+
<div class="space-y-2">
|
80
|
+
<h3 class="text-lg font-medium">Password Settings</h3>
|
81
|
+
<p class="text-sm text-muted-foreground">
|
82
|
+
Change your password here. After saving, you'll be logged out.
|
83
|
+
</p>
|
84
|
+
</div>
|
85
|
+
<div class="space-y-2">
|
86
|
+
<label class="text-sm font-medium">Current Password</label>
|
87
|
+
<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" />
|
88
|
+
</div>
|
89
|
+
<div class="space-y-2">
|
90
|
+
<label class="text-sm font-medium">New Password</label>
|
91
|
+
<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" />
|
92
|
+
</div>
|
93
|
+
</div>
|
94
|
+
<% end %>
|
95
|
+
<% end %>
|
96
|
+
</div>
|
97
|
+
<% end %>
|
98
|
+
|
99
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
100
|
+
title: "Tabs with rich content",
|
101
|
+
preview_content: default_tabs_html,
|
102
|
+
code: tabs_default_code,
|
103
|
+
ai_command: tabs_default_code
|
104
|
+
) %>
|
105
|
+
|
106
|
+
<!-- Multiple Tab Groups Example -->
|
107
|
+
<% multiple_tabs_html = capture do %>
|
108
|
+
<div class="w-full max-w-2xl">
|
109
|
+
<div class="space-y-8">
|
110
|
+
<div>
|
111
|
+
<h3 class="text-lg font-semibold mb-4">User Settings</h3>
|
112
|
+
<%= render M9sh::TabsComponent.new(default_value: "profile") do |tabs| %>
|
113
|
+
<% tabs.with_tabs_list do |list| %>
|
114
|
+
<%= render list.tabs_trigger(value: "profile") { "Profile" } %>
|
115
|
+
<%= render list.tabs_trigger(value: "preferences") { "Preferences" } %>
|
116
|
+
<% end %>
|
117
|
+
|
118
|
+
<% tabs.with_tabs_content(value: "profile") do %>
|
119
|
+
<p class="text-sm">Profile settings content</p>
|
120
|
+
<% end %>
|
121
|
+
|
122
|
+
<% tabs.with_tabs_content(value: "preferences") do %>
|
123
|
+
<p class="text-sm">Preferences content</p>
|
124
|
+
<% end %>
|
125
|
+
<% end %>
|
126
|
+
</div>
|
127
|
+
|
128
|
+
<div>
|
129
|
+
<h3 class="text-lg font-semibold mb-4">System Settings</h3>
|
130
|
+
<%= render M9sh::TabsComponent.new(default_value: "general") do |tabs| %>
|
131
|
+
<% tabs.with_tabs_list do |list| %>
|
132
|
+
<%= render list.tabs_trigger(value: "general") { "General" } %>
|
133
|
+
<%= render list.tabs_trigger(value: "advanced") { "Advanced" } %>
|
134
|
+
<% end %>
|
135
|
+
|
136
|
+
<% tabs.with_tabs_content(value: "general") do %>
|
137
|
+
<p class="text-sm">General settings content</p>
|
138
|
+
<% end %>
|
139
|
+
|
140
|
+
<% tabs.with_tabs_content(value: "advanced") do %>
|
141
|
+
<p class="text-sm">Advanced settings content</p>
|
142
|
+
<% end %>
|
143
|
+
<% end %>
|
144
|
+
</div>
|
145
|
+
</div>
|
146
|
+
</div>
|
147
|
+
<% end %>
|
148
|
+
|
149
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
150
|
+
title: "Multiple independent tab groups",
|
151
|
+
preview_content: multiple_tabs_html,
|
152
|
+
code: tabs_multiple_groups_code,
|
153
|
+
ai_command: tabs_multiple_groups_code
|
154
|
+
) %>
|
155
|
+
<% end %>
|
156
|
+
|
157
|
+
<% page.with_api do %>
|
158
|
+
<h3 class="text-lg font-semibold">TabsComponent</h3>
|
159
|
+
<%= render Docs::PropTableComponent.new(
|
160
|
+
props: [
|
161
|
+
{
|
162
|
+
name: "default_value",
|
163
|
+
type: "String",
|
164
|
+
default: "nil",
|
165
|
+
description: "The value of the tab that should be active by default"
|
166
|
+
}
|
167
|
+
]
|
168
|
+
) %>
|
169
|
+
|
170
|
+
<h3 class="text-lg font-semibold mt-6">Slots</h3>
|
171
|
+
|
172
|
+
<div class="mt-4 space-y-4">
|
173
|
+
<div>
|
174
|
+
<h4 class="text-base font-semibold">tabs_list</h4>
|
175
|
+
<p class="text-sm text-muted-foreground mt-1">
|
176
|
+
Container for tab triggers. Use <code class="text-xs bg-muted px-1 py-0.5 rounded">with_tabs_list</code> to define the list of tab buttons.
|
177
|
+
</p>
|
178
|
+
</div>
|
179
|
+
|
180
|
+
<div>
|
181
|
+
<h4 class="text-base font-semibold">tabs_content</h4>
|
182
|
+
<p class="text-sm text-muted-foreground mt-1">
|
183
|
+
Individual tab panel content. Use <code class="text-xs bg-muted px-1 py-0.5 rounded">with_tabs_content(value:)</code> for each tab's content.
|
184
|
+
</p>
|
185
|
+
<%= render Docs::PropTableComponent.new(
|
186
|
+
props: [
|
187
|
+
{
|
188
|
+
name: "value",
|
189
|
+
type: "String",
|
190
|
+
default: nil,
|
191
|
+
description: "A unique identifier that matches the trigger value (required)"
|
192
|
+
}
|
193
|
+
]
|
194
|
+
) %>
|
195
|
+
</div>
|
196
|
+
</div>
|
197
|
+
|
198
|
+
<h3 class="text-lg font-semibold mt-6">TabsTriggerComponent</h3>
|
199
|
+
<p class="text-sm text-muted-foreground mt-1 mb-4">
|
200
|
+
Created via <code class="text-xs bg-muted px-1 py-0.5 rounded">list.tabs_trigger(value:)</code> within the <code class="text-xs bg-muted px-1 py-0.5 rounded">with_tabs_list</code> block.
|
201
|
+
</p>
|
202
|
+
<%= render Docs::PropTableComponent.new(
|
203
|
+
props: [
|
204
|
+
{
|
205
|
+
name: "value",
|
206
|
+
type: "String",
|
207
|
+
default: nil,
|
208
|
+
description: "A unique identifier that matches the content value (required)"
|
209
|
+
}
|
210
|
+
]
|
211
|
+
) %>
|
212
|
+
|
213
|
+
<h3 class="text-lg font-semibold mt-6">Usage Pattern</h3>
|
214
|
+
<div class="text-sm text-muted-foreground mt-2 space-y-2">
|
215
|
+
<p>The Tabs component uses a slot-based architecture:</p>
|
216
|
+
<ol class="list-decimal list-inside space-y-1 ml-2">
|
217
|
+
<li>Render the TabsComponent with a block parameter</li>
|
218
|
+
<li>Define the tab list with <code class="text-xs bg-muted px-1 py-0.5 rounded">with_tabs_list</code></li>
|
219
|
+
<li>Add triggers using <code class="text-xs bg-muted px-1 py-0.5 rounded">render list.tabs_trigger(value:)</code></li>
|
220
|
+
<li>Define content for each tab with <code class="text-xs bg-muted px-1 py-0.5 rounded">with_tabs_content(value:)</code></li>
|
221
|
+
<li>Each trigger's value must match its corresponding content's value</li>
|
222
|
+
</ol>
|
223
|
+
</div>
|
224
|
+
<% end %>
|
225
|
+
<% end %>
|