@ryanhelsing/ry-ui 1.0.3 → 1.0.4

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.
@@ -42,7 +42,7 @@ ry {
42
42
  ry-page, ry-header, ry-main, ry-footer, ry-section, ry-aside,
43
43
  ry-grid, ry-stack, ry-cluster, ry-split, ry-center,
44
44
  ry-card, ry-accordion, ry-modal, ry-tabs, ry-dropdown,
45
- ry-button, ry-badge, ry-alert, ry-field, ry-nav, ry-logo, ry-actions,
45
+ ry-button, ry-button-group, ry-badge, ry-alert, ry-field, ry-nav, ry-logo, ry-actions,
46
46
  ry-accordion-item, ry-tab, ry-menu, ry-menu-item, ry-divider,
47
47
  ry-theme-toggle, ry-select, ry-switch, ry-tooltip, ry-drawer, ry-toast,
48
48
  ry-toggle-button, ry-knob, ry-slider, ry-number-select, ry-color-picker, ry-color-input,
@@ -180,6 +180,16 @@ ry-grid[cols="4"] { grid-template-columns: repeat(4, 1fr); }
180
180
  ry-grid[cols="5"] { grid-template-columns: repeat(5, 1fr); }
181
181
  ry-grid[cols="6"] { grid-template-columns: repeat(6, 1fr); }
182
182
 
183
+ /* Auto-fit mode: fluid columns based on min-width */
184
+ ry-grid[cols="auto-fit"] {
185
+ grid-template-columns: repeat(auto-fit, minmax(var(--ry-grid-min, 280px), 1fr));
186
+ }
187
+
188
+ ry-grid[cols="auto-fill"] {
189
+ grid-template-columns: repeat(auto-fill, minmax(var(--ry-grid-min, 280px), 1fr));
190
+ }
191
+
192
+ /* Default responsive behavior */
183
193
  @container (max-width: 640px) {
184
194
  :is(ry-grid[cols="2"], ry-grid[cols="3"], ry-grid[cols="4"],
185
195
  ry-grid[cols="5"], ry-grid[cols="6"]) {
@@ -194,6 +204,28 @@ ry-grid[cols="6"] { grid-template-columns: repeat(6, 1fr); }
194
204
  }
195
205
  }
196
206
 
207
+ /* Per-breakpoint column overrides: cols-sm, cols-md, cols-lg */
208
+ @container (max-width: 640px) {
209
+ ry-grid[cols-sm="1"] { grid-template-columns: 1fr; }
210
+ ry-grid[cols-sm="2"] { grid-template-columns: repeat(2, 1fr); }
211
+ ry-grid[cols-sm="3"] { grid-template-columns: repeat(3, 1fr); }
212
+ }
213
+
214
+ @container (min-width: 641px) and (max-width: 1024px) {
215
+ ry-grid[cols-md="1"] { grid-template-columns: 1fr; }
216
+ ry-grid[cols-md="2"] { grid-template-columns: repeat(2, 1fr); }
217
+ ry-grid[cols-md="3"] { grid-template-columns: repeat(3, 1fr); }
218
+ ry-grid[cols-md="4"] { grid-template-columns: repeat(4, 1fr); }
219
+ }
220
+
221
+ @container (min-width: 1025px) {
222
+ ry-grid[cols-lg="2"] { grid-template-columns: repeat(2, 1fr); }
223
+ ry-grid[cols-lg="3"] { grid-template-columns: repeat(3, 1fr); }
224
+ ry-grid[cols-lg="4"] { grid-template-columns: repeat(4, 1fr); }
225
+ ry-grid[cols-lg="5"] { grid-template-columns: repeat(5, 1fr); }
226
+ ry-grid[cols-lg="6"] { grid-template-columns: repeat(6, 1fr); }
227
+ }
228
+
197
229
  /* ═══════════════════════════════════════════════════════════════
198
230
  STACK (vertical)
199
231
  ═══════════════════════════════════════════════════════════════ */
@@ -239,7 +271,46 @@ ry-split > :first-child {
239
271
 
240
272
  ry-split > :last-child {
241
273
  flex-shrink: 0;
242
- width: 300px;
274
+ width: var(--ry-split-width, 300px);
275
+ min-width: var(--ry-split-min-width, 0);
276
+ }
277
+
278
+ /* Resize handle */
279
+ ry-split [data-ry-target="handle"] {
280
+ flex-shrink: 0;
281
+ width: 8px;
282
+ margin-inline: -4px;
283
+ cursor: col-resize;
284
+ position: relative;
285
+ z-index: 1;
286
+ touch-action: none;
287
+ }
288
+
289
+ /* Larger hit area via pseudo-element */
290
+ ry-split [data-ry-target="handle"]::before {
291
+ content: '';
292
+ position: absolute;
293
+ inset-block: 0;
294
+ inset-inline: -4px;
295
+ }
296
+
297
+ /* Visible drag indicator */
298
+ ry-split [data-ry-target="handle"]::after {
299
+ content: '';
300
+ position: absolute;
301
+ inset-block-start: 50%;
302
+ inset-inline-start: 50%;
303
+ width: 4px;
304
+ height: 32px;
305
+ transform: translate(-50%, -50%);
306
+ border-radius: 2px;
307
+ opacity: 0;
308
+ transition: opacity var(--ry-duration-fast, 100ms);
309
+ }
310
+
311
+ ry-split [data-ry-target="handle"]:hover::after,
312
+ ry-split[data-ry-resizing] [data-ry-target="handle"]::after {
313
+ opacity: 1;
243
314
  }
244
315
 
245
316
  @container (max-width: 768px) {
@@ -249,6 +320,9 @@ ry-split > :last-child {
249
320
  ry-split > :last-child {
250
321
  width: 100%;
251
322
  }
323
+ ry-split [data-ry-target="handle"] {
324
+ display: none;
325
+ }
252
326
  }
253
327
 
254
328
  /* ═══════════════════════════════════════════════════════════════
@@ -344,6 +418,37 @@ ry-button[size="lg"] {
344
418
  padding: var(--ry-space-3, 0.75rem) var(--ry-space-6, 1.5rem);
345
419
  }
346
420
 
421
+ /* Icon-only button */
422
+ ry-button[icon]:empty {
423
+ padding: var(--ry-space-2, 0.5rem);
424
+ }
425
+
426
+ ry-button[icon][size="sm"]:empty {
427
+ padding: var(--ry-space-1, 0.25rem);
428
+ }
429
+
430
+ /* ═══════════════════════════════════════════════════════════════
431
+ BUTTON GROUP
432
+ ═══════════════════════════════════════════════════════════════ */
433
+
434
+ ry-button-group {
435
+ display: inline-flex;
436
+ }
437
+
438
+ ry-button-group > :is(ry-button, ry-toggle-button) {
439
+ border-radius: 0;
440
+ }
441
+
442
+ ry-button-group > :is(ry-button, ry-toggle-button):first-child {
443
+ border-start-start-radius: var(--ry-radius-md, 0.375rem);
444
+ border-end-start-radius: var(--ry-radius-md, 0.375rem);
445
+ }
446
+
447
+ ry-button-group > :is(ry-button, ry-toggle-button):last-child {
448
+ border-start-end-radius: var(--ry-radius-md, 0.375rem);
449
+ border-end-end-radius: var(--ry-radius-md, 0.375rem);
450
+ }
451
+
347
452
  /* ═══════════════════════════════════════════════════════════════
348
453
  TOGGLE BUTTON
349
454
  ═══════════════════════════════════════════════════════════════ */
@@ -786,6 +891,19 @@ ry-field {
786
891
  margin-block-end: var(--ry-space-4, 1rem);
787
892
  }
788
893
 
894
+ ry-field [data-ry-target="error"]:empty,
895
+ ry-field [data-ry-target="hint"]:empty {
896
+ display: none;
897
+ }
898
+
899
+ ry-field [data-ry-target="error"]:not(:empty) ~ [data-ry-target="hint"] {
900
+ display: none;
901
+ }
902
+
903
+ ry-field :is([data-ry-target="error"], [data-ry-target="hint"]) {
904
+ margin-block-start: var(--ry-space-1, 0.25rem);
905
+ }
906
+
789
907
  /* ═══════════════════════════════════════════════════════════════
790
908
  ACCORDION
791
909
  ═══════════════════════════════════════════════════════════════ */
@@ -118,6 +118,28 @@ ry-divider {
118
118
  background-color: var(--ry-color-border);
119
119
  }
120
120
 
121
+ /* ═══════════════════════════════════════════════════════════════
122
+ SPLIT HANDLE
123
+ ═══════════════════════════════════════════════════════════════ */
124
+
125
+ ry-split [data-ry-target="handle"]::after {
126
+ background-color: var(--ry-color-border-strong);
127
+ }
128
+
129
+ ry-split[data-ry-resizing] [data-ry-target="handle"]::after {
130
+ background-color: var(--ry-color-primary);
131
+ }
132
+
133
+ ry-split [data-ry-target="handle"]:focus-visible {
134
+ outline: none;
135
+ }
136
+
137
+ ry-split [data-ry-target="handle"]:focus-visible::after {
138
+ opacity: 1;
139
+ background-color: var(--ry-color-primary);
140
+ box-shadow: var(--ry-focus-ring);
141
+ }
142
+
121
143
  /* ═══════════════════════════════════════════════════════════════
122
144
  BUTTONS
123
145
  ═══════════════════════════════════════════════════════════════ */
@@ -184,6 +206,47 @@ ry-divider {
184
206
  background-color: var(--ry-color-danger-hover);
185
207
  }
186
208
 
209
+ :is(.ry-btn--accent, ry-button[variant="accent"]) {
210
+ background-color: var(--ry-color-accent);
211
+ }
212
+ :is(.ry-btn--accent, ry-button[variant="accent"]):hover {
213
+ background-color: var(--ry-color-accent-hover);
214
+ }
215
+
216
+ /* Pressed/active toggle state */
217
+ :is(.ry-btn[aria-pressed="true"], ry-button[pressed]) {
218
+ background-color: var(--ry-color-primary);
219
+ color: var(--ry-color-text-inverse);
220
+ border-color: var(--ry-color-primary);
221
+ }
222
+ :is(.ry-btn[aria-pressed="true"], ry-button[pressed]):hover {
223
+ background-color: var(--ry-color-primary-hover);
224
+ border-color: var(--ry-color-primary-hover);
225
+ }
226
+
227
+ /* ═══════════════════════════════════════════════════════════════
228
+ BUTTON GROUP
229
+ ═══════════════════════════════════════════════════════════════ */
230
+
231
+ ry-button-group > :is(ry-button, ry-toggle-button) {
232
+ border-color: var(--ry-color-border);
233
+ }
234
+
235
+ ry-button-group > :is(ry-button, ry-toggle-button):not(:first-child) {
236
+ border-inline-start-color: transparent;
237
+ }
238
+
239
+ /* Default children to outline style for segmented look */
240
+ ry-button-group:not([variant]) > :is(ry-button, ry-toggle-button):not([pressed]) {
241
+ background-color: var(--ry-color-bg);
242
+ color: var(--ry-color-text);
243
+ border-color: var(--ry-color-border);
244
+ }
245
+
246
+ ry-button-group:not([variant]) > :is(ry-button, ry-toggle-button):not([pressed]):hover {
247
+ background-color: var(--ry-color-bg-muted);
248
+ }
249
+
187
250
  /* Button sizes (typography only - padding is structural) */
188
251
  :is(.ry-btn--sm, ry-button[size="sm"]) {
189
252
  font-size: var(--ry-text-xs);
@@ -660,6 +723,17 @@ ry-card p {
660
723
  color: var(--ry-color-text-inverse);
661
724
  }
662
725
 
726
+ :is(.ry-badge--accent, ry-badge[variant="accent"]) {
727
+ background-color: var(--ry-color-accent);
728
+ color: var(--ry-color-text-inverse);
729
+ }
730
+
731
+ /* Arbitrary color via style="--ry-badge-color: ..." */
732
+ ry-badge[style*="--ry-badge-color"] {
733
+ background-color: var(--ry-badge-color);
734
+ color: var(--ry-badge-text, var(--ry-color-text-inverse));
735
+ }
736
+
663
737
  /* ═══════════════════════════════════════════════════════════════
664
738
  ALERTS
665
739
  ═══════════════════════════════════════════════════════════════ */
@@ -741,6 +815,25 @@ ry-card p {
741
815
  color: var(--ry-color-text);
742
816
  }
743
817
 
818
+ .ry-field__error {
819
+ font-size: var(--ry-text-sm);
820
+ color: var(--ry-color-danger);
821
+ }
822
+
823
+ .ry-field__hint {
824
+ font-size: var(--ry-text-sm);
825
+ color: var(--ry-color-text-muted);
826
+ }
827
+
828
+ /* Error state on input */
829
+ ry-field:has([data-ry-target="error"]:not(:empty)) :is(input, textarea, select) {
830
+ border-color: var(--ry-color-danger);
831
+ }
832
+
833
+ ry-field:has([data-ry-target="error"]:not(:empty)) :is(input, textarea, select):focus {
834
+ box-shadow: 0 0 0 3px light-dark(oklch(0.637 0.208 25.3 / 0.3), oklch(0.637 0.208 25.3 / 0.3));
835
+ }
836
+
744
837
  /* ═══════════════════════════════════════════════════════════════
745
838
  ACCORDION
746
839
  ═══════════════════════════════════════════════════════════════ */
@@ -1909,6 +2002,13 @@ ry-tag[disabled] {
1909
2002
  font-size: var(--ry-text-sm);
1910
2003
  color: var(--ry-color-text);
1911
2004
  background: transparent;
2005
+ border: none;
2006
+ }
2007
+
2008
+ .ry-tag-input__input:focus,
2009
+ .ry-tag-input__input:focus-visible {
2010
+ outline: none;
2011
+ box-shadow: none;
1912
2012
  }
1913
2013
 
1914
2014
  .ry-tag-input__input::placeholder {
@@ -2071,4 +2171,29 @@ ry-pricing-card ul li:last-child {
2071
2171
  background-color: var(--ry-color-primary-hover);
2072
2172
  }
2073
2173
 
2174
+ /* ═══════════════════════════════════════════════════════════════
2175
+ CHECK LIST
2176
+ ═══════════════════════════════════════════════════════════════ */
2177
+
2178
+ .ry-check-list {
2179
+ list-style: none;
2180
+ padding: 0;
2181
+ margin: 0;
2182
+ }
2183
+
2184
+ .ry-check-list li {
2185
+ padding-inline-start: var(--ry-space-6);
2186
+ position: relative;
2187
+ margin-block-end: var(--ry-space-2);
2188
+ color: var(--ry-color-text);
2189
+ }
2190
+
2191
+ .ry-check-list li::before {
2192
+ content: '\2713';
2193
+ position: absolute;
2194
+ inset-inline-start: 0;
2195
+ color: var(--ry-color-success);
2196
+ font-weight: var(--ry-font-bold);
2197
+ }
2198
+
2074
2199
  } /* @layer ry-theme */
@@ -17,6 +17,9 @@
17
17
  @property --ry-color-secondary { syntax: "<color>"; inherits: true; initial-value: oklch(0.554 0.041 257.4); }
18
18
  @property --ry-color-secondary-hover { syntax: "<color>"; inherits: true; initial-value: oklch(0.446 0.037 257.3); }
19
19
  @property --ry-color-secondary-active { syntax: "<color>"; inherits: true; initial-value: oklch(0.372 0.039 257.3); }
20
+ @property --ry-color-accent { syntax: "<color>"; inherits: true; initial-value: oklch(0.627 0.213 303.9); }
21
+ @property --ry-color-accent-hover { syntax: "<color>"; inherits: true; initial-value: oklch(0.557 0.213 303.9); }
22
+ @property --ry-color-accent-active { syntax: "<color>"; inherits: true; initial-value: oklch(0.497 0.213 303.9); }
20
23
  @property --ry-color-success { syntax: "<color>"; inherits: true; initial-value: oklch(0.723 0.192 149.6); }
21
24
  @property --ry-color-warning { syntax: "<color>"; inherits: true; initial-value: oklch(0.769 0.165 70.1); }
22
25
  @property --ry-color-danger { syntax: "<color>"; inherits: true; initial-value: oklch(0.637 0.208 25.3); }
@@ -64,6 +67,11 @@
64
67
  --ry-color-secondary-hover: light-dark(oklch(0.446 0.037 257.3), oklch(0.869 0.02 252.9));
65
68
  --ry-color-secondary-active: light-dark(oklch(0.372 0.039 257.3), oklch(0.929 0.013 255.6));
66
69
 
70
+ /* Accent */
71
+ --ry-color-accent: light-dark(oklch(0.627 0.213 303.9), oklch(0.714 0.183 303.9));
72
+ --ry-color-accent-hover: light-dark(oklch(0.557 0.213 303.9), oklch(0.627 0.213 303.9));
73
+ --ry-color-accent-active: light-dark(oklch(0.497 0.213 303.9), oklch(0.557 0.213 303.9));
74
+
67
75
  /* Semantic */
68
76
  --ry-color-success: oklch(0.723 0.192 149.6);
69
77
  --ry-color-warning: oklch(0.769 0.165 70.1);