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,394 @@
|
|
1
|
+
<%= render Docs::ComponentPageComponent.new(title: "Navbar") do |page| %>
|
2
|
+
<% page.with_header(
|
3
|
+
name: "Navbar",
|
4
|
+
description: "A responsive navigation header component with logo, navigation links, and action buttons."
|
5
|
+
) %>
|
6
|
+
|
7
|
+
<% page.with_installation(component_name: "navbar") %>
|
8
|
+
|
9
|
+
<% page.with_usage do %>
|
10
|
+
<%= render Docs::CodeBlockComponent.new(
|
11
|
+
code: navbar_usage_code,
|
12
|
+
language: "erb"
|
13
|
+
) %>
|
14
|
+
<% end %>
|
15
|
+
|
16
|
+
<% page.with_examples do %>
|
17
|
+
<div class="space-y-8">
|
18
|
+
<div>
|
19
|
+
<h3 class="text-lg font-semibold mb-3">Live Example</h3>
|
20
|
+
<p class="text-muted-foreground mb-4">
|
21
|
+
The NavbarComponent is currently used throughout this application. You can see it in action at the top of this page!
|
22
|
+
</p>
|
23
|
+
</div>
|
24
|
+
|
25
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
26
|
+
title: "Transparent Navbar",
|
27
|
+
code: navbar_transparent_code,
|
28
|
+
mobile_optimized: true
|
29
|
+
) do %>
|
30
|
+
<div class="w-full bg-gradient-to-br from-blue-50 via-purple-50 to-pink-50 dark:from-blue-950 dark:via-purple-950 dark:to-pink-950 p-8">
|
31
|
+
<%= render M9sh::NavbarComponent.new(transparent: true, sticky: false) do |navbar| %>
|
32
|
+
<% navbar.with_brand do %>
|
33
|
+
<a href="#" class="flex items-center space-x-2">
|
34
|
+
<span class="font-bold text-xl text-foreground">Brand</span>
|
35
|
+
</a>
|
36
|
+
<% end %>
|
37
|
+
|
38
|
+
<% navbar.with_navigation do %>
|
39
|
+
<nav class="flex items-center gap-6">
|
40
|
+
<a href="#" class="text-sm font-medium text-foreground hover:text-foreground/80 transition-colors">Home</a>
|
41
|
+
<a href="#" class="text-sm font-medium text-foreground hover:text-foreground/80 transition-colors">About</a>
|
42
|
+
<a href="#" class="text-sm font-medium text-foreground hover:text-foreground/80 transition-colors">Services</a>
|
43
|
+
</nav>
|
44
|
+
<% end %>
|
45
|
+
|
46
|
+
<% navbar.with_actions do %>
|
47
|
+
<%= render M9sh::ButtonComponent.new(variant: :ghost, size: :sm) do %>
|
48
|
+
Get Started
|
49
|
+
<% end %>
|
50
|
+
<% end %>
|
51
|
+
<% end %>
|
52
|
+
</div>
|
53
|
+
<% end %>
|
54
|
+
|
55
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
56
|
+
title: "Full Width Navbar",
|
57
|
+
code: navbar_full_width_code,
|
58
|
+
mobile_optimized: true
|
59
|
+
) do %>
|
60
|
+
<div class="w-full">
|
61
|
+
<%= render M9sh::NavbarComponent.new(container: false, sticky: false) do |navbar| %>
|
62
|
+
<% navbar.with_brand do %>
|
63
|
+
<a href="#" class="font-bold text-xl">Full Width</a>
|
64
|
+
<% end %>
|
65
|
+
|
66
|
+
<% navbar.with_navigation do %>
|
67
|
+
<nav class="flex items-center gap-6">
|
68
|
+
<a href="#" class="text-sm font-medium">Features</a>
|
69
|
+
<a href="#" class="text-sm font-medium">Docs</a>
|
70
|
+
</nav>
|
71
|
+
<% end %>
|
72
|
+
|
73
|
+
<% navbar.with_actions do %>
|
74
|
+
<%= render M9sh::ButtonComponent.new(size: :sm) do %>
|
75
|
+
Sign Up
|
76
|
+
<% end %>
|
77
|
+
<% end %>
|
78
|
+
<% end %>
|
79
|
+
</div>
|
80
|
+
<% end %>
|
81
|
+
|
82
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
83
|
+
title: "Different Sizes",
|
84
|
+
code: navbar_sizes_code,
|
85
|
+
mobile_optimized: true
|
86
|
+
) do %>
|
87
|
+
<div class="w-full space-y-4">
|
88
|
+
<div class="rounded-lg border border-border overflow-hidden">
|
89
|
+
<%= render M9sh::NavbarComponent.new(size: :sm, sticky: false) do |navbar| %>
|
90
|
+
<% navbar.with_brand do %>
|
91
|
+
<a href="#" class="font-bold">Small</a>
|
92
|
+
<% end %>
|
93
|
+
<% navbar.with_actions do %>
|
94
|
+
<%= render M9sh::ButtonComponent.new(size: :sm) do %>
|
95
|
+
Action
|
96
|
+
<% end %>
|
97
|
+
<% end %>
|
98
|
+
<% end %>
|
99
|
+
</div>
|
100
|
+
|
101
|
+
<div class="rounded-lg border border-border overflow-hidden">
|
102
|
+
<%= render M9sh::NavbarComponent.new(sticky: false) do |navbar| %>
|
103
|
+
<% navbar.with_brand do %>
|
104
|
+
<a href="#" class="font-bold text-xl">Default</a>
|
105
|
+
<% end %>
|
106
|
+
<% navbar.with_actions do %>
|
107
|
+
<%= render M9sh::ButtonComponent.new(size: :sm) do %>
|
108
|
+
Action
|
109
|
+
<% end %>
|
110
|
+
<% end %>
|
111
|
+
<% end %>
|
112
|
+
</div>
|
113
|
+
|
114
|
+
<div class="rounded-lg border border-border overflow-hidden">
|
115
|
+
<%= render M9sh::NavbarComponent.new(size: :lg, sticky: false) do |navbar| %>
|
116
|
+
<% navbar.with_brand do %>
|
117
|
+
<a href="#" class="font-bold text-2xl">Large</a>
|
118
|
+
<% end %>
|
119
|
+
<% navbar.with_actions do %>
|
120
|
+
<%= render M9sh::ButtonComponent.new do %>
|
121
|
+
Action
|
122
|
+
<% end %>
|
123
|
+
<% end %>
|
124
|
+
<% end %>
|
125
|
+
</div>
|
126
|
+
</div>
|
127
|
+
<% end %>
|
128
|
+
|
129
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
130
|
+
title: "Blur Effect",
|
131
|
+
code: navbar_blur_code,
|
132
|
+
mobile_optimized: true
|
133
|
+
) do %>
|
134
|
+
<div class="w-full bg-gradient-to-r from-green-50 to-blue-50 dark:from-green-950 dark:to-blue-950 p-8">
|
135
|
+
<%= render M9sh::NavbarComponent.new(blur: true, sticky: false) do |navbar| %>
|
136
|
+
<% navbar.with_brand do %>
|
137
|
+
<a href="#" class="font-bold text-xl">Blur Effect</a>
|
138
|
+
<% end %>
|
139
|
+
|
140
|
+
<% navbar.with_navigation do %>
|
141
|
+
<nav class="flex items-center gap-6">
|
142
|
+
<a href="#" class="text-sm font-medium">Home</a>
|
143
|
+
<a href="#" class="text-sm font-medium">Products</a>
|
144
|
+
</nav>
|
145
|
+
<% end %>
|
146
|
+
|
147
|
+
<% navbar.with_actions do %>
|
148
|
+
<%= render M9sh::ButtonComponent.new(variant: :outline, size: :sm) do %>
|
149
|
+
Contact
|
150
|
+
<% end %>
|
151
|
+
<% end %>
|
152
|
+
<% end %>
|
153
|
+
</div>
|
154
|
+
<% end %>
|
155
|
+
|
156
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
157
|
+
title: "No Border",
|
158
|
+
code: navbar_no_border_code,
|
159
|
+
mobile_optimized: true
|
160
|
+
) do %>
|
161
|
+
<div class="w-full">
|
162
|
+
<%= render M9sh::NavbarComponent.new(border: false, sticky: false) do |navbar| %>
|
163
|
+
<% navbar.with_brand do %>
|
164
|
+
<a href="#" class="font-bold text-xl">No Border</a>
|
165
|
+
<% end %>
|
166
|
+
|
167
|
+
<% navbar.with_navigation do %>
|
168
|
+
<nav class="flex items-center gap-4">
|
169
|
+
<a href="#" class="text-sm">Link 1</a>
|
170
|
+
<a href="#" class="text-sm">Link 2</a>
|
171
|
+
</nav>
|
172
|
+
<% end %>
|
173
|
+
<% end %>
|
174
|
+
</div>
|
175
|
+
<% end %>
|
176
|
+
|
177
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
178
|
+
title: "Combined Options",
|
179
|
+
code: navbar_combined_options_code,
|
180
|
+
mobile_optimized: true
|
181
|
+
) do %>
|
182
|
+
<div class="w-full bg-gradient-to-br from-orange-50 via-red-50 to-pink-50 dark:from-orange-950 dark:via-red-950 dark:to-pink-950 p-8">
|
183
|
+
<%= render M9sh::NavbarComponent.new(
|
184
|
+
sticky: false,
|
185
|
+
transparent: true,
|
186
|
+
container: false,
|
187
|
+
size: :lg,
|
188
|
+
border: false
|
189
|
+
) do |navbar| %>
|
190
|
+
<% navbar.with_brand do %>
|
191
|
+
<a href="#" class="flex items-center space-x-2">
|
192
|
+
<span class="font-bold text-2xl">Custom</span>
|
193
|
+
</a>
|
194
|
+
<% end %>
|
195
|
+
|
196
|
+
<% navbar.with_navigation do %>
|
197
|
+
<nav class="flex items-center gap-6">
|
198
|
+
<a href="#" class="text-sm font-medium hover:text-primary transition-colors">Home</a>
|
199
|
+
<a href="#" class="text-sm font-medium hover:text-primary transition-colors">Features</a>
|
200
|
+
<a href="#" class="text-sm font-medium hover:text-primary transition-colors">Pricing</a>
|
201
|
+
<a href="#" class="text-sm font-medium hover:text-primary transition-colors">Contact</a>
|
202
|
+
</nav>
|
203
|
+
<% end %>
|
204
|
+
|
205
|
+
<% navbar.with_actions do %>
|
206
|
+
<%= render M9sh::ButtonComponent.new(variant: :ghost) do %>
|
207
|
+
Login
|
208
|
+
<% end %>
|
209
|
+
<% end %>
|
210
|
+
|
211
|
+
<% navbar.with_actions do %>
|
212
|
+
<%= render M9sh::ButtonComponent.new do %>
|
213
|
+
Get Started
|
214
|
+
<% end %>
|
215
|
+
<% end %>
|
216
|
+
<% end %>
|
217
|
+
</div>
|
218
|
+
<% end %>
|
219
|
+
|
220
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
221
|
+
title: "Mobile Menu",
|
222
|
+
code: navbar_mobile_menu_code,
|
223
|
+
mobile_optimized: true
|
224
|
+
) do %>
|
225
|
+
<div class="w-full">
|
226
|
+
<%= render M9sh::NavbarComponent.new(sticky: false) do |navbar| %>
|
227
|
+
<% navbar.with_brand do %>
|
228
|
+
<a href="#" class="font-bold text-xl">Brand</a>
|
229
|
+
<% end %>
|
230
|
+
|
231
|
+
<% navbar.with_navigation do %>
|
232
|
+
<nav class="flex items-center gap-6">
|
233
|
+
<a href="#" class="text-sm font-medium">Home</a>
|
234
|
+
<a href="#" class="text-sm font-medium">About</a>
|
235
|
+
<a href="#" class="text-sm font-medium">Services</a>
|
236
|
+
</nav>
|
237
|
+
<% end %>
|
238
|
+
|
239
|
+
<% navbar.with_actions do %>
|
240
|
+
<%= render M9sh::ButtonComponent.new(variant: :ghost, size: :sm) do %>
|
241
|
+
Login
|
242
|
+
<% end %>
|
243
|
+
<% end %>
|
244
|
+
|
245
|
+
<% navbar.with_actions do %>
|
246
|
+
<%= render M9sh::ButtonComponent.new(size: :sm) do %>
|
247
|
+
Sign Up
|
248
|
+
<% end %>
|
249
|
+
<% end %>
|
250
|
+
|
251
|
+
<% navbar.with_mobile_menu do %>
|
252
|
+
<%= render M9sh::DropdownMenuItemComponent.new(href: "#") do %>
|
253
|
+
Home
|
254
|
+
<% end %>
|
255
|
+
<%= render M9sh::DropdownMenuItemComponent.new(href: "#") do %>
|
256
|
+
About
|
257
|
+
<% end %>
|
258
|
+
<%= render M9sh::DropdownMenuItemComponent.new(href: "#") do %>
|
259
|
+
Services
|
260
|
+
<% end %>
|
261
|
+
<%= render M9sh::DropdownMenuSeparatorComponent.new %>
|
262
|
+
<%= render M9sh::DropdownMenuItemComponent.new(href: "#") do %>
|
263
|
+
Login
|
264
|
+
<% end %>
|
265
|
+
<%= render M9sh::DropdownMenuItemComponent.new(href: "#") do %>
|
266
|
+
Sign Up
|
267
|
+
<% end %>
|
268
|
+
<% end %>
|
269
|
+
<% end %>
|
270
|
+
</div>
|
271
|
+
<% end %>
|
272
|
+
|
273
|
+
<div class="mt-6">
|
274
|
+
<h3 class="text-lg font-semibold mb-3">More Examples</h3>
|
275
|
+
<p class="text-muted-foreground">
|
276
|
+
For complex real-world examples, check the layout files:
|
277
|
+
</p>
|
278
|
+
<ul class="list-disc list-inside text-sm text-muted-foreground space-y-1 ml-4 mt-2">
|
279
|
+
<li><code class="text-xs bg-muted px-1 py-0.5 rounded">app/views/layouts/application.html.erb</code> - Homepage navbar</li>
|
280
|
+
<li><code class="text-xs bg-muted px-1 py-0.5 rounded">app/views/layouts/docs.html.erb</code> - Documentation navbar (this page)</li>
|
281
|
+
<li><code class="text-xs bg-muted px-1 py-0.5 rounded">app/views/layouts/blocks.html.erb</code> - Blocks navbar</li>
|
282
|
+
</ul>
|
283
|
+
</div>
|
284
|
+
</div>
|
285
|
+
<% end %>
|
286
|
+
|
287
|
+
<% page.with_api do %>
|
288
|
+
<h3 class="text-lg font-semibold">NavbarComponent</h3>
|
289
|
+
|
290
|
+
<%= render Docs::PropTableComponent.new(
|
291
|
+
props: [
|
292
|
+
{
|
293
|
+
name: "sticky",
|
294
|
+
type: "Boolean",
|
295
|
+
default: "true",
|
296
|
+
description: "Whether the navbar should stick to the top of the viewport"
|
297
|
+
},
|
298
|
+
{
|
299
|
+
name: "transparent",
|
300
|
+
type: "Boolean",
|
301
|
+
default: "false",
|
302
|
+
description: "Whether to use a transparent backdrop-blur effect (glassmorphism)"
|
303
|
+
},
|
304
|
+
{
|
305
|
+
name: "container",
|
306
|
+
type: "Boolean",
|
307
|
+
default: "true",
|
308
|
+
description: "Whether to constrain content width with container class. Set to false for full width."
|
309
|
+
},
|
310
|
+
{
|
311
|
+
name: "size",
|
312
|
+
type: "Symbol",
|
313
|
+
default: ":default",
|
314
|
+
description: "Navbar height - :sm (48px), :default (64px), or :lg (80px)"
|
315
|
+
},
|
316
|
+
{
|
317
|
+
name: "border",
|
318
|
+
type: "Boolean",
|
319
|
+
default: "true",
|
320
|
+
description: "Whether to show bottom border"
|
321
|
+
},
|
322
|
+
{
|
323
|
+
name: "blur",
|
324
|
+
type: "Boolean",
|
325
|
+
default: "false",
|
326
|
+
description: "Add subtle blur effect without transparency"
|
327
|
+
}
|
328
|
+
]
|
329
|
+
) %>
|
330
|
+
|
331
|
+
<h3 class="text-lg font-semibold mt-6">Slots</h3>
|
332
|
+
|
333
|
+
<div class="mt-4 space-y-4">
|
334
|
+
<div>
|
335
|
+
<h4 class="text-base font-semibold">brand</h4>
|
336
|
+
<p class="text-sm text-muted-foreground mt-1">
|
337
|
+
Logo or brand section, typically on the left side. Use <code class="text-xs bg-muted px-1 py-0.5 rounded">with_brand</code> to define the brand content.
|
338
|
+
</p>
|
339
|
+
</div>
|
340
|
+
|
341
|
+
<div>
|
342
|
+
<h4 class="text-base font-semibold">navigation</h4>
|
343
|
+
<p class="text-sm text-muted-foreground mt-1">
|
344
|
+
Main navigation area, can contain links or a NavigationMenuComponent. Use <code class="text-xs bg-muted px-1 py-0.5 rounded">with_navigation</code> to define navigation content.
|
345
|
+
</p>
|
346
|
+
</div>
|
347
|
+
|
348
|
+
<div>
|
349
|
+
<h4 class="text-base font-semibold">actions</h4>
|
350
|
+
<p class="text-sm text-muted-foreground mt-1">
|
351
|
+
Action buttons on the right side (login, theme toggle, etc.). Use <code class="text-xs bg-muted px-1 py-0.5 rounded">with_actions</code> multiple times for multiple buttons.
|
352
|
+
</p>
|
353
|
+
</div>
|
354
|
+
|
355
|
+
<div>
|
356
|
+
<h4 class="text-base font-semibold">mobile_menu</h4>
|
357
|
+
<p class="text-sm text-muted-foreground mt-1">
|
358
|
+
Optional mobile menu content. Use <code class="text-xs bg-muted px-1 py-0.5 rounded">with_mobile_menu</code> to define mobile-specific navigation.
|
359
|
+
</p>
|
360
|
+
</div>
|
361
|
+
</div>
|
362
|
+
|
363
|
+
<div class="mt-6 space-y-2">
|
364
|
+
<h3 class="text-lg font-semibold">Usage Notes</h3>
|
365
|
+
<ul class="list-disc list-inside text-sm text-muted-foreground space-y-1">
|
366
|
+
<li>The navbar uses a container with responsive padding by default</li>
|
367
|
+
<li>The brand and navigation are grouped on the left</li>
|
368
|
+
<li>Actions appear on the right side</li>
|
369
|
+
<li>Three height options: 48px (sm), 64px (default), 80px (lg)</li>
|
370
|
+
<li>Navigation is automatically hidden on mobile (md breakpoint)</li>
|
371
|
+
<li>Desktop actions are automatically hidden on mobile (md breakpoint)</li>
|
372
|
+
<li>When <code class="text-xs bg-muted px-1 py-0.5 rounded">mobile_menu</code> is provided, a hamburger button appears on mobile</li>
|
373
|
+
<li>The hamburger button opens a dropdown menu below it with the mobile menu content</li>
|
374
|
+
<li>Use <code class="text-xs bg-muted px-1 py-0.5 rounded">DropdownMenuItemComponent</code> inside the mobile menu for menu items</li>
|
375
|
+
<li>Use <code class="text-xs bg-muted px-1 py-0.5 rounded">sticky: true</code> to make the navbar stick to the top</li>
|
376
|
+
<li>Use <code class="text-xs bg-muted px-1 py-0.5 rounded">transparent: true</code> for a glassmorphism effect</li>
|
377
|
+
<li>Use <code class="text-xs bg-muted px-1 py-0.5 rounded">blur: true</code> for a subtle blur without transparency</li>
|
378
|
+
<li>Use <code class="text-xs bg-muted px-1 py-0.5 rounded">container: false</code> to span the full viewport width</li>
|
379
|
+
<li>Use <code class="text-xs bg-muted px-1 py-0.5 rounded">border: false</code> to remove the bottom border</li>
|
380
|
+
<li>Combine with NavigationMenuComponent for dropdown menus</li>
|
381
|
+
<li>All options can be combined to create custom navbar styles</li>
|
382
|
+
</ul>
|
383
|
+
</div>
|
384
|
+
|
385
|
+
<div class="mt-6 space-y-2">
|
386
|
+
<h3 class="text-lg font-semibold">Related Components</h3>
|
387
|
+
<ul class="list-disc list-inside text-sm text-muted-foreground space-y-1">
|
388
|
+
<li><a href="/docs/navigation_menu" class="text-primary hover:underline">NavigationMenuComponent</a> - For dropdown navigation menus</li>
|
389
|
+
<li><a href="/docs/dropdown_menu" class="text-primary hover:underline">DropdownMenuComponent</a> - Automatically used for mobile menu dropdown</li>
|
390
|
+
<li><a href="/docs/button" class="text-primary hover:underline">ButtonComponent</a> - For action buttons</li>
|
391
|
+
</ul>
|
392
|
+
</div>
|
393
|
+
<% end %>
|
394
|
+
<% end %>
|
@@ -0,0 +1,226 @@
|
|
1
|
+
<%= render Docs::ComponentPageComponent.new(title: "Navigation Menu") do |page| %>
|
2
|
+
<% page.with_header(
|
3
|
+
name: "Navigation Menu",
|
4
|
+
description: "A collection of links for navigating websites."
|
5
|
+
) %>
|
6
|
+
|
7
|
+
<% page.with_installation(component_name: "navigation_menu") %>
|
8
|
+
|
9
|
+
<% page.with_usage do %>
|
10
|
+
<%= render Docs::CodeBlockComponent.new(
|
11
|
+
code: navigation_menu_usage_code,
|
12
|
+
language: "erb"
|
13
|
+
) %>
|
14
|
+
<% end %>
|
15
|
+
|
16
|
+
<% page.with_examples do %>
|
17
|
+
<!-- Default Example with Dropdowns -->
|
18
|
+
<% default_html = capture do %>
|
19
|
+
<div class="flex justify-center w-full py-8" style="min-height: 400px;">
|
20
|
+
<%= render M9sh::NavigationMenuComponent.new do |nav| %>
|
21
|
+
<% nav.with_item do |item| %>
|
22
|
+
<% item.with_trigger do %>
|
23
|
+
Getting started
|
24
|
+
<% end %>
|
25
|
+
<% item.with_menu_content do %>
|
26
|
+
<ul class="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-[.75fr_1fr] lg:w-[600px]">
|
27
|
+
<li class="row-span-3">
|
28
|
+
<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">
|
29
|
+
<div class="mb-2 mt-4 text-lg font-medium">
|
30
|
+
m9sh/ui
|
31
|
+
</div>
|
32
|
+
<p class="text-sm leading-tight text-muted-foreground">
|
33
|
+
Beautifully designed components built with ViewComponent and Tailwind CSS.
|
34
|
+
</p>
|
35
|
+
</div>
|
36
|
+
</li>
|
37
|
+
<li>
|
38
|
+
<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">
|
39
|
+
<div class="text-sm font-medium leading-none">Introduction</div>
|
40
|
+
<p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
|
41
|
+
Re-usable components built using ViewComponent and Tailwind CSS.
|
42
|
+
</p>
|
43
|
+
</a>
|
44
|
+
</li>
|
45
|
+
<li>
|
46
|
+
<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">
|
47
|
+
<div class="text-sm font-medium leading-none">Installation</div>
|
48
|
+
<p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
|
49
|
+
How to install dependencies and structure your app.
|
50
|
+
</p>
|
51
|
+
</a>
|
52
|
+
</li>
|
53
|
+
<li>
|
54
|
+
<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">
|
55
|
+
<div class="text-sm font-medium leading-none">Typography</div>
|
56
|
+
<p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
|
57
|
+
Styles for headings, paragraphs, lists...etc
|
58
|
+
</p>
|
59
|
+
</a>
|
60
|
+
</li>
|
61
|
+
</ul>
|
62
|
+
<% end %>
|
63
|
+
<% end %>
|
64
|
+
|
65
|
+
<% nav.with_item do |item| %>
|
66
|
+
<% item.with_trigger do %>
|
67
|
+
Components
|
68
|
+
<% end %>
|
69
|
+
<% item.with_menu_content do %>
|
70
|
+
<ul class="grid w-[600px] gap-3 p-6 md:grid-cols-2 lg:w-[800px]">
|
71
|
+
<li>
|
72
|
+
<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">
|
73
|
+
<div class="text-sm font-medium leading-none">Alert Dialog</div>
|
74
|
+
<p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
|
75
|
+
A modal dialog that interrupts the user with important content.
|
76
|
+
</p>
|
77
|
+
</a>
|
78
|
+
</li>
|
79
|
+
<li>
|
80
|
+
<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">
|
81
|
+
<div class="text-sm font-medium leading-none">Hover Card</div>
|
82
|
+
<p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
|
83
|
+
For sighted users to preview content available behind a link.
|
84
|
+
</p>
|
85
|
+
</a>
|
86
|
+
</li>
|
87
|
+
<li>
|
88
|
+
<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">
|
89
|
+
<div class="text-sm font-medium leading-none">Progress</div>
|
90
|
+
<p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
|
91
|
+
Displays an indicator showing the completion progress.
|
92
|
+
</p>
|
93
|
+
</a>
|
94
|
+
</li>
|
95
|
+
<li>
|
96
|
+
<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">
|
97
|
+
<div class="text-sm font-medium leading-none">Scroll-area</div>
|
98
|
+
<p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
|
99
|
+
Visually or semantically separates content.
|
100
|
+
</p>
|
101
|
+
</a>
|
102
|
+
</li>
|
103
|
+
<li>
|
104
|
+
<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">
|
105
|
+
<div class="text-sm font-medium leading-none">Tabs</div>
|
106
|
+
<p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
|
107
|
+
A set of layered sections of content.
|
108
|
+
</p>
|
109
|
+
</a>
|
110
|
+
</li>
|
111
|
+
<li>
|
112
|
+
<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">
|
113
|
+
<div class="text-sm font-medium leading-none">Tooltip</div>
|
114
|
+
<p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
|
115
|
+
A popup that displays information related to an element.
|
116
|
+
</p>
|
117
|
+
</a>
|
118
|
+
</li>
|
119
|
+
</ul>
|
120
|
+
<% end %>
|
121
|
+
<% end %>
|
122
|
+
<% end %>
|
123
|
+
</div>
|
124
|
+
<% end %>
|
125
|
+
|
126
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
127
|
+
title: "Default",
|
128
|
+
preview_content: default_html,
|
129
|
+
code: navigation_menu_default_code,
|
130
|
+
ai_command: navigation_menu_default_code
|
131
|
+
) %>
|
132
|
+
|
133
|
+
<!-- Simple Links Example -->
|
134
|
+
<% links_html = capture do %>
|
135
|
+
<div class="flex justify-center w-full py-8">
|
136
|
+
<%= render M9sh::NavigationMenuComponent.new do |nav| %>
|
137
|
+
<% nav.with_item do |item| %>
|
138
|
+
<% item.with_link(href: "#docs") do %>
|
139
|
+
Documentation
|
140
|
+
<% end %>
|
141
|
+
<% end %>
|
142
|
+
|
143
|
+
<% nav.with_item do |item| %>
|
144
|
+
<% item.with_link(href: "#components") do %>
|
145
|
+
Components
|
146
|
+
<% end %>
|
147
|
+
<% end %>
|
148
|
+
|
149
|
+
<% nav.with_item do |item| %>
|
150
|
+
<% item.with_link(href: "#examples") do %>
|
151
|
+
Examples
|
152
|
+
<% end %>
|
153
|
+
<% end %>
|
154
|
+
<% end %>
|
155
|
+
</div>
|
156
|
+
<% end %>
|
157
|
+
|
158
|
+
<%= render Docs::ComponentPreviewComponent.new(
|
159
|
+
title: "Simple Links",
|
160
|
+
preview_content: links_html,
|
161
|
+
code: navigation_menu_simple_links_code,
|
162
|
+
ai_command: navigation_menu_simple_links_code
|
163
|
+
) %>
|
164
|
+
<% end %>
|
165
|
+
|
166
|
+
<% page.with_api do %>
|
167
|
+
<h3 class="text-lg font-semibold mb-4">NavigationMenuComponent</h3>
|
168
|
+
<%= render Docs::PropTableComponent.new(
|
169
|
+
props: [
|
170
|
+
{
|
171
|
+
name: "items",
|
172
|
+
type: "renders_many",
|
173
|
+
default: "[]",
|
174
|
+
description: "Collection of navigation menu items (ItemComponent instances)"
|
175
|
+
}
|
176
|
+
]
|
177
|
+
) %>
|
178
|
+
|
179
|
+
<h3 class="text-lg font-semibold mb-4 mt-8">ItemComponent</h3>
|
180
|
+
<%= render Docs::PropTableComponent.new(
|
181
|
+
props: [
|
182
|
+
{
|
183
|
+
name: "trigger",
|
184
|
+
type: "renders_one",
|
185
|
+
default: "nil",
|
186
|
+
description: "Button trigger for dropdown menu with text/block content"
|
187
|
+
},
|
188
|
+
{
|
189
|
+
name: "menu_content",
|
190
|
+
type: "renders_one",
|
191
|
+
default: "nil",
|
192
|
+
description: "Dropdown menu content panel"
|
193
|
+
},
|
194
|
+
{
|
195
|
+
name: "link",
|
196
|
+
type: "renders_one",
|
197
|
+
default: "nil",
|
198
|
+
description: "Simple navigation link (alternative to trigger+menu_content)"
|
199
|
+
}
|
200
|
+
]
|
201
|
+
) %>
|
202
|
+
|
203
|
+
<div class="mt-6 space-y-3 text-sm">
|
204
|
+
<h3 class="text-lg font-semibold">Usage Notes</h3>
|
205
|
+
<ul class="list-disc list-inside space-y-2 text-muted-foreground">
|
206
|
+
<li>Use <code class="text-xs bg-muted px-1 py-0.5 rounded">trigger</code> and <code class="text-xs bg-muted px-1 py-0.5 rounded">menu_content</code> together for dropdown menus</li>
|
207
|
+
<li>Use <code class="text-xs bg-muted px-1 py-0.5 rounded">link</code> alone for simple navigation links</li>
|
208
|
+
<li>The component uses Stimulus.js for interactive dropdown behavior</li>
|
209
|
+
<li>Clicking outside an open dropdown will automatically close it</li>
|
210
|
+
<li>The dropdown content includes smooth animations for opening/closing</li>
|
211
|
+
<li>The trigger button shows a chevron icon that rotates when the menu opens</li>
|
212
|
+
</ul>
|
213
|
+
</div>
|
214
|
+
|
215
|
+
<div class="mt-6 space-y-3 text-sm">
|
216
|
+
<h3 class="text-lg font-semibold">Accessibility</h3>
|
217
|
+
<ul class="list-disc list-inside space-y-2 text-muted-foreground">
|
218
|
+
<li>Uses semantic <code class="text-xs bg-muted px-1 py-0.5 rounded"><nav></code> element</li>
|
219
|
+
<li>Trigger buttons have proper <code class="text-xs bg-muted px-1 py-0.5 rounded">type="button"</code> attribute</li>
|
220
|
+
<li>Chevron icon has <code class="text-xs bg-muted px-1 py-0.5 rounded">aria-hidden="true"</code> to prevent screen reader announcement</li>
|
221
|
+
<li>Focus states are styled with <code class="text-xs bg-muted px-1 py-0.5 rounded">focus:outline-none</code> and custom focus styling</li>
|
222
|
+
<li>Links use proper <code class="text-xs bg-muted px-1 py-0.5 rounded"><a></code> tags with href attributes</li>
|
223
|
+
</ul>
|
224
|
+
</div>
|
225
|
+
<% end %>
|
226
|
+
<% end %>
|