maquina-components 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +197 -11
- data/app/assets/stylesheets/maquina_components.css +99 -0
- data/app/helpers/components/icons_helper.rb +124 -0
- data/app/helpers/components/pagination_helper.rb +15 -0
- data/app/views/components/_alert.html.erb +11 -0
- data/app/views/components/_card.html.erb +10 -0
- data/app/views/components/_card_content.html.erb +5 -0
- data/app/views/components/_card_header.html.erb +8 -0
- data/app/views/components/_pagination.html.erb +34 -0
- data/app/views/components/_sidebar.html.erb +30 -0
- data/app/views/components/_sidebar_content.html.erb +8 -0
- data/app/views/components/_sidebar_group.html.erb +42 -0
- data/app/views/components/_sidebar_header.html.erb +3 -0
- data/lib/maquina_components/version.rb +1 -1
- metadata +14 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 61b5b2a30e1774c16e25bc87743e5b29e1e8ede10e55f76fbd0ab953108921f4
|
4
|
+
data.tar.gz: 7d932af15e3e997b0e369e54e5189c18f7ebb6ce407150957323444f70199aa5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4476d4fa6fa5cd882706e2a64a25ae8a5537b1f8d5d214f7d0960a7fc2b294f1d3f034b283be0979cd9e8f23290b4e7b46c2baf81c011727fa0b33551dea0a60
|
7
|
+
data.tar.gz: 53cd0563b8e6ce33ab34fd38ba19cec938514a1d0be558b4c6e95a36fffcd2068b25f9f7e07e2fde12f61c9a30e62f6e16f5b41bb56233b1b9fe5bd77a5adeee
|
data/README.md
CHANGED
@@ -1,28 +1,214 @@
|
|
1
|
-
#
|
2
|
-
Short description and motivation.
|
1
|
+
# Maquina Components
|
3
2
|
|
4
|
-
|
5
|
-
|
3
|
+
Modern UI components for Ruby on Rails, powered by TailwindCSS and Stimulus
|
4
|
+
|
5
|
+

|
6
|
+
|
7
|
+

|
8
|
+
|
9
|
+
## Overview
|
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.
|
14
|
+
|
15
|
+
### Key Features
|
16
|
+
|
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
|
6
24
|
|
7
25
|
## Installation
|
26
|
+
|
8
27
|
Add this line to your application's Gemfile:
|
9
28
|
|
10
29
|
```ruby
|
11
|
-
gem
|
30
|
+
gem 'maquina-components'
|
12
31
|
```
|
13
32
|
|
14
|
-
|
33
|
+
Then execute:
|
34
|
+
|
15
35
|
```bash
|
16
|
-
|
36
|
+
bundle install
|
17
37
|
```
|
18
38
|
|
19
|
-
|
20
|
-
|
21
|
-
|
39
|
+
### Setup
|
40
|
+
|
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:
|
44
|
+
|
45
|
+
```css
|
46
|
+
/* app/assets/stylesheets/application.css */
|
47
|
+
|
48
|
+
@theme {
|
49
|
+
/* Default background color of <body />...etc */
|
50
|
+
--color-background: var(--background);
|
51
|
+
--color-foreground: var(--foreground);
|
52
|
+
|
53
|
+
/* Primary colors for Button */
|
54
|
+
--color-primary: var(--primary-color);
|
55
|
+
--color-primary-foreground: var(--primary-foreground-color);
|
56
|
+
|
57
|
+
/* Muted colors */
|
58
|
+
--color-muted: var(--muted);
|
59
|
+
--color-muted-foreground: var(--muted-foreground);
|
60
|
+
|
61
|
+
/* Secondary colors */
|
62
|
+
--color-secondary: var(--secondary);
|
63
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
64
|
+
|
65
|
+
/* Accent colors */
|
66
|
+
--color-accent: var(--accent);
|
67
|
+
--color-accent-foreground: var(--accent-foreground);
|
68
|
+
|
69
|
+
/* Destructive colors */
|
70
|
+
--color-destructive: var(--destructive);
|
71
|
+
--color-destructive-foreground: var(--destructive-foreground);
|
72
|
+
|
73
|
+
/* Default input color */
|
74
|
+
--color-input: var(--input);
|
75
|
+
|
76
|
+
/* Default border color */
|
77
|
+
--color-border: var(--border);
|
78
|
+
|
79
|
+
/* Default ring color */
|
80
|
+
--color-ring: var(--ring);
|
81
|
+
--color-ring-destructive: var(--destructive);
|
82
|
+
|
83
|
+
/* Background color for Card */
|
84
|
+
--color-card: var(--card);
|
85
|
+
--color-card-foreground: var(--card-foreground);
|
86
|
+
|
87
|
+
/* Sidebar colors */
|
88
|
+
--color-sidebar: var(--sidebar-background);
|
89
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
90
|
+
|
91
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
92
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
93
|
+
|
94
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
95
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
96
|
+
|
97
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
98
|
+
--color-sidebar-border: var(--sidebar-border);
|
99
|
+
}
|
100
|
+
```
|
101
|
+
|
102
|
+
## Usage
|
103
|
+
|
104
|
+
### Basic Layout Example
|
105
|
+
|
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 %>
|
117
|
+
|
118
|
+
<%= render "components/sidebar_content" do %>
|
119
|
+
<!-- Sidebar content here -->
|
120
|
+
<% end %>
|
121
|
+
<% end %>
|
122
|
+
|
123
|
+
<main class="flex-1 pl-(--sidebar-width)">
|
124
|
+
<%= yield %>
|
125
|
+
</main>
|
126
|
+
</div>
|
127
|
+
</body>
|
128
|
+
```
|
129
|
+
|
130
|
+
### Components
|
131
|
+
|
132
|
+
#### Cards
|
133
|
+
|
134
|
+
```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>
|
147
|
+
<% end %>
|
148
|
+
<% end %>
|
149
|
+
```
|
150
|
+
|
151
|
+
#### Buttons
|
152
|
+
|
153
|
+
```erb
|
154
|
+
<%= link_to new_transaction_path, class: "button-primary" do %>
|
155
|
+
New Transaction
|
156
|
+
<%= icon_for(:money) %>
|
157
|
+
<% end %>
|
158
|
+
```
|
159
|
+
|
160
|
+
## Available Components
|
161
|
+
|
162
|
+
Work in progress...
|
163
|
+
|
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
|
179
|
+
|
180
|
+
## Customization
|
181
|
+
|
182
|
+
### Theme Configuration
|
183
|
+
|
184
|
+
Customize the look and feel of your components by modifying the theme variables:
|
185
|
+
|
186
|
+
```css
|
187
|
+
@theme {
|
188
|
+
/* Colors */
|
189
|
+
--color-primary: oklch(21.34% 0 0);
|
190
|
+
--color-primary-foreground: oklch(98.48% 0 0);
|
191
|
+
|
192
|
+
/* Typography */
|
193
|
+
--font-display: "Inter var", "sans-serif";
|
194
|
+
|
195
|
+
/* Spacing */
|
196
|
+
--sidebar-width: 16rem;
|
197
|
+
|
198
|
+
/* ... other customizations ... */
|
199
|
+
}
|
22
200
|
```
|
23
201
|
|
24
202
|
## Contributing
|
25
|
-
|
203
|
+
|
204
|
+
Bug reports and pull requests are welcome on GitHub at <https://github.com/maquina-app/maquina_components>.
|
26
205
|
|
27
206
|
## License
|
207
|
+
|
28
208
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
209
|
+
|
210
|
+
## Acknowledgments
|
211
|
+
|
212
|
+
- Design system inspired by [shadcn/ui](https://ui.shadcn.com/)
|
213
|
+
- Built with [TailwindCSS](https://tailwindcss.com/)
|
214
|
+
- Powered by [Ruby on Rails](https://rubyonrails.org/)
|
@@ -0,0 +1,99 @@
|
|
1
|
+
@utility button-base {
|
2
|
+
display: inline-flex;
|
3
|
+
align-items: center;
|
4
|
+
justify-content: center;
|
5
|
+
gap: 0.5rem;
|
6
|
+
/* gap-2 */
|
7
|
+
white-space: nowrap;
|
8
|
+
border-radius: 0.375rem;
|
9
|
+
/* rounded-md */
|
10
|
+
font-size: 0.875rem;
|
11
|
+
/* text-sm */
|
12
|
+
font-weight: 500;
|
13
|
+
/* font-medium */
|
14
|
+
height: 2.25rem;
|
15
|
+
/* h-9 */
|
16
|
+
padding: 0.5rem 1rem;
|
17
|
+
/* px-4 py-2 */
|
18
|
+
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
|
19
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
20
|
+
transition-duration: 150ms;
|
21
|
+
|
22
|
+
&:focus-visible {
|
23
|
+
outline: none;
|
24
|
+
ring-width: 1px;
|
25
|
+
ring-color: var(--color-ring);
|
26
|
+
}
|
27
|
+
|
28
|
+
&:disabled {
|
29
|
+
pointer-events: none;
|
30
|
+
opacity: 0.5;
|
31
|
+
}
|
32
|
+
|
33
|
+
& svg {
|
34
|
+
pointer-events: none;
|
35
|
+
width: 1rem;
|
36
|
+
/* size-4 */
|
37
|
+
height: 1rem;
|
38
|
+
/* size-4 */
|
39
|
+
flex-shrink: 0;
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
/* Form */
|
44
|
+
.form-base {
|
45
|
+
@apply flex flex-col w-full gap-6;
|
46
|
+
}
|
47
|
+
|
48
|
+
.form-group {
|
49
|
+
@apply flex flex-col gap-2;
|
50
|
+
}
|
51
|
+
|
52
|
+
.form-label {
|
53
|
+
@apply text-foreground text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70;
|
54
|
+
}
|
55
|
+
|
56
|
+
.form-input {
|
57
|
+
@apply flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm;
|
58
|
+
}
|
59
|
+
|
60
|
+
.form-select {
|
61
|
+
@apply col-start-1 row-start-1 w-full appearance-none rounded-md bg-transparent py-1.5 pl-3 pr-8 text-base text-foreground border border-input shadow-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 sm:text-sm/6;
|
62
|
+
}
|
63
|
+
|
64
|
+
.form-select-group {
|
65
|
+
@apply grid grid-cols-1;
|
66
|
+
|
67
|
+
& svg {
|
68
|
+
@apply pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-muted-foreground sm:size-4;
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
.form-help-text {
|
73
|
+
@apply text-sm text-muted-foreground;
|
74
|
+
}
|
75
|
+
|
76
|
+
.form-error-text {
|
77
|
+
@apply text-sm text-destructive;
|
78
|
+
}
|
79
|
+
|
80
|
+
/* Buttons */
|
81
|
+
.button-primary {
|
82
|
+
@apply button-base bg-primary text-primary-foreground hover:bg-primary/90;
|
83
|
+
}
|
84
|
+
|
85
|
+
.button-secondary {
|
86
|
+
@apply button-base bg-secondary text-secondary-foreground hover:bg-secondary/80;
|
87
|
+
}
|
88
|
+
|
89
|
+
.button-ghost {
|
90
|
+
@apply button-base hover:bg-secondary hover:text-secondary-foreground;
|
91
|
+
}
|
92
|
+
|
93
|
+
.button-outline {
|
94
|
+
@apply button-base border border-border bg-background shadow-sm hover:bg-secondary/40 hover:text-secondary-foreground;
|
95
|
+
}
|
96
|
+
|
97
|
+
.button-destructive {
|
98
|
+
@apply button-base bg-destructive text-destructive shadow-sm hover:bg-destructive/90;
|
99
|
+
}
|
@@ -0,0 +1,124 @@
|
|
1
|
+
module Components
|
2
|
+
module IconsHelper
|
3
|
+
def icon_for(name, options = {})
|
4
|
+
return nil unless name
|
5
|
+
|
6
|
+
svg = icon_svg_for(name.to_sym)
|
7
|
+
return nil unless svg
|
8
|
+
|
9
|
+
css_classes = options[:class]
|
10
|
+
svg = svg.gsub('class="', "class=\"#{css_classes} ")
|
11
|
+
|
12
|
+
if options[:stroke_width]
|
13
|
+
svg = svg.gsub('stroke-width="2"', "stroke-width=\"#{options[:stroke_width]}\"")
|
14
|
+
end
|
15
|
+
|
16
|
+
svg.html_safe
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def icon_svg_for(name)
|
22
|
+
case name
|
23
|
+
when :dollar
|
24
|
+
<<~SVG.freeze
|
25
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="">
|
26
|
+
<line x1="12" y1="2" x2="12" y2="22"></line>
|
27
|
+
<path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"></path>
|
28
|
+
</svg>
|
29
|
+
SVG
|
30
|
+
when :users
|
31
|
+
<<~SVG.freeze
|
32
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
33
|
+
<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"></path>
|
34
|
+
<circle cx="9" cy="7" r="4"></circle>
|
35
|
+
<path d="M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75"></path>
|
36
|
+
</svg>
|
37
|
+
SVG
|
38
|
+
when :credit_card
|
39
|
+
<<~SVG.freeze
|
40
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
41
|
+
<rect width="20" height="14" x="2" y="5" rx="2"></rect>
|
42
|
+
<line x1="2" y1="10" x2="22" y2="10"></line>
|
43
|
+
</svg>
|
44
|
+
SVG
|
45
|
+
when :activity
|
46
|
+
<<~SVG.freeze
|
47
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
48
|
+
<path d="M22 12h-4l-3 9L9 3l-3 9H2"></path>
|
49
|
+
</svg>
|
50
|
+
SVG
|
51
|
+
when :trend_up
|
52
|
+
<<~SVG.freeze
|
53
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="">
|
54
|
+
<polyline points="22 7 13.5 15.5 8.5 10.5 2 17"></polyline>
|
55
|
+
<polyline points="16 7 22 7 22 13"></polyline>
|
56
|
+
</svg>
|
57
|
+
SVG
|
58
|
+
when :trend_down
|
59
|
+
<<~SVG.freeze
|
60
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="">
|
61
|
+
<polyline points="22 17 13.5 8.5 8.5 13.5 2 7"></polyline>
|
62
|
+
<polyline points="16 17 22 17 22 11"></polyline>
|
63
|
+
</svg>
|
64
|
+
SVG
|
65
|
+
when :clock
|
66
|
+
<<~SVG.freeze
|
67
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="">
|
68
|
+
<circle cx="12" cy="12" r="10"></circle>
|
69
|
+
<polyline points="12 6 12 12 16 14"></polyline>
|
70
|
+
</svg>
|
71
|
+
SVG
|
72
|
+
when :money
|
73
|
+
<<~SVG.freeze
|
74
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="">
|
75
|
+
<rect width="20" height="12" x="2" y="6" rx="2"></rect>
|
76
|
+
<circle cx="12" cy="12" r="2"></circle>
|
77
|
+
<path d="M6 12h.01M18 12h.01"></path>
|
78
|
+
</svg>
|
79
|
+
SVG
|
80
|
+
when :line_chart
|
81
|
+
<<~SVG.freeze
|
82
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="">
|
83
|
+
<path d="M3 3v18h18"/><path d="m19 9-5 5-4-4-3 3"/>
|
84
|
+
</svg>
|
85
|
+
SVG
|
86
|
+
when :piggy_bank
|
87
|
+
<<~SVG.freeze
|
88
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="">
|
89
|
+
<path d="M19 5c-1.5 0-2.8 1.4-3 2-3.5-1.5-11-.3-11 5 0 1.8 0 3 2 4.5V20h4v-2h3v2h4v-4c1-.5 1.7-1 2-2h2v-4h-2c0-1-.5-1.5-1-2h0V5z"/>
|
90
|
+
<path d="M2 9v1c0 1.1.9 2 2 2h1"/>
|
91
|
+
<path d="M16 11h0"/>
|
92
|
+
</svg>
|
93
|
+
SVG
|
94
|
+
when :arrow_left
|
95
|
+
<<~SVG.freeze
|
96
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="">
|
97
|
+
<line x1="19" y1="12" x2="5" y2="12"></line>
|
98
|
+
<polyline points="12 19 5 12 12 5"></polyline>
|
99
|
+
</svg>
|
100
|
+
SVG
|
101
|
+
when :select_chevron
|
102
|
+
<<~SVG.freeze
|
103
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="" aria-hidden="true">
|
104
|
+
<path d="m6 9 6 6 6-6"></path>
|
105
|
+
</svg>
|
106
|
+
SVG
|
107
|
+
when :check
|
108
|
+
<<~SVG.freeze
|
109
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="">
|
110
|
+
<path d="M20 6 9 17l-5-5"/>
|
111
|
+
</svg>
|
112
|
+
SVG
|
113
|
+
when :circle_alert
|
114
|
+
<<~SVG.freeze
|
115
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="">
|
116
|
+
<circle cx="12" cy="12" r="10"/>
|
117
|
+
<line x1="12" x2="12" y1="8" y2="12"/>
|
118
|
+
<line x1="12" x2="12.01" y1="16" y2="16"/>
|
119
|
+
</svg>
|
120
|
+
SVG
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Components
|
2
|
+
module PaginationHelper
|
3
|
+
def paginated_page_param(pagy, page)
|
4
|
+
@page_param ||= pagy.vars[:page_param] || Pagy::VARS[:page_param]
|
5
|
+
@query_parameters ||= request.query_parameters
|
6
|
+
|
7
|
+
@query_parameters.merge(@page_param => page)
|
8
|
+
end
|
9
|
+
|
10
|
+
def paginated_path(path_helper, pagy, page, param)
|
11
|
+
page_query = paginated_page_param(pagy, page)
|
12
|
+
send(path_helper, param, page_query)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<%# locals: (title: nil) %>
|
2
|
+
<% if notice || alert %>
|
3
|
+
<div
|
4
|
+
role="alert"
|
5
|
+
class="<%= class_names('relative w-full rounded-lg border px-4 py-3 text-sm mx-auto mb-4 [&>svg]:size-4 [&>svg+div]:translate-y-(-3px) [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg~*]:pl-7 max-w-lg', '[&>svg]:text-foreground bg-background text-foreground': notice.present?, 'border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive': alert.present?) %>"
|
6
|
+
>
|
7
|
+
<%= icon_for(notice.present? ? :check : :circle_alert) %>
|
8
|
+
<h5 class="mb-1 font-medium leading-none tracking-tight"><%= title || (notice.present? ? "Éxito" : "Error") %></h5>
|
9
|
+
<div class="text-sm [&_p]:leading-relaxed"><%= notice %></div>
|
10
|
+
</div>
|
11
|
+
<% end %>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<%# locals: (title:, custom_classes: "", icon: nil, icon_classes: "h-4 w-4 text-muted-foreground") -%>
|
2
|
+
|
3
|
+
<div
|
4
|
+
class="<%= class_names("p-6 flex flex-row items-center justify-between space-y-0 pb-2", custom_classes) %>"
|
5
|
+
>
|
6
|
+
<h3 class="tracking-tight text-sm font-medium"><%= title %></h3>
|
7
|
+
<%= icon_for(icon, class: icon_classes) if icon.present? %>
|
8
|
+
</div>
|
@@ -0,0 +1,34 @@
|
|
1
|
+
<%# locals: (pagy:, route_helper:, param: nil, data: {turbo_action: :replace}) %>
|
2
|
+
<nav class="mx-auto flex w-full justify-center mt-4">
|
3
|
+
<ul class="flex flex-row items-center gap-1">
|
4
|
+
<li>
|
5
|
+
<% if pagy.prev.present? %>
|
6
|
+
<%= link_to "Previo",
|
7
|
+
paginated_path(route_helper, pagy, pagy.prev, param),
|
8
|
+
class: "button-ghost",
|
9
|
+
data: data %>
|
10
|
+
<% else %>
|
11
|
+
<button class="button-ghost" disabled>Previo</button>
|
12
|
+
<% end %>
|
13
|
+
</li>
|
14
|
+
<% pagy.series.each do |page| %>
|
15
|
+
<li>
|
16
|
+
<%= link_to page,
|
17
|
+
paginated_path(route_helper, pagy, page, param),
|
18
|
+
class: class_names("button-ghost", "button-outline": page.is_a?(String)),
|
19
|
+
data: data %>
|
20
|
+
</li>
|
21
|
+
<% end %>
|
22
|
+
|
23
|
+
<li>
|
24
|
+
<% if pagy.next.present? %>
|
25
|
+
<%= link_to "Siguiente",
|
26
|
+
paginated_path(route_helper, pagy, pagy.next, param),
|
27
|
+
class: "button-ghost",
|
28
|
+
data: data %>
|
29
|
+
<% else %>
|
30
|
+
<button class="button-ghost" disabled>Siguiente</button>
|
31
|
+
<% end %>
|
32
|
+
</li>
|
33
|
+
</ul>
|
34
|
+
</nav>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<aside
|
2
|
+
class="group peer hidden md:block text-sidebar-foreground"
|
3
|
+
data-controller="sidebars"
|
4
|
+
data-state="expanded"
|
5
|
+
data-collapsible=""
|
6
|
+
id="sidebar"
|
7
|
+
>
|
8
|
+
<!-- Mobile overlay -->
|
9
|
+
<div
|
10
|
+
class="
|
11
|
+
inset-0 bg-black/80 lg:hidden transition-opacity duration-300 hidden
|
12
|
+
"
|
13
|
+
data-sidebar-target="overlay"
|
14
|
+
data-action="click->sidebar#toggleMobile"
|
15
|
+
>
|
16
|
+
</div>
|
17
|
+
<!-- Sidebar container -->
|
18
|
+
<div
|
19
|
+
class="
|
20
|
+
duration-200 fixed inset-y-0 z-10 h-svh w-(--sidebar-width)
|
21
|
+
transition-[left,right,width] ease-linear md:flex left-0 border-r
|
22
|
+
border-sidebar-border group-data-[collapsible=icon]:w-[--sidebar-width-icon]
|
23
|
+
"
|
24
|
+
data-sidebar-target="container"
|
25
|
+
>
|
26
|
+
<div class=" flex h-full w-full flex-col bg-sidebar">
|
27
|
+
<%= yield %>
|
28
|
+
</div>
|
29
|
+
</div>
|
30
|
+
</aside>
|
@@ -0,0 +1,42 @@
|
|
1
|
+
<%# locals: (title: nil, title_action: {}, menu: []) -%>
|
2
|
+
<%- title ||= nil -%>
|
3
|
+
<%- title_action ||= {} -%>
|
4
|
+
<%- menu ||= [] -%>
|
5
|
+
|
6
|
+
<div class="relative flex w-full min-w-0 flex-col p-2">
|
7
|
+
<% if title.present? %>
|
8
|
+
<div
|
9
|
+
class="
|
10
|
+
duration-200 flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium
|
11
|
+
text-sidebar-foreground/70 outline-none ring-sidebar-ring
|
12
|
+
transition-[margin,opa] ease-linear focus-visible:ring-2 [&>svg]:size-4
|
13
|
+
[&>svg]:shrink-0 group-data-[collapsible=icon]:-mt-8
|
14
|
+
group-data-[collapsible=icon]:opacity-0
|
15
|
+
"
|
16
|
+
>
|
17
|
+
<%= title %>
|
18
|
+
|
19
|
+
<% if title_action.any? %>
|
20
|
+
<%= link_to title_action[:url], class: "flex aspect-square w-5 items-center justify-center rounded-md p-0 ml-auto text-sidebar-foreground outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0 after:absolute after:-inset-2 after:md:hidden" do %>
|
21
|
+
<%= render_icon(title_action[:icon]) %>
|
22
|
+
<span class="sr-only"><%= title_action[:title] %></span>
|
23
|
+
<% end %>
|
24
|
+
<% end %>
|
25
|
+
</div>
|
26
|
+
<% end %>
|
27
|
+
|
28
|
+
<% if menu.any? %>
|
29
|
+
<ul class="flex w-full min-w-0 flex-col gap-1">
|
30
|
+
<% menu.each do |item| %>
|
31
|
+
<li class="group/menu-item relative">
|
32
|
+
<%= sidebar_menu_item(
|
33
|
+
title: item[:title],
|
34
|
+
url: item[:url],
|
35
|
+
icon: item[:icon],
|
36
|
+
current: item[:active],
|
37
|
+
) %>
|
38
|
+
</li>
|
39
|
+
<% end %>
|
40
|
+
</ul>
|
41
|
+
<% end %>
|
42
|
+
</div>
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: maquina-components
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mario Alberto Chávez
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-01-
|
10
|
+
date: 2025-01-17 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: rails
|
@@ -33,6 +33,18 @@ files:
|
|
33
33
|
- MIT-LICENSE
|
34
34
|
- README.md
|
35
35
|
- Rakefile
|
36
|
+
- app/assets/stylesheets/maquina_components.css
|
37
|
+
- app/helpers/components/icons_helper.rb
|
38
|
+
- app/helpers/components/pagination_helper.rb
|
39
|
+
- app/views/components/_alert.html.erb
|
40
|
+
- app/views/components/_card.html.erb
|
41
|
+
- app/views/components/_card_content.html.erb
|
42
|
+
- app/views/components/_card_header.html.erb
|
43
|
+
- app/views/components/_pagination.html.erb
|
44
|
+
- app/views/components/_sidebar.html.erb
|
45
|
+
- app/views/components/_sidebar_content.html.erb
|
46
|
+
- app/views/components/_sidebar_group.html.erb
|
47
|
+
- app/views/components/_sidebar_header.html.erb
|
36
48
|
- lib/maquina-components.rb
|
37
49
|
- lib/maquina_components/engine.rb
|
38
50
|
- lib/maquina_components/version.rb
|