stimulus_plumbers_tailwind 0.4.0 → 0.4.3

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.
@@ -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 peer-placeholder-shown:translate-y-0
50
- peer-focus:scale-75 peer-focus:-translate-y-(--sp-space-4)
51
- rtl:peer-focus:translate-x-1/4 rtl:peer-focus:left-auto
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 peer-placeholder-shown:-translate-y-1/2 peer-placeholder-shown:top-1/2
57
- peer-focus:top-(--sp-space-2) peer-focus:scale-75 peer-focus:-translate-y-(--sp-space-4)
58
- rtl:peer-focus:translate-x-1/4 rtl:peer-focus:left-auto
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 peer-placeholder-shown:translate-y-0
64
- peer-focus:scale-75 peer-focus:-translate-y-(--sp-space-6)
65
- rtl:peer-focus:translate-x-1/4 rtl:peer-focus:left-auto
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-start flex-1 p-(--sp-space-4) cursor-pointer select-none
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
- peer-checked:border-(--card-ring) peer-checked:bg-(--card-ring)/10
101
- peer-checked:text-(--sp-color-fg) peer-checked:hover:bg-(--card-ring)/15
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
- peer-checked:border-(--card-ring) peer-checked:bg-(--card-ring)/10
109
- peer-checked:text-(--sp-color-fg) peer-checked:hover:bg-(--card-ring)/15
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 form_field_floating_classes(type: nil, error: false)
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 form_field_floating_label_classes(type: nil, error: false)
135
- color = error ? FLOATING_LABEL_ERROR : FLOATING_LABEL_FOCUS
136
- { classes: klasses(*FLOATING_LABEL_BASE, *FLOATING_LABEL_TYPES.fetch(type, []), *color) }
137
- end
138
-
139
- def form_field_label_classes(hidden: false, **)
140
- { classes: klasses(*LABEL, hidden ? "sr-only" : nil) }
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) text-(length:--sp-text-sm)
10
- text-(--sp-color-fg) bg-(--sp-color-bg) focus:outline-none focus:ring-2 focus:ring-offset-0
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-2 focus:ring-(--sp-focus-ring-color) focus:outline-none
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-2 focus:ring-(--sp-focus-ring-color) focus:outline-none
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-2 focus:ring-(--card-ring) focus:outline-none
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-2 focus:ring-(--sp-focus-ring-color) focus:outline-none
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 peer].freeze,
45
- card: %w[hidden peer].freeze
111
+ button: %w[hidden].freeze,
112
+ card: %w[hidden].freeze
46
113
  }.freeze
47
114
 
48
- INPUT_GROUP_BASE = %w[flex items-center overflow-hidden rounded-(--sp-radius-md) border].freeze
49
- INPUT_GROUP_BORDER = { error: "border-(--sp-color-error)", default: "border-(--sp-color-muted-fg)" }.freeze
50
-
51
- COMBOBOX_INPUT = %w[
52
- [&>input:not([type=hidden])]:border-0
53
- [&>input:not([type=hidden])]:rounded-none
54
- [&>input:not([type=hidden])]:px-0
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 = %w[
73
- self-stretch border-0 bg-transparent px-(--sp-space-2) cursor-pointer text-(--sp-color-muted-fg)
74
- hover:text-(--sp-color-fg) text-(length:--sp-text-sm)
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
- { classes: klasses(*INPUT_BASE, *(error ? INPUT_ERROR : INPUT_DEFAULT)) }
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
- { classes: klasses(*INPUT_GROUP_BASE, INPUT_GROUP_BORDER[error ? :error : :default]) }
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
- { classes: klasses(
111
- *INPUT_BASE,
112
- *(error ? INPUT_ERROR : INPUT_DEFAULT),
113
- *COMBOBOX_INPUT,
114
- *COMBOBOX_TRIGGER_GROUP
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(type: :default, variant: :primary)
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-default)" }
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
- DIVIDER_SEPARATOR = %w[border-t border-(--sp-color-border) my-(--sp-space-1)].freeze
8
- DIVIDER = %w[flex items-center gap-(--sp-space-3)].freeze
9
- DIVIDER_LABEL = %w[text-(length:--sp-text-sm) text-(--sp-color-fg-muted) whitespace-nowrap font-medium].freeze
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
- VARIANTS = {
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-control-size)", "stroke-current") }
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) divide-y divide-(--sp-color-border)") }
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-control-size)", "stroke-current") }
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