maquina-components 0.1.2 → 0.2.0

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 (113) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +349 -138
  3. data/app/assets/images/maquina.svg +1 -0
  4. data/app/assets/stylesheets/alert.css +143 -0
  5. data/app/assets/stylesheets/badge.css +145 -0
  6. data/app/assets/stylesheets/breadcrumbs.css +163 -0
  7. data/app/assets/stylesheets/card.css +128 -0
  8. data/app/assets/stylesheets/dropdown_menu.css +248 -0
  9. data/app/assets/stylesheets/empty.css +133 -0
  10. data/app/assets/stylesheets/form.css +617 -0
  11. data/app/assets/stylesheets/header.css +61 -0
  12. data/app/assets/stylesheets/maquina_components.css +143 -64
  13. data/app/assets/stylesheets/pagination.css +154 -0
  14. data/app/assets/stylesheets/sidebar.css +477 -0
  15. data/app/assets/stylesheets/table.css +205 -0
  16. data/app/assets/stylesheets/toggle_group.css +151 -0
  17. data/app/assets/tailwind/maquina_components_engine/engine.css +16 -0
  18. data/app/helpers/maquina_components/breadcrumbs_helper.rb +118 -0
  19. data/app/helpers/maquina_components/dropdown_menu_helper.rb +249 -0
  20. data/app/helpers/maquina_components/empty_helper.rb +102 -0
  21. data/app/helpers/{components → maquina_components}/icons_helper.rb +40 -3
  22. data/app/helpers/maquina_components/pagination_helper.rb +153 -0
  23. data/app/helpers/maquina_components/sidebar_helper.rb +63 -0
  24. data/app/helpers/maquina_components/table_helper.rb +144 -0
  25. data/app/helpers/maquina_components/toggle_group_helper.rb +172 -0
  26. data/app/javascript/controllers/breadcrumb_controller.js +71 -0
  27. data/app/javascript/controllers/dropdown_menu_controller.js +203 -0
  28. data/app/javascript/controllers/menu_button_controller.js +59 -0
  29. data/app/javascript/controllers/sidebar_controller.js +316 -0
  30. data/app/javascript/controllers/sidebar_trigger_controller.js +32 -0
  31. data/app/javascript/controllers/toggle_group_controller.js +178 -0
  32. data/app/views/components/_alert.html.erb +11 -10
  33. data/app/views/components/_badge.html.erb +10 -0
  34. data/app/views/components/_breadcrumbs.html.erb +16 -0
  35. data/app/views/components/_card.html.erb +4 -8
  36. data/app/views/components/_dropdown.html.erb +25 -0
  37. data/app/views/components/_dropdown_menu.html.erb +9 -0
  38. data/app/views/components/_empty.html.erb +10 -0
  39. data/app/views/components/_header.html.erb +8 -0
  40. data/app/views/components/_menu_button.html.erb +44 -0
  41. data/app/views/components/_pagination.html.erb +12 -33
  42. data/app/views/components/_separator.html.erb +11 -0
  43. data/app/views/components/_sidebar.html.erb +30 -20
  44. data/app/views/components/_simple_table.html.erb +49 -0
  45. data/app/views/components/_table.html.erb +21 -0
  46. data/app/views/components/_toggle_group.html.erb +24 -0
  47. data/app/views/components/alert/_description.html.erb +6 -0
  48. data/app/views/components/alert/_title.html.erb +6 -0
  49. data/app/views/components/breadcrumbs/_ellipsis.html.erb +9 -0
  50. data/app/views/components/breadcrumbs/_item.html.erb +8 -0
  51. data/app/views/components/breadcrumbs/_link.html.erb +8 -0
  52. data/app/views/components/breadcrumbs/_list.html.erb +8 -0
  53. data/app/views/components/breadcrumbs/_page.html.erb +8 -0
  54. data/app/views/components/breadcrumbs/_separator.html.erb +17 -0
  55. data/app/views/components/card/_action.html.erb +6 -0
  56. data/app/views/components/card/_content.html.erb +9 -0
  57. data/app/views/components/card/_description.html.erb +6 -0
  58. data/app/views/components/card/_footer.html.erb +17 -0
  59. data/app/views/components/card/_header.html.erb +9 -0
  60. data/app/views/components/card/_title.html.erb +9 -0
  61. data/app/views/components/dropdown_menu/_content.html.erb +20 -0
  62. data/app/views/components/dropdown_menu/_group.html.erb +12 -0
  63. data/app/views/components/dropdown_menu/_item.html.erb +29 -0
  64. data/app/views/components/dropdown_menu/_label.html.erb +13 -0
  65. data/app/views/components/dropdown_menu/_separator.html.erb +11 -0
  66. data/app/views/components/dropdown_menu/_shortcut.html.erb +12 -0
  67. data/app/views/components/dropdown_menu/_trigger.html.erb +24 -0
  68. data/app/views/components/empty/_content.html.erb +8 -0
  69. data/app/views/components/empty/_description.html.erb +12 -0
  70. data/app/views/components/empty/_header.html.erb +8 -0
  71. data/app/views/components/empty/_media.html.erb +13 -0
  72. data/app/views/components/empty/_title.html.erb +12 -0
  73. data/app/views/components/pagination/_content.html.erb +8 -0
  74. data/app/views/components/pagination/_ellipsis.html.erb +28 -0
  75. data/app/views/components/pagination/_item.html.erb +8 -0
  76. data/app/views/components/pagination/_link.html.erb +23 -0
  77. data/app/views/components/pagination/_next.html.erb +57 -0
  78. data/app/views/components/pagination/_previous.html.erb +57 -0
  79. data/app/views/components/sidebar/_content.html.erb +8 -0
  80. data/app/views/components/sidebar/_footer.html.erb +8 -0
  81. data/app/views/components/sidebar/_group.html.erb +12 -0
  82. data/app/views/components/sidebar/_header.html.erb +8 -0
  83. data/app/views/components/sidebar/_inset.html.erb +8 -0
  84. data/app/views/components/sidebar/_menu.html.erb +8 -0
  85. data/app/views/components/sidebar/_menu_button.html.erb +14 -0
  86. data/app/views/components/sidebar/_menu_item.html.erb +7 -0
  87. data/app/views/components/sidebar/_menu_link.html.erb +32 -0
  88. data/app/views/components/sidebar/_provider.html.erb +16 -0
  89. data/app/views/components/sidebar/_trigger.html.erb +12 -0
  90. data/app/views/components/stats/_stats_card.html.erb +100 -0
  91. data/app/views/components/stats/_stats_grid.html.erb +38 -0
  92. data/app/views/components/table/_body.html.erb +5 -0
  93. data/app/views/components/table/_caption.html.erb +5 -0
  94. data/app/views/components/table/_cell.html.erb +5 -0
  95. data/app/views/components/table/_footer.html.erb +5 -0
  96. data/app/views/components/table/_head.html.erb +8 -0
  97. data/app/views/components/table/_header.html.erb +8 -0
  98. data/app/views/components/table/_row.html.erb +8 -0
  99. data/app/views/components/toggle_group/_item.html.erb +19 -0
  100. data/config/importmap.rb +1 -0
  101. data/lib/generators/maquina_components/install/USAGE +39 -0
  102. data/lib/generators/maquina_components/install/install_generator.rb +123 -0
  103. data/lib/generators/maquina_components/install/templates/maquina_components_helper.rb.tt +68 -0
  104. data/lib/generators/maquina_components/install/templates/theme.css.tt +179 -0
  105. data/lib/maquina_components/engine.rb +10 -0
  106. data/lib/maquina_components/version.rb +1 -1
  107. metadata +116 -12
  108. data/app/helpers/components/pagination_helper.rb +0 -15
  109. data/app/views/components/_card_content.html.erb +0 -5
  110. data/app/views/components/_card_header.html.erb +0 -8
  111. data/app/views/components/_sidebar_content.html.erb +0 -8
  112. data/app/views/components/_sidebar_group.html.erb +0 -42
  113. data/app/views/components/_sidebar_header.html.erb +0 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 61b5b2a30e1774c16e25bc87743e5b29e1e8ede10e55f76fbd0ab953108921f4
4
- data.tar.gz: 7d932af15e3e997b0e369e54e5189c18f7ebb6ce407150957323444f70199aa5
3
+ metadata.gz: cdbbf854a700d7b0fa55c3b91f1975d7fd53282ddeb0a14db55011d055db96a3
4
+ data.tar.gz: 1b69e2f23f390efa573e3192410125e8945ec182001ca8f2db431fee72523efc
5
5
  SHA512:
6
- metadata.gz: 4476d4fa6fa5cd882706e2a64a25ae8a5537b1f8d5d214f7d0960a7fc2b294f1d3f034b283be0979cd9e8f23290b4e7b46c2baf81c011727fa0b33551dea0a60
7
- data.tar.gz: 53cd0563b8e6ce33ab34fd38ba19cec938514a1d0be558b4c6e95a36fffcd2068b25f9f7e07e2fde12f61c9a30e62f6e16f5b41bb56233b1b9fe5bd77a5adeee
6
+ metadata.gz: 07a7b92b85cdaf2987c2a816133bd174e1d838ff9af4ce16166ea218729c0896f7f4bbe71c7c8caaa3f175196dbe097d6f426c28db96e0cdd703054a788ba4f9
7
+ data.tar.gz: 53c9a63b128ed2cef878c3935185ed559d3e01274f1354ab34f438926a8e06cdac3980eabdd4c962e9a02765f7102c1694a106c9775cc05ce7f7358ed89add10
data/README.md CHANGED
@@ -1,214 +1,425 @@
1
1
  # Maquina Components
2
2
 
3
- Modern UI components for Ruby on Rails, powered by TailwindCSS and Stimulus
3
+ UI components for Ruby on Rails, built with ERB, TailwindCSS 4.0, and Stimulus.
4
4
 
5
- ![Dashboard Example](/imgs/home.png)
5
+ ---
6
6
 
7
- ![Form Example](/imgs/new.png)
7
+ ## Why This Exists
8
8
 
9
- ## Overview
9
+ I started building components inspired by [shadcn/ui](https://ui.shadcn.com/) for production Rails applications—mainly dashboards and admin interfaces. Over time, I iterated on these components across multiple projects, and they became inconsistent: different APIs, different styling approaches, different levels of completeness.
10
10
 
11
- Maquina Components provides a collection of ready-to-use UI components for Ruby on Rails applications. Built with ERB,
12
- TailwindCSS 4.0, and Stimulus, it offers a modern and maintainable approach to building beautiful user interfaces
13
- without the complexity of JavaScript frameworks.
11
+ It was time to extract the elements I use most and give them a **cohesive API and consistent styling**.
14
12
 
15
- ### Key Features
13
+ ### The Technical Choices
16
14
 
17
- - 🎨 Pre-built UI components based on shadcn/ui design system
18
- - ⚡️ Powered by TailwindCSS 4.0
19
- - 🧩 Seamless Rails integration with ERB partials
20
- - 📱 Fully responsive components
21
- - 🎯 Interactive behaviors with Stimulus controllers
22
- - 🌙 Dark mode support out of the box
23
- - ♿️ Accessibility-first components
15
+ I chose **ERB partials** with **TailwindCSS** and **Stimulus controllers** for interactive elements. For static components like form inputs, pure CSS with data attributes is enough.
24
16
 
25
- ## Installation
17
+ I'm aware of alternatives like [ViewComponent](https://viewcomponent.org/) and [Phlex](https://www.phlex.fun/). The projects I extracted these components from didn't use them. I see the benefits of using a Ruby class to render the UI, but bringing in any of these libraries into a project is a big commitment, and not all projects and teams are open to doing it. The reason is not technical; it is the feeling of moving away from "the Rails way." So I kept it simple: ERB partials that any Rails developer can understand immediately.
26
18
 
27
- Add this line to your application's Gemfile:
19
+ ### Composability Over Convenience
20
+
21
+ These components are built to be **composable**. They are built of many small ERB partials to render. But that's intentional—you can take these partials and compose them into larger, application-specific components. There are no limits, and you have a standard API to guide you.
22
+
23
+ I didn't copy shadcn/ui one-to-one. I extracted only the components I actually use in my applications. This is a practical toolkit, not a complete port.
24
+
25
+ ### One Approach Among Many
26
+
27
+ There's no single UI kit that rules Rails development. If this approach doesn't resonate with you, here are excellent alternatives:
28
+
29
+ - [RailsUI](https://railsui.com) — Premium UI templates and components
30
+ - [RailsBlocks](https://railsblocks.com) — Copy-paste components for Rails
31
+ - [shadcn-rails](https://shadcn.rails-components.com) — Another shadcn/ui port for Rails
32
+ - [Inertia Rails + shadcn Starter](https://evilmartians.com/opensource/inertia-rails-shadcn-starter) — React/Vue components with Inertia
33
+
34
+ If you're open to trying maquina_components and providing feedback, you're welcome to do so. If this isn't for you, that's okay too.
35
+
36
+ ---
37
+
38
+ ## Features
39
+
40
+ - **ERB partials** with strict locals (`locals:` magic comments)
41
+ - **TailwindCSS 4.0** with CSS custom properties for theming
42
+ - **Data attributes** (`data-component`, `data-*-part`) for CSS styling
43
+ - **Stimulus controllers** only used where interactivity is needed
44
+ - **Dark mode** support via CSS variables
45
+ - **shadcn/ui theming** convention (works with their color system)
46
+ - **Composable** — small partials you can combine freely
47
+
48
+ ![Test dummy app with light mode](/imgs/light.png)
49
+
50
+ ![Test dummy app with dark mode](/imgs/dark.png)
51
+
52
+ ---
53
+
54
+ ## Quick Start
55
+
56
+ ### 1. Add the Gem
28
57
 
29
58
  ```ruby
30
- gem 'maquina-components'
59
+ # Gemfile
60
+ gem "maquina-components"
31
61
  ```
32
62
 
33
- Then execute:
34
-
35
63
  ```bash
36
64
  bundle install
37
65
  ```
38
66
 
39
- ### Setup
67
+ ### 2. Run the Install Generator
40
68
 
41
- 1. Install TailwindCSS 4.0 in your Rails application
42
- 2. Add the required Stimulus controllers to your application
43
- 3. Use Shadcn/UI standard color variables:
69
+ ```bash
70
+ bin/rails generate maquina_components:install
71
+ ```
44
72
 
45
- ```css
46
- /* app/assets/stylesheets/application.css */
73
+ This will:
47
74
 
48
- @theme {
49
- /* Default background color of <body />...etc */
50
- --color-background: var(--background);
51
- --color-foreground: var(--foreground);
75
+ - Add the engine CSS import to your Tailwind file
76
+ - Add theme variables (light + dark mode)
77
+ - Create a helper file for icon customization
52
78
 
53
- /* Primary colors for Button */
54
- --color-primary: var(--primary-color);
55
- --color-primary-foreground: var(--primary-foreground-color);
79
+ ### 3. Use Components
56
80
 
57
- /* Muted colors */
58
- --color-muted: var(--muted);
59
- --color-muted-foreground: var(--muted-foreground);
81
+ ```erb
82
+ <%= render "components/card" do %>
83
+ <%= render "components/card/header" do %>
84
+ <%= render "components/card/title", text: "Account Settings" %>
85
+ <%= render "components/card/description", text: "Manage your preferences" %>
86
+ <% end %>
87
+ <%= render "components/card/content" do %>
88
+ <!-- Your content -->
89
+ <% end %>
90
+ <% end %>
91
+ ```
60
92
 
61
- /* Secondary colors */
62
- --color-secondary: var(--secondary);
63
- --color-secondary-foreground: var(--secondary-foreground);
93
+ For form elements, use data attributes with Rails helpers:
64
94
 
65
- /* Accent colors */
66
- --color-accent: var(--accent);
67
- --color-accent-foreground: var(--accent-foreground);
95
+ ```erb
96
+ <%= form_with model: @user do |f| %>
97
+ <%= f.text_field :name, data: { component: "input" } %>
98
+ <%= f.email_field :email, data: { component: "input" } %>
99
+ <%= f.submit "Save", data: { component: "button", variant: "primary" } %>
100
+ <% end %>
101
+ ```
68
102
 
69
- /* Destructive colors */
70
- --color-destructive: var(--destructive);
71
- --color-destructive-foreground: var(--destructive-foreground);
103
+ **[Full Getting Started Guide](https://maquina.app/documentation/components/)**
72
104
 
73
- /* Default input color */
74
- --color-input: var(--input);
105
+ ---
75
106
 
76
- /* Default border color */
77
- --color-border: var(--border);
107
+ ## Generator Options
78
108
 
79
- /* Default ring color */
80
- --color-ring: var(--ring);
81
- --color-ring-destructive: var(--destructive);
109
+ ```bash
110
+ # Default: adds everything
111
+ bin/rails generate maquina_components:install
82
112
 
83
- /* Background color for Card */
84
- --color-card: var(--card);
85
- --color-card-foreground: var(--card-foreground);
113
+ # Skip theme variables (if you have your own)
114
+ bin/rails generate maquina_components:install --skip-theme
86
115
 
87
- /* Sidebar colors */
88
- --color-sidebar: var(--sidebar-background);
89
- --color-sidebar-foreground: var(--sidebar-foreground);
116
+ # Skip helper file
117
+ bin/rails generate maquina_components:install --skip-helper
118
+ ```
90
119
 
91
- --color-sidebar-primary: var(--sidebar-primary);
92
- --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
120
+ **Prerequisite:** [tailwindcss-rails](https://github.com/rails/tailwindcss-rails) must be installed first.
93
121
 
94
- --color-sidebar-accent: var(--sidebar-accent);
95
- --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
122
+ ---
96
123
 
97
- --color-sidebar-ring: var(--sidebar-ring);
98
- --color-sidebar-border: var(--sidebar-border);
99
- }
100
- ```
124
+ ## Available Components
101
125
 
102
- ## Usage
126
+ ### Layout Components
103
127
 
104
- ### Basic Layout Example
128
+ | Component | Description | Documentation |
129
+ |-----------|-------------|---------------|
130
+ | **Sidebar** | Collapsible navigation with cookie persistence | [Sidebar](https://maquina.app/documentation/components/sidebar/) |
131
+ | **Header** | Top navigation bar | [Header](https://maquina.app/documentation/components/header/) |
105
132
 
106
- ```erb
107
- <%# app/views/layouts/application.html.erb %>
108
- <body class="bg-background text-primary font-display antialiased">
109
- <div class="flex min-h-screen">
110
- <%= render "components/sidebar" do %>
111
- <%= render "components/sidebar_header" do %>
112
- <%= render "shared/ui/menu_button",
113
- title: "My App",
114
- subtitle: "Dashboard",
115
- text_icon: "MA" %>
116
- <% end %>
133
+ ### Content Components
117
134
 
118
- <%= render "components/sidebar_content" do %>
119
- <!-- Sidebar content here -->
120
- <% end %>
135
+ | Component | Description | Documentation |
136
+ |-----------|-------------|---------------|
137
+ | **Card** | Content container with header, content, footer | [Card](https://maquina.app/documentation/components/card/) |
138
+ | **Alert** | Callout messages (info, warning, error) | [Alert](https://maquina.app/documentation/components/alert/) |
139
+ | **Badge** | Status indicators and labels | [Badge](https://maquina.app/documentation/components/badge/) |
140
+ | **Table** | Data tables with sorting support | [Table](https://maquina.app/documentation/components/table/) |
141
+ | **Empty State** | Placeholder for empty lists | [Empty State](https://maquina.app/documentation/components/empty/) |
142
+
143
+ ### Navigation Components
144
+
145
+ | Component | Description | Documentation |
146
+ |-----------|-------------|---------------|
147
+ | **Breadcrumbs** | Navigation trail with overflow handling | [Breadcrumbs](https://maquina.app/documentation/components/breadcrumbs/) |
148
+ | **Dropdown Menu** | Accessible dropdown with keyboard navigation | [Dropdown Menu](https://maquina.app/documentation/components/dropdown-menu/) |
149
+ | **Pagination** | Page navigation with Pagy integration | [Pagination](https://maquina.app/documentation/components/pagination/) |
150
+
151
+ ### Interactive Components
152
+
153
+ | Component | Description | Documentation |
154
+ |-----------|-------------|---------------|
155
+ | **Toggle Group** | Single/multiple selection button group | [Toggle Group](https://maquina.app/documentation/components/toggle-group/) |
156
+
157
+ ### Form Components
158
+
159
+ | Component | Data Attribute | Variants |
160
+ |-----------|----------------|----------|
161
+ | **Button** | `data-component="button"` | default, primary, secondary, destructive, outline, ghost, link |
162
+ | **Input** | `data-component="input"` | — |
163
+ | **Textarea** | `data-component="textarea"` | — |
164
+ | **Select** | `data-component="select"` | — |
165
+ | **Checkbox** | `data-component="checkbox"` | — |
166
+ | **Radio** | `data-component="radio"` | — |
167
+ | **Switch** | `data-component="switch"` | — |
168
+
169
+ **[Form Components Guide](https://maquina.app/documentation/components/form/)**
170
+
171
+ ---
172
+
173
+ ## Examples
174
+
175
+ ### Cards with Actions
176
+
177
+ ```erb
178
+ <%= render "components/card" do %>
179
+ <%= render "components/card/header", layout: :row do %>
180
+ <div>
181
+ <%= render "components/card/title", text: "Team Members" %>
182
+ <%= render "components/card/description", text: "Manage your team" %>
183
+ </div>
184
+ <%= render "components/card/action" do %>
185
+ <%= link_to "Add Member", new_member_path,
186
+ data: { component: "button", variant: "primary", size: "sm" } %>
121
187
  <% end %>
188
+ <% end %>
189
+ <%= render "components/card/content" do %>
190
+ <!-- Table or list -->
191
+ <% end %>
192
+ <% end %>
193
+ ```
122
194
 
123
- <main class="flex-1 pl-(--sidebar-width)">
124
- <%= yield %>
125
- </main>
126
- </div>
127
- </body>
195
+ ### Alerts
196
+
197
+ ```erb
198
+ <%= render "components/alert", variant: :destructive do %>
199
+ <%= render "components/alert/title", text: "Error" %>
200
+ <%= render "components/alert/description" do %>
201
+ Your session has expired. Please log in again.
202
+ <% end %>
203
+ <% end %>
128
204
  ```
129
205
 
130
- ### Components
206
+ ### Badges
207
+
208
+ ```erb
209
+ <%= render "components/badge", variant: :success do %>Active<% end %>
210
+ <%= render "components/badge", variant: :warning do %>Pending<% end %>
211
+ <%= render "components/badge", variant: :destructive do %>Failed<% end %>
212
+ ```
131
213
 
132
- #### Cards
214
+ ### Toggle Group
133
215
 
134
216
  ```erb
135
- <%= render "components/card" do %>
136
- <%= render "components/card_header",
137
- title: "Account Balance",
138
- icon: :dollar %>
139
-
140
- <%= render "components/card_content" do %>
141
- <p class="text-2xl font-bold">
142
- <%= number_to_currency(@balance) %>
143
- </p>
144
- <p class="text-xs text-muted-foreground">
145
- Current balance
146
- </p>
217
+ <%= render "components/toggle_group", type: :single, variant: :outline do %>
218
+ <%= render "components/toggle_group/item", value: "left", aria_label: "Align left" do %>
219
+ <%= icon_for :align_left %>
220
+ <% end %>
221
+ <%= render "components/toggle_group/item", value: "center", aria_label: "Align center" do %>
222
+ <%= icon_for :align_center %>
223
+ <% end %>
224
+ <%= render "components/toggle_group/item", value: "right", aria_label: "Align right" do %>
225
+ <%= icon_for :align_right %>
147
226
  <% end %>
148
227
  <% end %>
149
228
  ```
150
229
 
151
- #### Buttons
230
+ ### Dropdown Menu
152
231
 
153
232
  ```erb
154
- <%= link_to new_transaction_path, class: "button-primary" do %>
155
- New Transaction
156
- <%= icon_for(:money) %>
233
+ <%= render "components/dropdown_menu" do %>
234
+ <%= render "components/dropdown_menu/trigger" do %>Options<% end %>
235
+ <%= render "components/dropdown_menu/content" do %>
236
+ <%= render "components/dropdown_menu/item", href: profile_path do %>
237
+ <%= icon_for :user %>
238
+ Profile
239
+ <% end %>
240
+ <%= render "components/dropdown_menu/separator" %>
241
+ <%= render "components/dropdown_menu/item", href: logout_path, method: :delete, variant: :destructive do %>
242
+ <%= icon_for :log_out %>
243
+ Logout
244
+ <% end %>
245
+ <% end %>
157
246
  <% end %>
158
247
  ```
159
248
 
160
- ## Available Components
249
+ ### Pagination
250
+
251
+ ```erb
252
+ <%= pagination_nav(@pagy, :users_path) %>
253
+ ```
254
+
255
+ ### Tables
256
+
257
+ ```erb
258
+ <%= render "components/table" do %>
259
+ <%= render "components/table/header" do %>
260
+ <%= render "components/table/row" do %>
261
+ <%= render "components/table/head" do %>Name<% end %>
262
+ <%= render "components/table/head" do %>Email<% end %>
263
+ <%= render "components/table/head" do %>Role<% end %>
264
+ <% end %>
265
+ <% end %>
266
+ <%= render "components/table/body" do %>
267
+ <% @users.each do |user| %>
268
+ <%= render "components/table/row" do %>
269
+ <%= render "components/table/cell" do %><%= user.name %><% end %>
270
+ <%= render "components/table/cell" do %><%= user.email %><% end %>
271
+ <%= render "components/table/cell" do %>
272
+ <%= render "components/badge", variant: :outline do %><%= user.role %><% end %>
273
+ <% end %>
274
+ <% end %>
275
+ <% end %>
276
+ <% end %>
277
+ <% end %>
278
+ ```
279
+
280
+ ### Sidebar Layout
281
+
282
+ ```erb
283
+ <%= render "components/sidebar/provider", default_open: app_sidebar_open? do %>
284
+ <%= render "components/sidebar" do %>
285
+ <%= render "components/sidebar/header" do %>
286
+ <span class="font-semibold">My App</span>
287
+ <% end %>
288
+
289
+ <%= render "components/sidebar/content" do %>
290
+ <%= render "components/sidebar/group", title: "Navigation" do %>
291
+ <%= render "components/sidebar/menu" do %>
292
+ <%= render "components/sidebar/menu_item" do %>
293
+ <%= render "components/sidebar/menu_button",
294
+ title: "Dashboard",
295
+ url: dashboard_path,
296
+ icon_name: :home,
297
+ active: current_page?(dashboard_path) %>
298
+ <% end %>
299
+ <% end %>
300
+ <% end %>
301
+ <% end %>
302
+ <% end %>
161
303
 
162
- Work in progress...
304
+ <%= render "components/sidebar/inset" do %>
305
+ <%= render "components/header" do %>
306
+ <%= render "components/sidebar/trigger", icon_name: :panel_left %>
307
+ <% end %>
308
+
309
+ <main class="flex-1 p-6">
310
+ <%= yield %>
311
+ </main>
312
+ <% end %>
313
+ <% end %>
314
+ ```
163
315
 
164
- - Layout
165
- - Sidebar
166
- - Card
167
- - Navigation
168
- - Menu Button
169
- - Navigation Menu
170
- - Elements
171
- - Button
172
- - Alert
173
- - Badge
174
- - Forms
175
- - Input
176
- - Select
177
- - Checkbox
178
- - Radio
316
+ ---
179
317
 
180
- ## Customization
318
+ ## Theming
181
319
 
182
- ### Theme Configuration
320
+ Components use CSS variables following the [shadcn/ui theming convention](https://ui.shadcn.com/docs/theming).
183
321
 
184
- Customize the look and feel of your components by modifying the theme variables:
322
+ The install generator adds default theme variables. Customize them in `app/assets/tailwind/application.css`:
185
323
 
186
324
  ```css
325
+ :root {
326
+ /* Change primary to blue */
327
+ --primary: oklch(0.488 0.243 264.376);
328
+ --primary-foreground: oklch(0.985 0 0);
329
+
330
+ /* Add custom colors */
331
+ --success: oklch(0.6 0.2 145);
332
+ --success-foreground: oklch(0.985 0 0);
333
+ }
334
+
187
335
  @theme {
188
- /* Colors */
189
- --color-primary: oklch(21.34% 0 0);
190
- --color-primary-foreground: oklch(98.48% 0 0);
336
+ --color-success: var(--success);
337
+ --color-success-foreground: var(--success-foreground);
338
+ }
339
+ ```
191
340
 
192
- /* Typography */
193
- --font-display: "Inter var", "sans-serif";
341
+ ---
194
342
 
195
- /* Spacing */
196
- --sidebar-width: 16rem;
343
+ ## Helper Methods
197
344
 
198
- /* ... other customizations ... */
199
- }
345
+ | Helper | Purpose |
346
+ |--------|---------|
347
+ | `icon_for(name, options)` | Render an SVG icon |
348
+ | `sidebar_state(cookie_name)` | Get sidebar state (`:expanded` or `:collapsed`) |
349
+ | `sidebar_open?(cookie_name)` | Check if the sidebar is expanded |
350
+ | `pagination_nav(pagy, route)` | Render pagination from Pagy object |
351
+ | `pagination_simple(pagy, route)` | Render simple Previous/Next pagination |
352
+
353
+ ---
354
+
355
+ ## Documentation
356
+
357
+ ### Getting Started
358
+
359
+ - **[Getting Started](https://maquina.app/documentation/components/)** — Installation and setup
360
+
361
+ ### Layout
362
+
363
+ - **[Sidebar](https://maquina.app/documentation/components/sidebar/)** — Navigation sidebar
364
+ - **[Header](https://maquina.app/documentation/components/header/)** — Top navigation bar
365
+
366
+ ### Content
367
+
368
+ - **[Card](https://maquina.app/documentation/components/card/)** — Content containers
369
+ - **[Alert](https://maquina.app/documentation/components/alert/)** — Callout messages
370
+ - **[Badge](https://maquina.app/documentation/components/badge/)** — Status indicators
371
+ - **[Table](https://maquina.app/documentation/components/table/)** — Data tables
372
+ - **[Empty State](https://maquina.app/documentation/components/empty/)** — Empty state placeholders
373
+
374
+ ### Navigation
375
+
376
+ - **[Breadcrumbs](https://maquina.app/documentation/components/breadcrumbs/)** — Navigation trails
377
+ - **[Dropdown Menu](https://maquina.app/documentation/components/dropdown-menu/)** — Dropdown menus
378
+ - **[Pagination](https://maquina.app/documentation/components/pagination/)** — Page navigation
379
+
380
+ ### Interactive
381
+
382
+ - **[Toggle Group](https://maquina.app/documentation/components/toggle-group/)** — Toggle button groups
383
+
384
+ ### Forms
385
+
386
+ - **[Form Components](https://maquina.app/documentation/components/form/)** — Buttons, inputs, and form styling
387
+
388
+ ---
389
+
390
+ ## Development
391
+
392
+ Run the dummy app:
393
+
394
+ ```bash
395
+ cd test/dummy
396
+ bin/rails server
200
397
  ```
201
398
 
399
+ Run tests:
400
+
401
+ ```bash
402
+ bin/rails test
403
+ ```
404
+
405
+ ---
406
+
202
407
  ## Contributing
203
408
 
204
- Bug reports and pull requests are welcome on GitHub at <https://github.com/maquina-app/maquina_components>.
409
+ Bug reports and pull requests are welcome on GitHub at [github.com/maquina-app/maquina_components](https://github.com/maquina-app/maquina_components).
410
+
411
+ ---
205
412
 
206
413
  ## License
207
414
 
208
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
415
+ Copyright (c) [Mario Alberto Chávez Cárdenas](https://mariochavez.io)
416
+
417
+ The gem is available as open source under the terms of the [MIT License](MIT-LICENSE).
418
+
419
+ ---
209
420
 
210
- ## Acknowledgments
421
+ ## Credits
211
422
 
212
- - Design system inspired by [shadcn/ui](https://ui.shadcn.com/)
423
+ - Design patterns from [shadcn/ui](https://ui.shadcn.com/)
213
424
  - Built with [TailwindCSS](https://tailwindcss.com/)
214
425
  - Powered by [Ruby on Rails](https://rubyonrails.org/)
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="1268" height="326"><defs><linearGradient id="b" x1="21.152%" x2="100%" y1="21.848%" y2="93.468%"><stop offset="0%" stop-color="#50B1FD" stop-opacity=".96"/><stop offset="100%" stop-color="#DE77DE" stop-opacity=".96"/></linearGradient><filter id="a" width="109.8%" height="109.8%" x="-4.9%" y="-4.3%" filterUnits="objectBoundingBox"><feOffset dy="2" in="SourceAlpha" result="shadowOffsetOuter1"/><feGaussianBlur in="shadowOffsetOuter1" result="shadowBlurOuter1" stdDeviation="5"/><feColorMatrix in="shadowBlurOuter1" result="shadowMatrixOuter1" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.5 0"/><feMerge><feMergeNode in="shadowMatrixOuter1"/><feMergeNode in="SourceGraphic"/></feMerge></filter></defs><g fill="none" fill-rule="evenodd"><g fill="url(#b)" filter="url(#a)"><path d="M163 0c90.022 0 163 72.978 163 163s-72.978 163-163 163S0 253.022 0 163 72.978 0 163 0Zm-3.035 32.001-2.3.033C82.529 33.836 7.373 106.038 39.71 209.826l.128-.06.17-.085c.666-.337 2.097-1.105 4.294-2.305l.648-.355c7.567-4.142 23.12-12.79 46.658-25.942 8.07 31.143 36.39 54.144 70.088 54.144 11.29 0 21.975-2.582 31.498-7.186l38.287 21.06c-67.582 40.567-122.657 31.134-165.224-28.3l-17.485 10.496c38.51 66.185 141.812 96.167 215.685 13.364-1.55-1.057-18.929-11.076-52.136-30.058 13.432-13.13 21.768-31.441 21.768-51.698 0-24.865-12.561-46.8-31.69-59.816l-.125-44.132c68.28 39.383 86.722 92.078 55.326 158.086l17.666 10.189c39.273-65.736 15.44-170.532-92.866-194.936-.176 1.88-.526 22.209-1.052 60.983a72.517 72.517 0 0 0-19.652-2.696c-38.356 0-69.744 29.799-72.234 67.487L52.886 179.3c0-78.766 36.46-121.07 109.378-126.91V32.012l-2.3-.01Zm2.067 100.096c17.214 0 31.17 13.941 31.17 31.139 0 17.197-13.956 31.138-31.17 31.138-17.215 0-31.17-13.94-31.17-31.138s13.955-31.139 31.17-31.139Z"/></g><g fill="#50B1FD" fill-rule="nonzero"><path d="M424.59 217V102.97h23.1v48.93h-2.1c0-11.48 1.47-21.105 4.41-28.875 2.94-7.77 7.315-13.65 13.125-17.64S476.18 99.4 484.86 99.4h1.26c8.82 0 16.135 1.995 21.945 5.985 5.81 3.99 10.15 9.87 13.02 17.64 2.87 7.77 4.305 17.395 4.305 28.875h-7.35c0-11.48 1.505-21.105 4.515-28.875s7.42-13.65 13.23-17.64c5.81-3.99 13.055-5.985 21.735-5.985h1.26c8.82 0 16.17 1.995 22.05 5.985 5.88 3.99 10.325 9.87 13.335 17.64 3.01 7.77 4.515 17.395 4.515 28.875V217h-29.19v-67.83c0-7.14-1.82-12.845-5.46-17.115-3.64-4.27-8.82-6.405-15.54-6.405-6.72 0-12.11 2.205-16.17 6.615-4.06 4.41-6.09 10.325-6.09 17.745V217h-29.19v-67.83c0-7.14-1.82-12.845-5.46-17.115-3.64-4.27-8.82-6.405-15.54-6.405-6.72 0-12.11 2.205-16.17 6.615-4.06 4.41-6.09 10.325-6.09 17.745V217h-29.19ZM688.56 217v-33.81h-4.83V145.6c0-6.58-1.61-11.48-4.83-14.7-3.22-3.22-8.19-4.83-14.91-4.83-3.5 0-7.7.07-12.6.21-4.9.14-9.835.315-14.805.525-4.97.21-9.415.455-13.335.735v-24.78c3.22-.28 6.86-.56 10.92-.84 4.06-.28 8.225-.455 12.495-.525s8.295-.105 12.075-.105c11.76 0 21.525 1.54 29.295 4.62 7.77 3.08 13.65 7.91 17.64 14.49s5.985 15.19 5.985 25.83V217h-23.1Zm-36.75 2.94c-8.26 0-15.505-1.47-21.735-4.41-6.23-2.94-11.06-7.14-14.49-12.6-3.43-5.46-5.145-12.04-5.145-19.74 0-8.4 2.065-15.26 6.195-20.58 4.13-5.32 9.94-9.31 17.43-11.97s16.275-3.99 26.355-3.99h26.46v17.43H660c-6.72 0-11.865 1.645-15.435 4.935-3.57 3.29-5.355 7.525-5.355 12.705s1.785 9.38 5.355 12.6c3.57 3.22 8.715 4.83 15.435 4.83 4.06 0 7.805-.735 11.235-2.205 3.43-1.47 6.3-3.99 8.61-7.56 2.31-3.57 3.605-8.435 3.885-14.595l7.14 8.19c-.7 7.98-2.625 14.7-5.775 20.16-3.15 5.46-7.49 9.625-13.02 12.495-5.53 2.87-12.285 4.305-20.265 4.305ZM816.87 259v-75.81l8.61-13.44c-.42 10.92-2.66 20.195-6.72 27.825-4.06 7.63-9.52 13.405-16.38 17.325-6.86 3.92-14.77 5.88-23.73 5.88-8.12 0-15.47-1.505-22.05-4.515s-12.215-7.21-16.905-12.6c-4.69-5.39-8.33-11.62-10.92-18.69-2.59-7.07-3.885-14.735-3.885-22.995v-4.41c0-8.12 1.33-15.715 3.99-22.785s6.405-13.23 11.235-18.48c4.83-5.25 10.57-9.38 17.22-12.39 6.65-3.01 14.105-4.515 22.365-4.515 9.52 0 17.78 2.03 24.78 6.09 7 4.06 12.495 9.975 16.485 17.745 3.99 7.77 6.195 17.255 6.615 28.455h-4.62v-48.72h23.1V259h-29.19Zm-30.66-63.21c5.74 0 10.99-1.295 15.75-3.885s8.575-6.37 11.445-11.34c2.87-4.97 4.305-10.815 4.305-17.535v-8.4c0-6.72-1.47-12.355-4.41-16.905-2.94-4.55-6.79-8.05-11.55-10.5-4.76-2.45-9.94-3.675-15.54-3.675-6.3 0-11.865 1.505-16.695 4.515s-8.61 7.28-11.34 12.81c-2.73 5.53-4.095 11.865-4.095 19.005 0 7.14 1.4 13.405 4.2 18.795 2.8 5.39 6.615 9.59 11.445 12.6s10.325 4.515 16.485 4.515ZM907.59 220.57c-13.16 0-23.345-4.34-30.555-13.02-7.21-8.68-10.815-21.56-10.815-38.64v-66.15h29.19v68.67c0 7 1.96 12.565 5.88 16.695 3.92 4.13 9.24 6.195 15.96 6.195 6.72 0 12.215-2.17 16.485-6.51s6.405-10.22 6.405-17.64v-67.41h29.19V217h-23.1v-48.51h2.31c0 11.48-1.47 21.07-4.41 28.77-2.94 7.7-7.35 13.51-13.23 17.43-5.88 3.92-13.23 5.88-22.05 5.88h-1.26ZM997.89 217V102.97h29.19V217h-29.19Zm-15.96-92.19v-21.84h45.15v21.84h-45.15Zm26.67-35.49c-5.74 0-9.975-1.505-12.705-4.515-2.73-3.01-4.095-6.825-4.095-11.445s1.365-8.4 4.095-11.34c2.73-2.94 6.965-4.41 12.705-4.41s9.94 1.47 12.6 4.41c2.66 2.94 3.99 6.72 3.99 11.34s-1.33 8.435-3.99 11.445-6.86 4.515-12.6 4.515ZM1050.18 217V102.97h23.1v48.93h-2.1c0-11.62 1.54-21.315 4.62-29.085s7.665-13.615 13.755-17.535c6.09-3.92 13.685-5.88 22.785-5.88h1.26c13.58 0 23.87 4.375 30.87 13.125s10.5 21.805 10.5 39.165V217h-29.19v-67.83c0-7-1.995-12.67-5.985-17.01-3.99-4.34-9.485-6.51-16.485-6.51-7.14 0-12.915 2.205-17.325 6.615s-6.615 10.325-6.615 17.745V217h-29.19ZM1244.85 217v-33.81h-4.83V145.6c0-6.58-1.61-11.48-4.83-14.7-3.22-3.22-8.19-4.83-14.91-4.83-3.5 0-7.7.07-12.6.21-4.9.14-9.835.315-14.805.525-4.97.21-9.415.455-13.335.735v-24.78c3.22-.28 6.86-.56 10.92-.84 4.06-.28 8.225-.455 12.495-.525s8.295-.105 12.075-.105c11.76 0 21.525 1.54 29.295 4.62 7.77 3.08 13.65 7.91 17.64 14.49s5.985 15.19 5.985 25.83V217h-23.1Zm-36.75 2.94c-8.26 0-15.505-1.47-21.735-4.41-6.23-2.94-11.06-7.14-14.49-12.6-3.43-5.46-5.145-12.04-5.145-19.74 0-8.4 2.065-15.26 6.195-20.58 4.13-5.32 9.94-9.31 17.43-11.97s16.275-3.99 26.355-3.99h26.46v17.43h-26.88c-6.72 0-11.865 1.645-15.435 4.935-3.57 3.29-5.355 7.525-5.355 12.705s1.785 9.38 5.355 12.6c3.57 3.22 8.715 4.83 15.435 4.83 4.06 0 7.805-.735 11.235-2.205 3.43-1.47 6.3-3.99 8.61-7.56 2.31-3.57 3.605-8.435 3.885-14.595l7.14 8.19c-.7 7.98-2.625 14.7-5.775 20.16-3.15 5.46-7.49 9.625-13.02 12.495-5.53 2.87-12.285 4.305-20.265 4.305Z"/></g></g></svg>