@ryanhelsing/ry-ui 1.0.10 → 1.0.12
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/README.dev.md +302 -0
- package/README.md +460 -199
- package/dist/themes/antigravity.css +56 -0
- package/package.json +3 -5
- package/AGENT.md +0 -492
- package/AGENTS.md +0 -57
- package/examples/starter-local.html +0 -252
- package/examples/starter-minimal.html +0 -252
- package/examples/themes/skeuomorphic/css-dark-neon-led-volume-dial/LICENSE.txt +0 -21
- package/examples/themes/skeuomorphic/css-dark-neon-led-volume-dial/README.md +0 -7
- package/examples/themes/skeuomorphic/css-dark-neon-led-volume-dial/dist/index.html +0 -23
- package/examples/themes/skeuomorphic/css-dark-neon-led-volume-dial/dist/style.css +0 -126
- package/examples/themes/skeuomorphic/css-dark-neon-led-volume-dial/src/index.html +0 -5
- package/examples/themes/skeuomorphic/css-dark-neon-led-volume-dial/src/style.scss +0 -161
- package/examples/themes/skeuomorphic/led-controls/LICENSE.txt +0 -21
- package/examples/themes/skeuomorphic/led-controls/README.md +0 -7
- package/examples/themes/skeuomorphic/led-controls/dist/index.html +0 -17
- package/examples/themes/skeuomorphic/led-controls/dist/script.js +0 -27
- package/examples/themes/skeuomorphic/led-controls/dist/style.css +0 -135
- package/examples/themes/skeuomorphic/led-controls/src/index.html +0 -1
- package/examples/themes/skeuomorphic/led-controls/src/script.ts +0 -59
- package/examples/themes/skeuomorphic/led-controls/src/style.scss +0 -253
- package/llms.txt +0 -346
|
@@ -1,253 +0,0 @@
|
|
|
1
|
-
@use "sass:list";
|
|
2
|
-
@use "sass:map";
|
|
3
|
-
|
|
4
|
-
// mixins
|
|
5
|
-
@mixin coords-to-property($pixel-size,$coord-array,$property) {
|
|
6
|
-
$value-sets: ();
|
|
7
|
-
|
|
8
|
-
@each $coords in $coord-array {
|
|
9
|
-
$x: $pixel-size * map.get($coords,"x");
|
|
10
|
-
$y: $pixel-size * map.get($coords,"y");
|
|
11
|
-
$value-sets: list.append($value-sets,($x $y),comma);
|
|
12
|
-
}
|
|
13
|
-
@if $property == "box-shadow" {
|
|
14
|
-
box-shadow: $value-sets;
|
|
15
|
-
}
|
|
16
|
-
@else if $property == "clip-path" {
|
|
17
|
-
clip-path: polygon($value-sets);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
@mixin range-thumb($pixel-size) {
|
|
21
|
-
background-color: transparent;
|
|
22
|
-
border: 0;
|
|
23
|
-
border-radius: 0;
|
|
24
|
-
box-shadow: none;
|
|
25
|
-
cursor: pointer;
|
|
26
|
-
width: $pixel-size * 5;
|
|
27
|
-
height: $pixel-size * 21;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// normal styles
|
|
31
|
-
* {
|
|
32
|
-
border: 0;
|
|
33
|
-
box-sizing: border-box;
|
|
34
|
-
margin: 0;
|
|
35
|
-
padding: 0;
|
|
36
|
-
}
|
|
37
|
-
:root {
|
|
38
|
-
--hue: 223;
|
|
39
|
-
--sat: 10%;
|
|
40
|
-
--bg: hsl(var(--hue),var(--sat),30%);
|
|
41
|
-
--fg: hsl(var(--hue),var(--sat),90%);
|
|
42
|
-
font-size: 12px;
|
|
43
|
-
}
|
|
44
|
-
body,
|
|
45
|
-
input {
|
|
46
|
-
font: 1em/1.5 sans-serif;
|
|
47
|
-
}
|
|
48
|
-
body {
|
|
49
|
-
background-color: var(--bg);
|
|
50
|
-
color: var(--fg);
|
|
51
|
-
display: flex;
|
|
52
|
-
height: 100vh;
|
|
53
|
-
}
|
|
54
|
-
input {
|
|
55
|
-
outline: transparent;
|
|
56
|
-
-webkit-appearance: none;
|
|
57
|
-
appearance: none;
|
|
58
|
-
-webkit-tap-highlight-color: transparent;
|
|
59
|
-
}
|
|
60
|
-
main {
|
|
61
|
-
display: flex;
|
|
62
|
-
overflow-x: hidden;
|
|
63
|
-
padding: 1.5em 0;
|
|
64
|
-
width: 100vw;
|
|
65
|
-
height: 100vh;
|
|
66
|
-
}
|
|
67
|
-
.grid {
|
|
68
|
-
display: grid;
|
|
69
|
-
gap: 1.5em;
|
|
70
|
-
grid-template-columns: repeat(2,1fr);
|
|
71
|
-
margin: auto;
|
|
72
|
-
}
|
|
73
|
-
.led-control {
|
|
74
|
-
$border:
|
|
75
|
-
("x": 2, "y": 0),
|
|
76
|
-
("x": 19, "y": 0),
|
|
77
|
-
("x": 19, "y": 1),
|
|
78
|
-
("x": 20, "y": 1),
|
|
79
|
-
("x": 20, "y": 2),
|
|
80
|
-
("x": 21, "y": 2),
|
|
81
|
-
("x": 21, "y": 42),
|
|
82
|
-
("x": 20, "y": 42),
|
|
83
|
-
("x": 20, "y": 42),
|
|
84
|
-
("x": 20, "y": 43),
|
|
85
|
-
("x": 19, "y": 43),
|
|
86
|
-
("x": 19, "y": 44),
|
|
87
|
-
("x": 2, "y": 44),
|
|
88
|
-
("x": 2, "y": 43),
|
|
89
|
-
("x": 1, "y": 43),
|
|
90
|
-
("x": 1, "y": 42),
|
|
91
|
-
("x": 0, "y": 42),
|
|
92
|
-
("x": 0, "y": 2),
|
|
93
|
-
("x": 1, "y": 2),
|
|
94
|
-
("x": 1, "y": 1),
|
|
95
|
-
("x": 2, "y": 1);
|
|
96
|
-
$sprites: (
|
|
97
|
-
"audio":
|
|
98
|
-
("x": 5, "y": 1)
|
|
99
|
-
("x": 4, "y": 2)
|
|
100
|
-
("x": 5, "y": 2)
|
|
101
|
-
("x": 3, "y": 3)
|
|
102
|
-
("x": 4, "y": 3)
|
|
103
|
-
("x": 5, "y": 3)
|
|
104
|
-
("x": 9, "y": 3)
|
|
105
|
-
("x": 1, "y": 4)
|
|
106
|
-
("x": 2, "y": 4)
|
|
107
|
-
("x": 3, "y": 4)
|
|
108
|
-
("x": 4, "y": 4)
|
|
109
|
-
("x": 5, "y": 4)
|
|
110
|
-
("x": 8, "y": 4)
|
|
111
|
-
("x": 1, "y": 5)
|
|
112
|
-
("x": 2, "y": 5)
|
|
113
|
-
("x": 3, "y": 5)
|
|
114
|
-
("x": 4, "y": 5)
|
|
115
|
-
("x": 5, "y": 5)
|
|
116
|
-
("x": 9, "y": 5)
|
|
117
|
-
("x": 1, "y": 6)
|
|
118
|
-
("x": 2, "y": 6)
|
|
119
|
-
("x": 3, "y": 6)
|
|
120
|
-
("x": 4, "y": 6)
|
|
121
|
-
("x": 5, "y": 6)
|
|
122
|
-
("x": 8, "y": 6)
|
|
123
|
-
("x": 3, "y": 7)
|
|
124
|
-
("x": 4, "y": 7)
|
|
125
|
-
("x": 5, "y": 7)
|
|
126
|
-
("x": 9, "y": 7)
|
|
127
|
-
("x": 4, "y": 8)
|
|
128
|
-
("x": 5, "y": 8)
|
|
129
|
-
("x": 5, "y": 9),
|
|
130
|
-
"sun":
|
|
131
|
-
("x": 5, "y": 0)
|
|
132
|
-
("x": 1, "y": 1)
|
|
133
|
-
("x": 5, "y": 1)
|
|
134
|
-
("x": 9, "y": 1)
|
|
135
|
-
("x": 2, "y": 2)
|
|
136
|
-
("x": 4, "y": 2)
|
|
137
|
-
("x": 5, "y": 2)
|
|
138
|
-
("x": 6, "y": 2)
|
|
139
|
-
("x": 8, "y": 2)
|
|
140
|
-
("x": 3, "y": 3)
|
|
141
|
-
("x": 7, "y": 3)
|
|
142
|
-
("x": 2, "y": 4)
|
|
143
|
-
("x": 8, "y": 4)
|
|
144
|
-
("x": 0, "y": 5)
|
|
145
|
-
("x": 1, "y": 5)
|
|
146
|
-
("x": 2, "y": 5)
|
|
147
|
-
("x": 8, "y": 5)
|
|
148
|
-
("x": 9, "y": 5)
|
|
149
|
-
("x": 10, "y": 5)
|
|
150
|
-
("x": 2, "y": 6)
|
|
151
|
-
("x": 8, "y": 6)
|
|
152
|
-
("x": 3, "y": 7)
|
|
153
|
-
("x": 7, "y": 7)
|
|
154
|
-
("x": 2, "y": 8)
|
|
155
|
-
("x": 4, "y": 8)
|
|
156
|
-
("x": 5, "y": 8)
|
|
157
|
-
("x": 6, "y": 8)
|
|
158
|
-
("x": 8, "y": 8)
|
|
159
|
-
("x": 1, "y": 9)
|
|
160
|
-
("x": 5, "y": 9)
|
|
161
|
-
("x": 9, "y": 9)
|
|
162
|
-
("x": 5, "y": 10)
|
|
163
|
-
);
|
|
164
|
-
$pixel-size: 0.5em;
|
|
165
|
-
margin: auto;
|
|
166
|
-
position: relative;
|
|
167
|
-
width: $pixel-size * 21;
|
|
168
|
-
height: $pixel-size * 44;
|
|
169
|
-
|
|
170
|
-
&__icon {
|
|
171
|
-
color: #eee;
|
|
172
|
-
bottom: $pixel-size * 5;
|
|
173
|
-
left: $pixel-size * 5;
|
|
174
|
-
width: $pixel-size * 11;
|
|
175
|
-
height: $pixel-size * 11;
|
|
176
|
-
|
|
177
|
-
&,
|
|
178
|
-
&:before {
|
|
179
|
-
position: absolute;
|
|
180
|
-
}
|
|
181
|
-
&:before {
|
|
182
|
-
$dot-size: $pixel-size * 0.75;
|
|
183
|
-
$dot-margin: $pixel-size * 0.125;
|
|
184
|
-
border-radius: 50%;
|
|
185
|
-
content: "";
|
|
186
|
-
display: block;
|
|
187
|
-
// clean up artifacts on non-retina screens caused by layer overlap
|
|
188
|
-
filter:
|
|
189
|
-
drop-shadow(1px 1px var(--bg))
|
|
190
|
-
drop-shadow(-1px 0 var(--bg))
|
|
191
|
-
drop-shadow(0 -1px var(--bg));
|
|
192
|
-
top: $dot-margin;
|
|
193
|
-
left: $dot-margin;
|
|
194
|
-
width: $dot-size;
|
|
195
|
-
height: $dot-size;
|
|
196
|
-
}
|
|
197
|
-
@each $name, $pixels in $sprites {
|
|
198
|
-
&--#{$name} {
|
|
199
|
-
&:before {
|
|
200
|
-
@include coords-to-property($pixel-size,$pixels,"box-shadow");
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
&__input,
|
|
206
|
-
&__label,
|
|
207
|
-
&__layer,
|
|
208
|
-
&__layer-wrap {
|
|
209
|
-
position: absolute;
|
|
210
|
-
}
|
|
211
|
-
&__input {
|
|
212
|
-
background-color: transparent;
|
|
213
|
-
box-shadow: 0 0 0 0.25em transparent;
|
|
214
|
-
top: 50%;
|
|
215
|
-
left: 50%;
|
|
216
|
-
transform: translate(-50%,-50%) rotate(-90deg);
|
|
217
|
-
width: $pixel-size * 44;
|
|
218
|
-
height: $pixel-size * 21;
|
|
219
|
-
|
|
220
|
-
&:focus-visible {
|
|
221
|
-
box-shadow: 0 0 0 0.25em var(--fg);
|
|
222
|
-
}
|
|
223
|
-
&::-webkit-slider-thumb {
|
|
224
|
-
@include range-thumb($pixel-size);
|
|
225
|
-
-webkit-appearance: none;
|
|
226
|
-
}
|
|
227
|
-
&::-moz-range-thumb {
|
|
228
|
-
@include range-thumb($pixel-size);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
&__label {
|
|
232
|
-
overflow: hidden;
|
|
233
|
-
width: 1px;
|
|
234
|
-
height: 1px;
|
|
235
|
-
}
|
|
236
|
-
&__layer {
|
|
237
|
-
background: url("data:image/svg+xml,<svg viewBox='0 0 8 8' xmlns='http://www.w3.org/2000/svg'><circle fill='%23111' cx='4' cy='4' r='3' /></svg>") (0 0) / ($pixel-size $pixel-size);
|
|
238
|
-
|
|
239
|
-
&,
|
|
240
|
-
&-wrap {
|
|
241
|
-
inset: 0;
|
|
242
|
-
}
|
|
243
|
-
&-wrap {
|
|
244
|
-
@include coords-to-property($pixel-size,$border,"clip-path");
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
&__layer--inverted {
|
|
248
|
-
background-image: url("data:image/svg+xml,<svg viewBox='0 0 8 8' xmlns='http://www.w3.org/2000/svg'><circle fill='%23eee' cx='4' cy='4' r='3' /></svg>");
|
|
249
|
-
}
|
|
250
|
-
&__layer--inverted &__icon {
|
|
251
|
-
color: #111;
|
|
252
|
-
}
|
|
253
|
-
}
|
package/llms.txt
DELETED
|
@@ -1,346 +0,0 @@
|
|
|
1
|
-
# ry-ui
|
|
2
|
-
|
|
3
|
-
> Framework-agnostic Light DOM web components. Zero dependencies. CSS is the source of truth.
|
|
4
|
-
|
|
5
|
-
## Setup (2 lines)
|
|
6
|
-
|
|
7
|
-
```html
|
|
8
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ryanhelsing/ry-ui/dist/css/ry-ui.css">
|
|
9
|
-
<script type="module" src="https://cdn.jsdelivr.net/npm/@ryanhelsing/ry-ui/dist/ry-ui.js"></script>
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
Set theme on `<html>`: `data-ry-theme="light"` or `"dark"`. Omit for OS preference.
|
|
13
|
-
Set body colors: `<body style="background: var(--ry-color-bg); color: var(--ry-color-text);">`
|
|
14
|
-
|
|
15
|
-
## DON'T / DO
|
|
16
|
-
|
|
17
|
-
DON'T write flexbox/grid CSS for page layout.
|
|
18
|
-
DO: `<ry-page><ry-header>H</ry-header><ry-main>M</ry-main><ry-footer>F</ry-footer></ry-page>`
|
|
19
|
-
|
|
20
|
-
DON'T write a custom modal with backdrop, focus trap, escape handling.
|
|
21
|
-
DO: `<ry-button modal="m">Open</ry-button><ry-modal id="m" title="T">Content</ry-modal>`
|
|
22
|
-
|
|
23
|
-
DON'T write a slide-out drawer with CSS transforms.
|
|
24
|
-
DO: `<ry-button drawer="d">Open</ry-button><ry-drawer id="d" side="left">Content</ry-drawer>`
|
|
25
|
-
|
|
26
|
-
DON'T write tab switching logic or CSS.
|
|
27
|
-
DO: `<ry-tabs><ry-tab title="A" active>A</ry-tab><ry-tab title="B">B</ry-tab></ry-tabs>`
|
|
28
|
-
|
|
29
|
-
DON'T write a custom select dropdown with keyboard navigation.
|
|
30
|
-
DO: `<ry-select placeholder="Pick"><ry-option value="a">A</ry-option></ry-select>`
|
|
31
|
-
|
|
32
|
-
DON'T write CSS variables for colors, spacing, shadows.
|
|
33
|
-
DO: Use `--ry-color-*`, `--ry-space-*`, `--ry-radius-*`, `--ry-shadow-*` tokens.
|
|
34
|
-
|
|
35
|
-
DON'T write button styles with hover/active/focus states.
|
|
36
|
-
DO: `<ry-button variant="primary">Click</ry-button>`
|
|
37
|
-
|
|
38
|
-
DON'T write toast/notification CSS and JS.
|
|
39
|
-
DO: `RyToast.success('Saved!')` / `RyToast.error('Failed')`
|
|
40
|
-
|
|
41
|
-
DON'T write accordion expand/collapse logic.
|
|
42
|
-
DO: `<ry-accordion><ry-accordion-item title="Q" open>A</ry-accordion-item></ry-accordion>`
|
|
43
|
-
|
|
44
|
-
DON'T write a toggle switch from scratch.
|
|
45
|
-
DO: `<ry-switch name="notify" checked></ry-switch>`
|
|
46
|
-
|
|
47
|
-
## Full Page Template
|
|
48
|
-
|
|
49
|
-
```html
|
|
50
|
-
<!DOCTYPE html>
|
|
51
|
-
<html lang="en" data-ry-theme="light">
|
|
52
|
-
<head>
|
|
53
|
-
<meta charset="UTF-8">
|
|
54
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
55
|
-
<title>My App</title>
|
|
56
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ryanhelsing/ry-ui/dist/css/ry-ui.css">
|
|
57
|
-
</head>
|
|
58
|
-
<body style="background: var(--ry-color-bg); color: var(--ry-color-text);">
|
|
59
|
-
<ry-page>
|
|
60
|
-
<ry-header sticky>
|
|
61
|
-
<ry-cluster>
|
|
62
|
-
<strong>My App</strong>
|
|
63
|
-
<ry-nav>
|
|
64
|
-
<a href="/" aria-current="page">Home</a>
|
|
65
|
-
<a href="/about">About</a>
|
|
66
|
-
</ry-nav>
|
|
67
|
-
</ry-cluster>
|
|
68
|
-
<ry-actions>
|
|
69
|
-
<ry-theme-toggle themes="light,dark"></ry-theme-toggle>
|
|
70
|
-
</ry-actions>
|
|
71
|
-
</ry-header>
|
|
72
|
-
|
|
73
|
-
<ry-main>
|
|
74
|
-
<ry-section>
|
|
75
|
-
<h1>Hello World</h1>
|
|
76
|
-
<p>Your content here.</p>
|
|
77
|
-
</ry-section>
|
|
78
|
-
</ry-main>
|
|
79
|
-
|
|
80
|
-
<ry-footer>Built with ry-ui</ry-footer>
|
|
81
|
-
</ry-page>
|
|
82
|
-
|
|
83
|
-
<script type="module" src="https://cdn.jsdelivr.net/npm/@ryanhelsing/ry-ui/dist/ry-ui.js"></script>
|
|
84
|
-
</body>
|
|
85
|
-
</html>
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
## Components — Copy-Paste Reference
|
|
89
|
-
|
|
90
|
-
### Layout (CSS-only, no JS needed)
|
|
91
|
-
|
|
92
|
-
```html
|
|
93
|
-
<ry-page>
|
|
94
|
-
<ry-header sticky>Header</ry-header>
|
|
95
|
-
<ry-main><ry-section>Content</ry-section></ry-main>
|
|
96
|
-
<ry-footer>Footer</ry-footer>
|
|
97
|
-
</ry-page>
|
|
98
|
-
|
|
99
|
-
<ry-grid cols="3">
|
|
100
|
-
<div>1</div><div>2</div><div>3</div>
|
|
101
|
-
</ry-grid>
|
|
102
|
-
|
|
103
|
-
<!-- Responsive: cols-sm="1" cols-md="2" cols-lg="3" -->
|
|
104
|
-
<ry-grid cols="4" cols-sm="1" cols-md="2">...</ry-grid>
|
|
105
|
-
|
|
106
|
-
<ry-stack gap="md">Vertical stack</ry-stack>
|
|
107
|
-
<ry-cluster gap="sm">Horizontal row, wraps</ry-cluster>
|
|
108
|
-
<ry-center>Centered both axes</ry-center>
|
|
109
|
-
<ry-card>Card container (lifts on hover)</ry-card>
|
|
110
|
-
<ry-divider></ry-divider>
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
### Buttons
|
|
114
|
-
|
|
115
|
-
```html
|
|
116
|
-
<ry-button>Default</ry-button>
|
|
117
|
-
<ry-button variant="primary">Primary</ry-button>
|
|
118
|
-
<ry-button variant="secondary">Secondary</ry-button>
|
|
119
|
-
<ry-button variant="outline">Outline</ry-button>
|
|
120
|
-
<ry-button variant="ghost">Ghost</ry-button>
|
|
121
|
-
<ry-button variant="danger">Danger</ry-button>
|
|
122
|
-
<ry-button variant="accent">Accent</ry-button>
|
|
123
|
-
<ry-button size="sm">Small</ry-button>
|
|
124
|
-
<ry-button size="lg">Large</ry-button>
|
|
125
|
-
<ry-button disabled>Disabled</ry-button>
|
|
126
|
-
<ry-button modal="modal-id">Opens modal</ry-button>
|
|
127
|
-
<ry-button drawer="drawer-id">Opens drawer</ry-button>
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
### Modal
|
|
131
|
-
|
|
132
|
-
```html
|
|
133
|
-
<ry-button modal="my-modal">Open Modal</ry-button>
|
|
134
|
-
<ry-modal id="my-modal" title="Confirm">
|
|
135
|
-
<p>Are you sure?</p>
|
|
136
|
-
<ry-cluster>
|
|
137
|
-
<ry-button variant="danger">Delete</ry-button>
|
|
138
|
-
<ry-button variant="ghost">Cancel</ry-button>
|
|
139
|
-
</ry-cluster>
|
|
140
|
-
</ry-modal>
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### Drawer
|
|
144
|
-
|
|
145
|
-
```html
|
|
146
|
-
<ry-button drawer="my-drawer">Open Drawer</ry-button>
|
|
147
|
-
<ry-drawer id="my-drawer" side="left" title="Menu">
|
|
148
|
-
<!-- side: left | right | bottom -->
|
|
149
|
-
<nav>Navigation content</nav>
|
|
150
|
-
</ry-drawer>
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
### Tabs
|
|
154
|
-
|
|
155
|
-
```html
|
|
156
|
-
<ry-tabs>
|
|
157
|
-
<ry-tab title="Overview" active>First tab content</ry-tab>
|
|
158
|
-
<ry-tab title="Settings">Second tab content</ry-tab>
|
|
159
|
-
<ry-tab title="Logs">Third tab content</ry-tab>
|
|
160
|
-
</ry-tabs>
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
### Accordion
|
|
164
|
-
|
|
165
|
-
```html
|
|
166
|
-
<ry-accordion>
|
|
167
|
-
<ry-accordion-item title="Section One" open>Content</ry-accordion-item>
|
|
168
|
-
<ry-accordion-item title="Section Two">Content</ry-accordion-item>
|
|
169
|
-
</ry-accordion>
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
### Select
|
|
173
|
-
|
|
174
|
-
```html
|
|
175
|
-
<ry-select placeholder="Choose country" name="country">
|
|
176
|
-
<ry-option value="us">United States</ry-option>
|
|
177
|
-
<ry-option value="uk">United Kingdom</ry-option>
|
|
178
|
-
<ry-option value="ca">Canada</ry-option>
|
|
179
|
-
</ry-select>
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
### Forms
|
|
183
|
-
|
|
184
|
-
```html
|
|
185
|
-
<ry-field label="Email" hint="We'll never share it">
|
|
186
|
-
<input type="email" placeholder="you@example.com">
|
|
187
|
-
</ry-field>
|
|
188
|
-
|
|
189
|
-
<ry-field label="Password" error="Must be at least 8 characters">
|
|
190
|
-
<input type="password">
|
|
191
|
-
</ry-field>
|
|
192
|
-
|
|
193
|
-
<ry-switch name="notifications" checked></ry-switch>
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
### Dropdown Menu
|
|
197
|
-
|
|
198
|
-
```html
|
|
199
|
-
<ry-dropdown>
|
|
200
|
-
<ry-button slot="trigger">Actions</ry-button>
|
|
201
|
-
<ry-menu>
|
|
202
|
-
<ry-menu-item>Edit</ry-menu-item>
|
|
203
|
-
<ry-menu-item>Duplicate</ry-menu-item>
|
|
204
|
-
<ry-menu-item>Delete</ry-menu-item>
|
|
205
|
-
</ry-menu>
|
|
206
|
-
</ry-dropdown>
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
### Toast (JS only — no HTML needed)
|
|
210
|
-
|
|
211
|
-
```javascript
|
|
212
|
-
RyToast.success('Saved successfully!');
|
|
213
|
-
RyToast.error('Something went wrong');
|
|
214
|
-
RyToast.info('FYI...');
|
|
215
|
-
RyToast.warning('Be careful');
|
|
216
|
-
RyToast.show({ message: 'Custom', variant: 'info', duration: 5000 });
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
### Display
|
|
220
|
-
|
|
221
|
-
```html
|
|
222
|
-
<ry-alert type="info">Informational message</ry-alert>
|
|
223
|
-
<ry-alert type="success">Operation completed</ry-alert>
|
|
224
|
-
<ry-alert type="warning">Proceed with caution</ry-alert>
|
|
225
|
-
<ry-alert type="danger" dismissible>Something went wrong</ry-alert>
|
|
226
|
-
|
|
227
|
-
<ry-badge>Default</ry-badge>
|
|
228
|
-
<ry-badge variant="success">Active</ry-badge>
|
|
229
|
-
<ry-badge variant="danger">Error</ry-badge>
|
|
230
|
-
|
|
231
|
-
<ry-tooltip content="Help text" position="top">
|
|
232
|
-
<span>Hover me</span>
|
|
233
|
-
</ry-tooltip>
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
### Slider & Knob
|
|
237
|
-
|
|
238
|
-
```html
|
|
239
|
-
<ry-slider min="0" max="100" value="50" step="1"></ry-slider>
|
|
240
|
-
<ry-slider range start="20" end="80"></ry-slider>
|
|
241
|
-
<ry-knob min="0" max="100" value="50" label="Volume"></ry-knob>
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
### Split Layout (resizable sidebar)
|
|
245
|
-
|
|
246
|
-
```html
|
|
247
|
-
<ry-split resizable persist="sidebar">
|
|
248
|
-
<div>Main content</div>
|
|
249
|
-
<div>Sidebar</div>
|
|
250
|
-
</ry-split>
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
### Button Group (segmented control)
|
|
254
|
-
|
|
255
|
-
```html
|
|
256
|
-
<ry-button-group name="billing" value="monthly">
|
|
257
|
-
<ry-button value="monthly">Monthly</ry-button>
|
|
258
|
-
<ry-button value="annually">Annually</ry-button>
|
|
259
|
-
</ry-button-group>
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
### Nav Bar Pattern
|
|
263
|
-
|
|
264
|
-
```html
|
|
265
|
-
<ry-header sticky>
|
|
266
|
-
<ry-cluster>
|
|
267
|
-
<ry-logo>MyApp</ry-logo>
|
|
268
|
-
<ry-divider vertical></ry-divider>
|
|
269
|
-
<ry-nav>
|
|
270
|
-
<a href="/" aria-current="page">Home</a>
|
|
271
|
-
<a href="/docs">Docs</a>
|
|
272
|
-
</ry-nav>
|
|
273
|
-
</ry-cluster>
|
|
274
|
-
<ry-actions>
|
|
275
|
-
<ry-button variant="ghost" size="sm">Login</ry-button>
|
|
276
|
-
<ry-button size="sm">Sign Up</ry-button>
|
|
277
|
-
</ry-actions>
|
|
278
|
-
</ry-header>
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
### Interactive Card Grid
|
|
282
|
-
|
|
283
|
-
```html
|
|
284
|
-
<ry-grid cols="3">
|
|
285
|
-
<ry-card interactive>
|
|
286
|
-
<h3>Feature A</h3>
|
|
287
|
-
<p>Description of feature A</p>
|
|
288
|
-
</ry-card>
|
|
289
|
-
<ry-card interactive>
|
|
290
|
-
<h3>Feature B</h3>
|
|
291
|
-
<p>Description of feature B</p>
|
|
292
|
-
</ry-card>
|
|
293
|
-
</ry-grid>
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
## Events
|
|
297
|
-
|
|
298
|
-
All events are prefixed with `ry:`:
|
|
299
|
-
|
|
300
|
-
```javascript
|
|
301
|
-
element.addEventListener('ry:change', (e) => console.log(e.detail));
|
|
302
|
-
element.addEventListener('ry:open', () => {});
|
|
303
|
-
element.addEventListener('ry:close', () => {});
|
|
304
|
-
element.addEventListener('ry:click', () => {});
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
## Programmatic Control
|
|
308
|
-
|
|
309
|
-
```javascript
|
|
310
|
-
document.querySelector('ry-modal').open();
|
|
311
|
-
document.querySelector('ry-modal').close();
|
|
312
|
-
document.querySelector('ry-drawer').toggle();
|
|
313
|
-
document.querySelector('ry-select').value = 'new-value';
|
|
314
|
-
```
|
|
315
|
-
|
|
316
|
-
## Theming
|
|
317
|
-
|
|
318
|
-
Override tokens in your own CSS — no build step needed:
|
|
319
|
-
|
|
320
|
-
```css
|
|
321
|
-
:root {
|
|
322
|
-
--ry-color-primary: oklch(0.541 0.218 293);
|
|
323
|
-
--ry-color-primary-hover: oklch(0.491 0.234 292);
|
|
324
|
-
--ry-radius-md: 0;
|
|
325
|
-
}
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
Key tokens: `--ry-color-{primary,secondary,accent,success,warning,danger,info}`,
|
|
329
|
-
`--ry-color-{text,text-muted,bg,bg-subtle,border}`, `--ry-space-{1-20}`,
|
|
330
|
-
`--ry-radius-{sm,md,lg,xl,full}`, `--ry-shadow-{sm,md,lg,xl}`,
|
|
331
|
-
`--ry-font-{sans,mono}`, `--ry-text-{xs,sm,base,lg,xl,2xl,3xl,4xl}`
|
|
332
|
-
|
|
333
|
-
## Vendoring (no npm required)
|
|
334
|
-
|
|
335
|
-
Copy files into your project instead of using CDN:
|
|
336
|
-
|
|
337
|
-
```bash
|
|
338
|
-
npm pack @ryanhelsing/ry-ui && tar -xf ryanhelsing-ry-ui-*.tgz
|
|
339
|
-
cp -r package/dist ./vendor/ry-ui && rm -rf package ryanhelsing-ry-ui-*.tgz
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
Then use local paths:
|
|
343
|
-
```html
|
|
344
|
-
<link rel="stylesheet" href="/vendor/ry-ui/css/ry-ui.css">
|
|
345
|
-
<script type="module" src="/vendor/ry-ui/ry-ui.js"></script>
|
|
346
|
-
```
|