stimulus_plumbers_tailwind 0.4.0 → 0.4.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/CHANGELOG.md +33 -0
- data/README.md +6 -4
- data/lib/stimulus_plumbers/themes/tailwind/avatar.rb +12 -12
- data/lib/stimulus_plumbers/themes/tailwind/button.rb +26 -22
- data/lib/stimulus_plumbers/themes/tailwind/calendar.rb +23 -20
- data/lib/stimulus_plumbers/themes/tailwind/card.rb +4 -5
- data/lib/stimulus_plumbers/themes/tailwind/combobox.rb +27 -17
- data/lib/stimulus_plumbers/themes/tailwind/form/field.rb +44 -57
- data/lib/stimulus_plumbers/themes/tailwind/form/input.rb +140 -54
- data/lib/stimulus_plumbers/themes/tailwind/form.rb +1 -10
- data/lib/stimulus_plumbers/themes/tailwind/icon.rb +7 -2
- data/lib/stimulus_plumbers/themes/tailwind/layout.rb +6 -3
- data/lib/stimulus_plumbers/themes/tailwind/link.rb +31 -29
- data/lib/stimulus_plumbers/themes/tailwind/list.rb +15 -13
- data/lib/stimulus_plumbers/themes/tailwind/timeline/group.rb +28 -0
- data/lib/stimulus_plumbers/themes/tailwind/timeline.rb +104 -0
- data/lib/stimulus_plumbers/themes/tailwind_theme.rb +3 -0
- data/lib/stimulus_plumbers_tailwind/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d7821a54d820ecd2c76e2ce5afd0bcd00ab4fb2f78f3e4246a256a378b3bd631
|
|
4
|
+
data.tar.gz: f67b19c723fe3ba0e22c5f7e94698575bf17e905d6ec4db9305b919d6ae4a471
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 959b1d2a0f740c5630d85cc824da0148e7c172e9052b6359f4c873ee5c24ac23afdddf6bc5d4cd76602373f5c3f7d90cd0649fe13185b5eeb9b802deed618a6e
|
|
7
|
+
data.tar.gz: 4a0dd9d2040676acd2671eda6b2840ebb320f6704ce93ed23dcdcbb008ab37bc9abdd30e132bb224d9f0a97aa069941bdd4ee76b650eeeb71d97b7b12fe14f25
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,39 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [conventional commits](https://www.conventionalcommits.org/) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
---
|
|
6
|
+
## [0.4.2](https://github.com/ryancyq/stimulus-plumbers/compare/stimulus-plumbers-tailwind/v0.4.0..stimulus-plumbers-tailwind/v0.4.2) - 2026-06-30
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
- form submit button style ([#127](https://github.com/ryancyq/stimulus-plumbers/issues/127)) - ([2bbc73f](https://github.com/ryancyq/stimulus-plumbers/commit/2bbc73f15b7ffa2d9d8f87991adead33fab8156e)) - Ryan Chang
|
|
11
|
+
- various component styles ([#128](https://github.com/ryancyq/stimulus-plumbers/issues/128)) - ([011cc69](https://github.com/ryancyq/stimulus-plumbers/commit/011cc69bb6df3770949564521cdf949493d028cc)) - Ryan Chang
|
|
12
|
+
- use generic icon in core gem then provide alias in tailwind gem ([#129](https://github.com/ryancyq/stimulus-plumbers/issues/129)) - ([5c87d0d](https://github.com/ryancyq/stimulus-plumbers/commit/5c87d0da0c012652a3afa5aa8345b58d03e6ce5b)) - Ryan Chang
|
|
13
|
+
- combobox time ([#130](https://github.com/ryancyq/stimulus-plumbers/issues/130)) - ([ff5d968](https://github.com/ryancyq/stimulus-plumbers/commit/ff5d968da34fc723b0112a791bd95ef43f2b1640)) - Ryan Chang
|
|
14
|
+
- extract img avatar building block ([#132](https://github.com/ryancyq/stimulus-plumbers/issues/132)) - ([c3808b8](https://github.com/ryancyq/stimulus-plumbers/commit/c3808b8df38eecef940b51dab29f50bc815b4e74)) - Ryan Chang
|
|
15
|
+
- update floating style to label/input/group ([#135](https://github.com/ryancyq/stimulus-plumbers/issues/135)) - ([3947f38](https://github.com/ryancyq/stimulus-plumbers/commit/3947f38467e0a498fe51101d1859a573db93349f)) - Ryan Chang
|
|
16
|
+
- accessibility + plumber helpers ([#136](https://github.com/ryancyq/stimulus-plumbers/issues/136)) - ([e84053d](https://github.com/ryancyq/stimulus-plumbers/commit/e84053d43db4726c3704d459a0464f70529fff8b)) - Ryan Chang
|
|
17
|
+
- calendar disabled + out of range ([#148](https://github.com/ryancyq/stimulus-plumbers/issues/148)) - ([7bd1ca2](https://github.com/ryancyq/stimulus-plumbers/commit/7bd1ca21af1b982cf7df9460e0ba1c9e78866a87)) - Ryan Chang
|
|
18
|
+
|
|
19
|
+
### Dependencies
|
|
20
|
+
|
|
21
|
+
- **(deps-dev)** bump @playwright/test in /stimulus-plumbers-tailwind ([#147](https://github.com/ryancyq/stimulus-plumbers/issues/147)) - ([941634d](https://github.com/ryancyq/stimulus-plumbers/commit/941634de18e2accc39f926258cb3d1b2534d11dc)) - dependabot[bot]
|
|
22
|
+
- **(deps-dev)** bump prettier in /stimulus-plumbers-tailwind ([#146](https://github.com/ryancyq/stimulus-plumbers/issues/146)) - ([570c8ff](https://github.com/ryancyq/stimulus-plumbers/commit/570c8ff7630039bdbdc6e3d89c6a181bbc706dd8)) - dependabot[bot]
|
|
23
|
+
|
|
24
|
+
### Documentation
|
|
25
|
+
|
|
26
|
+
- update readme and component doc ([#134](https://github.com/ryancyq/stimulus-plumbers/issues/134)) - ([3e5f462](https://github.com/ryancyq/stimulus-plumbers/commit/3e5f4621c4fbf142af061659cfbb8cd3e99fd093)) - Ryan Chang
|
|
27
|
+
- update component documentation - ([89ecb78](https://github.com/ryancyq/stimulus-plumbers/commit/89ecb786d88eed66ab925921ac182aa84560207d)) - Ryan Chang
|
|
28
|
+
|
|
29
|
+
### Features
|
|
30
|
+
|
|
31
|
+
- calendar redesign ([#133](https://github.com/ryancyq/stimulus-plumbers/issues/133)) - ([e19df95](https://github.com/ryancyq/stimulus-plumbers/commit/e19df95f3814b3d947142722ff0295f1bdcef6b3)) - Ryan Chang
|
|
32
|
+
|
|
33
|
+
### Tests
|
|
34
|
+
|
|
35
|
+
- update sandbox view and spec coverage ([#122](https://github.com/ryancyq/stimulus-plumbers/issues/122)) - ([0fd3381](https://github.com/ryancyq/stimulus-plumbers/commit/0fd33817325070c29ffed82d37843b4c4be3e911)) - Ryan Chang
|
|
36
|
+
- update collection radio locator - ([f0fa9e8](https://github.com/ryancyq/stimulus-plumbers/commit/f0fa9e85bc0b835b3adc46f5dc406a8bdedbeefe)) - Ryan Chang
|
|
37
|
+
|
|
5
38
|
---
|
|
6
39
|
## [0.4.0](https://github.com/ryancyq/stimulus-plumbers/compare/stimulus-plumbers-tailwind/v0.3.3..stimulus-plumbers-tailwind/v0.4.0) - 2026-06-14
|
|
7
40
|
|
data/README.md
CHANGED
|
@@ -27,7 +27,7 @@ Activate the theme in an initializer or `config/application.rb`:
|
|
|
27
27
|
|
|
28
28
|
```ruby
|
|
29
29
|
StimulusPlumbers.configure do |config|
|
|
30
|
-
config.theme
|
|
30
|
+
config.theme.use(:tailwind)
|
|
31
31
|
end
|
|
32
32
|
```
|
|
33
33
|
|
|
@@ -46,7 +46,6 @@ Use `bundle show stimulus_plumbers_tailwind` to get the exact installed path.
|
|
|
46
46
|
|
|
47
47
|
| Module | Components |
|
|
48
48
|
|--------|------------|
|
|
49
|
-
| `Tailwind::ActionList` | Action list, menu items |
|
|
50
49
|
| `Tailwind::Avatar` | Avatar |
|
|
51
50
|
| `Tailwind::Button` | Button |
|
|
52
51
|
| `Tailwind::Calendar` | Calendar grid, date picker |
|
|
@@ -55,6 +54,9 @@ Use `bundle show stimulus_plumbers_tailwind` to get the exact installed path.
|
|
|
55
54
|
| `Tailwind::Form` | Form fields, labels, errors |
|
|
56
55
|
| `Tailwind::Icon` | Icon (SVG rendering, icon registry) |
|
|
57
56
|
| `Tailwind::Layout` | Layout primitives |
|
|
57
|
+
| `Tailwind::Link` | Link |
|
|
58
|
+
| `Tailwind::List` | List |
|
|
59
|
+
| `Tailwind::Timeline` | Timeline |
|
|
58
60
|
|
|
59
61
|
Custom themes can subclass `TailwindTheme` to override individual methods, or subclass `StimulusPlumbers::Themes::Base` directly.
|
|
60
62
|
|
|
@@ -85,8 +87,8 @@ bundle install
|
|
|
85
87
|
npm install
|
|
86
88
|
|
|
87
89
|
bundle exec rake test:unit # unit tests
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
node --run test:snapshots # visual snapshot tests (Playwright)
|
|
91
|
+
node --run test:snapshots:update # regenerate baseline screenshots
|
|
90
92
|
bundle exec rake rubocop # lint
|
|
91
93
|
bundle exec rake coverage # run tests with coverage + collate report
|
|
92
94
|
```
|
|
@@ -4,6 +4,18 @@ module StimulusPlumbers
|
|
|
4
4
|
module Themes
|
|
5
5
|
module Tailwind
|
|
6
6
|
module Avatar
|
|
7
|
+
BASE = %w[
|
|
8
|
+
rounded-(--sp-radius-full)
|
|
9
|
+
overflow-hidden
|
|
10
|
+
inline-flex items-center justify-center
|
|
11
|
+
].freeze
|
|
12
|
+
|
|
13
|
+
SIZES = {
|
|
14
|
+
sm: "size-(--sp-avatar-size-sm)",
|
|
15
|
+
md: "size-(--sp-avatar-size-md)",
|
|
16
|
+
lg: "size-(--sp-avatar-size-lg)"
|
|
17
|
+
}.freeze
|
|
18
|
+
|
|
7
19
|
VARIANTS = {
|
|
8
20
|
amber: "text-white bg-amber-600",
|
|
9
21
|
lime: "text-white bg-lime-600",
|
|
@@ -19,18 +31,6 @@ module StimulusPlumbers
|
|
|
19
31
|
blue: "text-white bg-blue-600"
|
|
20
32
|
}.freeze
|
|
21
33
|
|
|
22
|
-
SIZES = {
|
|
23
|
-
sm: "size-(--sp-icon-size)",
|
|
24
|
-
md: "size-(--sp-avatar-size)",
|
|
25
|
-
lg: "size-(--sp-avatar-size-lg)"
|
|
26
|
-
}.freeze
|
|
27
|
-
|
|
28
|
-
BASE = %w[
|
|
29
|
-
rounded-(--sp-radius-full)
|
|
30
|
-
overflow-hidden
|
|
31
|
-
inline-flex items-center justify-center
|
|
32
|
-
].freeze
|
|
33
|
-
|
|
34
34
|
def avatar_variants
|
|
35
35
|
VARIANTS
|
|
36
36
|
end
|
|
@@ -4,6 +4,25 @@ module StimulusPlumbers
|
|
|
4
4
|
module Themes
|
|
5
5
|
module Tailwind
|
|
6
6
|
module Button
|
|
7
|
+
# ── Structure ─────────────────────────────────────────────────────────
|
|
8
|
+
BASE = [
|
|
9
|
+
*Control::BASE,
|
|
10
|
+
"whitespace-nowrap",
|
|
11
|
+
"focus-visible:ring-(--btn-ring)"
|
|
12
|
+
].freeze
|
|
13
|
+
|
|
14
|
+
LAYOUT = %w[
|
|
15
|
+
inline-flex items-center justify-center gap-(--sp-space-2)
|
|
16
|
+
[&:not(:has(>span))]:aspect-square
|
|
17
|
+
[&:not(:has(>span))]:px-0
|
|
18
|
+
].freeze
|
|
19
|
+
|
|
20
|
+
CARD = %w[
|
|
21
|
+
inline-flex justify-start items-center flex-1 gap-(--sp-space-3) p-(--sp-space-4)
|
|
22
|
+
[&>:last-child:not(:first-child)]:ml-auto
|
|
23
|
+
].freeze
|
|
24
|
+
|
|
25
|
+
# ── Color tokens ──────────────────────────────────────────────────────
|
|
7
26
|
VARIANTS = {
|
|
8
27
|
primary: %w[
|
|
9
28
|
[--btn-bg:var(--sp-color-primary)]
|
|
@@ -56,6 +75,7 @@ module StimulusPlumbers
|
|
|
56
75
|
].freeze
|
|
57
76
|
}.freeze
|
|
58
77
|
|
|
78
|
+
# ── Type styles ───────────────────────────────────────────────────────
|
|
59
79
|
TYPES = {
|
|
60
80
|
default: %w[
|
|
61
81
|
rounded-(--sp-radius-md)
|
|
@@ -67,13 +87,13 @@ module StimulusPlumbers
|
|
|
67
87
|
rounded-(--sp-radius-md)
|
|
68
88
|
bg-(--sp-color-bg) text-(--btn-accent)
|
|
69
89
|
border border-(--btn-border)
|
|
70
|
-
hover:bg-(--btn-
|
|
90
|
+
hover:bg-(--btn-accent)/10
|
|
71
91
|
].freeze,
|
|
72
92
|
ghost: %w[
|
|
73
93
|
rounded-(--sp-radius-md)
|
|
74
94
|
bg-transparent text-(--btn-accent)
|
|
75
95
|
border border-transparent
|
|
76
|
-
hover:bg-(--btn-
|
|
96
|
+
hover:bg-(--btn-accent)/10
|
|
77
97
|
].freeze,
|
|
78
98
|
fab: %w[
|
|
79
99
|
rounded-(--sp-radius-full)
|
|
@@ -93,16 +113,17 @@ module StimulusPlumbers
|
|
|
93
113
|
rounded-(--sp-radius-md)
|
|
94
114
|
bg-(--sp-color-bg) text-(--btn-accent)
|
|
95
115
|
border border-dashed border-(--btn-border)
|
|
96
|
-
hover:bg-(--btn-
|
|
116
|
+
hover:bg-(--btn-accent)/10
|
|
97
117
|
].freeze,
|
|
98
118
|
card: %w[
|
|
99
119
|
rounded-(--sp-radius-md)
|
|
100
120
|
bg-(--sp-color-bg) text-(--btn-accent)
|
|
101
121
|
border border-(--btn-border) shadow-(--sp-shadow-xs)
|
|
102
|
-
hover:bg-(--btn-
|
|
122
|
+
hover:bg-(--btn-accent)/10
|
|
103
123
|
].freeze
|
|
104
124
|
}.freeze
|
|
105
125
|
|
|
126
|
+
# ── Sizes ─────────────────────────────────────────────────────────────
|
|
106
127
|
SIZES = {
|
|
107
128
|
xs: %w[h-7 px-(--sp-space-2) text-(length:--sp-text-xs)].freeze,
|
|
108
129
|
sm: %w[h-8 px-(--sp-space-3) text-(length:--sp-text-sm)].freeze,
|
|
@@ -111,23 +132,6 @@ module StimulusPlumbers
|
|
|
111
132
|
xl: %w[h-14 px-(--sp-space-6) text-(length:--sp-text-lg)].freeze
|
|
112
133
|
}.freeze
|
|
113
134
|
|
|
114
|
-
BASE = [
|
|
115
|
-
*Control::BASE,
|
|
116
|
-
"whitespace-nowrap",
|
|
117
|
-
"focus-visible:ring-(--btn-ring)"
|
|
118
|
-
].freeze
|
|
119
|
-
|
|
120
|
-
LAYOUT = %w[
|
|
121
|
-
inline-flex items-center justify-center gap-(--sp-space-2)
|
|
122
|
-
[&:not(:has(>span))]:aspect-square
|
|
123
|
-
[&:not(:has(>span))]:px-0
|
|
124
|
-
].freeze
|
|
125
|
-
|
|
126
|
-
CARD = %w[
|
|
127
|
-
inline-flex justify-start items-center flex-1 gap-(--sp-space-3) p-(--sp-space-4)
|
|
128
|
-
[&>:last-child:not(:first-child)]:ml-auto
|
|
129
|
-
].freeze
|
|
130
|
-
|
|
131
135
|
private
|
|
132
136
|
|
|
133
137
|
def button_classes(type: :default, variant: :primary, size: :md)
|
|
@@ -143,7 +147,7 @@ module StimulusPlumbers
|
|
|
143
147
|
end
|
|
144
148
|
|
|
145
149
|
def button_icon_classes
|
|
146
|
-
{ classes: klasses("size-(--sp-
|
|
150
|
+
{ classes: klasses("size-(--sp-icon-size-sm)", "stroke-current") }
|
|
147
151
|
end
|
|
148
152
|
end
|
|
149
153
|
end
|
|
@@ -4,7 +4,7 @@ module StimulusPlumbers
|
|
|
4
4
|
module Themes
|
|
5
5
|
module Tailwind
|
|
6
6
|
module Calendar
|
|
7
|
-
GRID =
|
|
7
|
+
GRID = [].freeze
|
|
8
8
|
|
|
9
9
|
DAYS_OF_WEEK = %w[
|
|
10
10
|
grid grid-cols-7 text-center text-(length:--sp-text-xs)
|
|
@@ -16,41 +16,52 @@ module StimulusPlumbers
|
|
|
16
16
|
DAY = %w[
|
|
17
17
|
size-(--sp-calendar-day-size) rounded-(--sp-radius-md)
|
|
18
18
|
flex items-center justify-center text-(length:--sp-text-sm)
|
|
19
|
-
hover:bg-(--sp-color-muted) cursor-pointer
|
|
19
|
+
[&:is(button)]:hover:bg-(--sp-color-muted) [&:is(button)]:cursor-pointer
|
|
20
20
|
aria-[current=date]:font-bold
|
|
21
21
|
aria-selected:bg-(--sp-color-primary)
|
|
22
22
|
aria-selected:text-(--sp-color-primary-fg)
|
|
23
23
|
aria-selected:hover:bg-(--sp-color-primary)/90
|
|
24
24
|
aria-[hidden=true]:pointer-events-none
|
|
25
|
-
aria-[
|
|
25
|
+
aria-[disabled=true]:text-(--sp-color-muted-fg)
|
|
26
|
+
aria-[disabled=true]:opacity-40
|
|
27
|
+
aria-[disabled=true]:pointer-events-none
|
|
28
|
+
disabled:text-(--sp-color-muted-fg)
|
|
29
|
+
disabled:opacity-40
|
|
30
|
+
disabled:pointer-events-none
|
|
26
31
|
].freeze
|
|
27
32
|
|
|
28
|
-
QUARTER_GRID = %w[grid grid-cols-4].freeze
|
|
33
|
+
QUARTER_GRID = %w[grid grid-cols-4 gap-(--sp-space-1)].freeze
|
|
29
34
|
|
|
30
35
|
MONTHS_OF_YEAR = "contents"
|
|
31
36
|
|
|
32
37
|
MONTH = %w[
|
|
33
38
|
rounded-(--sp-radius-md) flex items-center justify-center
|
|
34
|
-
text-(length:--sp-text-sm) h-10 flex-1
|
|
39
|
+
text-(length:--sp-text-sm) h-10 flex-1 px-(--sp-space-2)
|
|
35
40
|
hover:bg-(--sp-color-muted) cursor-pointer
|
|
36
41
|
aria-selected:bg-(--sp-color-primary)
|
|
37
42
|
aria-selected:text-(--sp-color-primary-fg)
|
|
38
43
|
aria-selected:hover:bg-(--sp-color-primary)/90
|
|
39
|
-
aria-disabled:pointer-events-none aria-disabled:text-(--sp-color-disabled-fg)
|
|
40
44
|
aria-[current=month]:font-bold
|
|
45
|
+
aria-[disabled=true]:text-(--sp-color-muted-fg)
|
|
46
|
+
aria-[disabled=true]:opacity-40
|
|
47
|
+
aria-[disabled=true]:pointer-events-none
|
|
48
|
+
aria-[disabled=true]:hover:bg-transparent
|
|
41
49
|
].freeze
|
|
42
50
|
|
|
43
51
|
YEARS_OF_DECADE = "contents"
|
|
44
52
|
|
|
45
53
|
YEAR = %w[
|
|
46
54
|
rounded-(--sp-radius-md) flex items-center justify-center
|
|
47
|
-
text-(length:--sp-text-sm) h-10 flex-1
|
|
55
|
+
text-(length:--sp-text-sm) h-10 flex-1 px-(--sp-space-2)
|
|
48
56
|
hover:bg-(--sp-color-muted) cursor-pointer
|
|
49
57
|
aria-selected:bg-(--sp-color-primary)
|
|
50
58
|
aria-selected:text-(--sp-color-primary-fg)
|
|
51
59
|
aria-selected:hover:bg-(--sp-color-primary)/90
|
|
52
|
-
aria-disabled:pointer-events-none aria-disabled:text-(--sp-color-disabled-fg)
|
|
53
60
|
aria-[current=year]:font-bold
|
|
61
|
+
aria-[disabled=true]:text-(--sp-color-muted-fg)
|
|
62
|
+
aria-[disabled=true]:opacity-40
|
|
63
|
+
aria-[disabled=true]:pointer-events-none
|
|
64
|
+
aria-[disabled=true]:hover:bg-transparent
|
|
54
65
|
].freeze
|
|
55
66
|
|
|
56
67
|
private
|
|
@@ -80,21 +91,13 @@ module StimulusPlumbers
|
|
|
80
91
|
end
|
|
81
92
|
|
|
82
93
|
def calendar_day_classes(outside: false, **)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
*DAY,
|
|
86
|
-
*(outside ? %w[text-(--sp-color-disabled-fg)] : [])
|
|
87
|
-
)
|
|
88
|
-
}
|
|
94
|
+
extra = outside ? %w[text-(--sp-color-muted-fg)] : []
|
|
95
|
+
{ classes: klasses(*DAY, *extra) }
|
|
89
96
|
end
|
|
90
97
|
|
|
91
|
-
def calendar_month_classes(**)
|
|
92
|
-
{ classes: klasses(*MONTH) }
|
|
93
|
-
end
|
|
98
|
+
def calendar_month_classes(**) = { classes: klasses(*MONTH) }
|
|
94
99
|
|
|
95
|
-
def calendar_year_classes(**)
|
|
96
|
-
{ classes: klasses(*YEAR) }
|
|
97
|
-
end
|
|
100
|
+
def calendar_year_classes(**) = { classes: klasses(*YEAR) }
|
|
98
101
|
|
|
99
102
|
def calendar_quarter_grid_classes
|
|
100
103
|
{ classes: klasses(*QUARTER_GRID) }
|
|
@@ -5,6 +5,7 @@ module StimulusPlumbers
|
|
|
5
5
|
module Tailwind
|
|
6
6
|
module Card
|
|
7
7
|
BASE = %w[
|
|
8
|
+
flex flex-col
|
|
8
9
|
rounded-(--sp-radius-md) border border-(--card-ring)
|
|
9
10
|
bg-(--sp-color-bg) shadow-(--sp-shadow-xs)
|
|
10
11
|
].freeze
|
|
@@ -21,7 +22,7 @@ module StimulusPlumbers
|
|
|
21
22
|
|
|
22
23
|
HEADER_BASE = %w[
|
|
23
24
|
flex items-center gap-(--sp-space-3)
|
|
24
|
-
px-(--sp-space-6)
|
|
25
|
+
px-(--sp-space-6) py-(--sp-space-6)
|
|
25
26
|
].freeze
|
|
26
27
|
|
|
27
28
|
ICON_BASE = %w[
|
|
@@ -33,12 +34,10 @@ module StimulusPlumbers
|
|
|
33
34
|
].freeze
|
|
34
35
|
|
|
35
36
|
BODY_BASE = %w[
|
|
36
|
-
px-(--sp-space-6)
|
|
37
|
+
px-(--sp-space-6) py-(--sp-space-3)
|
|
37
38
|
].freeze
|
|
38
39
|
|
|
39
|
-
ACTION_BASE = %w[
|
|
40
|
-
px-(--sp-space-6) pb-(--sp-space-6) pt-(--sp-space-4)
|
|
41
|
-
].freeze
|
|
40
|
+
ACTION_BASE = %w[w-full justify-start].freeze
|
|
42
41
|
|
|
43
42
|
private
|
|
44
43
|
|
|
@@ -4,8 +4,13 @@ module StimulusPlumbers
|
|
|
4
4
|
module Themes
|
|
5
5
|
module Tailwind
|
|
6
6
|
module Combobox
|
|
7
|
+
# ── Container / popover ───────────────────────────────────────────────
|
|
8
|
+
CONTAINER = %w[relative].freeze
|
|
9
|
+
POPOVER = %w[absolute top-full left-0 min-w-full].freeze
|
|
10
|
+
|
|
11
|
+
# ── Trigger ───────────────────────────────────────────────────────────
|
|
7
12
|
TRIGGER = %w[
|
|
8
|
-
w-full rounded-(--sp-radius-md) border border-(--sp-color-muted-fg)
|
|
13
|
+
w-full rounded-(--sp-radius-md) border border-(--sp-color-muted-fg) hover:border-(--sp-color-fg)
|
|
9
14
|
px-(--sp-space-3) py-(--sp-space-2)
|
|
10
15
|
text-(length:--sp-text-sm) text-(--sp-color-fg) bg-(--sp-color-bg)
|
|
11
16
|
focus:outline-none focus:ring-2 focus:ring-(--sp-focus-ring-color)
|
|
@@ -13,7 +18,7 @@ module StimulusPlumbers
|
|
|
13
18
|
|
|
14
19
|
TRIGGER_GROUP = %w[
|
|
15
20
|
flex items-center gap-(--sp-space-2) overflow-hidden
|
|
16
|
-
rounded-(--sp-radius-md) border border-(--sp-color-muted-fg) bg-(--sp-color-bg)
|
|
21
|
+
rounded-(--sp-radius-md) border border-(--sp-color-muted-fg) hover:border-(--sp-color-fg) bg-(--sp-color-bg)
|
|
17
22
|
px-(--sp-space-3) py-(--sp-space-2)
|
|
18
23
|
focus-within:outline-none focus-within:ring-2 focus-within:ring-(--sp-focus-ring-color)
|
|
19
24
|
[&>input]:border-0 [&>input]:rounded-none
|
|
@@ -22,8 +27,9 @@ module StimulusPlumbers
|
|
|
22
27
|
[&>input]:focus:ring-0
|
|
23
28
|
].freeze
|
|
24
29
|
|
|
30
|
+
# ── Listbox / options ─────────────────────────────────────────────────
|
|
25
31
|
LISTBOX = %w[
|
|
26
|
-
py-(--sp-space-1) overflow-y-auto max-h-60
|
|
32
|
+
py-(--sp-space-1) overflow-y-auto max-h-60 min-h-(--sp-space-6)
|
|
27
33
|
].freeze
|
|
28
34
|
|
|
29
35
|
OPTION_BASE = %w[
|
|
@@ -44,6 +50,7 @@ module StimulusPlumbers
|
|
|
44
50
|
|
|
45
51
|
OPTION_GROUP = %w[py-(--sp-space-1)].freeze
|
|
46
52
|
|
|
53
|
+
# ── Typeahead states ──────────────────────────────────────────────────
|
|
47
54
|
TYPEAHEAD_LOADING = %w[
|
|
48
55
|
flex items-center justify-center
|
|
49
56
|
py-(--sp-space-2) text-(length:--sp-text-sm) text-(--sp-color-muted-fg)
|
|
@@ -54,20 +61,15 @@ module StimulusPlumbers
|
|
|
54
61
|
py-(--sp-space-2) text-(length:--sp-text-sm) text-(--sp-color-muted-fg)
|
|
55
62
|
].freeze
|
|
56
63
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
DATE_NAV_BTN = [
|
|
62
|
-
*Control::BASE,
|
|
63
|
-
"inline-flex items-center justify-center",
|
|
64
|
-
"size-(--sp-calendar-day-size) rounded-(--sp-radius-md)",
|
|
65
|
-
"text-(--sp-color-fg) hover:bg-(--sp-color-muted)",
|
|
66
|
-
"focus-visible:ring-(--sp-focus-ring-color)"
|
|
67
|
-
].freeze
|
|
64
|
+
# ── Time picker ───────────────────────────────────────────────────────
|
|
65
|
+
TIME = %w[flex gap-(--sp-space-2) overflow-hidden].freeze
|
|
66
|
+
TIME_DRUM_UNIT = %w[flex-1 min-w-0].freeze
|
|
67
|
+
TIME_DRUM_PERIOD = %w[shrink-0].freeze
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
# ── Date navigation ───────────────────────────────────────────────────
|
|
70
|
+
DATE_NAV = %w[flex items-center justify-between gap-(--sp-space-1) mb-(--sp-space-2)].freeze
|
|
71
|
+
DATE_NAV_BTN = %w[].freeze
|
|
72
|
+
DATE_NAV_TITLE = %w[flex-1 text-center].freeze
|
|
71
73
|
|
|
72
74
|
private
|
|
73
75
|
|
|
@@ -110,7 +112,7 @@ module StimulusPlumbers
|
|
|
110
112
|
end
|
|
111
113
|
|
|
112
114
|
def combobox_typeahead_loading_icon_classes
|
|
113
|
-
{ classes: klasses("size-(--sp-icon-size)", "animate-spin") }
|
|
115
|
+
{ classes: klasses("size-(--sp-icon-size-md)", "animate-spin") }
|
|
114
116
|
end
|
|
115
117
|
|
|
116
118
|
def combobox_typeahead_empty_classes
|
|
@@ -121,6 +123,10 @@ module StimulusPlumbers
|
|
|
121
123
|
{ classes: klasses(*TIME) }
|
|
122
124
|
end
|
|
123
125
|
|
|
126
|
+
def combobox_time_drum_classes(type: :unit)
|
|
127
|
+
{ classes: klasses(*(type == :period ? TIME_DRUM_PERIOD : TIME_DRUM_UNIT)) }
|
|
128
|
+
end
|
|
129
|
+
|
|
124
130
|
def combobox_date_navigation_classes
|
|
125
131
|
{ classes: klasses(*DATE_NAV) }
|
|
126
132
|
end
|
|
@@ -128,6 +134,10 @@ module StimulusPlumbers
|
|
|
128
134
|
def combobox_date_navigation_navigator_classes
|
|
129
135
|
{ classes: klasses(*DATE_NAV_BTN) }
|
|
130
136
|
end
|
|
137
|
+
|
|
138
|
+
def combobox_date_navigation_title_classes
|
|
139
|
+
{ classes: klasses(*DATE_NAV_TITLE) }
|
|
140
|
+
end
|
|
131
141
|
end
|
|
132
142
|
end
|
|
133
143
|
end
|
|
@@ -10,27 +10,6 @@ module StimulusPlumbers
|
|
|
10
10
|
HINT = %w[text-(length:--sp-text-xs) text-(--sp-color-muted-fg)].freeze
|
|
11
11
|
ERROR_TEXT = %w[text-(length:--sp-text-xs) text-(--sp-color-error)].freeze
|
|
12
12
|
|
|
13
|
-
FLOATING_INPUT_BASE = %w[
|
|
14
|
-
peer w-full text-(length:--sp-text-sm) text-(--sp-color-fg) appearance-none
|
|
15
|
-
focus:outline-none focus:ring-0
|
|
16
|
-
].freeze
|
|
17
|
-
FLOATING_INPUT_TYPES = {
|
|
18
|
-
filled: %w[
|
|
19
|
-
rounded-t-(--sp-radius-md) px-(--sp-space-2-5) pb-(--sp-space-2-5) pt-(--sp-space-5)
|
|
20
|
-
bg-(--sp-color-bg-muted) border-0 border-b-2
|
|
21
|
-
].freeze,
|
|
22
|
-
outlined: %w[
|
|
23
|
-
px-(--sp-space-2-5) pb-(--sp-space-2-5) pt-(--sp-space-4)
|
|
24
|
-
bg-transparent rounded-(--sp-radius-md) border
|
|
25
|
-
].freeze,
|
|
26
|
-
standard: %w[
|
|
27
|
-
py-(--sp-space-2-5) px-0
|
|
28
|
-
bg-transparent border-0 border-b-2
|
|
29
|
-
].freeze
|
|
30
|
-
}.freeze
|
|
31
|
-
FLOATING_INPUT_ERROR = %w[border-(--sp-color-error)].freeze
|
|
32
|
-
FLOATING_INPUT_DEFAULT = %w[border-(--sp-color-muted-fg) focus:border-(--sp-color-primary)].freeze
|
|
33
|
-
|
|
34
13
|
FLOATING_GROUP_TYPES = {
|
|
35
14
|
filled: %w[relative].freeze,
|
|
36
15
|
outlined: %w[relative].freeze,
|
|
@@ -41,28 +20,42 @@ module StimulusPlumbers
|
|
|
41
20
|
absolute text-(length:--sp-text-sm) text-(--sp-color-muted-fg)
|
|
42
21
|
duration-300 transform origin-[0]
|
|
43
22
|
].freeze
|
|
44
|
-
FLOATING_LABEL_FOCUS = %w[peer-focus:text-(--sp-color-primary)].freeze
|
|
23
|
+
FLOATING_LABEL_FOCUS = %w[peer-focus-within:text-(--sp-color-primary)].freeze
|
|
45
24
|
FLOATING_LABEL_ERROR = %w[text-(--sp-color-error)].freeze
|
|
46
25
|
FLOATING_LABEL_TYPES = {
|
|
47
26
|
filled: %w[
|
|
48
27
|
-translate-y-(--sp-space-4) scale-75 top-(--sp-space-4) z-10 start-(--sp-space-2-5)
|
|
49
|
-
peer-placeholder-shown:scale-100
|
|
50
|
-
peer-
|
|
51
|
-
|
|
28
|
+
peer-placeholder-shown:scale-100
|
|
29
|
+
peer-placeholder-shown:translate-y-0
|
|
30
|
+
peer-has-[input:not(:focus):placeholder-shown]:scale-100
|
|
31
|
+
peer-has-[input:not(:focus):placeholder-shown]:translate-y-0
|
|
32
|
+
peer-focus-within:scale-75
|
|
33
|
+
peer-focus-within:-translate-y-(--sp-space-4)
|
|
34
|
+
rtl:peer-focus-within:translate-x-1/4 rtl:peer-focus-within:left-auto
|
|
52
35
|
].freeze,
|
|
53
36
|
outlined: %w[
|
|
54
37
|
-translate-y-(--sp-space-4) scale-75 top-(--sp-space-2) z-10 start-1
|
|
55
|
-
bg-(--sp-color-bg) px-(--sp-space-2) peer-focus:px-(--sp-space-2)
|
|
56
|
-
peer-placeholder-shown:scale-100
|
|
57
|
-
peer-
|
|
58
|
-
|
|
38
|
+
bg-(--sp-color-bg) px-(--sp-space-2) peer-focus-within:px-(--sp-space-2)
|
|
39
|
+
peer-placeholder-shown:scale-100
|
|
40
|
+
peer-placeholder-shown:-translate-y-1/2
|
|
41
|
+
peer-placeholder-shown:top-1/2
|
|
42
|
+
peer-has-[input:not(:focus):placeholder-shown]:scale-100
|
|
43
|
+
peer-has-[input:not(:focus):placeholder-shown]:-translate-y-1/2
|
|
44
|
+
peer-has-[input:not(:focus):placeholder-shown]:top-1/2
|
|
45
|
+
peer-focus-within:top-(--sp-space-2) peer-focus-within:scale-75
|
|
46
|
+
peer-focus-within:-translate-y-(--sp-space-4)
|
|
47
|
+
rtl:peer-focus-within:translate-x-1/4 rtl:peer-focus-within:left-auto
|
|
59
48
|
].freeze,
|
|
60
49
|
standard: %w[
|
|
61
50
|
-translate-y-(--sp-space-6) scale-75 top-(--sp-space-3) -z-10 start-0
|
|
62
|
-
peer-focus:start-0
|
|
63
|
-
peer-placeholder-shown:scale-100
|
|
64
|
-
peer-
|
|
65
|
-
|
|
51
|
+
peer-focus-within:start-0
|
|
52
|
+
peer-placeholder-shown:scale-100
|
|
53
|
+
peer-placeholder-shown:translate-y-0
|
|
54
|
+
peer-has-[input:not(:focus):placeholder-shown]:scale-100
|
|
55
|
+
peer-has-[input:not(:focus):placeholder-shown]:translate-y-0
|
|
56
|
+
peer-focus-within:scale-75
|
|
57
|
+
peer-focus-within:-translate-y-(--sp-space-6)
|
|
58
|
+
rtl:peer-focus-within:translate-x-1/4 rtl:peer-focus-within:left-auto
|
|
66
59
|
].freeze
|
|
67
60
|
}.freeze
|
|
68
61
|
|
|
@@ -78,7 +71,7 @@ module StimulusPlumbers
|
|
|
78
71
|
hover:bg-(--sp-color-muted)
|
|
79
72
|
].freeze,
|
|
80
73
|
card: %w[
|
|
81
|
-
flex justify-between items-
|
|
74
|
+
flex justify-between items-center gap-(--sp-space-3) flex-1 p-(--sp-space-4) cursor-pointer select-none
|
|
82
75
|
text-(length:--sp-text-sm) text-(--sp-color-muted-fg)
|
|
83
76
|
bg-(--sp-color-bg) border border-(--sp-color-border) rounded-(--sp-radius-md) shadow-(--sp-shadow-xs)
|
|
84
77
|
hover:bg-(--sp-color-muted) hover:border-(--sp-color-border-strong) hover:text-(--sp-color-fg)
|
|
@@ -97,16 +90,16 @@ module StimulusPlumbers
|
|
|
97
90
|
text-(length:--sp-text-sm) text-(--sp-color-muted-fg)
|
|
98
91
|
bg-(--sp-color-bg) border border-(--sp-color-border) rounded-(--sp-radius-md)
|
|
99
92
|
hover:bg-(--sp-color-muted)
|
|
100
|
-
|
|
101
|
-
|
|
93
|
+
group-has-[:checked]:border-(--card-ring) group-has-[:checked]:bg-(--card-ring)/10
|
|
94
|
+
group-has-[:checked]:text-(--sp-color-fg) group-has-[:checked]:hover:bg-(--card-ring)/15
|
|
102
95
|
].freeze,
|
|
103
96
|
card: %w[
|
|
104
97
|
flex items-start flex-1 p-(--sp-space-4) cursor-pointer select-none
|
|
105
98
|
text-(length:--sp-text-sm) text-(--sp-color-muted-fg)
|
|
106
99
|
bg-(--sp-color-bg) border border-(--sp-color-border) rounded-(--sp-radius-md) shadow-(--sp-shadow-xs)
|
|
107
100
|
hover:bg-(--sp-color-muted) hover:border-(--sp-color-border-strong) hover:text-(--sp-color-fg)
|
|
108
|
-
|
|
109
|
-
|
|
101
|
+
group-has-[:checked]:border-(--card-ring) group-has-[:checked]:bg-(--card-ring)/10
|
|
102
|
+
group-has-[:checked]:text-(--sp-color-fg) group-has-[:checked]:hover:bg-(--card-ring)/15
|
|
110
103
|
].freeze
|
|
111
104
|
}.freeze
|
|
112
105
|
|
|
@@ -117,27 +110,17 @@ module StimulusPlumbers
|
|
|
117
110
|
|
|
118
111
|
private
|
|
119
112
|
|
|
120
|
-
def
|
|
121
|
-
{
|
|
122
|
-
classes: klasses(
|
|
123
|
-
*FLOATING_INPUT_BASE,
|
|
124
|
-
*FLOATING_INPUT_TYPES.fetch(type, []),
|
|
125
|
-
*(error ? FLOATING_INPUT_ERROR : FLOATING_INPUT_DEFAULT)
|
|
126
|
-
)
|
|
127
|
-
}
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
def form_field_floating_group_classes(type: nil)
|
|
131
|
-
{ classes: klasses(*FLOATING_GROUP_TYPES.fetch(type, [])) }
|
|
113
|
+
def form_field_input_group_classes(floating: nil)
|
|
114
|
+
{ classes: klasses(*FLOATING_GROUP_TYPES.fetch(floating, [])) }
|
|
132
115
|
end
|
|
133
116
|
|
|
134
|
-
def
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
117
|
+
def form_field_label_classes(floating: nil, hidden: false, error: false, **)
|
|
118
|
+
if floating
|
|
119
|
+
color = error ? FLOATING_LABEL_ERROR : FLOATING_LABEL_FOCUS
|
|
120
|
+
{ classes: klasses(*FLOATING_LABEL_BASE, *FLOATING_LABEL_TYPES.fetch(floating, []), *color) }
|
|
121
|
+
else
|
|
122
|
+
{ classes: klasses(*LABEL, hidden ? "sr-only" : nil) }
|
|
123
|
+
end
|
|
141
124
|
end
|
|
142
125
|
|
|
143
126
|
def form_field_required_mark_classes
|
|
@@ -165,6 +148,10 @@ module StimulusPlumbers
|
|
|
165
148
|
card_color = %i[button card].include?(type) ? Card::VARIANTS.fetch(variant, Card::VARIANTS[:tertiary]) : []
|
|
166
149
|
{ classes: klasses(*RADIO_LABEL_TYPES.fetch(type), *card_color) }
|
|
167
150
|
end
|
|
151
|
+
|
|
152
|
+
def form_field_radio_item_group_classes
|
|
153
|
+
{ classes: "contents group" }
|
|
154
|
+
end
|
|
168
155
|
end
|
|
169
156
|
end
|
|
170
157
|
end
|
|
@@ -5,31 +5,98 @@ module StimulusPlumbers
|
|
|
5
5
|
module Tailwind
|
|
6
6
|
module Form
|
|
7
7
|
module Input
|
|
8
|
+
# ── Standalone input ──────────────────────────────────────────────────
|
|
8
9
|
INPUT_BASE = %w[
|
|
9
|
-
w-full rounded-(--sp-radius-md) border px-(--sp-space-3) py-(--sp-space-2)
|
|
10
|
-
text-(--sp-color-fg) bg-(--sp-color-bg)
|
|
10
|
+
w-full rounded-(--sp-radius-md) border px-(--sp-space-3) py-(--sp-space-2)
|
|
11
|
+
text-(length:--sp-text-sm) text-(--sp-color-fg) bg-(--sp-color-bg)
|
|
12
|
+
focus:outline-none focus:ring-(length:--sp-focus-ring-width) focus:ring-offset-0
|
|
13
|
+
].freeze
|
|
14
|
+
INPUT_DEFAULT = %w[
|
|
15
|
+
border-(--sp-color-muted-fg) hover:border-(--sp-color-fg)
|
|
16
|
+
focus:ring-(--sp-focus-ring-color)
|
|
17
|
+
].freeze
|
|
18
|
+
INPUT_ERROR = %w[border-(--sp-color-error) focus:ring-(--sp-color-error)].freeze
|
|
19
|
+
|
|
20
|
+
# ── Floating input ────────────────────────────────────────────────────
|
|
21
|
+
FLOATING_INPUT_BASE = %w[
|
|
22
|
+
peer w-full text-(length:--sp-text-sm) text-(--sp-color-fg) appearance-none
|
|
23
|
+
focus:outline-none focus:ring-0
|
|
24
|
+
focus-visible:outline-none focus-visible:ring-0
|
|
25
|
+
].freeze
|
|
26
|
+
FLOATING_INPUT_TYPES = {
|
|
27
|
+
filled: %w[
|
|
28
|
+
rounded-t-(--sp-radius-md) px-(--sp-space-2-5) pb-(--sp-space-2-5) pt-(--sp-space-5)
|
|
29
|
+
bg-(--sp-color-bg-muted) border-0 border-b-2
|
|
30
|
+
].freeze,
|
|
31
|
+
outlined: %w[
|
|
32
|
+
px-(--sp-space-2-5) pb-(--sp-space-2-5) pt-(--sp-space-4)
|
|
33
|
+
bg-transparent rounded-(--sp-radius-md) border
|
|
34
|
+
].freeze,
|
|
35
|
+
standard: %w[
|
|
36
|
+
py-(--sp-space-2-5) px-0
|
|
37
|
+
bg-transparent border-0 border-b-2
|
|
38
|
+
].freeze
|
|
39
|
+
}.freeze
|
|
40
|
+
FLOATING_INPUT_DEFAULT = %w[
|
|
41
|
+
border-(--sp-color-muted-fg) hover:border-(--sp-color-fg)
|
|
42
|
+
focus:border-(--sp-color-primary)
|
|
43
|
+
].freeze
|
|
44
|
+
FLOATING_INPUT_ERROR = %w[border-(--sp-color-error)].freeze
|
|
45
|
+
|
|
46
|
+
# ── Input group ───────────────────────────────────────────────────────
|
|
47
|
+
INPUT_GROUP_BASE = %w[flex items-center overflow-hidden rounded-(--sp-radius-md) border].freeze
|
|
48
|
+
INPUT_GROUP_BORDER = { error: "border-(--sp-color-error)", default: "border-(--sp-color-muted-fg)" }.freeze
|
|
49
|
+
|
|
50
|
+
# ── Floating input group ──────────────────────────────────────────────
|
|
51
|
+
FLOATING_INPUT_GROUP_BASE = %w[flex items-center overflow-hidden peer].freeze
|
|
52
|
+
FLOATING_INPUT_GROUP_TYPES = {
|
|
53
|
+
filled: %w[rounded-t-(--sp-radius-md) bg-(--sp-color-bg-muted) border-0 border-b-2].freeze,
|
|
54
|
+
outlined: %w[rounded-(--sp-radius-md) border].freeze,
|
|
55
|
+
standard: %w[rounded-none bg-transparent border-0 border-b-2].freeze
|
|
56
|
+
}.freeze
|
|
57
|
+
FLOATING_INPUT_GROUP_DEFAULT = %w[
|
|
58
|
+
border-(--sp-color-muted-fg) hover:border-(--sp-color-fg)
|
|
59
|
+
focus-within:border-(--sp-color-primary)
|
|
60
|
+
].freeze
|
|
61
|
+
FLOATING_INPUT_GROUP_ERROR = %w[border-(--sp-color-error)].freeze
|
|
62
|
+
|
|
63
|
+
# ── Combobox wrappers ─────────────────────────────────────────────────
|
|
64
|
+
COMBOBOX_INPUT = %w[
|
|
65
|
+
[&>input:not([type=hidden])]:border-0
|
|
66
|
+
[&>input:not([type=hidden])]:rounded-none
|
|
67
|
+
[&>input:not([type=hidden])]:px-0
|
|
68
|
+
[&>input:not([type=hidden])]:py-0
|
|
69
|
+
[&>input:not([type=hidden])]:bg-transparent
|
|
70
|
+
[&>input:not([type=hidden])]:shadow-none
|
|
71
|
+
[&>input:not([type=hidden])]:focus:ring-0
|
|
72
|
+
].freeze
|
|
73
|
+
COMBOBOX_TRIGGER_GROUP = %w[
|
|
74
|
+
[&>div:first-child]:border-0
|
|
75
|
+
[&>div:first-child]:rounded-none
|
|
76
|
+
[&>div:first-child]:px-0
|
|
77
|
+
[&>div:first-child]:py-0
|
|
78
|
+
[&>div:first-child]:focus-within:ring-0
|
|
11
79
|
].freeze
|
|
12
|
-
INPUT_ERROR = %w[border-(--sp-color-error) focus:ring-(--sp-color-error)].freeze
|
|
13
|
-
INPUT_DEFAULT = %w[border-(--sp-color-muted-fg) focus:ring-(--sp-focus-ring-color)].freeze
|
|
14
80
|
|
|
81
|
+
# ── Choice inputs ─────────────────────────────────────────────────────
|
|
15
82
|
CHECKBOX_TYPES = {
|
|
16
83
|
default: %w[
|
|
17
84
|
size-(--sp-control-size) rounded-(--sp-radius-sm) shrink-0
|
|
18
85
|
border border-(--sp-color-border) bg-(--sp-color-muted)
|
|
19
|
-
focus:ring-
|
|
86
|
+
focus:ring-(length:--sp-focus-ring-width) focus:ring-(--sp-focus-ring-color) focus:outline-none
|
|
20
87
|
disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer
|
|
21
88
|
].freeze,
|
|
22
89
|
button: %w[
|
|
23
90
|
size-(--sp-control-size) rounded-(--sp-radius-sm) shrink-0
|
|
24
91
|
border border-(--sp-color-border) bg-(--sp-color-muted)
|
|
25
|
-
focus:ring-
|
|
92
|
+
focus:ring-(length:--sp-focus-ring-width) focus:ring-(--sp-focus-ring-color) focus:outline-none
|
|
26
93
|
disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer
|
|
27
94
|
].freeze,
|
|
28
95
|
card: %w[
|
|
29
96
|
size-(--sp-control-size) rounded-(--sp-radius-sm) shrink-0
|
|
30
97
|
border border-(--sp-color-border) bg-(--sp-color-muted)
|
|
31
98
|
checked:border-(--card-ring)
|
|
32
|
-
focus:ring-
|
|
99
|
+
focus:ring-(length:--sp-focus-ring-width) focus:ring-(--card-ring) focus:outline-none
|
|
33
100
|
disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer
|
|
34
101
|
].freeze
|
|
35
102
|
}.freeze
|
|
@@ -38,58 +105,54 @@ module StimulusPlumbers
|
|
|
38
105
|
default: %w[
|
|
39
106
|
size-(--sp-control-size) rounded-full shrink-0
|
|
40
107
|
[accent-color:var(--sp-color-primary)] cursor-pointer
|
|
41
|
-
focus:ring-
|
|
108
|
+
focus:ring-(length:--sp-focus-ring-width) focus:ring-(--sp-focus-ring-color) focus:outline-none
|
|
42
109
|
disabled:opacity-50 disabled:cursor-not-allowed
|
|
43
110
|
].freeze,
|
|
44
|
-
button: %w[hidden
|
|
45
|
-
card: %w[hidden
|
|
111
|
+
button: %w[hidden].freeze,
|
|
112
|
+
card: %w[hidden].freeze
|
|
46
113
|
}.freeze
|
|
47
114
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
[&>input:not([type=hidden])]:py-0
|
|
56
|
-
[&>input:not([type=hidden])]:bg-transparent
|
|
57
|
-
[&>input:not([type=hidden])]:shadow-none
|
|
58
|
-
[&>input:not([type=hidden])]:focus:ring-0
|
|
59
|
-
].freeze
|
|
60
|
-
COMBOBOX_TRIGGER_GROUP = %w[
|
|
61
|
-
[&>div:first-child]:border-0
|
|
62
|
-
[&>div:first-child]:rounded-none
|
|
63
|
-
[&>div:first-child]:px-0
|
|
64
|
-
[&>div:first-child]:py-0
|
|
65
|
-
[&>div:first-child]:focus-within:ring-0
|
|
66
|
-
].freeze
|
|
67
|
-
|
|
68
|
-
BUTTON_REVEAL = %w[
|
|
69
|
-
self-stretch border-0 bg-transparent px-(--sp-space-3) cursor-pointer text-(--sp-color-muted-fg)
|
|
70
|
-
hover:text-(--sp-color-fg) text-(length:--sp-text-sm)
|
|
115
|
+
# ── Utility buttons ───────────────────────────────────────────────────
|
|
116
|
+
BUTTON_REVEAL = [
|
|
117
|
+
*Control::BASE,
|
|
118
|
+
"inline-flex items-center justify-center",
|
|
119
|
+
"focus-visible:ring-(--sp-focus-ring-color)",
|
|
120
|
+
"self-stretch px-(--sp-space-2) border-0 bg-transparent cursor-pointer text-(--sp-color-muted-fg)",
|
|
121
|
+
"rounded-(--sp-radius-sm) hover:bg-(--sp-color-muted) hover:text-(--sp-color-fg)"
|
|
71
122
|
].freeze
|
|
72
|
-
BUTTON_CLEAR =
|
|
73
|
-
|
|
74
|
-
|
|
123
|
+
BUTTON_CLEAR = [
|
|
124
|
+
*Control::BASE,
|
|
125
|
+
"inline-flex items-center justify-center",
|
|
126
|
+
"focus-visible:ring-(--sp-focus-ring-color)",
|
|
127
|
+
"self-stretch px-(--sp-space-2) border-0 bg-transparent cursor-pointer text-(--sp-color-muted-fg)",
|
|
128
|
+
"rounded-(--sp-radius-sm) hover:bg-(--sp-color-muted) hover:text-(--sp-color-fg)"
|
|
75
129
|
].freeze
|
|
76
130
|
|
|
77
131
|
private
|
|
78
132
|
|
|
79
|
-
def form_field_input_classes(error: false)
|
|
80
|
-
|
|
133
|
+
def form_field_input_classes(floating: nil, error: false)
|
|
134
|
+
if floating
|
|
135
|
+
{ classes: klasses(
|
|
136
|
+
*FLOATING_INPUT_BASE,
|
|
137
|
+
*FLOATING_INPUT_TYPES.fetch(floating, []),
|
|
138
|
+
*(error ? FLOATING_INPUT_ERROR : FLOATING_INPUT_DEFAULT)
|
|
139
|
+
)
|
|
140
|
+
}
|
|
141
|
+
else
|
|
142
|
+
{ classes: klasses(*INPUT_BASE, *(error ? INPUT_ERROR : INPUT_DEFAULT)) }
|
|
143
|
+
end
|
|
81
144
|
end
|
|
82
145
|
|
|
83
|
-
def form_field_input_textarea_classes(error: false)
|
|
84
|
-
form_field_input_classes(error: error)
|
|
146
|
+
def form_field_input_textarea_classes(floating: nil, error: false)
|
|
147
|
+
form_field_input_classes(floating: floating, error: error)
|
|
85
148
|
end
|
|
86
149
|
|
|
87
|
-
def form_field_input_file_classes(error: false)
|
|
88
|
-
form_field_input_classes(error: error)
|
|
150
|
+
def form_field_input_file_classes(floating: nil, error: false)
|
|
151
|
+
form_field_input_classes(floating: floating, error: error)
|
|
89
152
|
end
|
|
90
153
|
|
|
91
|
-
def form_field_input_select_classes(error: false)
|
|
92
|
-
form_field_input_classes(error: error)
|
|
154
|
+
def form_field_input_select_classes(floating: nil, error: false)
|
|
155
|
+
form_field_input_classes(floating: floating, error: error)
|
|
93
156
|
end
|
|
94
157
|
|
|
95
158
|
def form_field_input_checkbox_classes(type: :default, variant: :default, **)
|
|
@@ -102,23 +165,46 @@ module StimulusPlumbers
|
|
|
102
165
|
{ classes: klasses(*RADIO_TYPES.fetch(type), *card_color) }
|
|
103
166
|
end
|
|
104
167
|
|
|
105
|
-
def input_group_classes(error: false)
|
|
106
|
-
|
|
168
|
+
def input_group_classes(error: false, floating: nil)
|
|
169
|
+
if floating
|
|
170
|
+
color = error ? FLOATING_INPUT_GROUP_ERROR : FLOATING_INPUT_GROUP_DEFAULT
|
|
171
|
+
{ classes: klasses(*FLOATING_INPUT_GROUP_BASE, *FLOATING_INPUT_GROUP_TYPES.fetch(floating, []), *color) }
|
|
172
|
+
else
|
|
173
|
+
{ classes: klasses(*INPUT_GROUP_BASE, INPUT_GROUP_BORDER[error ? :error : :default]) }
|
|
174
|
+
end
|
|
107
175
|
end
|
|
108
176
|
|
|
109
|
-
def form_field_input_combobox_classes(error: false)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
177
|
+
def form_field_input_combobox_classes(floating: nil, error: false)
|
|
178
|
+
if floating
|
|
179
|
+
form_field_input_combobox_floating_classes(floating: floating, error: error)
|
|
180
|
+
else
|
|
181
|
+
{
|
|
182
|
+
classes: klasses(
|
|
183
|
+
*INPUT_BASE,
|
|
184
|
+
*(error ? INPUT_ERROR : INPUT_DEFAULT),
|
|
185
|
+
*COMBOBOX_INPUT,
|
|
186
|
+
*COMBOBOX_TRIGGER_GROUP
|
|
187
|
+
)
|
|
188
|
+
}
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def form_field_input_combobox_floating_classes(floating: :standard, error: false)
|
|
193
|
+
{
|
|
194
|
+
classes: klasses(
|
|
195
|
+
*FLOATING_INPUT_BASE,
|
|
196
|
+
*FLOATING_INPUT_TYPES.fetch(floating, []),
|
|
197
|
+
*(error ? FLOATING_INPUT_ERROR : FLOATING_INPUT_DEFAULT),
|
|
198
|
+
*COMBOBOX_INPUT,
|
|
199
|
+
*COMBOBOX_TRIGGER_GROUP
|
|
200
|
+
)
|
|
201
|
+
}
|
|
117
202
|
end
|
|
118
203
|
|
|
119
204
|
def form_field_input_reveal_classes(**)
|
|
120
205
|
{
|
|
121
206
|
classes: klasses(
|
|
207
|
+
"peer",
|
|
122
208
|
"[&>input]:border-0",
|
|
123
209
|
"[&>input]:rounded-none",
|
|
124
210
|
"[&>input]:bg-transparent",
|
|
@@ -13,16 +13,7 @@ module StimulusPlumbers
|
|
|
13
13
|
{ classes: klasses(*GROUP_BASE, layout == :inline ? GROUP_INLINE : "flex-col") }
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
def form_submit_classes(
|
|
17
|
-
{ classes: klasses(
|
|
18
|
-
*Button::BASE,
|
|
19
|
-
*Button::LAYOUT,
|
|
20
|
-
*Button::VARIANTS.fetch(variant, Button::VARIANTS[:primary]),
|
|
21
|
-
*Button::TYPES.fetch(type, Button::TYPES[:default]),
|
|
22
|
-
*(type == :card ? [] : Button::SIZES[:md])
|
|
23
|
-
)
|
|
24
|
-
}
|
|
25
|
-
end
|
|
16
|
+
def form_submit_classes(**) = {}
|
|
26
17
|
end
|
|
27
18
|
end
|
|
28
19
|
end
|
|
@@ -10,8 +10,13 @@ module StimulusPlumbers
|
|
|
10
10
|
module Icon
|
|
11
11
|
ALIASES = {
|
|
12
12
|
"close" => "x-mark",
|
|
13
|
+
"download" => "arrow-down-tray",
|
|
14
|
+
"book" => "book-open",
|
|
15
|
+
"edit" => "pencil",
|
|
16
|
+
"email" => "envelope",
|
|
13
17
|
"calendar" => "calendar-days",
|
|
14
|
-
"external-link" => "arrow-top-right-on-square"
|
|
18
|
+
"external-link" => "arrow-top-right-on-square",
|
|
19
|
+
"reveal" => "eye"
|
|
15
20
|
}.freeze
|
|
16
21
|
|
|
17
22
|
ICONS = StimulusPlumbers::Themes::Icons::Registry.new(
|
|
@@ -26,7 +31,7 @@ module StimulusPlumbers
|
|
|
26
31
|
private
|
|
27
32
|
|
|
28
33
|
def icon_classes
|
|
29
|
-
{ classes: "size-(--sp-icon-
|
|
34
|
+
{ classes: "size-(--sp-icon-size-lg)" }
|
|
30
35
|
end
|
|
31
36
|
end
|
|
32
37
|
end
|
|
@@ -4,9 +4,12 @@ module StimulusPlumbers
|
|
|
4
4
|
module Themes
|
|
5
5
|
module Tailwind
|
|
6
6
|
module Layout
|
|
7
|
-
|
|
8
|
-
DIVIDER = %w[flex items-center gap-(--sp-space-3)].freeze
|
|
9
|
-
|
|
7
|
+
# ── Divider ───────────────────────────────────────────────────────────
|
|
8
|
+
DIVIDER = %w[w-full flex items-center gap-(--sp-space-3)].freeze
|
|
9
|
+
DIVIDER_SEPARATOR = %w[flex-1 h-px bg-(--sp-color-border) border-0].freeze
|
|
10
|
+
DIVIDER_LABEL = %w[text-(length:--sp-text-sm) text-(--sp-color-muted-fg) whitespace-nowrap font-medium].freeze
|
|
11
|
+
|
|
12
|
+
# ── Popover ───────────────────────────────────────────────────────────
|
|
10
13
|
POPOVER_WRAPPER = %w[relative inline-block].freeze
|
|
11
14
|
POPOVER_TRIGGER = [
|
|
12
15
|
*Control::BASE,
|
|
@@ -4,34 +4,7 @@ module StimulusPlumbers
|
|
|
4
4
|
module Themes
|
|
5
5
|
module Tailwind
|
|
6
6
|
module Link
|
|
7
|
-
|
|
8
|
-
default: %w[
|
|
9
|
-
[--link-color:var(--sp-color-primary)]
|
|
10
|
-
[--link-ring:var(--sp-color-primary)]
|
|
11
|
-
[--link-bg:var(--sp-color-primary)]
|
|
12
|
-
].freeze,
|
|
13
|
-
success: %w[
|
|
14
|
-
[--link-color:var(--sp-color-success)]
|
|
15
|
-
[--link-ring:var(--sp-color-success-ring)]
|
|
16
|
-
[--link-bg:var(--sp-color-success)]
|
|
17
|
-
].freeze,
|
|
18
|
-
destructive: %w[
|
|
19
|
-
[--link-color:var(--sp-color-destructive)]
|
|
20
|
-
[--link-ring:var(--sp-color-destructive)]
|
|
21
|
-
[--link-bg:var(--sp-color-destructive)]
|
|
22
|
-
].freeze,
|
|
23
|
-
warning: %w[
|
|
24
|
-
[--link-color:var(--sp-color-warning)]
|
|
25
|
-
[--link-ring:var(--sp-color-warning-ring)]
|
|
26
|
-
[--link-bg:var(--sp-color-warning)]
|
|
27
|
-
].freeze,
|
|
28
|
-
info: %w[
|
|
29
|
-
[--link-color:var(--sp-color-info)]
|
|
30
|
-
[--link-ring:var(--sp-color-info-ring)]
|
|
31
|
-
[--link-bg:var(--sp-color-info)]
|
|
32
|
-
].freeze
|
|
33
|
-
}.freeze
|
|
34
|
-
|
|
7
|
+
# ── Type styles ───────────────────────────────────────────────────────
|
|
35
8
|
BASE = [
|
|
36
9
|
*Control::BASE,
|
|
37
10
|
"inline-flex items-center gap-(--sp-space-1)",
|
|
@@ -65,6 +38,35 @@ module StimulusPlumbers
|
|
|
65
38
|
"focus-visible:ring-(--link-ring)"
|
|
66
39
|
].freeze
|
|
67
40
|
|
|
41
|
+
# ── Color tokens ──────────────────────────────────────────────────────
|
|
42
|
+
VARIANTS = {
|
|
43
|
+
default: %w[
|
|
44
|
+
[--link-color:var(--sp-color-primary)]
|
|
45
|
+
[--link-ring:var(--sp-color-primary)]
|
|
46
|
+
[--link-bg:var(--sp-color-primary)]
|
|
47
|
+
].freeze,
|
|
48
|
+
success: %w[
|
|
49
|
+
[--link-color:var(--sp-color-success)]
|
|
50
|
+
[--link-ring:var(--sp-color-success-ring)]
|
|
51
|
+
[--link-bg:var(--sp-color-success)]
|
|
52
|
+
].freeze,
|
|
53
|
+
destructive: %w[
|
|
54
|
+
[--link-color:var(--sp-color-destructive)]
|
|
55
|
+
[--link-ring:var(--sp-color-destructive)]
|
|
56
|
+
[--link-bg:var(--sp-color-destructive)]
|
|
57
|
+
].freeze,
|
|
58
|
+
warning: %w[
|
|
59
|
+
[--link-color:var(--sp-color-warning)]
|
|
60
|
+
[--link-ring:var(--sp-color-warning-ring)]
|
|
61
|
+
[--link-bg:var(--sp-color-warning)]
|
|
62
|
+
].freeze,
|
|
63
|
+
info: %w[
|
|
64
|
+
[--link-color:var(--sp-color-info)]
|
|
65
|
+
[--link-ring:var(--sp-color-info-ring)]
|
|
66
|
+
[--link-bg:var(--sp-color-info)]
|
|
67
|
+
].freeze
|
|
68
|
+
}.freeze
|
|
69
|
+
|
|
68
70
|
private
|
|
69
71
|
|
|
70
72
|
def link_classes(type: :default, variant: :default)
|
|
@@ -77,7 +79,7 @@ module StimulusPlumbers
|
|
|
77
79
|
end
|
|
78
80
|
|
|
79
81
|
def link_icon_classes
|
|
80
|
-
{ classes: klasses("size-(--sp-
|
|
82
|
+
{ classes: klasses("size-(--sp-icon-size-sm)", "stroke-current") }
|
|
81
83
|
end
|
|
82
84
|
end
|
|
83
85
|
end
|
|
@@ -4,6 +4,19 @@ module StimulusPlumbers
|
|
|
4
4
|
module Themes
|
|
5
5
|
module Tailwind
|
|
6
6
|
module List
|
|
7
|
+
# ── Section ───────────────────────────────────────────────────────────
|
|
8
|
+
SECTION_TITLE_BASE = %w[
|
|
9
|
+
block px-(--sp-space-2) pb-(--sp-space-1)
|
|
10
|
+
text-(length:--sp-text-xs) font-semibold uppercase tracking-wider
|
|
11
|
+
text-(--sp-color-muted-fg)
|
|
12
|
+
].freeze
|
|
13
|
+
|
|
14
|
+
SECTION_DESCRIPTION_BASE = %w[
|
|
15
|
+
block px-(--sp-space-2) pb-(--sp-space-1)
|
|
16
|
+
text-(length:--sp-text-xs) text-(--sp-color-muted-fg)
|
|
17
|
+
].freeze
|
|
18
|
+
|
|
19
|
+
# ── Item ──────────────────────────────────────────────────────────────
|
|
7
20
|
ITEM_BASE = [
|
|
8
21
|
*Control::BASE,
|
|
9
22
|
"flex items-center gap-(--sp-space-2) w-full",
|
|
@@ -28,21 +41,10 @@ module StimulusPlumbers
|
|
|
28
41
|
text-(length:--sp-text-xs) text-(--sp-color-muted-fg)
|
|
29
42
|
].freeze
|
|
30
43
|
|
|
31
|
-
SECTION_TITLE_BASE = %w[
|
|
32
|
-
block px-(--sp-space-2) pb-(--sp-space-1)
|
|
33
|
-
text-(length:--sp-text-xs) font-semibold uppercase tracking-wider
|
|
34
|
-
text-(--sp-color-muted-fg)
|
|
35
|
-
].freeze
|
|
36
|
-
|
|
37
|
-
SECTION_DESCRIPTION_BASE = %w[
|
|
38
|
-
block px-(--sp-space-2) pb-(--sp-space-1)
|
|
39
|
-
text-(length:--sp-text-xs) text-(--sp-color-muted-fg)
|
|
40
|
-
].freeze
|
|
41
|
-
|
|
42
44
|
private
|
|
43
45
|
|
|
44
46
|
def list_classes
|
|
45
|
-
{ classes: klasses("py-(--sp-space-1)
|
|
47
|
+
{ classes: klasses("py-(--sp-space-1)") }
|
|
46
48
|
end
|
|
47
49
|
|
|
48
50
|
def list_section_classes
|
|
@@ -62,7 +64,7 @@ module StimulusPlumbers
|
|
|
62
64
|
end
|
|
63
65
|
|
|
64
66
|
def list_item_icon_classes
|
|
65
|
-
{ classes: klasses("size-(--sp-
|
|
67
|
+
{ classes: klasses("size-(--sp-icon-size-sm)", "stroke-current") }
|
|
66
68
|
end
|
|
67
69
|
|
|
68
70
|
def list_item_content_classes
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module StimulusPlumbers
|
|
4
|
+
module Themes
|
|
5
|
+
module Tailwind
|
|
6
|
+
module Timeline
|
|
7
|
+
module Group
|
|
8
|
+
WRAPPER = %w[space-y-4].freeze
|
|
9
|
+
SECTION = %w[
|
|
10
|
+
p-4
|
|
11
|
+
bg-(--sp-color-bg-muted)
|
|
12
|
+
border border-(--sp-color-border)
|
|
13
|
+
rounded-lg
|
|
14
|
+
].freeze
|
|
15
|
+
DATE = %w[text-base font-semibold text-(--sp-color-fg)].freeze
|
|
16
|
+
LIST = %w[mt-3 divide-y divide-(--sp-color-border)].freeze
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def timeline_group_classes = { classes: klasses(WRAPPER) }
|
|
21
|
+
def timeline_group_section_classes = { classes: klasses(SECTION) }
|
|
22
|
+
def timeline_group_section_date_classes = { classes: klasses(DATE) }
|
|
23
|
+
def timeline_group_section_list_classes = { classes: klasses(LIST) }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "timeline/group"
|
|
4
|
+
|
|
5
|
+
module StimulusPlumbers
|
|
6
|
+
module Themes
|
|
7
|
+
module Tailwind
|
|
8
|
+
module Timeline
|
|
9
|
+
TRACK_VERTICAL = %w[flex flex-col gap-y-10].freeze
|
|
10
|
+
TRACK_HORIZONTAL = %w[flex].freeze
|
|
11
|
+
|
|
12
|
+
TRACK_LINE_VERTICAL = %w[absolute inset-y-0 start-3 w-px bg-(--sp-color-border)].freeze
|
|
13
|
+
|
|
14
|
+
ITEM_VERTICAL = %w[flex gap-x-4 items-start].freeze
|
|
15
|
+
ITEM_HORIZONTAL = %w[relative flex-1].freeze
|
|
16
|
+
|
|
17
|
+
ITEM_INDICATOR_DOT = %w[
|
|
18
|
+
mt-1 flex shrink-0 size-6 items-center justify-center rounded-full z-10
|
|
19
|
+
bg-(--sp-color-bg) ring-4 ring-(--sp-color-bg)
|
|
20
|
+
].freeze
|
|
21
|
+
ITEM_INDICATOR_DOT_MARK = %w[size-3 rounded-full bg-(--sp-color-indicator)].freeze
|
|
22
|
+
|
|
23
|
+
ITEM_INDICATOR_ICON = %w[
|
|
24
|
+
mt-1 flex shrink-0 size-6 items-center justify-center rounded-full z-10
|
|
25
|
+
bg-(--sp-color-primary) text-(--sp-color-primary-fg)
|
|
26
|
+
ring-4 ring-(--sp-color-bg)
|
|
27
|
+
].freeze
|
|
28
|
+
|
|
29
|
+
ITEM_INDICATOR_ICON_SLOT = %w[size-(--sp-icon-size-sm) stroke-current].freeze
|
|
30
|
+
|
|
31
|
+
ITEM_INDICATOR_DOT_HORIZONTAL = %w[
|
|
32
|
+
z-10 flex shrink-0 size-6 items-center justify-center rounded-full
|
|
33
|
+
bg-(--sp-color-bg) ring-4 ring-(--sp-color-bg)
|
|
34
|
+
].freeze
|
|
35
|
+
|
|
36
|
+
ITEM_INDICATOR_ICON_HORIZONTAL = %w[
|
|
37
|
+
z-10 flex shrink-0 size-6 items-center justify-center rounded-full
|
|
38
|
+
bg-(--sp-color-primary) text-(--sp-color-primary-fg)
|
|
39
|
+
ring-4 ring-(--sp-color-bg)
|
|
40
|
+
].freeze
|
|
41
|
+
|
|
42
|
+
ITEM_CONNECTOR_HORIZONTAL = %w[w-full h-px bg-(--sp-color-border) last:hidden].freeze
|
|
43
|
+
ITEM_CONTENT_HORIZONTAL = %w[mt-3 pe-2].freeze
|
|
44
|
+
|
|
45
|
+
ITEM_TIME = %w[mb-1 block text-sm leading-none text-(--sp-color-muted-fg)].freeze
|
|
46
|
+
ITEM_TIME_BADGE = %w[
|
|
47
|
+
mb-1 inline-block
|
|
48
|
+
bg-(--sp-color-bg-muted) border border-(--sp-color-border)
|
|
49
|
+
text-(--sp-color-fg) text-xs font-medium px-1.5 py-0.5 rounded
|
|
50
|
+
].freeze
|
|
51
|
+
ITEM_TITLE = %w[mb-1 text-base font-semibold text-(--sp-color-fg)].freeze
|
|
52
|
+
ITEM_HEADING = %w[mb-1].freeze
|
|
53
|
+
ITEM_TRIGGER = %w[
|
|
54
|
+
w-full text-left text-base font-semibold
|
|
55
|
+
text-(--sp-color-fg)
|
|
56
|
+
hover:text-(--sp-color-primary)
|
|
57
|
+
focus-visible:outline-none focus-visible:ring-2
|
|
58
|
+
focus-visible:ring-(--sp-color-primary) focus-visible:rounded-sm
|
|
59
|
+
].freeze
|
|
60
|
+
ITEM_DESCRIPTION = %w[text-sm text-(--sp-color-muted-fg)].freeze
|
|
61
|
+
ITEM_DETAIL = %w[mt-2 text-sm text-(--sp-color-muted-fg)].freeze
|
|
62
|
+
ITEM_ACTIONS = %w[mt-3 flex flex-wrap items-center gap-2].freeze
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
def timeline_classes(orientation: :vertical)
|
|
67
|
+
track = orientation.to_sym == :horizontal ? TRACK_HORIZONTAL : TRACK_VERTICAL
|
|
68
|
+
{ classes: klasses(track) }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def timeline_item_classes(orientation: :vertical)
|
|
72
|
+
item = orientation.to_sym == :horizontal ? ITEM_HORIZONTAL : ITEM_VERTICAL
|
|
73
|
+
{ classes: klasses(item) }
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def timeline_item_indicator_classes(type: :dot, orientation: :vertical)
|
|
77
|
+
base = if orientation.to_sym == :horizontal
|
|
78
|
+
type.to_sym == :icon ? ITEM_INDICATOR_ICON_HORIZONTAL : ITEM_INDICATOR_DOT_HORIZONTAL
|
|
79
|
+
else
|
|
80
|
+
type.to_sym == :icon ? ITEM_INDICATOR_ICON : ITEM_INDICATOR_DOT
|
|
81
|
+
end
|
|
82
|
+
{ classes: klasses(base) }
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def timeline_item_time_classes(type: :default)
|
|
86
|
+
base = type.to_sym == :badge ? ITEM_TIME_BADGE : ITEM_TIME
|
|
87
|
+
{ classes: klasses(base) }
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def timeline_item_title_classes = { classes: klasses(ITEM_TITLE) }
|
|
91
|
+
def timeline_item_heading_classes = { classes: klasses(ITEM_HEADING) }
|
|
92
|
+
def timeline_item_trigger_classes = { classes: klasses(ITEM_TRIGGER) }
|
|
93
|
+
def timeline_item_description_classes = { classes: klasses(ITEM_DESCRIPTION) }
|
|
94
|
+
def timeline_item_detail_classes = { classes: klasses(ITEM_DETAIL) }
|
|
95
|
+
def timeline_item_actions_classes = { classes: klasses(ITEM_ACTIONS) }
|
|
96
|
+
def timeline_item_indicator_dot_classes = { classes: klasses(ITEM_INDICATOR_DOT_MARK) }
|
|
97
|
+
def timeline_item_connector_classes = { classes: klasses(ITEM_CONNECTOR_HORIZONTAL) }
|
|
98
|
+
def timeline_item_content_classes = { classes: klasses(ITEM_CONTENT_HORIZONTAL) }
|
|
99
|
+
def timeline_track_line_classes = { classes: klasses(TRACK_LINE_VERTICAL) }
|
|
100
|
+
def timeline_item_indicator_icon_slot_classes = { classes: klasses(ITEM_INDICATOR_ICON_SLOT) }
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
@@ -14,6 +14,7 @@ require_relative "tailwind/form/input"
|
|
|
14
14
|
require_relative "tailwind/icon"
|
|
15
15
|
require_relative "tailwind/layout"
|
|
16
16
|
require_relative "tailwind/link"
|
|
17
|
+
require_relative "tailwind/timeline"
|
|
17
18
|
|
|
18
19
|
module StimulusPlumbers
|
|
19
20
|
module Themes
|
|
@@ -31,6 +32,8 @@ module StimulusPlumbers
|
|
|
31
32
|
include Tailwind::Icon
|
|
32
33
|
include Tailwind::Layout
|
|
33
34
|
include Tailwind::Link
|
|
35
|
+
include Tailwind::Timeline
|
|
36
|
+
include Tailwind::Timeline::Group
|
|
34
37
|
|
|
35
38
|
private
|
|
36
39
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: stimulus_plumbers_tailwind
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ryan Chang
|
|
@@ -698,6 +698,8 @@ files:
|
|
|
698
698
|
- lib/stimulus_plumbers/themes/tailwind/layout.rb
|
|
699
699
|
- lib/stimulus_plumbers/themes/tailwind/link.rb
|
|
700
700
|
- lib/stimulus_plumbers/themes/tailwind/list.rb
|
|
701
|
+
- lib/stimulus_plumbers/themes/tailwind/timeline.rb
|
|
702
|
+
- lib/stimulus_plumbers/themes/tailwind/timeline/group.rb
|
|
701
703
|
- lib/stimulus_plumbers/themes/tailwind_theme.rb
|
|
702
704
|
- lib/stimulus_plumbers_tailwind.rb
|
|
703
705
|
- lib/stimulus_plumbers_tailwind/engine.rb
|