@ryanhelsing/ry-ui 1.0.5 → 1.0.6

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.
package/AGENT.md CHANGED
@@ -66,6 +66,7 @@ Wrap markup in `<ry>` to use unprefixed tags:
66
66
  | `<ry-tabs>` | — | Container. Children: `<ry-tab title="...">content</ry-tab>` |
67
67
  | `<ry-dropdown>` | — | Dropdown trigger + menu |
68
68
  | `<ry-select>` | `placeholder`, `name`, `value`, `disabled` | `ry:change` `{value}`. Children: `<ry-option value="...">` |
69
+ | `<ry-combobox>` | `placeholder`, `name`, `value`, `disabled` | `ry:change` `{value, label}`, `ry:input` `{value}`. Searchable dropdown — type to filter. Children: `<ry-option value="...">` |
69
70
  | `<ry-switch>` | `checked`, `disabled`, `name` | `ry:change` `{checked}` |
70
71
  | `<ry-tooltip>` | `content`, `position` | Hover tooltip |
71
72
  | `<ry-toast>` | — | Programmatic: `RyToast.success('msg')`, `.error()`, `.warning()`, `.info()` |
package/README.md CHANGED
@@ -12,6 +12,16 @@ ry-ui normalizes this. No decisions to make. No architecture to debate. An LLM c
12
12
 
13
13
  **The goal:** Write once in HTML/CSS/JS. Deploy to web, iOS, Android, desktop. The primitives are portable because they're universal.
14
14
 
15
+ ### FUNCTION / FORM / THEME
16
+
17
+ Every component is three independent layers:
18
+
19
+ - **FUNCTION** (JS) — Behavior. Extends `RyElement`. Manages state, events, keyboard, ARIA. Queries via `data-ry-target`.
20
+ - **FORM** (Structure CSS) — Layout. `ry-structure.css`. Display, flex, grid, padding, overflow, transform/opacity transitions. No colors.
21
+ - **THEME** (Visual CSS) — Appearance. `ry-theme.css`. Colors, shadows, borders, typography, focus rings. Entirely swappable.
22
+
23
+ These layers are independently replaceable. Structure works with any theme or no theme. Function works regardless of CSS loaded.
24
+
15
25
  ---
16
26
 
17
27
  - [x] separate the css minimal structure from the theme
@@ -66,6 +76,7 @@ ry-ui normalizes this. No decisions to make. No architecture to debate. An LLM c
66
76
  - `<ry-tabs>` - Tabbed content
67
77
  - `<ry-dropdown>` - Dropdown menus
68
78
  - `<ry-select>` - Custom select
79
+ - `<ry-combobox>` - Searchable dropdown
69
80
  - `<ry-switch>` - Toggle switch
70
81
  - `<ry-tooltip>` - Hover tooltips
71
82
  - `<ry-toast>` - Notifications
@@ -0,0 +1,25 @@
1
+ /**
2
+ * <ry-combobox>
3
+ *
4
+ * Searchable dropdown with text input filtering.
5
+ *
6
+ * Usage:
7
+ * <ry-combobox placeholder="Search countries..." name="country">
8
+ * <ry-option value="us">United States</ry-option>
9
+ * <ry-option value="uk">United Kingdom</ry-option>
10
+ * </ry-combobox>
11
+ *
12
+ * JS uses data-ry-target for queries, CSS uses classes for styling.
13
+ */
14
+ import { RyElement } from '../core/ry-element.js';
15
+ export declare class RyCombobox extends RyElement {
16
+ #private;
17
+ static observedAttributes: readonly ["value", "disabled"];
18
+ setup(): void;
19
+ open(): void;
20
+ close(): void;
21
+ toggle(): void;
22
+ get value(): string;
23
+ set value(val: string);
24
+ }
25
+ //# sourceMappingURL=ry-combobox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ry-combobox.d.ts","sourceRoot":"","sources":["../../src/ts/components/ry-combobox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAKlD,qBAAa,UAAW,SAAQ,SAAS;;IAKvC,MAAM,CAAC,kBAAkB,iCAAkC;IAE3D,KAAK,IAAI,IAAI;IAmSb,IAAI,IAAI,IAAI;IAsCZ,KAAK,IAAI,IAAI;IAmBb,MAAM,IAAI,IAAI;IAQd,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,IAAI,KAAK,CAAC,GAAG,EAAE,MAAM,EAKpB;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"ry-transform.d.ts","sourceRoot":"","sources":["../../src/ts/core/ry-transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAsDH;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAgBxC"}
1
+ {"version":3,"file":"ry-transform.d.ts","sourceRoot":"","sources":["../../src/ts/core/ry-transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAuDH;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAgBxC"}
@@ -48,7 +48,7 @@ ry {
48
48
  ry-toggle-button, ry-knob, ry-slider, ry-number-select, ry-color-picker, ry-color-input,
49
49
  ry-gradient-picker, ry-tree, ry-tree-item,
50
50
  ry-tag, ry-tag-input, ry-hero, ry-stat, ry-feature, ry-feature-grid,
51
- ry-pricing, ry-pricing-card, ry-carousel) {
51
+ ry-pricing, ry-pricing-card, ry-carousel, ry-combobox) {
52
52
  box-sizing: border-box;
53
53
  }
54
54
 
@@ -433,20 +433,13 @@ ry-button[icon][size="sm"]:empty {
433
433
 
434
434
  ry-button-group {
435
435
  display: inline-flex;
436
+ gap: 2px;
437
+ padding: 2px;
438
+ border-radius: var(--ry-radius-md, 0.375rem);
436
439
  }
437
440
 
438
441
  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);
442
+ border-radius: calc(var(--ry-radius-md, 0.375rem) - 2px);
450
443
  }
451
444
 
452
445
  /* ═══════════════════════════════════════════════════════════════
@@ -2824,4 +2817,124 @@ ry-carousel [data-ry-target="dot"] {
2824
2817
  cursor: pointer;
2825
2818
  }
2826
2819
 
2820
+ /* ═══════════════════════════════════════════════════════════════
2821
+ COMBOBOX
2822
+ ═══════════════════════════════════════════════════════════════ */
2823
+
2824
+ ry-combobox {
2825
+ position: relative;
2826
+ display: inline-block;
2827
+ min-width: 12rem;
2828
+ }
2829
+
2830
+ ry-combobox[disabled] {
2831
+ cursor: not-allowed;
2832
+ }
2833
+
2834
+ ry-combobox [data-ry-target="input-wrapper"] {
2835
+ display: flex;
2836
+ align-items: center;
2837
+ gap: var(--ry-space-2, 0.5rem);
2838
+ width: 100%;
2839
+ }
2840
+
2841
+ ry-combobox [data-ry-target="input"] {
2842
+ flex: 1;
2843
+ width: 100%;
2844
+ min-width: 0;
2845
+ padding: var(--ry-space-2, 0.5rem) var(--ry-space-3, 0.75rem);
2846
+ border: none;
2847
+ outline: none;
2848
+ background: transparent;
2849
+ }
2850
+
2851
+ ry-combobox [data-ry-target="arrow"] {
2852
+ flex-shrink: 0;
2853
+ padding-inline-end: var(--ry-space-2, 0.5rem);
2854
+ cursor: pointer;
2855
+ transition: transform var(--ry-duration-fast, 100ms) var(--ry-ease, ease);
2856
+ }
2857
+
2858
+ ry-combobox[data-ry-state="open"] [data-ry-target="arrow"] {
2859
+ transform: rotate(180deg);
2860
+ }
2861
+
2862
+ ry-combobox [data-ry-target="dropdown"] {
2863
+ position: absolute;
2864
+ top: 100%;
2865
+ left: 0;
2866
+ right: 0;
2867
+ z-index: var(--ry-z-dropdown, 1000);
2868
+ margin-block-start: var(--ry-space-1, 0.25rem);
2869
+ padding: var(--ry-space-1, 0.25rem);
2870
+ max-height: 15rem;
2871
+ overflow-y: auto;
2872
+ overscroll-behavior: contain;
2873
+ opacity: 0;
2874
+ visibility: hidden;
2875
+ transform: translateY(-0.5rem);
2876
+ transition: opacity var(--ry-duration-fast, 100ms) var(--ry-ease, ease),
2877
+ visibility var(--ry-duration-fast, 100ms) var(--ry-ease, ease),
2878
+ transform var(--ry-duration-fast, 100ms) var(--ry-ease, ease);
2879
+ transition-behavior: allow-discrete;
2880
+ }
2881
+
2882
+ ry-combobox[data-ry-state="open"] [data-ry-target="dropdown"] {
2883
+ opacity: 1;
2884
+ visibility: visible;
2885
+ transform: translateY(0);
2886
+ }
2887
+
2888
+ @starting-style {
2889
+ ry-combobox[data-ry-state="open"] [data-ry-target="dropdown"] {
2890
+ opacity: 0;
2891
+ transform: translateY(-0.5rem);
2892
+ }
2893
+ }
2894
+
2895
+ ry-combobox[data-ry-position="top"] [data-ry-target="dropdown"] {
2896
+ top: auto;
2897
+ bottom: 100%;
2898
+ margin-block-start: 0;
2899
+ margin-block-end: var(--ry-space-1, 0.25rem);
2900
+ transform: translateY(0.5rem);
2901
+ }
2902
+
2903
+ ry-combobox[data-ry-position="top"][data-ry-state="open"] [data-ry-target="dropdown"] {
2904
+ transform: translateY(0);
2905
+ }
2906
+
2907
+ ry-combobox [data-ry-target="option"] {
2908
+ padding: var(--ry-space-2, 0.5rem) var(--ry-space-3, 0.75rem);
2909
+ cursor: pointer;
2910
+ }
2911
+
2912
+ ry-combobox [data-ry-target="option"][hidden] {
2913
+ display: none;
2914
+ }
2915
+
2916
+ ry-combobox [data-ry-target="option"][data-disabled] {
2917
+ cursor: not-allowed;
2918
+ }
2919
+
2920
+ ry-combobox [data-ry-target="empty"] {
2921
+ padding: var(--ry-space-3, 0.75rem);
2922
+ text-align: center;
2923
+ }
2924
+
2925
+ ry-combobox [data-ry-target="empty"][hidden] {
2926
+ display: none;
2927
+ }
2928
+
2929
+ ry-combobox [data-ry-target="native"] {
2930
+ position: absolute;
2931
+ width: 1px;
2932
+ height: 1px;
2933
+ margin: -1px;
2934
+ padding: 0;
2935
+ overflow: hidden;
2936
+ clip: rect(0, 0, 0, 0);
2937
+ border: 0;
2938
+ }
2939
+
2827
2940
  } /* @layer ry-structure */
@@ -228,23 +228,18 @@ ry-split [data-ry-target="handle"]:focus-visible::after {
228
228
  BUTTON GROUP
229
229
  ═══════════════════════════════════════════════════════════════ */
230
230
 
231
- ry-button-group > :is(ry-button, ry-toggle-button) {
232
- border-color: var(--ry-color-border);
231
+ ry-button-group {
232
+ background-color: var(--ry-color-bg-muted);
233
233
  }
234
234
 
235
- ry-button-group > :is(ry-button, ry-toggle-button):not(:first-child) {
236
- border-inline-start-color: transparent;
235
+ ry-button-group > :is(ry-button, ry-toggle-button) {
236
+ border-color: transparent;
237
+ background-color: transparent;
238
+ color: var(--ry-color-text-muted);
237
239
  }
238
240
 
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);
241
+ ry-button-group > :is(ry-button, ry-toggle-button):hover:not([pressed]) {
242
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
243
  }
249
244
 
250
245
  /* Button sizes (typography only - padding is structural) */
@@ -2208,4 +2203,86 @@ ry-pricing-card ul li:last-child {
2208
2203
  font-weight: var(--ry-font-bold);
2209
2204
  }
2210
2205
 
2206
+ /* ═══════════════════════════════════════════════════════════════
2207
+ COMBOBOX
2208
+ ═══════════════════════════════════════════════════════════════ */
2209
+
2210
+ ry-combobox[disabled] {
2211
+ opacity: 0.5;
2212
+ }
2213
+
2214
+ .ry-combobox__input-wrapper {
2215
+ font-family: var(--ry-font-sans);
2216
+ font-size: var(--ry-text-base);
2217
+ line-height: var(--ry-leading-normal);
2218
+ background-color: var(--ry-color-bg);
2219
+ border: var(--ry-border-width) solid var(--ry-color-border);
2220
+ border-radius: var(--ry-radius-md);
2221
+ transition: border-color var(--ry-duration-fast) var(--ry-ease),
2222
+ box-shadow var(--ry-duration-fast) var(--ry-ease);
2223
+ }
2224
+
2225
+ ry-combobox:hover .ry-combobox__input-wrapper {
2226
+ border-color: var(--ry-color-border-strong);
2227
+ }
2228
+
2229
+ ry-combobox:focus-within .ry-combobox__input-wrapper {
2230
+ border-color: var(--ry-color-primary);
2231
+ box-shadow: var(--ry-focus-ring);
2232
+ }
2233
+
2234
+ ry-combobox[data-ry-state="open"] .ry-combobox__input-wrapper {
2235
+ border-color: var(--ry-color-primary);
2236
+ }
2237
+
2238
+ .ry-combobox__input {
2239
+ font: inherit;
2240
+ color: var(--ry-color-text);
2241
+ }
2242
+
2243
+ .ry-combobox__input::placeholder {
2244
+ color: var(--ry-color-text-muted);
2245
+ }
2246
+
2247
+ .ry-combobox__arrow {
2248
+ font-size: var(--ry-text-xs);
2249
+ color: var(--ry-color-text-muted);
2250
+ }
2251
+
2252
+ .ry-combobox__dropdown {
2253
+ background-color: var(--ry-color-bg);
2254
+ border: var(--ry-border-width) solid var(--ry-color-border);
2255
+ border-radius: var(--ry-radius-lg);
2256
+ box-shadow: var(--ry-shadow-lg);
2257
+ }
2258
+
2259
+ .ry-combobox__option {
2260
+ font-size: var(--ry-text-sm);
2261
+ color: var(--ry-color-text);
2262
+ border-radius: var(--ry-radius-md);
2263
+ transition: background-color var(--ry-duration-fast) var(--ry-ease);
2264
+ }
2265
+
2266
+ .ry-combobox__option:is(:hover, [data-highlighted]) {
2267
+ background-color: var(--ry-color-bg-muted);
2268
+ }
2269
+
2270
+ .ry-combobox__option[aria-selected="true"] {
2271
+ background-color: var(--ry-color-primary);
2272
+ color: var(--ry-color-text-inverse);
2273
+ }
2274
+
2275
+ .ry-combobox__option[data-disabled] {
2276
+ opacity: 0.5;
2277
+ }
2278
+
2279
+ .ry-combobox__option[data-disabled]:hover {
2280
+ background-color: transparent;
2281
+ }
2282
+
2283
+ .ry-combobox__empty {
2284
+ font-size: var(--ry-text-sm);
2285
+ color: var(--ry-color-text-muted);
2286
+ }
2287
+
2211
2288
  } /* @layer ry-theme */
@@ -290,7 +290,7 @@ ry {
290
290
  ry-toggle-button, ry-knob, ry-slider, ry-number-select, ry-color-picker, ry-color-input,
291
291
  ry-gradient-picker, ry-tree, ry-tree-item,
292
292
  ry-tag, ry-tag-input, ry-hero, ry-stat, ry-feature, ry-feature-grid,
293
- ry-pricing, ry-pricing-card, ry-carousel) {
293
+ ry-pricing, ry-pricing-card, ry-carousel, ry-combobox) {
294
294
  box-sizing: border-box;
295
295
  }
296
296
 
@@ -675,20 +675,13 @@ ry-button[icon][size="sm"]:empty {
675
675
 
676
676
  ry-button-group {
677
677
  display: inline-flex;
678
+ gap: 2px;
679
+ padding: 2px;
680
+ border-radius: var(--ry-radius-md, 0.375rem);
678
681
  }
679
682
 
680
683
  ry-button-group > :is(ry-button, ry-toggle-button) {
681
- border-radius: 0;
682
- }
683
-
684
- ry-button-group > :is(ry-button, ry-toggle-button):first-child {
685
- border-start-start-radius: var(--ry-radius-md, 0.375rem);
686
- border-end-start-radius: var(--ry-radius-md, 0.375rem);
687
- }
688
-
689
- ry-button-group > :is(ry-button, ry-toggle-button):last-child {
690
- border-start-end-radius: var(--ry-radius-md, 0.375rem);
691
- border-end-end-radius: var(--ry-radius-md, 0.375rem);
684
+ border-radius: calc(var(--ry-radius-md, 0.375rem) - 2px);
692
685
  }
693
686
 
694
687
  /* ═══════════════════════════════════════════════════════════════
@@ -3066,6 +3059,126 @@ ry-carousel [data-ry-target="dot"] {
3066
3059
  cursor: pointer;
3067
3060
  }
3068
3061
 
3062
+ /* ═══════════════════════════════════════════════════════════════
3063
+ COMBOBOX
3064
+ ═══════════════════════════════════════════════════════════════ */
3065
+
3066
+ ry-combobox {
3067
+ position: relative;
3068
+ display: inline-block;
3069
+ min-width: 12rem;
3070
+ }
3071
+
3072
+ ry-combobox[disabled] {
3073
+ cursor: not-allowed;
3074
+ }
3075
+
3076
+ ry-combobox [data-ry-target="input-wrapper"] {
3077
+ display: flex;
3078
+ align-items: center;
3079
+ gap: var(--ry-space-2, 0.5rem);
3080
+ width: 100%;
3081
+ }
3082
+
3083
+ ry-combobox [data-ry-target="input"] {
3084
+ flex: 1;
3085
+ width: 100%;
3086
+ min-width: 0;
3087
+ padding: var(--ry-space-2, 0.5rem) var(--ry-space-3, 0.75rem);
3088
+ border: none;
3089
+ outline: none;
3090
+ background: transparent;
3091
+ }
3092
+
3093
+ ry-combobox [data-ry-target="arrow"] {
3094
+ flex-shrink: 0;
3095
+ padding-inline-end: var(--ry-space-2, 0.5rem);
3096
+ cursor: pointer;
3097
+ transition: transform var(--ry-duration-fast, 100ms) var(--ry-ease, ease);
3098
+ }
3099
+
3100
+ ry-combobox[data-ry-state="open"] [data-ry-target="arrow"] {
3101
+ transform: rotate(180deg);
3102
+ }
3103
+
3104
+ ry-combobox [data-ry-target="dropdown"] {
3105
+ position: absolute;
3106
+ top: 100%;
3107
+ left: 0;
3108
+ right: 0;
3109
+ z-index: var(--ry-z-dropdown, 1000);
3110
+ margin-block-start: var(--ry-space-1, 0.25rem);
3111
+ padding: var(--ry-space-1, 0.25rem);
3112
+ max-height: 15rem;
3113
+ overflow-y: auto;
3114
+ overscroll-behavior: contain;
3115
+ opacity: 0;
3116
+ visibility: hidden;
3117
+ transform: translateY(-0.5rem);
3118
+ transition: opacity var(--ry-duration-fast, 100ms) var(--ry-ease, ease),
3119
+ visibility var(--ry-duration-fast, 100ms) var(--ry-ease, ease),
3120
+ transform var(--ry-duration-fast, 100ms) var(--ry-ease, ease);
3121
+ transition-behavior: allow-discrete;
3122
+ }
3123
+
3124
+ ry-combobox[data-ry-state="open"] [data-ry-target="dropdown"] {
3125
+ opacity: 1;
3126
+ visibility: visible;
3127
+ transform: translateY(0);
3128
+ }
3129
+
3130
+ @starting-style {
3131
+ ry-combobox[data-ry-state="open"] [data-ry-target="dropdown"] {
3132
+ opacity: 0;
3133
+ transform: translateY(-0.5rem);
3134
+ }
3135
+ }
3136
+
3137
+ ry-combobox[data-ry-position="top"] [data-ry-target="dropdown"] {
3138
+ top: auto;
3139
+ bottom: 100%;
3140
+ margin-block-start: 0;
3141
+ margin-block-end: var(--ry-space-1, 0.25rem);
3142
+ transform: translateY(0.5rem);
3143
+ }
3144
+
3145
+ ry-combobox[data-ry-position="top"][data-ry-state="open"] [data-ry-target="dropdown"] {
3146
+ transform: translateY(0);
3147
+ }
3148
+
3149
+ ry-combobox [data-ry-target="option"] {
3150
+ padding: var(--ry-space-2, 0.5rem) var(--ry-space-3, 0.75rem);
3151
+ cursor: pointer;
3152
+ }
3153
+
3154
+ ry-combobox [data-ry-target="option"][hidden] {
3155
+ display: none;
3156
+ }
3157
+
3158
+ ry-combobox [data-ry-target="option"][data-disabled] {
3159
+ cursor: not-allowed;
3160
+ }
3161
+
3162
+ ry-combobox [data-ry-target="empty"] {
3163
+ padding: var(--ry-space-3, 0.75rem);
3164
+ text-align: center;
3165
+ }
3166
+
3167
+ ry-combobox [data-ry-target="empty"][hidden] {
3168
+ display: none;
3169
+ }
3170
+
3171
+ ry-combobox [data-ry-target="native"] {
3172
+ position: absolute;
3173
+ width: 1px;
3174
+ height: 1px;
3175
+ margin: -1px;
3176
+ padding: 0;
3177
+ overflow: hidden;
3178
+ clip: rect(0, 0, 0, 0);
3179
+ border: 0;
3180
+ }
3181
+
3069
3182
  } /* @layer ry-structure */
3070
3183
 
3071
3184
  /**
@@ -3298,23 +3411,18 @@ ry-split [data-ry-target="handle"]:focus-visible::after {
3298
3411
  BUTTON GROUP
3299
3412
  ═══════════════════════════════════════════════════════════════ */
3300
3413
 
3301
- ry-button-group > :is(ry-button, ry-toggle-button) {
3302
- border-color: var(--ry-color-border);
3414
+ ry-button-group {
3415
+ background-color: var(--ry-color-bg-muted);
3303
3416
  }
3304
3417
 
3305
- ry-button-group > :is(ry-button, ry-toggle-button):not(:first-child) {
3306
- border-inline-start-color: transparent;
3418
+ ry-button-group > :is(ry-button, ry-toggle-button) {
3419
+ border-color: transparent;
3420
+ background-color: transparent;
3421
+ color: var(--ry-color-text-muted);
3307
3422
  }
3308
3423
 
3309
- /* Default children to outline style for segmented look */
3310
- ry-button-group:not([variant]) > :is(ry-button, ry-toggle-button):not([pressed]) {
3311
- background-color: var(--ry-color-bg);
3424
+ ry-button-group > :is(ry-button, ry-toggle-button):hover:not([pressed]) {
3312
3425
  color: var(--ry-color-text);
3313
- border-color: var(--ry-color-border);
3314
- }
3315
-
3316
- ry-button-group:not([variant]) > :is(ry-button, ry-toggle-button):not([pressed]):hover {
3317
- background-color: var(--ry-color-bg-muted);
3318
3426
  }
3319
3427
 
3320
3428
  /* Button sizes (typography only - padding is structural) */
@@ -5278,4 +5386,86 @@ ry-pricing-card ul li:last-child {
5278
5386
  font-weight: var(--ry-font-bold);
5279
5387
  }
5280
5388
 
5389
+ /* ═══════════════════════════════════════════════════════════════
5390
+ COMBOBOX
5391
+ ═══════════════════════════════════════════════════════════════ */
5392
+
5393
+ ry-combobox[disabled] {
5394
+ opacity: 0.5;
5395
+ }
5396
+
5397
+ .ry-combobox__input-wrapper {
5398
+ font-family: var(--ry-font-sans);
5399
+ font-size: var(--ry-text-base);
5400
+ line-height: var(--ry-leading-normal);
5401
+ background-color: var(--ry-color-bg);
5402
+ border: var(--ry-border-width) solid var(--ry-color-border);
5403
+ border-radius: var(--ry-radius-md);
5404
+ transition: border-color var(--ry-duration-fast) var(--ry-ease),
5405
+ box-shadow var(--ry-duration-fast) var(--ry-ease);
5406
+ }
5407
+
5408
+ ry-combobox:hover .ry-combobox__input-wrapper {
5409
+ border-color: var(--ry-color-border-strong);
5410
+ }
5411
+
5412
+ ry-combobox:focus-within .ry-combobox__input-wrapper {
5413
+ border-color: var(--ry-color-primary);
5414
+ box-shadow: var(--ry-focus-ring);
5415
+ }
5416
+
5417
+ ry-combobox[data-ry-state="open"] .ry-combobox__input-wrapper {
5418
+ border-color: var(--ry-color-primary);
5419
+ }
5420
+
5421
+ .ry-combobox__input {
5422
+ font: inherit;
5423
+ color: var(--ry-color-text);
5424
+ }
5425
+
5426
+ .ry-combobox__input::placeholder {
5427
+ color: var(--ry-color-text-muted);
5428
+ }
5429
+
5430
+ .ry-combobox__arrow {
5431
+ font-size: var(--ry-text-xs);
5432
+ color: var(--ry-color-text-muted);
5433
+ }
5434
+
5435
+ .ry-combobox__dropdown {
5436
+ background-color: var(--ry-color-bg);
5437
+ border: var(--ry-border-width) solid var(--ry-color-border);
5438
+ border-radius: var(--ry-radius-lg);
5439
+ box-shadow: var(--ry-shadow-lg);
5440
+ }
5441
+
5442
+ .ry-combobox__option {
5443
+ font-size: var(--ry-text-sm);
5444
+ color: var(--ry-color-text);
5445
+ border-radius: var(--ry-radius-md);
5446
+ transition: background-color var(--ry-duration-fast) var(--ry-ease);
5447
+ }
5448
+
5449
+ .ry-combobox__option:is(:hover, [data-highlighted]) {
5450
+ background-color: var(--ry-color-bg-muted);
5451
+ }
5452
+
5453
+ .ry-combobox__option[aria-selected="true"] {
5454
+ background-color: var(--ry-color-primary);
5455
+ color: var(--ry-color-text-inverse);
5456
+ }
5457
+
5458
+ .ry-combobox__option[data-disabled] {
5459
+ opacity: 0.5;
5460
+ }
5461
+
5462
+ .ry-combobox__option[data-disabled]:hover {
5463
+ background-color: transparent;
5464
+ }
5465
+
5466
+ .ry-combobox__empty {
5467
+ font-size: var(--ry-text-sm);
5468
+ color: var(--ry-color-text-muted);
5469
+ }
5470
+
5281
5471
  } /* @layer ry-theme */
package/dist/ry-ui.d.ts CHANGED
@@ -38,6 +38,7 @@ export { RyTooltip } from './components/ry-tooltip.js';
38
38
  export { RyDrawer } from './components/ry-drawer.js';
39
39
  export { RyToast } from './components/ry-toast.js';
40
40
  export { RySelect } from './components/ry-select.js';
41
+ export { RyCombobox } from './components/ry-combobox.js';
41
42
  export { RyCode } from './components/ry-code.js';
42
43
  export { RyExample } from './components/ry-example.js';
43
44
  export { RyIcon } from './components/ry-icon.js';
@@ -1 +1 @@
1
- {"version":3,"file":"ry-ui.d.ts","sourceRoot":"","sources":["../src/ts/ry-ui.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ry-ui.d.ts","sourceRoot":"","sources":["../src/ts/ry-ui.ts"],"names":[],"mappings":"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"}