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.
Files changed (125) hide show
  1. checksums.yaml +4 -4
  2. data/.idea/hotcdn.iml +30 -0
  3. data/.mise.toml +2 -2
  4. data/app/assets/config/manifest.js +4 -0
  5. data/app/assets/images/icons/activity.svg +3 -0
  6. data/app/assets/images/icons/bell.svg +4 -0
  7. data/app/assets/images/icons/book.svg +4 -0
  8. data/app/assets/images/icons/chevron-down.svg +3 -0
  9. data/app/assets/images/icons/chevron-left.svg +3 -0
  10. data/app/assets/images/icons/chevron-right.svg +3 -0
  11. data/app/assets/images/icons/credit-card.svg +4 -0
  12. data/app/assets/images/icons/dollar-sign.svg +3 -0
  13. data/app/assets/images/icons/edit.svg +4 -0
  14. data/app/assets/images/icons/github.svg +3 -0
  15. data/app/assets/images/icons/home.svg +4 -0
  16. data/app/assets/images/icons/info.svg +5 -0
  17. data/app/assets/images/icons/layout.svg +6 -0
  18. data/app/assets/images/icons/logout.svg +5 -0
  19. data/app/assets/images/icons/menu.svg +5 -0
  20. data/app/assets/images/icons/moon.svg +3 -0
  21. data/app/assets/images/icons/paintbrush.svg +6 -0
  22. data/app/assets/images/icons/search.svg +4 -0
  23. data/app/assets/images/icons/settings.svg +4 -0
  24. data/app/assets/images/icons/sun.svg +11 -0
  25. data/app/assets/images/icons/user.svg +4 -0
  26. data/app/assets/images/icons/users.svg +5 -0
  27. data/app/assets/stylesheets/tailwind.css +1180 -0
  28. data/app/components/backdrop_component.rb +103 -0
  29. data/app/components/docs/code_block_component.rb +56 -0
  30. data/app/components/docs/component_api_component.rb +16 -0
  31. data/app/components/docs/component_examples_component.rb +16 -0
  32. data/app/components/docs/component_header_component.html.erb +8 -0
  33. data/app/components/docs/component_header_component.rb +14 -0
  34. data/app/components/docs/component_installation_component.html.erb +15 -0
  35. data/app/components/docs/component_installation_component.rb +13 -0
  36. data/app/components/docs/component_page_component.html.erb +9 -0
  37. data/app/components/docs/component_page_component.rb +19 -0
  38. data/app/components/docs/component_preview_component.rb +318 -0
  39. data/app/components/docs/component_usage_component.rb +18 -0
  40. data/app/components/docs/prop_table_component.rb +64 -0
  41. data/app/controllers/application_controller.rb +3 -0
  42. data/app/controllers/blocks_controller.rb +51 -0
  43. data/app/controllers/docs_controller.rb +162 -0
  44. data/app/controllers/showcase_controller.rb +42 -0
  45. data/app/helpers/blocks_helper.rb +343 -0
  46. data/app/helpers/docs_helper.rb +3807 -0
  47. data/app/helpers/m9sh/toast_helper.rb +46 -0
  48. data/app/helpers/m9sh_helper.rb +343 -0
  49. data/app/javascript/application.js +3 -0
  50. data/app/javascript/controllers/application.js +9 -0
  51. data/app/javascript/controllers/backdrop_controller.js +137 -0
  52. data/app/javascript/controllers/color_customizer_controller.js +569 -0
  53. data/app/javascript/controllers/color_theme_controller.js +120 -0
  54. data/app/javascript/controllers/docs/component_preview_controller.js +149 -0
  55. data/app/javascript/controllers/docs/copy_button_controller.js +20 -0
  56. data/app/javascript/controllers/index.js +6 -0
  57. data/app/javascript/controllers/theme_controller.js +23 -0
  58. data/app/views/blocks/_sidebar.html.erb +31 -0
  59. data/app/views/blocks/_toc.html.erb +29 -0
  60. data/app/views/blocks/examples/dashboard-01.html.erb +180 -0
  61. data/app/views/blocks/examples/dashboard-02.html.erb +190 -0
  62. data/app/views/blocks/examples/dashboard-03.html.erb +210 -0
  63. data/app/views/blocks/examples/settings-01.html.erb +220 -0
  64. data/app/views/blocks/examples/settings-02.html.erb +231 -0
  65. data/app/views/blocks/examples/settings-03.html.erb +340 -0
  66. data/app/views/blocks/index.html.erb +65 -0
  67. data/app/views/docs/_sidebar.html.erb +47 -0
  68. data/app/views/docs/_toc.html.erb +19 -0
  69. data/app/views/docs/about.html.erb +68 -0
  70. data/app/views/docs/components/accordion.html.erb +196 -0
  71. data/app/views/docs/components/alert.html.erb +272 -0
  72. data/app/views/docs/components/alert_dialog.html.erb +232 -0
  73. data/app/views/docs/components/avatar.html.erb +207 -0
  74. data/app/views/docs/components/badge.html.erb +145 -0
  75. data/app/views/docs/components/breadcrumb.html.erb +264 -0
  76. data/app/views/docs/components/button.html.erb +229 -0
  77. data/app/views/docs/components/card.html.erb +378 -0
  78. data/app/views/docs/components/checkbox.html.erb +212 -0
  79. data/app/views/docs/components/collapsible.html.erb +252 -0
  80. data/app/views/docs/components/dialog.html.erb +323 -0
  81. data/app/views/docs/components/dropdown_menu.html.erb +289 -0
  82. data/app/views/docs/components/hover_card.html.erb +220 -0
  83. data/app/views/docs/components/input.html.erb +254 -0
  84. data/app/views/docs/components/label.html.erb +128 -0
  85. data/app/views/docs/components/main.html.erb +352 -0
  86. data/app/views/docs/components/navbar.html.erb +394 -0
  87. data/app/views/docs/components/navigation_menu.html.erb +226 -0
  88. data/app/views/docs/components/popover.html.erb +267 -0
  89. data/app/views/docs/components/progress.html.erb +107 -0
  90. data/app/views/docs/components/radio_group.html.erb +209 -0
  91. data/app/views/docs/components/select.html.erb +260 -0
  92. data/app/views/docs/components/separator.html.erb +162 -0
  93. data/app/views/docs/components/sheet.html.erb +270 -0
  94. data/app/views/docs/components/sidebar.html.erb +597 -0
  95. data/app/views/docs/components/skeleton.html.erb +150 -0
  96. data/app/views/docs/components/slider.html.erb +218 -0
  97. data/app/views/docs/components/spinner.html.erb +132 -0
  98. data/app/views/docs/components/switch.html.erb +148 -0
  99. data/app/views/docs/components/table.html.erb +259 -0
  100. data/app/views/docs/components/tabs.html.erb +225 -0
  101. data/app/views/docs/components/textarea.html.erb +239 -0
  102. data/app/views/docs/components/theme_toggle.html.erb +135 -0
  103. data/app/views/docs/components/toast.html.erb +205 -0
  104. data/app/views/docs/components/toaster.html.erb +227 -0
  105. data/app/views/docs/components/toggle.html.erb +154 -0
  106. data/app/views/docs/components/tooltip.html.erb +216 -0
  107. data/app/views/docs/components/typography.html.erb +180 -0
  108. data/app/views/docs/index.html.erb +143 -0
  109. data/app/views/docs/installation.html.erb +155 -0
  110. data/app/views/docs/simple_test.html.erb +13 -0
  111. data/app/views/docs/test_accordion.html.erb +14 -0
  112. data/app/views/docs/usage.html.erb +272 -0
  113. data/app/views/layouts/application.html.erb +107 -0
  114. data/app/views/layouts/backdrop.html.erb +77 -0
  115. data/app/views/shared/_app_navbar.html.erb +240 -0
  116. data/app/views/shared/_navbar.html.erb +69 -0
  117. data/app/views/showcase/v2/_components_grid.html.erb +38 -0
  118. data/app/views/showcase/v2/_features.html.erb +59 -0
  119. data/app/views/showcase/v2/_forms.html.erb +195 -0
  120. data/app/views/showcase/v2/_hero.html.erb +55 -0
  121. data/app/views/showcase/v2/_metrics.html.erb +107 -0
  122. data/app/views/showcase/v2.html.erb +18 -0
  123. data/lib/m9sh/version.rb +1 -1
  124. data/m9sh.gemspec +1 -1
  125. metadata +120 -1
@@ -0,0 +1,340 @@
1
+ <% content_for :title, "Settings 03 - Blocks" %>
2
+
3
+ <!-- Page Header -->
4
+ <div class="space-y-2 mb-8">
5
+ <h1 class="text-3xl font-bold tracking-tight">Settings 03</h1>
6
+ <p class="text-muted-foreground">
7
+ Notifications and integrations settings with connected accounts, email preferences, and API access. Perfect for managing external services and notifications.
8
+ </p>
9
+ </div>
10
+
11
+ <!-- Settings Preview -->
12
+ <% settings_html = capture do %>
13
+ <div class="w-full">
14
+ <div class="max-w-3xl mx-auto space-y-8">
15
+ <%# CODE_START %>
16
+ <!-- Page Header -->
17
+ <div class="space-y-1">
18
+ <h2 class="text-2xl font-semibold tracking-tight">Notifications & Integrations</h2>
19
+ <p class="text-sm text-muted-foreground">
20
+ Manage your notifications and connected services.
21
+ </p>
22
+ </div>
23
+
24
+ <%= render M9sh::SeparatorComponent.new(class: "my-6") %>
25
+
26
+ <!-- Tabs for different sections -->
27
+ <%= render M9sh::TabsComponent.new(default_value: "notifications") do |tabs| %>
28
+ <!-- Tab List -->
29
+ <% tabs.with_tabs_list do |list| %>
30
+ <%= render list.tabs_trigger(value: "notifications") { "Notifications" } %>
31
+ <%= render list.tabs_trigger(value: "integrations") { "Integrations" } %>
32
+ <%= render list.tabs_trigger(value: "api") { "API Access" } %>
33
+ <% end %>
34
+
35
+ <!-- Notifications Tab -->
36
+ <% tabs.with_tabs_content(value: "notifications") do %>
37
+ <div class="space-y-6 mt-6">
38
+ <!-- Email Notifications -->
39
+ <%= render M9sh::CardComponent.new do |card| %>
40
+ <% card.with_header do |header| %>
41
+ <% header.with_title { "Email Notifications" } %>
42
+ <% header.with_description { "Choose what updates you receive via email." } %>
43
+ <% end %>
44
+ <% card.with_body do %>
45
+ <div class="space-y-4">
46
+ <% [
47
+ { id: "email-comments", label: "Comments", description: "Receive notifications when someone comments on your posts.", checked: true },
48
+ { id: "email-mentions", label: "Mentions", description: "Get notified when someone mentions you.", checked: true },
49
+ { id: "email-followers", label: "New Followers", description: "Receive emails about new followers." },
50
+ { id: "email-digest", label: "Weekly Digest", description: "Get a weekly summary of activity.", checked: true }
51
+ ].each do |notification| %>
52
+ <div class="flex items-center justify-between space-x-2 py-2">
53
+ <div class="space-y-0.5 flex-1">
54
+ <%= render M9sh::LabelComponent.new(for: notification[:id], class: "font-medium cursor-pointer") { notification[:label] } %>
55
+ <p class="text-sm text-muted-foreground"><%= notification[:description] %></p>
56
+ </div>
57
+ <%= render M9sh::SwitchComponent.new(id: notification[:id], checked: notification[:checked] || false) %>
58
+ </div>
59
+ <%= render M9sh::SeparatorComponent.new unless notification[:id] == "email-digest" %>
60
+ <% end %>
61
+ </div>
62
+ <% end %>
63
+ <% end %>
64
+
65
+ <!-- Push Notifications -->
66
+ <%= render M9sh::CardComponent.new do |card| %>
67
+ <% card.with_header do |header| %>
68
+ <% header.with_title { "Push Notifications" } %>
69
+ <% header.with_description { "Manage browser and mobile push notifications." } %>
70
+ <% end %>
71
+ <% card.with_body do %>
72
+ <div class="space-y-4">
73
+ <% [
74
+ { id: "push-messages", label: "Messages", description: "Get notified about new messages.", checked: true },
75
+ { id: "push-updates", label: "Product Updates", description: "Notifications about new features and updates." },
76
+ { id: "push-reminders", label: "Reminders", description: "Receive reminders about tasks and events.", checked: true }
77
+ ].each do |notification| %>
78
+ <div class="flex items-center justify-between space-x-2 py-2">
79
+ <div class="space-y-0.5 flex-1">
80
+ <%= render M9sh::LabelComponent.new(for: notification[:id], class: "font-medium cursor-pointer") { notification[:label] } %>
81
+ <p class="text-sm text-muted-foreground"><%= notification[:description] %></p>
82
+ </div>
83
+ <%= render M9sh::SwitchComponent.new(id: notification[:id], checked: notification[:checked] || false) %>
84
+ </div>
85
+ <%= render M9sh::SeparatorComponent.new unless notification[:id] == "push-reminders" %>
86
+ <% end %>
87
+ </div>
88
+ <% end %>
89
+ <% card.with_footer do %>
90
+ <%= render M9sh::ButtonComponent.new do %>
91
+ Save Preferences
92
+ <% end %>
93
+ <% end %>
94
+ <% end %>
95
+ </div>
96
+ <% end %>
97
+
98
+ <!-- Integrations Tab -->
99
+ <% tabs.with_tabs_content(value: "integrations") do %>
100
+ <div class="space-y-6 mt-6">
101
+ <!-- Connected Accounts -->
102
+ <%= render M9sh::CardComponent.new do |card| %>
103
+ <% card.with_header do |header| %>
104
+ <% header.with_title { "Connected Accounts" } %>
105
+ <% header.with_description { "Manage your connected services and integrations." } %>
106
+ <% end %>
107
+ <% card.with_body do %>
108
+ <div class="space-y-4">
109
+ <% [
110
+ { name: "GitHub", status: "Connected", description: "Connected as @johndoe", connected: true },
111
+ { name: "Google", status: "Connected", description: "john.doe@gmail.com", connected: true },
112
+ { name: "Slack", status: "Not Connected", description: "Connect your Slack workspace", connected: false },
113
+ { name: "Discord", status: "Not Connected", description: "Connect your Discord account", connected: false }
114
+ ].each do |service| %>
115
+ <div class="flex items-center justify-between space-x-4 py-3">
116
+ <div class="flex items-center gap-3 flex-1">
117
+ <div class="h-10 w-10 rounded-full bg-muted flex items-center justify-center">
118
+ <span class="text-sm font-medium"><%= service[:name][0] %></span>
119
+ </div>
120
+ <div class="space-y-1">
121
+ <div class="flex items-center gap-2">
122
+ <p class="font-medium"><%= service[:name] %></p>
123
+ <%= render M9sh::BadgeComponent.new(variant: service[:connected] ? :default : :secondary) do %>
124
+ <%= service[:status] %>
125
+ <% end %>
126
+ </div>
127
+ <p class="text-sm text-muted-foreground"><%= service[:description] %></p>
128
+ </div>
129
+ </div>
130
+ <% if service[:connected] %>
131
+ <%= render M9sh::ButtonComponent.new(variant: :outline, size: :sm) do %>
132
+ Disconnect
133
+ <% end %>
134
+ <% else %>
135
+ <%= render M9sh::ButtonComponent.new(size: :sm) do %>
136
+ Connect
137
+ <% end %>
138
+ <% end %>
139
+ </div>
140
+ <%= render M9sh::SeparatorComponent.new unless service[:name] == "Discord" %>
141
+ <% end %>
142
+ </div>
143
+ <% end %>
144
+ <% end %>
145
+
146
+ <!-- Webhooks -->
147
+ <%= render M9sh::CardComponent.new do |card| %>
148
+ <% card.with_header do |header| %>
149
+ <% header.with_title { "Webhooks" } %>
150
+ <% header.with_description { "Configure webhooks for external integrations." } %>
151
+ <% end %>
152
+ <% card.with_body do %>
153
+ <div class="space-y-4">
154
+ <div class="space-y-2">
155
+ <%= render M9sh::LabelComponent.new(for: "webhook-url") { "Webhook URL" } %>
156
+ <%= render M9sh::InputComponent.new(
157
+ id: "webhook-url",
158
+ placeholder: "https://example.com/webhook",
159
+ value: "https://api.example.com/webhook"
160
+ ) %>
161
+ <p class="text-xs text-muted-foreground">Events will be sent to this URL.</p>
162
+ </div>
163
+ <div class="flex items-center space-x-3">
164
+ <%= render M9sh::CheckboxComponent.new(id: "webhook-active", checked: true) %>
165
+ <%= render M9sh::LabelComponent.new(for: "webhook-active", class: "font-medium cursor-pointer") { "Webhook Enabled" } %>
166
+ </div>
167
+ </div>
168
+ <% end %>
169
+ <% card.with_footer do %>
170
+ <div class="flex gap-2">
171
+ <%= render M9sh::ButtonComponent.new(variant: :outline) do %>
172
+ Test Webhook
173
+ <% end %>
174
+ <%= render M9sh::ButtonComponent.new do %>
175
+ Save Configuration
176
+ <% end %>
177
+ </div>
178
+ <% end %>
179
+ <% end %>
180
+ </div>
181
+ <% end %>
182
+
183
+ <!-- API Access Tab -->
184
+ <% tabs.with_tabs_content(value: "api") do %>
185
+ <div class="space-y-6 mt-6">
186
+ <!-- API Keys -->
187
+ <%= render M9sh::CardComponent.new do |card| %>
188
+ <% card.with_header do |header| %>
189
+ <% header.with_title { "API Keys" } %>
190
+ <% header.with_description { "Manage your API keys for programmatic access." } %>
191
+ <% end %>
192
+ <% card.with_body do %>
193
+ <div class="space-y-4">
194
+ <%= render M9sh::AlertComponent.new(variant: :default) do %>
195
+ <div class="space-y-1">
196
+ <p class="font-medium">Keep your API keys secure</p>
197
+ <p class="text-sm">Never share your API keys in publicly accessible areas such as GitHub, client-side code, and so forth.</p>
198
+ </div>
199
+ <% end %>
200
+
201
+ <div class="space-y-2">
202
+ <%= render M9sh::LabelComponent.new(for: "api-key") { "Production API Key" } %>
203
+ <div class="flex gap-2">
204
+ <%= render M9sh::InputComponent.new(
205
+ id: "api-key",
206
+ type: :password,
207
+ value: "sk_live_1234567890abcdef",
208
+ readonly: true
209
+ ) %>
210
+ <%= render M9sh::ButtonComponent.new(variant: :outline, size: :sm) do %>
211
+ Copy
212
+ <% end %>
213
+ </div>
214
+ </div>
215
+
216
+ <div class="space-y-2">
217
+ <%= render M9sh::LabelComponent.new(for: "test-api-key") { "Test API Key" } %>
218
+ <div class="flex gap-2">
219
+ <%= render M9sh::InputComponent.new(
220
+ id: "test-api-key",
221
+ type: :password,
222
+ value: "sk_test_0987654321fedcba",
223
+ readonly: true
224
+ ) %>
225
+ <%= render M9sh::ButtonComponent.new(variant: :outline, size: :sm) do %>
226
+ Copy
227
+ <% end %>
228
+ </div>
229
+ </div>
230
+ </div>
231
+ <% end %>
232
+ <% card.with_footer do %>
233
+ <div class="flex justify-between items-center">
234
+ <%= render M9sh::ButtonComponent.new(variant: :destructive, size: :sm) do %>
235
+ Regenerate Keys
236
+ <% end %>
237
+ <p class="text-xs text-muted-foreground">Last regenerated 2 days ago</p>
238
+ </div>
239
+ <% end %>
240
+ <% end %>
241
+
242
+ <!-- API Usage -->
243
+ <%= render M9sh::CardComponent.new do |card| %>
244
+ <% card.with_header do |header| %>
245
+ <% header.with_title { "API Usage" } %>
246
+ <% header.with_description { "Monitor your API usage and rate limits." } %>
247
+ <% end %>
248
+ <% card.with_body do %>
249
+ <div class="space-y-4">
250
+ <div class="space-y-2">
251
+ <div class="flex items-center justify-between text-sm">
252
+ <span class="text-muted-foreground">Requests this month</span>
253
+ <span class="font-medium">8,547 / 10,000</span>
254
+ </div>
255
+ <%= render M9sh::ProgressComponent.new(value: 85.47) %>
256
+ </div>
257
+ <div class="space-y-2">
258
+ <div class="flex items-center justify-between text-sm">
259
+ <span class="text-muted-foreground">Rate limit</span>
260
+ <span class="font-medium">100 requests/min</span>
261
+ </div>
262
+ </div>
263
+ </div>
264
+ <% end %>
265
+ <% card.with_footer do %>
266
+ <%= render M9sh::ButtonComponent.new(variant: :outline) do %>
267
+ View Documentation
268
+ <% end %>
269
+ <% end %>
270
+ <% end %>
271
+ </div>
272
+ <% end %>
273
+ <% end %>
274
+ <%# CODE_END %>
275
+ </div>
276
+ </div>
277
+ <% end %>
278
+
279
+ <%= render Docs::ComponentPreviewComponent.new(
280
+ title: "Notifications & Integrations",
281
+ preview_content: settings_html,
282
+ code: extract_block_code("<%# CODE_START %>", "<%# CODE_END %>"),
283
+ ai_command: extract_block_code("<%# CODE_START %>", "<%# CODE_END %>")
284
+ ) %>
285
+
286
+ <!-- Usage Section -->
287
+ <div class="mt-12 space-y-4">
288
+ <h2 class="text-2xl font-semibold tracking-tight">Usage</h2>
289
+ <p class="text-muted-foreground leading-relaxed">
290
+ A comprehensive settings page for notifications and integrations. Features tabbed navigation for organizing email/push notifications, connected accounts, webhooks, and API access management.
291
+ </p>
292
+
293
+ <%= render M9sh::CardComponent.new(class: "mt-6") do |card| %>
294
+ <% card.with_header do |header| %>
295
+ <% header.with_title do %>
296
+ Required Components
297
+ <% end %>
298
+ <% header.with_description do %>
299
+ Make sure these components are installed in your project
300
+ <% end %>
301
+ <% end %>
302
+ <% card.with_body do %>
303
+ <div class="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
304
+ <%= render M9sh::BadgeComponent.new(variant: :secondary) do %>
305
+ TabsComponent
306
+ <% end %>
307
+ <%= render M9sh::BadgeComponent.new(variant: :secondary) do %>
308
+ CardComponent
309
+ <% end %>
310
+ <%= render M9sh::BadgeComponent.new(variant: :secondary) do %>
311
+ InputComponent
312
+ <% end %>
313
+ <%= render M9sh::BadgeComponent.new(variant: :secondary) do %>
314
+ LabelComponent
315
+ <% end %>
316
+ <%= render M9sh::BadgeComponent.new(variant: :secondary) do %>
317
+ ButtonComponent
318
+ <% end %>
319
+ <%= render M9sh::BadgeComponent.new(variant: :secondary) do %>
320
+ SwitchComponent
321
+ <% end %>
322
+ <%= render M9sh::BadgeComponent.new(variant: :secondary) do %>
323
+ CheckboxComponent
324
+ <% end %>
325
+ <%= render M9sh::BadgeComponent.new(variant: :secondary) do %>
326
+ BadgeComponent
327
+ <% end %>
328
+ <%= render M9sh::BadgeComponent.new(variant: :secondary) do %>
329
+ AlertComponent
330
+ <% end %>
331
+ <%= render M9sh::BadgeComponent.new(variant: :secondary) do %>
332
+ ProgressComponent
333
+ <% end %>
334
+ <%= render M9sh::BadgeComponent.new(variant: :secondary) do %>
335
+ SeparatorComponent
336
+ <% end %>
337
+ </div>
338
+ <% end %>
339
+ <% end %>
340
+ </div>
@@ -0,0 +1,65 @@
1
+ <% content_for :title, "Blocks - m9sh/ui" %>
2
+
3
+ <div class="space-y-12">
4
+ <!-- Hero Section -->
5
+ <div class="space-y-6 py-8">
6
+ <div class="space-y-4">
7
+ <h1 class="scroll-m-20 text-5xl font-bold tracking-tight lg:text-6xl">
8
+ Building Blocks for the Web
9
+ </h1>
10
+ <p class="text-xl text-muted-foreground max-w-[700px]">
11
+ Beautifully designed blocks built with m9sh/ui components. Copy and paste into your apps.
12
+ </p>
13
+ </div>
14
+ </div>
15
+
16
+ <!-- Blocks by Category -->
17
+ <% BlocksController::BLOCK_CATEGORIES.each do |category, blocks| %>
18
+ <div id="<%= category.downcase %>" class="space-y-6">
19
+ <div>
20
+ <h2 class="scroll-m-20 pb-2 text-3xl font-semibold tracking-tight transition-colors">
21
+ <%= category %>
22
+ </h2>
23
+ <%= render M9sh::SeparatorComponent.new(class: "my-4") %>
24
+ </div>
25
+
26
+ <div class="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
27
+ <% blocks.each do |block| %>
28
+ <%= link_to block_path(block), class: "group" do %>
29
+ <%= render M9sh::CardComponent.new(class: "h-full transition-all hover:border-primary") do |card| %>
30
+ <% card.with_header do %>
31
+ <div class="space-y-1">
32
+ <h3 class="font-semibold group-hover:text-primary transition-colors">
33
+ <%= block.titleize %>
34
+ </h3>
35
+ <p class="text-sm text-muted-foreground">
36
+ <%= BlocksController::BLOCK_DESCRIPTIONS[block] %>
37
+ </p>
38
+ </div>
39
+ <% end %>
40
+ <% card.with_body do %>
41
+ <div class="aspect-video bg-muted rounded-md flex items-center justify-center">
42
+ <%= render M9sh::SkeletonComponent.new(class: "w-full h-full") %>
43
+ </div>
44
+ <% end %>
45
+ <% end %>
46
+ <% end %>
47
+ <% end %>
48
+ </div>
49
+ </div>
50
+ <% end %>
51
+
52
+ <!-- Info Section -->
53
+ <div id="about" class="pt-8 space-y-4">
54
+ <%= render M9sh::SeparatorComponent.new %>
55
+ <div class="space-y-2">
56
+ <h3 class="font-semibold">About Blocks</h3>
57
+ <p class="text-sm text-muted-foreground leading-7">
58
+ Blocks are fully functional examples built using m9sh/ui components. They demonstrate how to compose multiple components together to create common UI patterns and layouts.
59
+ </p>
60
+ <p class="text-sm text-muted-foreground leading-7">
61
+ Each block is a complete, working example that you can copy and customize for your application.
62
+ </p>
63
+ </div>
64
+ </div>
65
+ </div>
@@ -0,0 +1,47 @@
1
+ <nav class="px-12 py-8 space-y-8">
2
+ <!-- Getting Started Section -->
3
+ <div>
4
+ <h4 class="mb-2 text-sm font-semibold">Getting Started</h4>
5
+ <ul class="space-y-1">
6
+ <li>
7
+ <a href="<%= docs_path %>"
8
+ class="inline-flex w-full items-center justify-start whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground h-9 px-3 <%= @current_page == 'introduction' ? 'bg-sidebar-accent text-sidebar-accent-foreground' : '' %>">
9
+ Introduction
10
+ </a>
11
+ </li>
12
+ <li>
13
+ <a href="<%= docs_installation_path %>"
14
+ class="inline-flex w-full items-center justify-start whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground h-9 px-3 <%= @current_page == 'installation' ? 'bg-sidebar-accent text-sidebar-accent-foreground' : '' %>">
15
+ Installation
16
+ </a>
17
+ </li>
18
+ <li>
19
+ <a href="<%= docs_usage_path %>"
20
+ class="inline-flex w-full items-center justify-start whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground h-9 px-3 <%= @current_page == 'usage' ? 'bg-sidebar-accent text-sidebar-accent-foreground' : '' %>">
21
+ Usage
22
+ </a>
23
+ </li>
24
+ <li>
25
+ <a href="<%= docs_about_path %>"
26
+ class="inline-flex w-full items-center justify-start whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground h-9 px-3 <%= @current_page == 'about' ? 'bg-sidebar-accent text-sidebar-accent-foreground' : '' %>">
27
+ About
28
+ </a>
29
+ </li>
30
+ </ul>
31
+ </div>
32
+
33
+ <!-- Components Section -->
34
+ <div>
35
+ <h4 class="mb-2 text-sm font-semibold">Components</h4>
36
+ <ul class="space-y-1">
37
+ <% DocsController::COMPONENTS.each do |component| %>
38
+ <li>
39
+ <a href="<%= docs_component_path(component) %>"
40
+ class="inline-flex w-full items-center justify-start whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground h-9 px-3 <%= @component == component ? 'bg-sidebar-accent text-sidebar-accent-foreground' : '' %>">
41
+ <%= component.titleize.gsub('_', ' ') %>
42
+ </a>
43
+ </li>
44
+ <% end %>
45
+ </ul>
46
+ </div>
47
+ </nav>
@@ -0,0 +1,19 @@
1
+ <% if @component.present? || @current_page.present? %>
2
+ <div class="px-12 py-8">
3
+ <p class="font-semibold text-sm mb-2 px-3">On This Page</p>
4
+ <nav class="space-y-0.5">
5
+ <a href="#installation" class="block text-sm px-3 py-1.5 rounded-lg hover:bg-sidebar-accent transition-colors">
6
+ Installation
7
+ </a>
8
+ <a href="#usage" class="block text-sm px-3 py-1.5 rounded-lg hover:bg-sidebar-accent transition-colors">
9
+ Usage
10
+ </a>
11
+ <a href="#examples" class="block text-sm px-3 py-1.5 rounded-lg hover:bg-sidebar-accent transition-colors">
12
+ Examples
13
+ </a>
14
+ <a href="#api-reference" class="block text-sm px-3 py-1.5 rounded-lg hover:bg-sidebar-accent transition-colors">
15
+ API Reference
16
+ </a>
17
+ </nav>
18
+ </div>
19
+ <% end %>
@@ -0,0 +1,68 @@
1
+ <% content_for :title, "About - m9sh/ui" %>
2
+
3
+ <div class="space-y-12 max-w-3xl">
4
+ <!-- Page Header -->
5
+ <div class="space-y-4">
6
+ <h1 class="scroll-m-20 text-4xl font-bold tracking-tight lg:text-5xl">
7
+ About
8
+ </h1>
9
+ <p class="text-lg text-muted-foreground">
10
+ Learn more about the project and its goals.
11
+ </p>
12
+ </div>
13
+
14
+ <!-- Content -->
15
+ <div class="space-y-6">
16
+ <div>
17
+ <h2 class="scroll-m-20 pb-2 text-3xl font-semibold tracking-tight transition-colors">
18
+ What is this project?
19
+ </h2>
20
+ <%= render M9sh::SeparatorComponent.new(class: "my-4") %>
21
+ <p class="mt-4 text-muted-foreground leading-7">
22
+ m9sh/ui is a collection of re-usable ViewComponents built with Rails and Tailwind CSS. The project is inspired by shadcn/ui and follows the same philosophy of giving developers full control over their component code.
23
+ </p>
24
+ <p class="mt-4 text-muted-foreground leading-7">
25
+ Instead of installing a gem and importing components, you copy the component code directly into your Rails application. This approach gives you complete ownership and the flexibility to customize components to match your needs.
26
+ </p>
27
+ </div>
28
+
29
+ <div>
30
+ <h2 class="scroll-m-20 pb-2 text-3xl font-semibold tracking-tight transition-colors">
31
+ Why ViewComponents?
32
+ </h2>
33
+ <%= render M9sh::SeparatorComponent.new(class: "my-4") %>
34
+ <p class="mt-4 text-muted-foreground leading-7">
35
+ ViewComponent is a framework for building reusable, testable & encapsulated view components in Ruby on Rails. It integrates seamlessly with Rails applications and provides a Ruby-native way to build UI components.
36
+ </p>
37
+ <p class="mt-4 text-muted-foreground leading-7">
38
+ Combined with Stimulus for JavaScript interactions and Tailwind CSS for styling, ViewComponents provide a powerful foundation for building modern Rails applications.
39
+ </p>
40
+ </div>
41
+
42
+ <div>
43
+ <h2 class="scroll-m-20 pb-2 text-3xl font-semibold tracking-tight transition-colors">
44
+ Credits
45
+ </h2>
46
+ <%= render M9sh::SeparatorComponent.new(class: "my-4") %>
47
+ <p class="mt-4 text-muted-foreground leading-7">
48
+ This project is built on the shoulders of giants:
49
+ </p>
50
+ <ul class="mt-4 ml-6 list-disc text-muted-foreground leading-7 space-y-2">
51
+ <li><a href="https://ui.shadcn.com" class="font-medium underline underline-offset-4" target="_blank" rel="noopener">shadcn/ui</a> - The original inspiration and design system</li>
52
+ <li><a href="https://viewcomponent.org" class="font-medium underline underline-offset-4" target="_blank" rel="noopener">ViewComponent</a> - Framework for building reusable view components</li>
53
+ <li><a href="https://tailwindcss.com" class="font-medium underline underline-offset-4" target="_blank" rel="noopener">Tailwind CSS</a> - Utility-first CSS framework</li>
54
+ <li><a href="https://stimulus.hotwired.dev" class="font-medium underline underline-offset-4" target="_blank" rel="noopener">Stimulus</a> - JavaScript framework for HTML</li>
55
+ </ul>
56
+ </div>
57
+
58
+ <div>
59
+ <h2 class="scroll-m-20 pb-2 text-3xl font-semibold tracking-tight transition-colors">
60
+ License
61
+ </h2>
62
+ <%= render M9sh::SeparatorComponent.new(class: "my-4") %>
63
+ <p class="mt-4 text-muted-foreground leading-7">
64
+ MIT License. Free to use for personal and commercial projects. No attribution required.
65
+ </p>
66
+ </div>
67
+ </div>
68
+ </div>