maquina-components 0.1.2 → 0.3.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 (135) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +399 -137
  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/combobox.css +218 -0
  9. data/app/assets/stylesheets/dropdown_menu.css +248 -0
  10. data/app/assets/stylesheets/empty.css +133 -0
  11. data/app/assets/stylesheets/form.css +617 -0
  12. data/app/assets/stylesheets/header.css +61 -0
  13. data/app/assets/stylesheets/maquina_components.css +143 -64
  14. data/app/assets/stylesheets/pagination.css +154 -0
  15. data/app/assets/stylesheets/sidebar.css +477 -0
  16. data/app/assets/stylesheets/table.css +205 -0
  17. data/app/assets/stylesheets/toast.css +433 -0
  18. data/app/assets/stylesheets/toggle_group.css +151 -0
  19. data/app/assets/tailwind/maquina_components_engine/engine.css +18 -0
  20. data/app/helpers/maquina_components/breadcrumbs_helper.rb +118 -0
  21. data/app/helpers/maquina_components/combobox_helper.rb +300 -0
  22. data/app/helpers/maquina_components/dropdown_menu_helper.rb +249 -0
  23. data/app/helpers/maquina_components/empty_helper.rb +102 -0
  24. data/app/helpers/{components → maquina_components}/icons_helper.rb +40 -3
  25. data/app/helpers/maquina_components/pagination_helper.rb +153 -0
  26. data/app/helpers/maquina_components/sidebar_helper.rb +63 -0
  27. data/app/helpers/maquina_components/table_helper.rb +144 -0
  28. data/app/helpers/maquina_components/toast_helper.rb +115 -0
  29. data/app/helpers/maquina_components/toggle_group_helper.rb +172 -0
  30. data/app/javascript/controllers/breadcrumb_controller.js +71 -0
  31. data/app/javascript/controllers/combobox_controller.js +325 -0
  32. data/app/javascript/controllers/dropdown_menu_controller.js +203 -0
  33. data/app/javascript/controllers/menu_button_controller.js +59 -0
  34. data/app/javascript/controllers/sidebar_controller.js +316 -0
  35. data/app/javascript/controllers/sidebar_trigger_controller.js +32 -0
  36. data/app/javascript/controllers/toast_controller.js +115 -0
  37. data/app/javascript/controllers/toaster_controller.js +226 -0
  38. data/app/javascript/controllers/toggle_group_controller.js +178 -0
  39. data/app/views/components/_alert.html.erb +11 -10
  40. data/app/views/components/_badge.html.erb +10 -0
  41. data/app/views/components/_breadcrumbs.html.erb +16 -0
  42. data/app/views/components/_card.html.erb +4 -8
  43. data/app/views/components/_combobox.html.erb +13 -0
  44. data/app/views/components/_dropdown.html.erb +25 -0
  45. data/app/views/components/_dropdown_menu.html.erb +9 -0
  46. data/app/views/components/_empty.html.erb +10 -0
  47. data/app/views/components/_header.html.erb +8 -0
  48. data/app/views/components/_menu_button.html.erb +44 -0
  49. data/app/views/components/_pagination.html.erb +12 -33
  50. data/app/views/components/_separator.html.erb +11 -0
  51. data/app/views/components/_sidebar.html.erb +30 -20
  52. data/app/views/components/_simple_table.html.erb +49 -0
  53. data/app/views/components/_table.html.erb +21 -0
  54. data/app/views/components/_toast.html.erb +53 -0
  55. data/app/views/components/_toaster.html.erb +17 -0
  56. data/app/views/components/_toggle_group.html.erb +24 -0
  57. data/app/views/components/alert/_description.html.erb +6 -0
  58. data/app/views/components/alert/_title.html.erb +6 -0
  59. data/app/views/components/breadcrumbs/_ellipsis.html.erb +9 -0
  60. data/app/views/components/breadcrumbs/_item.html.erb +8 -0
  61. data/app/views/components/breadcrumbs/_link.html.erb +8 -0
  62. data/app/views/components/breadcrumbs/_list.html.erb +8 -0
  63. data/app/views/components/breadcrumbs/_page.html.erb +8 -0
  64. data/app/views/components/breadcrumbs/_separator.html.erb +17 -0
  65. data/app/views/components/card/_action.html.erb +6 -0
  66. data/app/views/components/card/_content.html.erb +9 -0
  67. data/app/views/components/card/_description.html.erb +6 -0
  68. data/app/views/components/card/_footer.html.erb +17 -0
  69. data/app/views/components/card/_header.html.erb +9 -0
  70. data/app/views/components/card/_title.html.erb +9 -0
  71. data/app/views/components/combobox/_content.html.erb +17 -0
  72. data/app/views/components/combobox/_empty.html.erb +9 -0
  73. data/app/views/components/combobox/_group.html.erb +8 -0
  74. data/app/views/components/combobox/_input.html.erb +18 -0
  75. data/app/views/components/combobox/_label.html.erb +8 -0
  76. data/app/views/components/combobox/_list.html.erb +8 -0
  77. data/app/views/components/combobox/_option.html.erb +24 -0
  78. data/app/views/components/combobox/_separator.html.erb +6 -0
  79. data/app/views/components/combobox/_trigger.html.erb +22 -0
  80. data/app/views/components/dropdown_menu/_content.html.erb +20 -0
  81. data/app/views/components/dropdown_menu/_group.html.erb +12 -0
  82. data/app/views/components/dropdown_menu/_item.html.erb +29 -0
  83. data/app/views/components/dropdown_menu/_label.html.erb +13 -0
  84. data/app/views/components/dropdown_menu/_separator.html.erb +11 -0
  85. data/app/views/components/dropdown_menu/_shortcut.html.erb +12 -0
  86. data/app/views/components/dropdown_menu/_trigger.html.erb +24 -0
  87. data/app/views/components/empty/_content.html.erb +8 -0
  88. data/app/views/components/empty/_description.html.erb +12 -0
  89. data/app/views/components/empty/_header.html.erb +8 -0
  90. data/app/views/components/empty/_media.html.erb +13 -0
  91. data/app/views/components/empty/_title.html.erb +12 -0
  92. data/app/views/components/pagination/_content.html.erb +8 -0
  93. data/app/views/components/pagination/_ellipsis.html.erb +28 -0
  94. data/app/views/components/pagination/_item.html.erb +8 -0
  95. data/app/views/components/pagination/_link.html.erb +23 -0
  96. data/app/views/components/pagination/_next.html.erb +57 -0
  97. data/app/views/components/pagination/_previous.html.erb +57 -0
  98. data/app/views/components/sidebar/_content.html.erb +8 -0
  99. data/app/views/components/sidebar/_footer.html.erb +8 -0
  100. data/app/views/components/sidebar/_group.html.erb +12 -0
  101. data/app/views/components/sidebar/_header.html.erb +8 -0
  102. data/app/views/components/sidebar/_inset.html.erb +8 -0
  103. data/app/views/components/sidebar/_menu.html.erb +8 -0
  104. data/app/views/components/sidebar/_menu_button.html.erb +14 -0
  105. data/app/views/components/sidebar/_menu_item.html.erb +7 -0
  106. data/app/views/components/sidebar/_menu_link.html.erb +32 -0
  107. data/app/views/components/sidebar/_provider.html.erb +16 -0
  108. data/app/views/components/sidebar/_trigger.html.erb +12 -0
  109. data/app/views/components/stats/_stats_card.html.erb +100 -0
  110. data/app/views/components/stats/_stats_grid.html.erb +38 -0
  111. data/app/views/components/table/_body.html.erb +5 -0
  112. data/app/views/components/table/_caption.html.erb +5 -0
  113. data/app/views/components/table/_cell.html.erb +5 -0
  114. data/app/views/components/table/_footer.html.erb +5 -0
  115. data/app/views/components/table/_head.html.erb +8 -0
  116. data/app/views/components/table/_header.html.erb +8 -0
  117. data/app/views/components/table/_row.html.erb +8 -0
  118. data/app/views/components/toast/_action.html.erb +14 -0
  119. data/app/views/components/toast/_description.html.erb +8 -0
  120. data/app/views/components/toast/_title.html.erb +8 -0
  121. data/app/views/components/toggle_group/_item.html.erb +19 -0
  122. data/config/importmap.rb +1 -0
  123. data/lib/generators/maquina_components/install/USAGE +39 -0
  124. data/lib/generators/maquina_components/install/install_generator.rb +123 -0
  125. data/lib/generators/maquina_components/install/templates/maquina_components_helper.rb.tt +68 -0
  126. data/lib/generators/maquina_components/install/templates/theme.css.tt +179 -0
  127. data/lib/maquina_components/engine.rb +10 -0
  128. data/lib/maquina_components/version.rb +1 -1
  129. metadata +138 -12
  130. data/app/helpers/components/pagination_helper.rb +0 -15
  131. data/app/views/components/_card_content.html.erb +0 -5
  132. data/app/views/components/_card_header.html.erb +0 -8
  133. data/app/views/components/_sidebar_content.html.erb +0 -8
  134. data/app/views/components/_sidebar_group.html.erb +0 -42
  135. 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: e04564783a082eb56e58395e1de24dc21deb1312c49ebc47e48428a4230e6925
4
+ data.tar.gz: 78630e11ca92ae6a964c2bc100a7357722d7618df3a5a0a7d0619bbc48eeb5d3
5
5
  SHA512:
6
- metadata.gz: 4476d4fa6fa5cd882706e2a64a25ae8a5537b1f8d5d214f7d0960a7fc2b294f1d3f034b283be0979cd9e8f23290b4e7b46c2baf81c011727fa0b33551dea0a60
7
- data.tar.gz: 53cd0563b8e6ce33ab34fd38ba19cec938514a1d0be558b4c6e95a36fffcd2068b25f9f7e07e2fde12f61c9a30e62f6e16f5b41bb56233b1b9fe5bd77a5adeee
6
+ metadata.gz: 225bbf4a0100ac2f80a03e3bcf38f6080365db13228fade762fa5c8378631b2f0aa5d45d71654e2ecfa6577fe88f9c317163a8c29b44f003657146870bd3c44f
7
+ data.tar.gz: f3b563c5a789cb8039fc5e30e5461114556ca37289bd2b9859b0516973f1c4d7f54204745ad48628271ae24574522784cae4e8865f83e596326b5707d903a4ea
data/README.md CHANGED
@@ -1,214 +1,476 @@
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
78
+
79
+ ### 3. Use Components
80
+
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
+ ```
52
92
 
53
- /* Primary colors for Button */
54
- --color-primary: var(--primary-color);
55
- --color-primary-foreground: var(--primary-foreground-color);
93
+ For form elements, use data attributes with Rails helpers:
56
94
 
57
- /* Muted colors */
58
- --color-muted: var(--muted);
59
- --color-muted-foreground: var(--muted-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
+ ```
60
102
 
61
- /* Secondary colors */
62
- --color-secondary: var(--secondary);
63
- --color-secondary-foreground: var(--secondary-foreground);
103
+ **[Full Getting Started Guide](https://maquina.app/documentation/components/)**
64
104
 
65
- /* Accent colors */
66
- --color-accent: var(--accent);
67
- --color-accent-foreground: var(--accent-foreground);
105
+ ---
68
106
 
69
- /* Destructive colors */
70
- --color-destructive: var(--destructive);
71
- --color-destructive-foreground: var(--destructive-foreground);
107
+ ## Generator Options
72
108
 
73
- /* Default input color */
74
- --color-input: var(--input);
109
+ ```bash
110
+ # Default: adds everything
111
+ bin/rails generate maquina_components:install
75
112
 
76
- /* Default border color */
77
- --color-border: var(--border);
113
+ # Skip theme variables (if you have your own)
114
+ bin/rails generate maquina_components:install --skip-theme
78
115
 
79
- /* Default ring color */
80
- --color-ring: var(--ring);
81
- --color-ring-destructive: var(--destructive);
116
+ # Skip helper file
117
+ bin/rails generate maquina_components:install --skip-helper
118
+ ```
82
119
 
83
- /* Background color for Card */
84
- --color-card: var(--card);
85
- --color-card-foreground: var(--card-foreground);
120
+ **Prerequisite:** [tailwindcss-rails](https://github.com/rails/tailwindcss-rails) must be installed first.
86
121
 
87
- /* Sidebar colors */
88
- --color-sidebar: var(--sidebar-background);
89
- --color-sidebar-foreground: var(--sidebar-foreground);
122
+ ---
90
123
 
91
- --color-sidebar-primary: var(--sidebar-primary);
92
- --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
124
+ ## Available Components
93
125
 
94
- --color-sidebar-accent: var(--sidebar-accent);
95
- --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
126
+ ### Layout Components
96
127
 
97
- --color-sidebar-ring: var(--sidebar-ring);
98
- --color-sidebar-border: var(--sidebar-border);
99
- }
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/) |
132
+
133
+ ### Content Components
134
+
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
+ | **Combobox** | Searchable dropdown with keyboard navigation | [Combobox](https://maquina.app/documentation/components/combobox/) |
156
+ | **Toggle Group** | Single/multiple selection button group | [Toggle Group](https://maquina.app/documentation/components/toggle-group/) |
157
+
158
+ ### Feedback Components
159
+
160
+ | Component | Description | Documentation |
161
+ |-----------|-------------|---------------|
162
+ | **Toast** | Non-intrusive notifications with auto-dismiss | [Toast](https://maquina.app/documentation/components/toast/) |
163
+
164
+ ### Form Components
165
+
166
+ | Component | Data Attribute | Variants |
167
+ |-----------|----------------|----------|
168
+ | **Button** | `data-component="button"` | default, primary, secondary, destructive, outline, ghost, link |
169
+ | **Input** | `data-component="input"` | — |
170
+ | **Textarea** | `data-component="textarea"` | — |
171
+ | **Select** | `data-component="select"` | — |
172
+ | **Checkbox** | `data-component="checkbox"` | — |
173
+ | **Radio** | `data-component="radio"` | — |
174
+ | **Switch** | `data-component="switch"` | — |
175
+
176
+ **[Form Components Guide](https://maquina.app/documentation/components/form/)**
177
+
178
+ ---
179
+
180
+ ## Examples
181
+
182
+ ### Cards with Actions
183
+
184
+ ```erb
185
+ <%= render "components/card" do %>
186
+ <%= render "components/card/header", layout: :row do %>
187
+ <div>
188
+ <%= render "components/card/title", text: "Team Members" %>
189
+ <%= render "components/card/description", text: "Manage your team" %>
190
+ </div>
191
+ <%= render "components/card/action" do %>
192
+ <%= link_to "Add Member", new_member_path,
193
+ data: { component: "button", variant: "primary", size: "sm" } %>
194
+ <% end %>
195
+ <% end %>
196
+ <%= render "components/card/content" do %>
197
+ <!-- Table or list -->
198
+ <% end %>
199
+ <% end %>
100
200
  ```
101
201
 
102
- ## Usage
202
+ ### Alerts
103
203
 
104
- ### Basic Layout Example
204
+ ```erb
205
+ <%= render "components/alert", variant: :destructive do %>
206
+ <%= render "components/alert/title", text: "Error" %>
207
+ <%= render "components/alert/description" do %>
208
+ Your session has expired. Please log in again.
209
+ <% end %>
210
+ <% end %>
211
+ ```
212
+
213
+ ### Badges
105
214
 
106
215
  ```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 %>
216
+ <%= render "components/badge", variant: :success do %>Active<% end %>
217
+ <%= render "components/badge", variant: :warning do %>Pending<% end %>
218
+ <%= render "components/badge", variant: :destructive do %>Failed<% end %>
219
+ ```
117
220
 
118
- <%= render "components/sidebar_content" do %>
119
- <!-- Sidebar content here -->
120
- <% end %>
121
- <% end %>
221
+ ### Toggle Group
122
222
 
123
- <main class="flex-1 pl-(--sidebar-width)">
124
- <%= yield %>
125
- </main>
126
- </div>
127
- </body>
223
+ ```erb
224
+ <%= render "components/toggle_group", type: :single, variant: :outline do %>
225
+ <%= render "components/toggle_group/item", value: "left", aria_label: "Align left" do %>
226
+ <%= icon_for :align_left %>
227
+ <% end %>
228
+ <%= render "components/toggle_group/item", value: "center", aria_label: "Align center" do %>
229
+ <%= icon_for :align_center %>
230
+ <% end %>
231
+ <%= render "components/toggle_group/item", value: "right", aria_label: "Align right" do %>
232
+ <%= icon_for :align_right %>
233
+ <% end %>
234
+ <% end %>
128
235
  ```
129
236
 
130
- ### Components
237
+ ### Dropdown Menu
131
238
 
132
- #### Cards
239
+ ```erb
240
+ <%= render "components/dropdown_menu" do %>
241
+ <%= render "components/dropdown_menu/trigger" do %>Options<% end %>
242
+ <%= render "components/dropdown_menu/content" do %>
243
+ <%= render "components/dropdown_menu/item", href: profile_path do %>
244
+ <%= icon_for :user %>
245
+ Profile
246
+ <% end %>
247
+ <%= render "components/dropdown_menu/separator" %>
248
+ <%= render "components/dropdown_menu/item", href: logout_path, method: :delete, variant: :destructive do %>
249
+ <%= icon_for :log_out %>
250
+ Logout
251
+ <% end %>
252
+ <% end %>
253
+ <% end %>
254
+ ```
255
+
256
+ ### Pagination
133
257
 
134
258
  ```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>
259
+ <%= pagination_nav(@pagy, :users_path) %>
260
+ ```
261
+
262
+ ### Combobox
263
+
264
+ ```erb
265
+ <%= render "components/combobox", placeholder: "Select framework..." do |combobox_id| %>
266
+ <%= render "components/combobox/trigger", for_id: combobox_id, placeholder: "Select framework..." %>
267
+ <%= render "components/combobox/content", id: combobox_id do %>
268
+ <%= render "components/combobox/input", placeholder: "Search..." %>
269
+ <%= render "components/combobox/list" do %>
270
+ <%= render "components/combobox/option", value: "rails" do %>Ruby on Rails<% end %>
271
+ <%= render "components/combobox/option", value: "hanami" do %>Hanami<% end %>
272
+ <%= render "components/combobox/option", value: "sinatra" do %>Sinatra<% end %>
273
+ <% end %>
274
+ <%= render "components/combobox/empty" %>
147
275
  <% end %>
148
276
  <% end %>
149
277
  ```
150
278
 
151
- #### Buttons
279
+ ### Toast Notifications
152
280
 
153
281
  ```erb
154
- <%= link_to new_transaction_path, class: "button-primary" do %>
155
- New Transaction
156
- <%= icon_for(:money) %>
282
+ <%# Add toaster to your layout %>
283
+ <%= render "components/toaster", position: :bottom_right do %>
284
+ <%= toast_flash_messages %>
157
285
  <% end %>
286
+
287
+ <%# In your controller %>
288
+ flash[:success] = "Changes saved successfully!"
289
+
290
+ <%# Or use the JavaScript API %>
291
+ <script>
292
+ Toast.success("Profile updated!")
293
+ Toast.error("Something went wrong", { description: "Please try again." })
294
+ </script>
158
295
  ```
159
296
 
160
- ## Available Components
297
+ ### Tables
298
+
299
+ ```erb
300
+ <%= render "components/table" do %>
301
+ <%= render "components/table/header" do %>
302
+ <%= render "components/table/row" do %>
303
+ <%= render "components/table/head" do %>Name<% end %>
304
+ <%= render "components/table/head" do %>Email<% end %>
305
+ <%= render "components/table/head" do %>Role<% end %>
306
+ <% end %>
307
+ <% end %>
308
+ <%= render "components/table/body" do %>
309
+ <% @users.each do |user| %>
310
+ <%= render "components/table/row" do %>
311
+ <%= render "components/table/cell" do %><%= user.name %><% end %>
312
+ <%= render "components/table/cell" do %><%= user.email %><% end %>
313
+ <%= render "components/table/cell" do %>
314
+ <%= render "components/badge", variant: :outline do %><%= user.role %><% end %>
315
+ <% end %>
316
+ <% end %>
317
+ <% end %>
318
+ <% end %>
319
+ <% end %>
320
+ ```
321
+
322
+ ### Sidebar Layout
161
323
 
162
- Work in progress...
324
+ ```erb
325
+ <%= render "components/sidebar/provider", default_open: app_sidebar_open? do %>
326
+ <%= render "components/sidebar" do %>
327
+ <%= render "components/sidebar/header" do %>
328
+ <span class="font-semibold">My App</span>
329
+ <% end %>
330
+
331
+ <%= render "components/sidebar/content" do %>
332
+ <%= render "components/sidebar/group", title: "Navigation" do %>
333
+ <%= render "components/sidebar/menu" do %>
334
+ <%= render "components/sidebar/menu_item" do %>
335
+ <%= render "components/sidebar/menu_button",
336
+ title: "Dashboard",
337
+ url: dashboard_path,
338
+ icon_name: :home,
339
+ active: current_page?(dashboard_path) %>
340
+ <% end %>
341
+ <% end %>
342
+ <% end %>
343
+ <% end %>
344
+ <% end %>
163
345
 
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
346
+ <%= render "components/sidebar/inset" do %>
347
+ <%= render "components/header" do %>
348
+ <%= render "components/sidebar/trigger", icon_name: :panel_left %>
349
+ <% end %>
350
+
351
+ <main class="flex-1 p-6">
352
+ <%= yield %>
353
+ </main>
354
+ <% end %>
355
+ <% end %>
356
+ ```
179
357
 
180
- ## Customization
358
+ ---
181
359
 
182
- ### Theme Configuration
360
+ ## Theming
183
361
 
184
- Customize the look and feel of your components by modifying the theme variables:
362
+ Components use CSS variables following the [shadcn/ui theming convention](https://ui.shadcn.com/docs/theming).
363
+
364
+ The install generator adds default theme variables. Customize them in `app/assets/tailwind/application.css`:
185
365
 
186
366
  ```css
367
+ :root {
368
+ /* Change primary to blue */
369
+ --primary: oklch(0.488 0.243 264.376);
370
+ --primary-foreground: oklch(0.985 0 0);
371
+
372
+ /* Add custom colors */
373
+ --success: oklch(0.6 0.2 145);
374
+ --success-foreground: oklch(0.985 0 0);
375
+ }
376
+
187
377
  @theme {
188
- /* Colors */
189
- --color-primary: oklch(21.34% 0 0);
190
- --color-primary-foreground: oklch(98.48% 0 0);
378
+ --color-success: var(--success);
379
+ --color-success-foreground: var(--success-foreground);
380
+ }
381
+ ```
191
382
 
192
- /* Typography */
193
- --font-display: "Inter var", "sans-serif";
383
+ ---
194
384
 
195
- /* Spacing */
196
- --sidebar-width: 16rem;
385
+ ## Helper Methods
197
386
 
198
- /* ... other customizations ... */
199
- }
387
+ | Helper | Purpose |
388
+ |--------|---------|
389
+ | `icon_for(name, options)` | Render an SVG icon |
390
+ | `sidebar_state(cookie_name)` | Get sidebar state (`:expanded` or `:collapsed`) |
391
+ | `sidebar_open?(cookie_name)` | Check if the sidebar is expanded |
392
+ | `pagination_nav(pagy, route)` | Render pagination from Pagy object |
393
+ | `pagination_simple(pagy, route)` | Render simple Previous/Next pagination |
394
+ | `toast_flash_messages` | Render all flash messages as toasts |
395
+ | `toast(variant, title, **options)` | Render a single toast notification |
396
+ | `combobox(placeholder:, **options, &block)` | Builder pattern for combobox |
397
+ | `combobox_simple(options:, **options)` | Data-driven simple combobox |
398
+
399
+ ---
400
+
401
+ ## Documentation
402
+
403
+ ### Getting Started
404
+
405
+ - **[Getting Started](https://maquina.app/documentation/components/)** — Installation and setup
406
+
407
+ ### Layout
408
+
409
+ - **[Sidebar](https://maquina.app/documentation/components/sidebar/)** — Navigation sidebar
410
+ - **[Header](https://maquina.app/documentation/components/header/)** — Top navigation bar
411
+
412
+ ### Content
413
+
414
+ - **[Card](https://maquina.app/documentation/components/card/)** — Content containers
415
+ - **[Alert](https://maquina.app/documentation/components/alert/)** — Callout messages
416
+ - **[Badge](https://maquina.app/documentation/components/badge/)** — Status indicators
417
+ - **[Table](https://maquina.app/documentation/components/table/)** — Data tables
418
+ - **[Empty State](https://maquina.app/documentation/components/empty/)** — Empty state placeholders
419
+
420
+ ### Navigation
421
+
422
+ - **[Breadcrumbs](https://maquina.app/documentation/components/breadcrumbs/)** — Navigation trails
423
+ - **[Dropdown Menu](https://maquina.app/documentation/components/dropdown-menu/)** — Dropdown menus
424
+ - **[Pagination](https://maquina.app/documentation/components/pagination/)** — Page navigation
425
+
426
+ ### Interactive
427
+
428
+ - **[Combobox](https://maquina.app/documentation/components/combobox/)** — Searchable dropdown selection
429
+ - **[Toggle Group](https://maquina.app/documentation/components/toggle-group/)** — Toggle button groups
430
+
431
+ ### Feedback
432
+
433
+ - **[Toast](https://maquina.app/documentation/components/toast/)** — Toast notifications
434
+
435
+ ### Forms
436
+
437
+ - **[Form Components](https://maquina.app/documentation/components/form/)** — Buttons, inputs, and form styling
438
+
439
+ ---
440
+
441
+ ## Development
442
+
443
+ Run the dummy app:
444
+
445
+ ```bash
446
+ cd test/dummy
447
+ bin/rails server
200
448
  ```
201
449
 
450
+ Run tests:
451
+
452
+ ```bash
453
+ bin/rails test
454
+ ```
455
+
456
+ ---
457
+
202
458
  ## Contributing
203
459
 
204
- Bug reports and pull requests are welcome on GitHub at <https://github.com/maquina-app/maquina_components>.
460
+ Bug reports and pull requests are welcome on GitHub at [github.com/maquina-app/maquina_components](https://github.com/maquina-app/maquina_components).
461
+
462
+ ---
205
463
 
206
464
  ## License
207
465
 
208
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
466
+ Copyright (c) [Mario Alberto Chávez Cárdenas](https://mariochavez.io)
467
+
468
+ The gem is available as open source under the terms of the [MIT License](MIT-LICENSE).
469
+
470
+ ---
209
471
 
210
- ## Acknowledgments
472
+ ## Credits
211
473
 
212
- - Design system inspired by [shadcn/ui](https://ui.shadcn.com/)
474
+ - Design patterns from [shadcn/ui](https://ui.shadcn.com/)
213
475
  - Built with [TailwindCSS](https://tailwindcss.com/)
214
476
  - 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>