@ryanhelsing/ry-ui 1.0.8 → 1.0.10
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/.claude/skills/ry-ui-builder/SKILL.md +186 -0
- package/AGENT.md +3 -1
- package/README.md +16 -2
- package/dist/_redirects +1 -0
- package/dist/app.d.ts +2 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/components/ry-testimonial.d.ts +19 -0
- package/dist/components/ry-testimonial.d.ts.map +1 -0
- package/dist/components/ry-theme-panel.d.ts +25 -0
- package/dist/components/ry-theme-panel.d.ts.map +1 -0
- package/dist/core/ry-icons.d.ts.map +1 -1
- package/dist/core/ry-transform.d.ts.map +1 -1
- package/dist/css/ry-structure.css +123 -3
- package/dist/css/ry-theme.css +141 -2
- package/dist/css/ry-tokens.css +4 -26
- package/dist/css/ry-ui.css +268 -31
- package/dist/pages/components.html +1827 -0
- package/dist/pages/landing.html +229 -0
- package/dist/ry-ui.d.ts +2 -0
- package/dist/ry-ui.d.ts.map +1 -1
- package/dist/ry-ui.js +382 -245
- package/dist/ry-ui.js.map +1 -1
- package/docs/components/forms.md +10 -3
- package/examples/starter-local.html +252 -0
- package/examples/starter-minimal.html +252 -0
- package/examples/themes/skeuomorphic/css-dark-neon-led-volume-dial/LICENSE.txt +21 -0
- package/examples/themes/skeuomorphic/css-dark-neon-led-volume-dial/README.md +7 -0
- package/examples/themes/skeuomorphic/css-dark-neon-led-volume-dial/dist/index.html +23 -0
- package/examples/themes/skeuomorphic/css-dark-neon-led-volume-dial/dist/style.css +126 -0
- package/examples/themes/skeuomorphic/css-dark-neon-led-volume-dial/src/index.html +5 -0
- package/examples/themes/skeuomorphic/css-dark-neon-led-volume-dial/src/style.scss +161 -0
- package/examples/themes/skeuomorphic/led-controls/LICENSE.txt +21 -0
- package/examples/themes/skeuomorphic/led-controls/README.md +7 -0
- package/examples/themes/skeuomorphic/led-controls/dist/index.html +17 -0
- package/examples/themes/skeuomorphic/led-controls/dist/script.js +27 -0
- package/examples/themes/skeuomorphic/led-controls/dist/style.css +135 -0
- package/examples/themes/skeuomorphic/led-controls/src/index.html +1 -0
- package/examples/themes/skeuomorphic/led-controls/src/script.ts +59 -0
- package/examples/themes/skeuomorphic/led-controls/src/style.scss +253 -0
- package/llms.txt +346 -0
- package/package.json +12 -4
|
@@ -0,0 +1,1827 @@
|
|
|
1
|
+
<ry-page>
|
|
2
|
+
|
|
3
|
+
<ry-header sticky>
|
|
4
|
+
<ry-cluster>
|
|
5
|
+
<strong>ry-ui</strong>
|
|
6
|
+
<span>Kitchen Sink</span>
|
|
7
|
+
</ry-cluster>
|
|
8
|
+
|
|
9
|
+
</ry-header>
|
|
10
|
+
|
|
11
|
+
<ry-theme-panel></ry-theme-panel>
|
|
12
|
+
|
|
13
|
+
<ry-main>
|
|
14
|
+
|
|
15
|
+
<!-- Sticky -->
|
|
16
|
+
<ry-section>
|
|
17
|
+
<h2>Sticky</h2>
|
|
18
|
+
<ry-example title="sticky" stacked>
|
|
19
|
+
<template>
|
|
20
|
+
<div style="height: 150px; overflow-y: auto; border: 1px solid var(--ry-color-border); border-radius: var(--ry-radius-lg);">
|
|
21
|
+
<header sticky style="background: var(--ry-color-bg); padding: var(--ry-space-3); border-bottom: 1px solid var(--ry-color-border);">
|
|
22
|
+
<strong>Sticky header</strong>
|
|
23
|
+
</header>
|
|
24
|
+
<stack style="padding: var(--ry-space-4);">
|
|
25
|
+
<p>Scroll down...</p>
|
|
26
|
+
<p>Keep scrolling...</p>
|
|
27
|
+
<p>The header sticks!</p>
|
|
28
|
+
<p>More content here...</p>
|
|
29
|
+
<p>Almost there...</p>
|
|
30
|
+
<p>Bottom reached.</p>
|
|
31
|
+
</stack>
|
|
32
|
+
</div>
|
|
33
|
+
</template>
|
|
34
|
+
</ry-example>
|
|
35
|
+
<table>
|
|
36
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
37
|
+
<tbody>
|
|
38
|
+
<tr><td><code>sticky</code></td><td>boolean</td><td>Sticks to top of scroll container</td></tr>
|
|
39
|
+
</tbody>
|
|
40
|
+
</table>
|
|
41
|
+
</ry-section>
|
|
42
|
+
|
|
43
|
+
<!-- Grid -->
|
|
44
|
+
<ry-section>
|
|
45
|
+
<h2>Grid</h2>
|
|
46
|
+
<ry-example title="grid">
|
|
47
|
+
<template>
|
|
48
|
+
<grid cols="3">
|
|
49
|
+
<card>One</card>
|
|
50
|
+
<card>Two</card>
|
|
51
|
+
<card>Three</card>
|
|
52
|
+
</grid>
|
|
53
|
+
</template>
|
|
54
|
+
</ry-example>
|
|
55
|
+
<ry-example title="grid auto-fit">
|
|
56
|
+
<template>
|
|
57
|
+
<grid cols="auto-fit" style="--ry-grid-min: 200px">
|
|
58
|
+
<card>Auto</card>
|
|
59
|
+
<card>Fit</card>
|
|
60
|
+
<card>Cards</card>
|
|
61
|
+
<card>Wrap</card>
|
|
62
|
+
<card>Fluidly</card>
|
|
63
|
+
</grid>
|
|
64
|
+
</template>
|
|
65
|
+
</ry-example>
|
|
66
|
+
<ry-example title="grid responsive breakpoints">
|
|
67
|
+
<template>
|
|
68
|
+
<grid cols="5" cols-md="3" cols-sm="1">
|
|
69
|
+
<card>1</card>
|
|
70
|
+
<card>2</card>
|
|
71
|
+
<card>3</card>
|
|
72
|
+
<card>4</card>
|
|
73
|
+
<card>5</card>
|
|
74
|
+
</grid>
|
|
75
|
+
</template>
|
|
76
|
+
</ry-example>
|
|
77
|
+
<table>
|
|
78
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
79
|
+
<tbody>
|
|
80
|
+
<tr><td><code>cols</code></td><td>1-6 | auto-fit | auto-fill</td><td>Number of columns or fluid mode</td></tr>
|
|
81
|
+
<tr><td><code>cols-sm</code></td><td>1-3</td><td>Columns at ≤640px</td></tr>
|
|
82
|
+
<tr><td><code>cols-md</code></td><td>1-4</td><td>Columns at 641-1024px</td></tr>
|
|
83
|
+
<tr><td><code>cols-lg</code></td><td>2-6</td><td>Columns at ≥1025px</td></tr>
|
|
84
|
+
<tr><td><code>--ry-grid-min</code></td><td>CSS length</td><td>Min column width for auto-fit/auto-fill (default 280px)</td></tr>
|
|
85
|
+
</tbody>
|
|
86
|
+
</table>
|
|
87
|
+
</ry-section>
|
|
88
|
+
|
|
89
|
+
<!-- Stack -->
|
|
90
|
+
<ry-section>
|
|
91
|
+
<h2>Stack</h2>
|
|
92
|
+
<ry-example title="stack">
|
|
93
|
+
<template>
|
|
94
|
+
<stack gap="sm">
|
|
95
|
+
<card>Stacked item 1</card>
|
|
96
|
+
<card>Stacked item 2</card>
|
|
97
|
+
<card>Stacked item 3</card>
|
|
98
|
+
</stack>
|
|
99
|
+
</template>
|
|
100
|
+
</ry-example>
|
|
101
|
+
<table>
|
|
102
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
103
|
+
<tbody>
|
|
104
|
+
<tr><td><code>gap</code></td><td>sm | md | lg</td><td>Vertical spacing</td></tr>
|
|
105
|
+
</tbody>
|
|
106
|
+
</table>
|
|
107
|
+
</ry-section>
|
|
108
|
+
|
|
109
|
+
<!-- Cluster -->
|
|
110
|
+
<ry-section>
|
|
111
|
+
<h2>Cluster</h2>
|
|
112
|
+
<ry-example title="cluster">
|
|
113
|
+
<template>
|
|
114
|
+
<cluster>
|
|
115
|
+
<badge>Tag 1</badge>
|
|
116
|
+
<badge>Tag 2</badge>
|
|
117
|
+
<badge>Tag 3</badge>
|
|
118
|
+
<badge>Tag 4</badge>
|
|
119
|
+
</cluster>
|
|
120
|
+
</template>
|
|
121
|
+
</ry-example>
|
|
122
|
+
<table>
|
|
123
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
124
|
+
<tbody>
|
|
125
|
+
<tr><td><code>gap</code></td><td>sm | md | lg</td><td>Horizontal spacing</td></tr>
|
|
126
|
+
</tbody>
|
|
127
|
+
</table>
|
|
128
|
+
</ry-section>
|
|
129
|
+
|
|
130
|
+
<!-- Card -->
|
|
131
|
+
<ry-section>
|
|
132
|
+
<h2>Card</h2>
|
|
133
|
+
<ry-example title="card">
|
|
134
|
+
<template>
|
|
135
|
+
<card>
|
|
136
|
+
<h3>Card Title</h3>
|
|
137
|
+
<p>Card content goes here.</p>
|
|
138
|
+
<actions>
|
|
139
|
+
<button>Action</button>
|
|
140
|
+
<button variant="ghost">Cancel</button>
|
|
141
|
+
</actions>
|
|
142
|
+
</card>
|
|
143
|
+
</template>
|
|
144
|
+
</ry-example>
|
|
145
|
+
<ry-example title="interactive cards" stacked>
|
|
146
|
+
<template>
|
|
147
|
+
<grid cols="3">
|
|
148
|
+
<card interactive>
|
|
149
|
+
<h3>Hover Me</h3>
|
|
150
|
+
<p>All cards lift on hover. Interactive cards get a stronger effect with primary border.</p>
|
|
151
|
+
</card>
|
|
152
|
+
<card interactive href="#card-demo">
|
|
153
|
+
<h3>With Link</h3>
|
|
154
|
+
<p>Interactive cards with <code>href</code> navigate on click or Enter key.</p>
|
|
155
|
+
</card>
|
|
156
|
+
<card interactive>
|
|
157
|
+
<h3>Keyboard Accessible</h3>
|
|
158
|
+
<p>Tab to focus, Enter or Space to activate. Emits <code>ry:click</code>.</p>
|
|
159
|
+
</card>
|
|
160
|
+
</grid>
|
|
161
|
+
</template>
|
|
162
|
+
</ry-example>
|
|
163
|
+
<table>
|
|
164
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
165
|
+
<tbody>
|
|
166
|
+
<tr><td><code>interactive</code></td><td>boolean</td><td>Clickable card with hover lift, focus ring, keyboard support</td></tr>
|
|
167
|
+
<tr><td><code>href</code></td><td>URL</td><td>Navigate on click (requires <code>interactive</code>)</td></tr>
|
|
168
|
+
</tbody>
|
|
169
|
+
</table>
|
|
170
|
+
</ry-section>
|
|
171
|
+
|
|
172
|
+
<!-- Button -->
|
|
173
|
+
<ry-section>
|
|
174
|
+
<h2>Button</h2>
|
|
175
|
+
<ry-example title="button">
|
|
176
|
+
<template>
|
|
177
|
+
<cluster>
|
|
178
|
+
<button>Primary</button>
|
|
179
|
+
<button variant="secondary">Secondary</button>
|
|
180
|
+
<button variant="outline">Outline</button>
|
|
181
|
+
<button variant="ghost">Ghost</button>
|
|
182
|
+
<button variant="danger">Danger</button>
|
|
183
|
+
<button variant="accent">Accent</button>
|
|
184
|
+
<button pressed>Pressed</button>
|
|
185
|
+
</cluster>
|
|
186
|
+
</template>
|
|
187
|
+
</ry-example>
|
|
188
|
+
<table>
|
|
189
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
190
|
+
<tbody>
|
|
191
|
+
<tr><td><code>variant</code></td><td>primary | secondary | outline | ghost | danger | accent</td><td>Button style</td></tr>
|
|
192
|
+
<tr><td><code>size</code></td><td>sm | md | lg</td><td>Button size</td></tr>
|
|
193
|
+
<tr><td><code>pressed</code></td><td>boolean</td><td>Pressed/active toggle state</td></tr>
|
|
194
|
+
<tr><td><code>modal</code></td><td>modal-id</td><td>Opens modal on click</td></tr>
|
|
195
|
+
<tr><td><code>drawer</code></td><td>drawer-id</td><td>Opens drawer on click</td></tr>
|
|
196
|
+
</tbody>
|
|
197
|
+
</table>
|
|
198
|
+
</ry-section>
|
|
199
|
+
|
|
200
|
+
<!-- Button Group -->
|
|
201
|
+
<ry-section>
|
|
202
|
+
<h2>Button Group</h2>
|
|
203
|
+
<ry-example title="button-group">
|
|
204
|
+
<template>
|
|
205
|
+
<stack gap="lg">
|
|
206
|
+
<button-group name="billing" value="monthly">
|
|
207
|
+
<button value="monthly">Monthly</button>
|
|
208
|
+
<button value="annually">Annually</button>
|
|
209
|
+
</button-group>
|
|
210
|
+
|
|
211
|
+
<button-group name="mode" value="terminal">
|
|
212
|
+
<button value="direct">Direct</button>
|
|
213
|
+
<button value="terminal">Terminal</button>
|
|
214
|
+
<button value="release">Release</button>
|
|
215
|
+
</button-group>
|
|
216
|
+
</stack>
|
|
217
|
+
</template>
|
|
218
|
+
<script slot="js" type="text/plain">
|
|
219
|
+
const group = document.querySelector('ry-button-group');
|
|
220
|
+
|
|
221
|
+
// Listen for selection changes
|
|
222
|
+
group.addEventListener('ry:change', (e) => {
|
|
223
|
+
console.log(e.detail.value); // "monthly" or "annually"
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
// Get/set programmatically
|
|
227
|
+
group.value; // "monthly"
|
|
228
|
+
group.value = 'annually'; // Switch selection
|
|
229
|
+
</script>
|
|
230
|
+
</ry-example>
|
|
231
|
+
<table>
|
|
232
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
233
|
+
<tbody>
|
|
234
|
+
<tr><td><code>name</code></td><td>string</td><td>Group name</td></tr>
|
|
235
|
+
<tr><td><code>value</code></td><td>string</td><td>Currently selected value</td></tr>
|
|
236
|
+
</tbody>
|
|
237
|
+
</table>
|
|
238
|
+
</ry-section>
|
|
239
|
+
|
|
240
|
+
<!-- Split -->
|
|
241
|
+
<ry-section>
|
|
242
|
+
<h2>Split</h2>
|
|
243
|
+
<ry-example title="split" stacked>
|
|
244
|
+
<template>
|
|
245
|
+
<split style="--ry-split-width: 200px; height: 120px;">
|
|
246
|
+
<card>Main content (flex: 1)</card>
|
|
247
|
+
<card>Sidebar (200px)</card>
|
|
248
|
+
</split>
|
|
249
|
+
</template>
|
|
250
|
+
</ry-example>
|
|
251
|
+
<ry-example title="split resizable" stacked>
|
|
252
|
+
<template>
|
|
253
|
+
<split resizable style="height: 150px;">
|
|
254
|
+
<card>Drag the handle to resize →</card>
|
|
255
|
+
<card>Resizable sidebar (default 300px)</card>
|
|
256
|
+
</split>
|
|
257
|
+
</template>
|
|
258
|
+
</ry-example>
|
|
259
|
+
<ry-example title="split resizable + persist" stacked>
|
|
260
|
+
<template>
|
|
261
|
+
<split resizable persist="demo-panel" style="height: 150px; --ry-split-width: 250px;">
|
|
262
|
+
<card>Width persists across page reloads. Double-click handle to reset.</card>
|
|
263
|
+
<card>Persisted sidebar</card>
|
|
264
|
+
</split>
|
|
265
|
+
</template>
|
|
266
|
+
<script slot="js" type="text/plain">
|
|
267
|
+
const split = document.querySelector('ry-split[resizable]');
|
|
268
|
+
|
|
269
|
+
// Listen for resize
|
|
270
|
+
split.addEventListener('ry:resize', (e) => {
|
|
271
|
+
console.log(e.detail.width); // new width in px
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
// Keyboard: Arrow keys (±10px), Shift+Arrow (±50px)
|
|
275
|
+
// Home = min width, End = max width
|
|
276
|
+
// Double-click handle = reset to default
|
|
277
|
+
</script>
|
|
278
|
+
</ry-example>
|
|
279
|
+
<table>
|
|
280
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
281
|
+
<tbody>
|
|
282
|
+
<tr><td><code>resizable</code></td><td>boolean</td><td>Enable drag-to-resize handle</td></tr>
|
|
283
|
+
<tr><td><code>persist</code></td><td>string</td><td>localStorage key — saves width across reloads</td></tr>
|
|
284
|
+
<tr><td><code>--ry-split-width</code></td><td>CSS length</td><td>Sidebar width (default 300px)</td></tr>
|
|
285
|
+
<tr><td><code>--ry-split-min-width</code></td><td>CSS length</td><td>Min width during resize (default 100px)</td></tr>
|
|
286
|
+
<tr><td><code>--ry-split-max-width</code></td><td>CSS length</td><td>Max width during resize (default 80% of container)</td></tr>
|
|
287
|
+
</tbody>
|
|
288
|
+
</table>
|
|
289
|
+
</ry-section>
|
|
290
|
+
|
|
291
|
+
<!-- Check List -->
|
|
292
|
+
<ry-section>
|
|
293
|
+
<h2>Check List</h2>
|
|
294
|
+
<ry-example title="check-list">
|
|
295
|
+
<template>
|
|
296
|
+
<ul class="ry-check-list">
|
|
297
|
+
<li>Unlimited projects</li>
|
|
298
|
+
<li>Priority support</li>
|
|
299
|
+
<li>Advanced analytics</li>
|
|
300
|
+
<li>Custom domains</li>
|
|
301
|
+
</ul>
|
|
302
|
+
</template>
|
|
303
|
+
</ry-example>
|
|
304
|
+
<table>
|
|
305
|
+
<thead><tr><th>Class</th><th>Description</th></tr></thead>
|
|
306
|
+
<tbody>
|
|
307
|
+
<tr><td><code>.ry-check-list</code></td><td>Green checkmark list (CSS-only, no JS)</td></tr>
|
|
308
|
+
</tbody>
|
|
309
|
+
</table>
|
|
310
|
+
</ry-section>
|
|
311
|
+
|
|
312
|
+
<!-- Accordion -->
|
|
313
|
+
<ry-section>
|
|
314
|
+
<h2>Accordion</h2>
|
|
315
|
+
<ry-example title="accordion">
|
|
316
|
+
<template>
|
|
317
|
+
<accordion>
|
|
318
|
+
<accordion-item title="What is ry-ui?" open>
|
|
319
|
+
A framework-agnostic, Light DOM component library.
|
|
320
|
+
</accordion-item>
|
|
321
|
+
<accordion-item title="Do I need a build step?">
|
|
322
|
+
Nope! Just link the CSS and JS files.
|
|
323
|
+
</accordion-item>
|
|
324
|
+
</accordion>
|
|
325
|
+
</template>
|
|
326
|
+
<script slot="js" type="text/plain">
|
|
327
|
+
const accordion = document.querySelector('ry-accordion');
|
|
328
|
+
const item = document.querySelector('ry-accordion-item');
|
|
329
|
+
|
|
330
|
+
// Listen for open/close
|
|
331
|
+
item.addEventListener('ry:toggle', (e) => {
|
|
332
|
+
console.log(e.detail.open); // true or false
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
// Open/close programmatically
|
|
336
|
+
item.open = true; // Expand
|
|
337
|
+
item.open = false; // Collapse
|
|
338
|
+
|
|
339
|
+
// Toggle
|
|
340
|
+
item.toggle();
|
|
341
|
+
</script>
|
|
342
|
+
</ry-example>
|
|
343
|
+
<table>
|
|
344
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
345
|
+
<tbody>
|
|
346
|
+
<tr><td><code>title</code></td><td>string</td><td>Header text (on accordion-item)</td></tr>
|
|
347
|
+
<tr><td><code>open</code></td><td>boolean</td><td>Initially expanded (on accordion-item)</td></tr>
|
|
348
|
+
</tbody>
|
|
349
|
+
</table>
|
|
350
|
+
</ry-section>
|
|
351
|
+
|
|
352
|
+
<!-- Tabs -->
|
|
353
|
+
<ry-section>
|
|
354
|
+
<h2>Tabs</h2>
|
|
355
|
+
<ry-example title="tabs">
|
|
356
|
+
<template>
|
|
357
|
+
<tabs>
|
|
358
|
+
<tab title="Overview" active>
|
|
359
|
+
<p>This is the overview tab content.</p>
|
|
360
|
+
</tab>
|
|
361
|
+
<tab title="Features">
|
|
362
|
+
<p>This is the features tab content.</p>
|
|
363
|
+
</tab>
|
|
364
|
+
</tabs>
|
|
365
|
+
</template>
|
|
366
|
+
<script slot="js" type="text/plain">
|
|
367
|
+
const tabs = document.querySelector('ry-tabs');
|
|
368
|
+
|
|
369
|
+
// Listen for tab changes
|
|
370
|
+
tabs.addEventListener('ry:change', (e) => {
|
|
371
|
+
console.log(e.detail.index); // 0, 1, 2...
|
|
372
|
+
console.log(e.detail.title); // "Overview"
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
// Switch tabs programmatically
|
|
376
|
+
tabs.activeIndex = 1; // Switch to second tab
|
|
377
|
+
</script>
|
|
378
|
+
</ry-example>
|
|
379
|
+
<table>
|
|
380
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
381
|
+
<tbody>
|
|
382
|
+
<tr><td><code>title</code></td><td>string</td><td>Tab label (on tab)</td></tr>
|
|
383
|
+
<tr><td><code>active</code></td><td>boolean</td><td>Initially selected (on tab)</td></tr>
|
|
384
|
+
</tbody>
|
|
385
|
+
</table>
|
|
386
|
+
</ry-section>
|
|
387
|
+
|
|
388
|
+
<!-- Modal -->
|
|
389
|
+
<ry-section>
|
|
390
|
+
<h2>Modal</h2>
|
|
391
|
+
<ry-example title="modal">
|
|
392
|
+
<template>
|
|
393
|
+
<button modal="example-modal">Open Modal</button>
|
|
394
|
+
|
|
395
|
+
<modal id="example-modal" title="Modal Title">
|
|
396
|
+
<p>Modal content with focus trapping.</p>
|
|
397
|
+
<actions slot="footer">
|
|
398
|
+
<button variant="ghost" close>Cancel</button>
|
|
399
|
+
<button>Confirm</button>
|
|
400
|
+
</actions>
|
|
401
|
+
</modal>
|
|
402
|
+
</template>
|
|
403
|
+
<script slot="js" type="text/plain">
|
|
404
|
+
const modal = document.querySelector('ry-modal');
|
|
405
|
+
|
|
406
|
+
// Listen for open/close
|
|
407
|
+
modal.addEventListener('ry:open', () => {
|
|
408
|
+
console.log('Modal opened');
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
modal.addEventListener('ry:close', () => {
|
|
412
|
+
console.log('Modal closed');
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
// Open/close programmatically
|
|
416
|
+
modal.open();
|
|
417
|
+
modal.close();
|
|
418
|
+
|
|
419
|
+
// Check state
|
|
420
|
+
if (modal.state === 'open') { ... }
|
|
421
|
+
</script>
|
|
422
|
+
</ry-example>
|
|
423
|
+
<table>
|
|
424
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
425
|
+
<tbody>
|
|
426
|
+
<tr><td><code>id</code></td><td>string</td><td>Modal identifier</td></tr>
|
|
427
|
+
<tr><td><code>title</code></td><td>string</td><td>Header title</td></tr>
|
|
428
|
+
<tr><td><code>close</code></td><td>boolean</td><td>Closes modal (on button)</td></tr>
|
|
429
|
+
</tbody>
|
|
430
|
+
</table>
|
|
431
|
+
</ry-section>
|
|
432
|
+
|
|
433
|
+
<!-- Dropdown -->
|
|
434
|
+
<ry-section>
|
|
435
|
+
<h2>Dropdown</h2>
|
|
436
|
+
<ry-example title="dropdown">
|
|
437
|
+
<template>
|
|
438
|
+
<dropdown>
|
|
439
|
+
<button slot="trigger">Options ▾</button>
|
|
440
|
+
<menu>
|
|
441
|
+
<menu-item>Edit</menu-item>
|
|
442
|
+
<menu-item>Duplicate</menu-item>
|
|
443
|
+
<divider></divider>
|
|
444
|
+
<menu-item>Delete</menu-item>
|
|
445
|
+
</menu>
|
|
446
|
+
</dropdown>
|
|
447
|
+
</template>
|
|
448
|
+
<script slot="js" type="text/plain">
|
|
449
|
+
const dropdown = document.querySelector('ry-dropdown');
|
|
450
|
+
|
|
451
|
+
// Listen for menu item selection
|
|
452
|
+
dropdown.addEventListener('ry:select', (e) => {
|
|
453
|
+
console.log(e.detail.value); // "Edit", "Delete", etc.
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
// Open/close programmatically
|
|
457
|
+
dropdown.open();
|
|
458
|
+
dropdown.close();
|
|
459
|
+
</script>
|
|
460
|
+
</ry-example>
|
|
461
|
+
<table>
|
|
462
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
463
|
+
<tbody>
|
|
464
|
+
<tr><td><code>slot="trigger"</code></td><td>—</td><td>Marks the trigger element</td></tr>
|
|
465
|
+
</tbody>
|
|
466
|
+
</table>
|
|
467
|
+
</ry-section>
|
|
468
|
+
|
|
469
|
+
<!-- Field -->
|
|
470
|
+
<ry-section>
|
|
471
|
+
<h2>Field</h2>
|
|
472
|
+
<ry-example title="field">
|
|
473
|
+
<template>
|
|
474
|
+
<stack>
|
|
475
|
+
<field label="Email" hint="We'll never share your email">
|
|
476
|
+
<input type="email" placeholder="you@example.com">
|
|
477
|
+
</field>
|
|
478
|
+
<field label="Password" error="Must be at least 8 characters">
|
|
479
|
+
<input type="password" placeholder="Enter password">
|
|
480
|
+
</field>
|
|
481
|
+
<field label="Message">
|
|
482
|
+
<textarea rows="3" placeholder="Your message..."></textarea>
|
|
483
|
+
</field>
|
|
484
|
+
</stack>
|
|
485
|
+
</template>
|
|
486
|
+
</ry-example>
|
|
487
|
+
<table>
|
|
488
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
489
|
+
<tbody>
|
|
490
|
+
<tr><td><code>label</code></td><td>string</td><td>Field label text</td></tr>
|
|
491
|
+
<tr><td><code>error</code></td><td>string</td><td>Error message (hides hint when set)</td></tr>
|
|
492
|
+
<tr><td><code>hint</code></td><td>string</td><td>Helper text below input</td></tr>
|
|
493
|
+
</tbody>
|
|
494
|
+
</table>
|
|
495
|
+
</ry-section>
|
|
496
|
+
|
|
497
|
+
<!-- Checkbox -->
|
|
498
|
+
<ry-section>
|
|
499
|
+
<h2>Checkbox</h2>
|
|
500
|
+
<ry-example title="checkbox">
|
|
501
|
+
<template>
|
|
502
|
+
<stack gap="sm">
|
|
503
|
+
<label>
|
|
504
|
+
<input type="checkbox" checked> Accept terms and conditions
|
|
505
|
+
</label>
|
|
506
|
+
<label>
|
|
507
|
+
<input type="checkbox"> Subscribe to newsletter
|
|
508
|
+
</label>
|
|
509
|
+
<label>
|
|
510
|
+
<input type="checkbox" disabled> Disabled option
|
|
511
|
+
</label>
|
|
512
|
+
</stack>
|
|
513
|
+
</template>
|
|
514
|
+
</ry-example>
|
|
515
|
+
<table>
|
|
516
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
517
|
+
<tbody>
|
|
518
|
+
<tr><td><code>checked</code></td><td>boolean</td><td>Initially checked</td></tr>
|
|
519
|
+
<tr><td><code>disabled</code></td><td>boolean</td><td>Disable interaction</td></tr>
|
|
520
|
+
</tbody>
|
|
521
|
+
</table>
|
|
522
|
+
</ry-section>
|
|
523
|
+
|
|
524
|
+
<!-- Radio -->
|
|
525
|
+
<ry-section>
|
|
526
|
+
<h2>Radio</h2>
|
|
527
|
+
<ry-example title="radio">
|
|
528
|
+
<template>
|
|
529
|
+
<stack gap="sm">
|
|
530
|
+
<label>
|
|
531
|
+
<input type="radio" name="plan" value="free" checked> Free plan
|
|
532
|
+
</label>
|
|
533
|
+
<label>
|
|
534
|
+
<input type="radio" name="plan" value="pro"> Pro plan
|
|
535
|
+
</label>
|
|
536
|
+
<label>
|
|
537
|
+
<input type="radio" name="plan" value="enterprise"> Enterprise
|
|
538
|
+
</label>
|
|
539
|
+
<label>
|
|
540
|
+
<input type="radio" name="plan" value="disabled" disabled> Disabled
|
|
541
|
+
</label>
|
|
542
|
+
</stack>
|
|
543
|
+
</template>
|
|
544
|
+
</ry-example>
|
|
545
|
+
<table>
|
|
546
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
547
|
+
<tbody>
|
|
548
|
+
<tr><td><code>name</code></td><td>string</td><td>Groups radios together</td></tr>
|
|
549
|
+
<tr><td><code>value</code></td><td>string</td><td>Value when selected</td></tr>
|
|
550
|
+
<tr><td><code>checked</code></td><td>boolean</td><td>Initially selected</td></tr>
|
|
551
|
+
<tr><td><code>disabled</code></td><td>boolean</td><td>Disable interaction</td></tr>
|
|
552
|
+
</tbody>
|
|
553
|
+
</table>
|
|
554
|
+
</ry-section>
|
|
555
|
+
|
|
556
|
+
<!-- Badge -->
|
|
557
|
+
<ry-section>
|
|
558
|
+
<h2>Badge</h2>
|
|
559
|
+
<ry-example title="badge">
|
|
560
|
+
<template>
|
|
561
|
+
<cluster>
|
|
562
|
+
<badge>Default</badge>
|
|
563
|
+
<badge variant="primary">Primary</badge>
|
|
564
|
+
<badge variant="success">Success</badge>
|
|
565
|
+
<badge variant="warning">Warning</badge>
|
|
566
|
+
<badge variant="danger">Danger</badge>
|
|
567
|
+
<badge variant="accent">Accent</badge>
|
|
568
|
+
<badge style="--ry-badge-color: oklch(0.6 0.2 150)">Custom Color</badge>
|
|
569
|
+
</cluster>
|
|
570
|
+
</template>
|
|
571
|
+
</ry-example>
|
|
572
|
+
<table>
|
|
573
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
574
|
+
<tbody>
|
|
575
|
+
<tr><td><code>variant</code></td><td>default | primary | success | warning | danger | accent</td><td>Badge style</td></tr>
|
|
576
|
+
<tr><td><code>--ry-badge-color</code></td><td>CSS color</td><td>Arbitrary background color via style</td></tr>
|
|
577
|
+
<tr><td><code>--ry-badge-text</code></td><td>CSS color</td><td>Arbitrary text color via style</td></tr>
|
|
578
|
+
</tbody>
|
|
579
|
+
</table>
|
|
580
|
+
</ry-section>
|
|
581
|
+
|
|
582
|
+
<!-- Alert -->
|
|
583
|
+
<ry-section>
|
|
584
|
+
<h2>Alert</h2>
|
|
585
|
+
<ry-example title="alert">
|
|
586
|
+
<template>
|
|
587
|
+
<stack>
|
|
588
|
+
<alert type="info" title="Info">
|
|
589
|
+
This is an informational message.
|
|
590
|
+
</alert>
|
|
591
|
+
<alert type="success" title="Success">
|
|
592
|
+
Operation completed successfully.
|
|
593
|
+
</alert>
|
|
594
|
+
<alert type="warning" title="Warning">
|
|
595
|
+
Please review before continuing.
|
|
596
|
+
</alert>
|
|
597
|
+
<alert type="danger" title="Error">
|
|
598
|
+
Something went wrong.
|
|
599
|
+
</alert>
|
|
600
|
+
</stack>
|
|
601
|
+
</template>
|
|
602
|
+
</ry-example>
|
|
603
|
+
<table>
|
|
604
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
605
|
+
<tbody>
|
|
606
|
+
<tr><td><code>type</code></td><td>info | success | warning | danger</td><td>Alert style</td></tr>
|
|
607
|
+
<tr><td><code>title</code></td><td>string</td><td>Alert heading</td></tr>
|
|
608
|
+
</tbody>
|
|
609
|
+
</table>
|
|
610
|
+
</ry-section>
|
|
611
|
+
|
|
612
|
+
<!-- Switch -->
|
|
613
|
+
<ry-section>
|
|
614
|
+
<h2>Switch</h2>
|
|
615
|
+
<ry-example title="switch">
|
|
616
|
+
<template>
|
|
617
|
+
<stack gap="sm">
|
|
618
|
+
<switch name="notifications" checked>Enable notifications</switch>
|
|
619
|
+
<switch name="darkMode">Dark mode</switch>
|
|
620
|
+
<switch disabled>Disabled switch</switch>
|
|
621
|
+
</stack>
|
|
622
|
+
</template>
|
|
623
|
+
<script slot="js" type="text/plain">
|
|
624
|
+
const toggle = document.querySelector('ry-switch');
|
|
625
|
+
|
|
626
|
+
// Listen for changes
|
|
627
|
+
toggle.addEventListener('ry:change', (e) => {
|
|
628
|
+
console.log(e.detail.checked); // true or false
|
|
629
|
+
console.log(e.detail.name); // "notifications"
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
// Get/set programmatically
|
|
633
|
+
toggle.checked; // true
|
|
634
|
+
toggle.checked = false; // Turn off
|
|
635
|
+
|
|
636
|
+
// Form usage with hidden input
|
|
637
|
+
const hidden = document.querySelector('input[name="notifications"]');
|
|
638
|
+
toggle.addEventListener('ry:change', (e) => {
|
|
639
|
+
hidden.value = e.detail.checked ? '1' : '0';
|
|
640
|
+
});
|
|
641
|
+
</script>
|
|
642
|
+
</ry-example>
|
|
643
|
+
<table>
|
|
644
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
645
|
+
<tbody>
|
|
646
|
+
<tr><td><code>name</code></td><td>string</td><td>Form field name</td></tr>
|
|
647
|
+
<tr><td><code>checked</code></td><td>boolean</td><td>Initially checked</td></tr>
|
|
648
|
+
<tr><td><code>disabled</code></td><td>boolean</td><td>Disable interaction</td></tr>
|
|
649
|
+
</tbody>
|
|
650
|
+
</table>
|
|
651
|
+
</ry-section>
|
|
652
|
+
|
|
653
|
+
<!-- Slider -->
|
|
654
|
+
<ry-section>
|
|
655
|
+
<h2>Slider</h2>
|
|
656
|
+
<ry-example title="slider" stacked>
|
|
657
|
+
<template>
|
|
658
|
+
<stack gap="lg">
|
|
659
|
+
<slider min="0" max="100" value="50"></slider>
|
|
660
|
+
|
|
661
|
+
<slider min="0" max="100" start="25" end="75" range labeled></slider>
|
|
662
|
+
|
|
663
|
+
<slider min="0" max="10" step="1" value="5" ticked labeled tooltip></slider>
|
|
664
|
+
|
|
665
|
+
<stack gap="sm">
|
|
666
|
+
<slider min="0" max="100" value="60" color="success"></slider>
|
|
667
|
+
<slider min="0" max="100" value="60" color="warning"></slider>
|
|
668
|
+
<slider min="0" max="100" value="60" color="danger"></slider>
|
|
669
|
+
<slider min="0" max="100" value="60" color="info"></slider>
|
|
670
|
+
</stack>
|
|
671
|
+
|
|
672
|
+
<slider min="0" max="100" value="50" disabled></slider>
|
|
673
|
+
</stack>
|
|
674
|
+
</template>
|
|
675
|
+
<script slot="js" type="text/plain">
|
|
676
|
+
const slider = document.querySelector('ry-slider');
|
|
677
|
+
|
|
678
|
+
// Listen for changes (fires during drag)
|
|
679
|
+
slider.addEventListener('ry:input', (e) => {
|
|
680
|
+
console.log(e.detail.value); // 50 (single slider)
|
|
681
|
+
// For range slider:
|
|
682
|
+
// e.detail.start, e.detail.end
|
|
683
|
+
});
|
|
684
|
+
|
|
685
|
+
// Listen for final value (fires on mouseup)
|
|
686
|
+
slider.addEventListener('ry:change', (e) => {
|
|
687
|
+
saveVolume(e.detail.value);
|
|
688
|
+
});
|
|
689
|
+
|
|
690
|
+
// Get/set programmatically
|
|
691
|
+
slider.value; // 50
|
|
692
|
+
slider.value = 75; // Update value
|
|
693
|
+
|
|
694
|
+
// Range slider
|
|
695
|
+
rangeSlider.start; // 25
|
|
696
|
+
rangeSlider.end; // 75
|
|
697
|
+
rangeSlider.start = 10;
|
|
698
|
+
</script>
|
|
699
|
+
</ry-example>
|
|
700
|
+
<table>
|
|
701
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
702
|
+
<tbody>
|
|
703
|
+
<tr><td><code>min</code></td><td>number</td><td>Minimum value (default: 0)</td></tr>
|
|
704
|
+
<tr><td><code>max</code></td><td>number</td><td>Maximum value (default: 100)</td></tr>
|
|
705
|
+
<tr><td><code>step</code></td><td>number</td><td>Step increment, 0 for smooth (default: 1)</td></tr>
|
|
706
|
+
<tr><td><code>value</code></td><td>number</td><td>Current value (single slider)</td></tr>
|
|
707
|
+
<tr><td><code>start</code> / <code>end</code></td><td>number</td><td>Range values (with range attribute)</td></tr>
|
|
708
|
+
<tr><td><code>range</code></td><td>boolean</td><td>Enable dual-handle range mode</td></tr>
|
|
709
|
+
<tr><td><code>labeled</code></td><td>boolean</td><td>Show value labels</td></tr>
|
|
710
|
+
<tr><td><code>ticked</code></td><td>boolean</td><td>Show tick marks</td></tr>
|
|
711
|
+
<tr><td><code>tooltip</code></td><td>boolean</td><td>Show value on thumb hover</td></tr>
|
|
712
|
+
<tr><td><code>vertical</code></td><td>boolean</td><td>Vertical orientation</td></tr>
|
|
713
|
+
<tr><td><code>reversed</code></td><td>boolean</td><td>Reverse direction</td></tr>
|
|
714
|
+
<tr><td><code>color</code></td><td>primary | secondary | success | warning | danger | info</td><td>Track color</td></tr>
|
|
715
|
+
<tr><td><code>size</code></td><td>sm | lg</td><td>Size variant</td></tr>
|
|
716
|
+
<tr><td><code>disabled</code></td><td>boolean</td><td>Disable interaction</td></tr>
|
|
717
|
+
</tbody>
|
|
718
|
+
</table>
|
|
719
|
+
</ry-section>
|
|
720
|
+
|
|
721
|
+
<!-- Knob -->
|
|
722
|
+
<ry-section>
|
|
723
|
+
<h2>Knob</h2>
|
|
724
|
+
<ry-example title="knob" stacked>
|
|
725
|
+
<template>
|
|
726
|
+
<stack gap="lg">
|
|
727
|
+
<cluster>
|
|
728
|
+
<knob min="0" max="100" value="50" label="Volume" description="Master output volume"></knob>
|
|
729
|
+
<knob min="0" max="100" value="75" label="Pan" description="Left/right stereo position"></knob>
|
|
730
|
+
<knob min="0" max="100" value="25" label="Reverb" description="Room reverb amount"></knob>
|
|
731
|
+
</cluster>
|
|
732
|
+
|
|
733
|
+
<cluster>
|
|
734
|
+
<knob min="0" max="3" step="1" value="1" labels="Off,Low,Med,High" label="Mode"></knob>
|
|
735
|
+
<knob min="0" max="4" step="1" value="2" labels="∿,△,▢,▲,◇" label="Wave"></knob>
|
|
736
|
+
</cluster>
|
|
737
|
+
|
|
738
|
+
<cluster>
|
|
739
|
+
<knob value="60" color="success" label="Success"></knob>
|
|
740
|
+
<knob value="60" color="warning" label="Warning"></knob>
|
|
741
|
+
<knob value="60" color="danger" label="Danger"></knob>
|
|
742
|
+
<knob value="60" color="secondary" label="Secondary"></knob>
|
|
743
|
+
</cluster>
|
|
744
|
+
|
|
745
|
+
<cluster>
|
|
746
|
+
<knob size="sm" value="25" label="Small"></knob>
|
|
747
|
+
<knob value="50" label="Default"></knob>
|
|
748
|
+
<knob size="lg" value="75" label="Large"></knob>
|
|
749
|
+
</cluster>
|
|
750
|
+
|
|
751
|
+
<knob min="0" max="100" value="50" label="Disabled" disabled></knob>
|
|
752
|
+
</stack>
|
|
753
|
+
</template>
|
|
754
|
+
<script slot="js" type="text/plain">
|
|
755
|
+
const knob = document.querySelector('ry-knob');
|
|
756
|
+
|
|
757
|
+
// Listen for changes (fires during drag)
|
|
758
|
+
knob.addEventListener('ry:input', (e) => {
|
|
759
|
+
console.log(e.detail.value); // 0-100
|
|
760
|
+
updateVolume(e.detail.value);
|
|
761
|
+
});
|
|
762
|
+
|
|
763
|
+
// Listen for final value (fires on release)
|
|
764
|
+
knob.addEventListener('ry:change', (e) => {
|
|
765
|
+
saveSettings({ volume: e.detail.value });
|
|
766
|
+
});
|
|
767
|
+
|
|
768
|
+
// Get/set programmatically
|
|
769
|
+
knob.value; // 50
|
|
770
|
+
knob.value = 75; // Update value
|
|
771
|
+
|
|
772
|
+
// For discrete knobs with labels
|
|
773
|
+
modeKnob.value; // 1 (index)
|
|
774
|
+
// Labels: "Off,Low,Med,High" → value 1 = "Low"
|
|
775
|
+
</script>
|
|
776
|
+
</ry-example>
|
|
777
|
+
<table>
|
|
778
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
779
|
+
<tbody>
|
|
780
|
+
<tr><td><code>min</code></td><td>number</td><td>Minimum value (default: 0)</td></tr>
|
|
781
|
+
<tr><td><code>max</code></td><td>number</td><td>Maximum value (default: 100)</td></tr>
|
|
782
|
+
<tr><td><code>step</code></td><td>number</td><td>Step increment, 0 for smooth (default: 0)</td></tr>
|
|
783
|
+
<tr><td><code>value</code></td><td>number</td><td>Current value</td></tr>
|
|
784
|
+
<tr><td><code>label</code></td><td>string</td><td>Label text below knob</td></tr>
|
|
785
|
+
<tr><td><code>labels</code></td><td>string</td><td>Comma-separated display labels for discrete values</td></tr>
|
|
786
|
+
<tr><td><code>description</code></td><td>string</td><td>Tooltip text shown on hover</td></tr>
|
|
787
|
+
<tr><td><code>color</code></td><td>primary | secondary | success | warning | danger</td><td>Track color</td></tr>
|
|
788
|
+
<tr><td><code>size</code></td><td>sm | lg</td><td>Size variant</td></tr>
|
|
789
|
+
<tr><td><code>disabled</code></td><td>boolean</td><td>Disable interaction</td></tr>
|
|
790
|
+
</tbody>
|
|
791
|
+
</table>
|
|
792
|
+
</ry-section>
|
|
793
|
+
|
|
794
|
+
<!-- Number Select -->
|
|
795
|
+
<ry-section>
|
|
796
|
+
<h2>Number Select</h2>
|
|
797
|
+
<ry-example title="number-select" stacked>
|
|
798
|
+
<template>
|
|
799
|
+
<ry-stack gap="xl">
|
|
800
|
+
|
|
801
|
+
<p><strong>Arrow placement</strong></p>
|
|
802
|
+
<ry-cluster gap="lg">
|
|
803
|
+
<ry-number-select min="0" max="100" value="50"></ry-number-select>
|
|
804
|
+
<ry-number-select min="0" max="100" value="50" arrows="start"></ry-number-select>
|
|
805
|
+
<ry-number-select min="0" max="100" value="50" arrows="end"></ry-number-select>
|
|
806
|
+
<ry-number-select min="0" max="100" value="50" arrows="none"></ry-number-select>
|
|
807
|
+
<ry-number-select min="0" max="100" value="50" arrows="stacked"></ry-number-select>
|
|
808
|
+
<ry-number-select min="0" max="100" value="50" arrows="stacked-end" icons="chevron"></ry-number-select>
|
|
809
|
+
<ry-number-select min="0" max="100" value="50" arrows="stacked-start" icons="chevron"></ry-number-select>
|
|
810
|
+
</ry-cluster>
|
|
811
|
+
|
|
812
|
+
<p><strong>Icon styles</strong></p>
|
|
813
|
+
<ry-cluster gap="lg">
|
|
814
|
+
<ry-number-select min="0" max="100" value="50"></ry-number-select>
|
|
815
|
+
<ry-number-select min="0" max="100" value="50" icons="chevron"></ry-number-select>
|
|
816
|
+
<ry-number-select min="0" max="100" value="50" icons="arrow"></ry-number-select>
|
|
817
|
+
<ry-number-select min="0" max="100" value="50" icons="chevron" arrows="stacked"></ry-number-select>
|
|
818
|
+
<ry-number-select min="0" max="100" value="50" icons="arrow" arrows="stacked"></ry-number-select>
|
|
819
|
+
</ry-cluster>
|
|
820
|
+
|
|
821
|
+
<p><strong>Drag direction</strong> — stacked defaults to vertical</p>
|
|
822
|
+
<ry-cluster gap="lg">
|
|
823
|
+
<ry-number-select min="0" max="100" value="50"></ry-number-select>
|
|
824
|
+
<ry-number-select min="0" max="100" value="50" drag="y"></ry-number-select>
|
|
825
|
+
<ry-number-select min="0" max="100" value="50" drag="none"></ry-number-select>
|
|
826
|
+
</ry-cluster>
|
|
827
|
+
|
|
828
|
+
<p><strong>Prefix & suffix</strong></p>
|
|
829
|
+
<ry-cluster gap="lg">
|
|
830
|
+
<ry-number-select min="0" max="1000" value="50" prefix="$"></ry-number-select>
|
|
831
|
+
<ry-number-select min="0" max="360" value="90" suffix="°" icons="chevron" arrows="stacked"></ry-number-select>
|
|
832
|
+
<ry-number-select min="0" max="100" value="75" suffix="%"></ry-number-select>
|
|
833
|
+
<ry-number-select min="0" max="100" value="50" prefix="$" suffix="USD" editable></ry-number-select>
|
|
834
|
+
</ry-cluster>
|
|
835
|
+
|
|
836
|
+
<p><strong>Step intervals</strong></p>
|
|
837
|
+
<ry-cluster gap="lg">
|
|
838
|
+
<ry-number-select min="0" max="100" value="50" step="1"></ry-number-select>
|
|
839
|
+
<ry-number-select min="0" max="100" value="50" step="5"></ry-number-select>
|
|
840
|
+
<ry-number-select min="0" max="10" value="5" step="0.1"></ry-number-select>
|
|
841
|
+
<ry-number-select min="0" max="1" value="0.5" step="0.01"></ry-number-select>
|
|
842
|
+
</ry-cluster>
|
|
843
|
+
|
|
844
|
+
<p><strong>Behaviors</strong></p>
|
|
845
|
+
<ry-cluster gap="lg">
|
|
846
|
+
<ry-number-select min="0" max="100" value="50" editable></ry-number-select>
|
|
847
|
+
<ry-number-select min="0" max="7" value="3" wrap></ry-number-select>
|
|
848
|
+
<ry-number-select min="0" max="100" value="50" disabled></ry-number-select>
|
|
849
|
+
</ry-cluster>
|
|
850
|
+
|
|
851
|
+
<p><strong>Sizes</strong></p>
|
|
852
|
+
<ry-cluster gap="lg" style="align-items: center">
|
|
853
|
+
<ry-number-select min="0" max="100" value="50" size="xs"></ry-number-select>
|
|
854
|
+
<ry-number-select min="0" max="100" value="50" size="sm"></ry-number-select>
|
|
855
|
+
<ry-number-select min="0" max="100" value="50"></ry-number-select>
|
|
856
|
+
<ry-number-select min="0" max="100" value="50" size="lg"></ry-number-select>
|
|
857
|
+
</ry-cluster>
|
|
858
|
+
|
|
859
|
+
</ry-stack>
|
|
860
|
+
</template>
|
|
861
|
+
<script slot="js" type="text/plain">
|
|
862
|
+
const ns = document.querySelector('ry-number-select');
|
|
863
|
+
|
|
864
|
+
// Events — ry:input fires during drag, ry:change on commit
|
|
865
|
+
ns.addEventListener('ry:input', (e) => {
|
|
866
|
+
console.log('input:', e.detail.value);
|
|
867
|
+
});
|
|
868
|
+
ns.addEventListener('ry:change', (e) => {
|
|
869
|
+
console.log('change:', e.detail.value);
|
|
870
|
+
});
|
|
871
|
+
|
|
872
|
+
// Programmatic API
|
|
873
|
+
ns.value; // 50
|
|
874
|
+
ns.value = 75;
|
|
875
|
+
ns.min = 10;
|
|
876
|
+
ns.step = 5;
|
|
877
|
+
ns.drag = 'y'; // switch drag direction
|
|
878
|
+
ns.disabled = true;
|
|
879
|
+
</script>
|
|
880
|
+
</ry-example>
|
|
881
|
+
<table>
|
|
882
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
883
|
+
<tbody>
|
|
884
|
+
<tr><td><code>min</code></td><td>number</td><td>Minimum value (default: 0)</td></tr>
|
|
885
|
+
<tr><td><code>max</code></td><td>number</td><td>Maximum value (default: 100)</td></tr>
|
|
886
|
+
<tr><td><code>step</code></td><td>number</td><td>Step increment (default: 1)</td></tr>
|
|
887
|
+
<tr><td><code>value</code></td><td>number</td><td>Current value (default: 0)</td></tr>
|
|
888
|
+
<tr><td><code>arrows</code></td><td>both | start | end | stacked | none</td><td>Button placement (default: both)</td></tr>
|
|
889
|
+
<tr><td><code>icons</code></td><td>plus-minus | chevron | arrow</td><td>Button icon style (default: plus-minus)</td></tr>
|
|
890
|
+
<tr><td><code>drag</code></td><td>x | y | none</td><td>Drag direction (default: x, stacked defaults to y)</td></tr>
|
|
891
|
+
<tr><td><code>prefix</code></td><td>string</td><td>Text before value (e.g. "$")</td></tr>
|
|
892
|
+
<tr><td><code>suffix</code></td><td>string</td><td>Text after value (e.g. "°", "%")</td></tr>
|
|
893
|
+
<tr><td><code>editable</code></td><td>boolean</td><td>Allow direct typing on click</td></tr>
|
|
894
|
+
<tr><td><code>wrap</code></td><td>boolean</td><td>Wrap around min/max boundaries</td></tr>
|
|
895
|
+
<tr><td><code>size</code></td><td>xs | sm | lg</td><td>Size variant</td></tr>
|
|
896
|
+
<tr><td><code>disabled</code></td><td>boolean</td><td>Disable interaction</td></tr>
|
|
897
|
+
</tbody>
|
|
898
|
+
</table>
|
|
899
|
+
</ry-section>
|
|
900
|
+
|
|
901
|
+
<!-- Color Picker -->
|
|
902
|
+
<ry-section>
|
|
903
|
+
<h2>Color Picker</h2>
|
|
904
|
+
<ry-example title="color-picker" stacked>
|
|
905
|
+
<template>
|
|
906
|
+
<stack gap="lg">
|
|
907
|
+
<p><strong>Dropdown mode (default)</strong> - click to open:</p>
|
|
908
|
+
<cluster>
|
|
909
|
+
<color-picker value="#3b82f6"></color-picker>
|
|
910
|
+
<color-picker value="#22c55e"></color-picker>
|
|
911
|
+
<color-picker value="#8b5cf6"></color-picker>
|
|
912
|
+
<color-picker value="#ef4444" opacity></color-picker>
|
|
913
|
+
</cluster>
|
|
914
|
+
|
|
915
|
+
<p><strong>With swatches:</strong></p>
|
|
916
|
+
<color-picker
|
|
917
|
+
value="#3b82f6"
|
|
918
|
+
swatches="#ef4444;#f59e0b;#22c55e;#3b82f6;#8b5cf6;#ec4899;#1e293b;#ffffff"
|
|
919
|
+
></color-picker>
|
|
920
|
+
|
|
921
|
+
<p><strong>Inline mode</strong> - always visible:</p>
|
|
922
|
+
<color-picker value="#3b82f6" inline></color-picker>
|
|
923
|
+
|
|
924
|
+
<p><strong>With opacity + swatches (inline):</strong></p>
|
|
925
|
+
<color-picker
|
|
926
|
+
value="rgba(59, 130, 246, 0.7)"
|
|
927
|
+
format="rgb"
|
|
928
|
+
opacity
|
|
929
|
+
inline
|
|
930
|
+
swatches="#ef4444;#f59e0b;#22c55e;#3b82f6;#8b5cf6;#ec4899"
|
|
931
|
+
></color-picker>
|
|
932
|
+
|
|
933
|
+
<cluster>
|
|
934
|
+
<color-picker value="#64748b" disabled></color-picker>
|
|
935
|
+
<span style="color: var(--ry-color-text-muted)">Disabled</span>
|
|
936
|
+
</cluster>
|
|
937
|
+
</stack>
|
|
938
|
+
</template>
|
|
939
|
+
<script slot="js" type="text/plain">
|
|
940
|
+
// Get the element
|
|
941
|
+
const picker = document.querySelector('ry-color-picker');
|
|
942
|
+
|
|
943
|
+
// Listen for changes (fires during drag)
|
|
944
|
+
picker.addEventListener('ry:input', (e) => {
|
|
945
|
+
console.log(e.detail.value); // "#3b82f6"
|
|
946
|
+
console.log(e.detail.rgb); // { r: 59, g: 130, b: 246 }
|
|
947
|
+
console.log(e.detail.hsv); // { h: 217, s: 76, v: 96 }
|
|
948
|
+
});
|
|
949
|
+
|
|
950
|
+
// Listen for final value (fires on mouseup/blur)
|
|
951
|
+
picker.addEventListener('ry:change', (e) => {
|
|
952
|
+
saveColor(e.detail.value);
|
|
953
|
+
});
|
|
954
|
+
|
|
955
|
+
// Get/set programmatically
|
|
956
|
+
picker.value; // "#3b82f6"
|
|
957
|
+
picker.value = '#ff0000'; // Set new color
|
|
958
|
+
picker.setColor('hsl(200, 100%, 50%)'); // Accepts any format
|
|
959
|
+
|
|
960
|
+
// Access color in different formats
|
|
961
|
+
picker.rgb; // { r: 59, g: 130, b: 246 }
|
|
962
|
+
picker.hsl; // { h: 217, s: 89, l: 60 }
|
|
963
|
+
picker.hsv; // { h: 217, s: 76, v: 96 }
|
|
964
|
+
|
|
965
|
+
// Form submission
|
|
966
|
+
form.addEventListener('submit', (e) => {
|
|
967
|
+
const color = picker.value;
|
|
968
|
+
fetch('/api/save', { body: JSON.stringify({ color }) });
|
|
969
|
+
});
|
|
970
|
+
</script>
|
|
971
|
+
</ry-example>
|
|
972
|
+
<table>
|
|
973
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
974
|
+
<tbody>
|
|
975
|
+
<tr><td><code>value</code></td><td>color string</td><td>Initial color (hex, rgb, hsl)</td></tr>
|
|
976
|
+
<tr><td><code>format</code></td><td>hex | rgb | hsl</td><td>Output format (default: hex)</td></tr>
|
|
977
|
+
<tr><td><code>inline</code></td><td>boolean</td><td>Always show picker (no dropdown)</td></tr>
|
|
978
|
+
<tr><td><code>opacity</code></td><td>boolean</td><td>Enable alpha channel slider</td></tr>
|
|
979
|
+
<tr><td><code>swatches</code></td><td>string</td><td>Preset colors separated by semicolons</td></tr>
|
|
980
|
+
<tr><td><code>disabled</code></td><td>boolean</td><td>Disable interaction</td></tr>
|
|
981
|
+
</tbody>
|
|
982
|
+
</table>
|
|
983
|
+
</ry-section>
|
|
984
|
+
|
|
985
|
+
<!-- Color Input -->
|
|
986
|
+
<ry-section>
|
|
987
|
+
<h2>Color Input</h2>
|
|
988
|
+
<ry-example title="color-input" stacked>
|
|
989
|
+
<template>
|
|
990
|
+
<stack gap="lg">
|
|
991
|
+
<p>Input-style color picker with editable hex value:</p>
|
|
992
|
+
<cluster>
|
|
993
|
+
<color-input value="#3b82f6"></color-input>
|
|
994
|
+
<color-input value="#22c55e"></color-input>
|
|
995
|
+
<color-input value="#ef4444"></color-input>
|
|
996
|
+
</cluster>
|
|
997
|
+
|
|
998
|
+
<p>With opacity support:</p>
|
|
999
|
+
<color-input value="rgba(139, 92, 246, 0.8)" opacity></color-input>
|
|
1000
|
+
|
|
1001
|
+
<cluster>
|
|
1002
|
+
<color-input value="#64748b" disabled></color-input>
|
|
1003
|
+
<span style="color: var(--ry-color-text-muted)">Disabled</span>
|
|
1004
|
+
</cluster>
|
|
1005
|
+
</stack>
|
|
1006
|
+
</template>
|
|
1007
|
+
<script slot="js" type="text/plain">
|
|
1008
|
+
const input = document.querySelector('ry-color-input');
|
|
1009
|
+
|
|
1010
|
+
// Listen for changes
|
|
1011
|
+
input.addEventListener('ry:change', (e) => {
|
|
1012
|
+
console.log(e.detail.value); // "#3b82f6"
|
|
1013
|
+
});
|
|
1014
|
+
|
|
1015
|
+
// Get/set programmatically
|
|
1016
|
+
input.value; // "#3b82f6"
|
|
1017
|
+
input.value = '#ff0000';
|
|
1018
|
+
|
|
1019
|
+
// Works great in forms
|
|
1020
|
+
const hidden = document.querySelector('input[name="brandColor"]');
|
|
1021
|
+
input.addEventListener('ry:change', (e) => {
|
|
1022
|
+
hidden.value = e.detail.value;
|
|
1023
|
+
});
|
|
1024
|
+
</script>
|
|
1025
|
+
</ry-example>
|
|
1026
|
+
<table>
|
|
1027
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
1028
|
+
<tbody>
|
|
1029
|
+
<tr><td><code>value</code></td><td>color string</td><td>Initial color (hex, rgb, hsl)</td></tr>
|
|
1030
|
+
<tr><td><code>format</code></td><td>hex | rgb | hsl</td><td>Output format (default: hex)</td></tr>
|
|
1031
|
+
<tr><td><code>opacity</code></td><td>boolean</td><td>Enable alpha channel slider</td></tr>
|
|
1032
|
+
<tr><td><code>placeholder</code></td><td>string</td><td>Placeholder text for input</td></tr>
|
|
1033
|
+
<tr><td><code>disabled</code></td><td>boolean</td><td>Disable interaction</td></tr>
|
|
1034
|
+
</tbody>
|
|
1035
|
+
</table>
|
|
1036
|
+
</ry-section>
|
|
1037
|
+
|
|
1038
|
+
<!-- Gradient Picker -->
|
|
1039
|
+
<ry-section>
|
|
1040
|
+
<h2>Gradient Picker</h2>
|
|
1041
|
+
<ry-example title="gradient-picker" stacked>
|
|
1042
|
+
<template>
|
|
1043
|
+
<stack gap="lg">
|
|
1044
|
+
<p><strong>Linear gradient</strong> (default):</p>
|
|
1045
|
+
<gradient-picker value="linear-gradient(90deg, #3b82f6 0%, #8b5cf6 100%)"></gradient-picker>
|
|
1046
|
+
|
|
1047
|
+
<p><strong>Multi-stop rainbow with CSS output:</strong></p>
|
|
1048
|
+
<gradient-picker value="linear-gradient(90deg, #ef4444 0%, #f59e0b 25%, #22c55e 50%, #3b82f6 75%, #8b5cf6 100%)" output></gradient-picker>
|
|
1049
|
+
|
|
1050
|
+
<p><strong>Radial gradient:</strong></p>
|
|
1051
|
+
<gradient-picker value="radial-gradient(circle, #fbbf24 0%, #f97316 50%, #dc2626 100%)"></gradient-picker>
|
|
1052
|
+
</stack>
|
|
1053
|
+
</template>
|
|
1054
|
+
<script slot="js" type="text/plain">
|
|
1055
|
+
const picker = document.querySelector('ry-gradient-picker');
|
|
1056
|
+
|
|
1057
|
+
// Listen for changes
|
|
1058
|
+
picker.addEventListener('ry:input', (e) => {
|
|
1059
|
+
console.log(e.detail.value); // CSS gradient string
|
|
1060
|
+
console.log(e.detail.stops); // [{ id, color, position }, ...]
|
|
1061
|
+
console.log(e.detail.type); // "linear" | "radial"
|
|
1062
|
+
console.log(e.detail.angle); // 90 (degrees, linear only)
|
|
1063
|
+
});
|
|
1064
|
+
|
|
1065
|
+
picker.addEventListener('ry:change', (e) => {
|
|
1066
|
+
applyGradient(e.detail.value);
|
|
1067
|
+
});
|
|
1068
|
+
|
|
1069
|
+
// Get/set programmatically
|
|
1070
|
+
picker.value; // "linear-gradient(90deg, ...)"
|
|
1071
|
+
picker.value = 'radial-gradient(circle, #ff0000 0%, #0000ff 100%)';
|
|
1072
|
+
picker.type; // "linear" | "radial"
|
|
1073
|
+
picker.angle; // 0-360
|
|
1074
|
+
picker.stops; // [{ id, color, position }, ...]
|
|
1075
|
+
|
|
1076
|
+
// Add/remove stops
|
|
1077
|
+
picker.addStop('#ff00ff', 50);
|
|
1078
|
+
picker.removeStop('stop-2');
|
|
1079
|
+
</script>
|
|
1080
|
+
</ry-example>
|
|
1081
|
+
<table>
|
|
1082
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
1083
|
+
<tbody>
|
|
1084
|
+
<tr><td><code>value</code></td><td>CSS gradient string</td><td>Initial gradient value</td></tr>
|
|
1085
|
+
<tr><td><code>disabled</code></td><td>boolean</td><td>Disable interaction</td></tr>
|
|
1086
|
+
</tbody>
|
|
1087
|
+
</table>
|
|
1088
|
+
</ry-section>
|
|
1089
|
+
|
|
1090
|
+
<!-- Toggle Button -->
|
|
1091
|
+
<ry-section>
|
|
1092
|
+
<h2>Toggle Button</h2>
|
|
1093
|
+
<ry-example title="toggle-button" stacked>
|
|
1094
|
+
<template>
|
|
1095
|
+
<stack gap="lg">
|
|
1096
|
+
<grid cols="3">
|
|
1097
|
+
<toggle-button name="plan" value="bronze" block>
|
|
1098
|
+
<strong>Bronze</strong><br>
|
|
1099
|
+
<small>Standard Network</small><br>
|
|
1100
|
+
<big><b>$85</b>/month</big><br>
|
|
1101
|
+
<small>Deductible: $6,000 · Coverage: 60%</small><br>
|
|
1102
|
+
<small>✓ Preventive care ✓ Generic Rx ✓ Telehealth</small>
|
|
1103
|
+
</toggle-button>
|
|
1104
|
+
<toggle-button name="plan" value="silver" block>
|
|
1105
|
+
<strong>Silver</strong><br>
|
|
1106
|
+
<small>Enhanced Network</small><br>
|
|
1107
|
+
<big><b>$145</b>/month</big><br>
|
|
1108
|
+
<small>Deductible: $3,000 · Coverage: 80%</small><br>
|
|
1109
|
+
<small>✓ Lower deductible ✓ Specialists ✓ Mental health</small>
|
|
1110
|
+
</toggle-button>
|
|
1111
|
+
<toggle-button name="plan" value="gold" block>
|
|
1112
|
+
<strong>Gold</strong><br>
|
|
1113
|
+
<small>Premium Network</small><br>
|
|
1114
|
+
<big><b>$220</b>/month</big><br>
|
|
1115
|
+
<small>Deductible: $1,000 · Coverage: 90%</small><br>
|
|
1116
|
+
<small>✓ Lowest out-of-pocket ✓ Full Rx ✓ No referrals</small>
|
|
1117
|
+
</toggle-button>
|
|
1118
|
+
</grid>
|
|
1119
|
+
|
|
1120
|
+
<cluster>
|
|
1121
|
+
<toggle-button name="coverage" value="medical" pressed>🏥 Medical</toggle-button>
|
|
1122
|
+
<toggle-button name="coverage" value="dental">🦷 Dental</toggle-button>
|
|
1123
|
+
<toggle-button name="coverage" value="vision">👁 Vision</toggle-button>
|
|
1124
|
+
</cluster>
|
|
1125
|
+
|
|
1126
|
+
<stack>
|
|
1127
|
+
<grid cols="2">
|
|
1128
|
+
<toggle-button name="selection" value="ppo200" block>
|
|
1129
|
+
<strong>Blue PPO $200</strong><br>
|
|
1130
|
+
<small>Employee Only · $200 Deductible</small><br>
|
|
1131
|
+
<b>$171.28</b>/month
|
|
1132
|
+
</toggle-button>
|
|
1133
|
+
<toggle-button name="selection" value="ppo500" block>
|
|
1134
|
+
<strong>Blue PPO $500</strong><br>
|
|
1135
|
+
<small>Employee Only · $500 Deductible</small><br>
|
|
1136
|
+
<b>$142.53</b>/month
|
|
1137
|
+
</toggle-button>
|
|
1138
|
+
</grid>
|
|
1139
|
+
<toggle-button name="selection" value="waive" pressed>Waive $0/month</toggle-button>
|
|
1140
|
+
</stack>
|
|
1141
|
+
</stack>
|
|
1142
|
+
</template>
|
|
1143
|
+
<script slot="js" type="text/plain">
|
|
1144
|
+
const buttons = document.querySelectorAll('ry-toggle-button[name="plan"]');
|
|
1145
|
+
|
|
1146
|
+
// Listen for changes on each button
|
|
1147
|
+
buttons.forEach(btn => {
|
|
1148
|
+
btn.addEventListener('ry:change', (e) => {
|
|
1149
|
+
console.log(e.detail.pressed); // true or false
|
|
1150
|
+
console.log(e.detail.value); // "bronze", "silver", etc.
|
|
1151
|
+
});
|
|
1152
|
+
});
|
|
1153
|
+
|
|
1154
|
+
// Get selected value from a group
|
|
1155
|
+
function getSelectedPlan() {
|
|
1156
|
+
const pressed = document.querySelector(
|
|
1157
|
+
'ry-toggle-button[name="plan"][pressed]'
|
|
1158
|
+
);
|
|
1159
|
+
return pressed?.value; // "gold"
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
// Set programmatically
|
|
1163
|
+
button.pressed = true;
|
|
1164
|
+
|
|
1165
|
+
// Form submission
|
|
1166
|
+
form.addEventListener('submit', (e) => {
|
|
1167
|
+
const plan = getSelectedPlan();
|
|
1168
|
+
fetch('/api/enroll', { body: JSON.stringify({ plan }) });
|
|
1169
|
+
});
|
|
1170
|
+
</script>
|
|
1171
|
+
</ry-example>
|
|
1172
|
+
<table>
|
|
1173
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
1174
|
+
<tbody>
|
|
1175
|
+
<tr><td><code>name</code></td><td>string</td><td>Groups buttons (same name = only one pressed)</td></tr>
|
|
1176
|
+
<tr><td><code>value</code></td><td>string</td><td>Value when selected</td></tr>
|
|
1177
|
+
<tr><td><code>pressed</code></td><td>boolean</td><td>Currently pressed</td></tr>
|
|
1178
|
+
<tr><td><code>disabled</code></td><td>boolean</td><td>Disable interaction</td></tr>
|
|
1179
|
+
<tr><td><code>size</code></td><td>sm | md | lg</td><td>Button size</td></tr>
|
|
1180
|
+
</tbody>
|
|
1181
|
+
</table>
|
|
1182
|
+
</ry-section>
|
|
1183
|
+
|
|
1184
|
+
<!-- Tooltip -->
|
|
1185
|
+
<ry-section>
|
|
1186
|
+
<h2>Tooltip</h2>
|
|
1187
|
+
<ry-example title="tooltip">
|
|
1188
|
+
<template>
|
|
1189
|
+
<cluster>
|
|
1190
|
+
<tooltip content="Top tooltip" position="top">
|
|
1191
|
+
<button>Top</button>
|
|
1192
|
+
</tooltip>
|
|
1193
|
+
<tooltip content="Bottom tooltip" position="bottom">
|
|
1194
|
+
<button>Bottom</button>
|
|
1195
|
+
</tooltip>
|
|
1196
|
+
<tooltip content="Left tooltip" position="left">
|
|
1197
|
+
<button>Left</button>
|
|
1198
|
+
</tooltip>
|
|
1199
|
+
<tooltip content="Right tooltip" position="right">
|
|
1200
|
+
<button>Right</button>
|
|
1201
|
+
</tooltip>
|
|
1202
|
+
</cluster>
|
|
1203
|
+
</template>
|
|
1204
|
+
</ry-example>
|
|
1205
|
+
<table>
|
|
1206
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
1207
|
+
<tbody>
|
|
1208
|
+
<tr><td><code>content</code></td><td>string</td><td>Tooltip text</td></tr>
|
|
1209
|
+
<tr><td><code>position</code></td><td>top | bottom | left | right</td><td>Tooltip position</td></tr>
|
|
1210
|
+
</tbody>
|
|
1211
|
+
</table>
|
|
1212
|
+
</ry-section>
|
|
1213
|
+
|
|
1214
|
+
<!-- Drawer -->
|
|
1215
|
+
<ry-section>
|
|
1216
|
+
<h2>Drawer</h2>
|
|
1217
|
+
<ry-example title="drawer">
|
|
1218
|
+
<template>
|
|
1219
|
+
<button drawer="example-drawer">Open Drawer</button>
|
|
1220
|
+
|
|
1221
|
+
<drawer id="example-drawer" side="right">
|
|
1222
|
+
<h3>Drawer Title</h3>
|
|
1223
|
+
<p>Drawer content here.</p>
|
|
1224
|
+
</drawer>
|
|
1225
|
+
</template>
|
|
1226
|
+
<script slot="js" type="text/plain">
|
|
1227
|
+
const drawer = document.querySelector('ry-drawer');
|
|
1228
|
+
|
|
1229
|
+
// Listen for open/close
|
|
1230
|
+
drawer.addEventListener('ry:open', () => {
|
|
1231
|
+
console.log('Drawer opened');
|
|
1232
|
+
});
|
|
1233
|
+
|
|
1234
|
+
drawer.addEventListener('ry:close', () => {
|
|
1235
|
+
console.log('Drawer closed');
|
|
1236
|
+
});
|
|
1237
|
+
|
|
1238
|
+
// Open/close programmatically
|
|
1239
|
+
drawer.open();
|
|
1240
|
+
drawer.close();
|
|
1241
|
+
|
|
1242
|
+
// Check state
|
|
1243
|
+
if (drawer.state === 'open') { ... }
|
|
1244
|
+
</script>
|
|
1245
|
+
</ry-example>
|
|
1246
|
+
<table>
|
|
1247
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
1248
|
+
<tbody>
|
|
1249
|
+
<tr><td><code>id</code></td><td>string</td><td>Drawer identifier</td></tr>
|
|
1250
|
+
<tr><td><code>side</code></td><td>left | right | bottom</td><td>Slide direction</td></tr>
|
|
1251
|
+
</tbody>
|
|
1252
|
+
</table>
|
|
1253
|
+
</ry-section>
|
|
1254
|
+
|
|
1255
|
+
<!-- Toast -->
|
|
1256
|
+
<ry-section>
|
|
1257
|
+
<h2>Toast</h2>
|
|
1258
|
+
<ry-example title="toast">
|
|
1259
|
+
<template>
|
|
1260
|
+
<cluster>
|
|
1261
|
+
<button onclick="RyToast.success('Saved!')">Success</button>
|
|
1262
|
+
<button onclick="RyToast.error('Failed!')">Error</button>
|
|
1263
|
+
<button onclick="RyToast.warning('Warning!')">Warning</button>
|
|
1264
|
+
<button onclick="RyToast.info('Info!')">Info</button>
|
|
1265
|
+
</cluster>
|
|
1266
|
+
</template>
|
|
1267
|
+
<script slot="js" type="text/plain">
|
|
1268
|
+
// Show toasts (global API)
|
|
1269
|
+
RyToast.success('Changes saved!');
|
|
1270
|
+
RyToast.error('Something went wrong');
|
|
1271
|
+
RyToast.warning('Please review');
|
|
1272
|
+
RyToast.info('New update available');
|
|
1273
|
+
|
|
1274
|
+
// With options
|
|
1275
|
+
RyToast.success('Saved!', {
|
|
1276
|
+
duration: 5000, // ms (default: 3000)
|
|
1277
|
+
});
|
|
1278
|
+
|
|
1279
|
+
// Common patterns
|
|
1280
|
+
async function saveData() {
|
|
1281
|
+
try {
|
|
1282
|
+
await api.save(data);
|
|
1283
|
+
RyToast.success('Saved!');
|
|
1284
|
+
} catch (err) {
|
|
1285
|
+
RyToast.error(err.message);
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
</script>
|
|
1289
|
+
</ry-example>
|
|
1290
|
+
<table>
|
|
1291
|
+
<thead><tr><th>Method</th><th>Description</th></tr></thead>
|
|
1292
|
+
<tbody>
|
|
1293
|
+
<tr><td><code>RyToast.success(msg)</code></td><td>Show success toast</td></tr>
|
|
1294
|
+
<tr><td><code>RyToast.error(msg)</code></td><td>Show error toast</td></tr>
|
|
1295
|
+
<tr><td><code>RyToast.warning(msg)</code></td><td>Show warning toast</td></tr>
|
|
1296
|
+
<tr><td><code>RyToast.info(msg)</code></td><td>Show info toast</td></tr>
|
|
1297
|
+
</tbody>
|
|
1298
|
+
</table>
|
|
1299
|
+
</ry-section>
|
|
1300
|
+
|
|
1301
|
+
<!-- Select -->
|
|
1302
|
+
<ry-section>
|
|
1303
|
+
<h2>Select</h2>
|
|
1304
|
+
<ry-example title="select">
|
|
1305
|
+
<template>
|
|
1306
|
+
<select placeholder="Choose a country" name="country">
|
|
1307
|
+
<option value="us">United States</option>
|
|
1308
|
+
<option value="uk">United Kingdom</option>
|
|
1309
|
+
<option value="ca">Canada</option>
|
|
1310
|
+
<option value="au">Australia</option>
|
|
1311
|
+
</select>
|
|
1312
|
+
</template>
|
|
1313
|
+
<script slot="js" type="text/plain">
|
|
1314
|
+
const select = document.querySelector('ry-select');
|
|
1315
|
+
|
|
1316
|
+
// Listen for selection changes
|
|
1317
|
+
select.addEventListener('ry:change', (e) => {
|
|
1318
|
+
console.log(e.detail.value); // "us"
|
|
1319
|
+
console.log(e.detail.label); // "United States"
|
|
1320
|
+
});
|
|
1321
|
+
|
|
1322
|
+
// Get/set programmatically
|
|
1323
|
+
select.value; // "us"
|
|
1324
|
+
select.value = 'uk'; // Select United Kingdom
|
|
1325
|
+
|
|
1326
|
+
// Open/close the dropdown
|
|
1327
|
+
select.open();
|
|
1328
|
+
select.close();
|
|
1329
|
+
|
|
1330
|
+
// Form integration
|
|
1331
|
+
const formData = new FormData(form);
|
|
1332
|
+
formData.get('country'); // "us"
|
|
1333
|
+
</script>
|
|
1334
|
+
</ry-example>
|
|
1335
|
+
<table>
|
|
1336
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
1337
|
+
<tbody>
|
|
1338
|
+
<tr><td><code>placeholder</code></td><td>string</td><td>Placeholder text</td></tr>
|
|
1339
|
+
<tr><td><code>name</code></td><td>string</td><td>Form field name</td></tr>
|
|
1340
|
+
<tr><td><code>disabled</code></td><td>boolean</td><td>Disable select (on option)</td></tr>
|
|
1341
|
+
<tr><td><code>multiple</code></td><td>boolean</td><td>Enable multi-select with tags</td></tr>
|
|
1342
|
+
<tr><td><code>clearable</code></td><td>boolean</td><td>Show clear button (multi)</td></tr>
|
|
1343
|
+
<tr><td><code>max-selections</code></td><td>number</td><td>Max selections (multi)</td></tr>
|
|
1344
|
+
</tbody>
|
|
1345
|
+
</table>
|
|
1346
|
+
|
|
1347
|
+
<h3 style="margin-top: var(--ry-space-6);">Multi-Select</h3>
|
|
1348
|
+
<ry-example title="select-multi" stacked>
|
|
1349
|
+
<template>
|
|
1350
|
+
<select multiple clearable placeholder="Choose countries...">
|
|
1351
|
+
<option value="us">United States</option>
|
|
1352
|
+
<option value="uk">United Kingdom</option>
|
|
1353
|
+
<option value="ca">Canada</option>
|
|
1354
|
+
<option value="au">Australia</option>
|
|
1355
|
+
<option value="de">Germany</option>
|
|
1356
|
+
<option value="fr">France</option>
|
|
1357
|
+
</select>
|
|
1358
|
+
</template>
|
|
1359
|
+
</ry-example>
|
|
1360
|
+
</ry-section>
|
|
1361
|
+
|
|
1362
|
+
<!-- Combobox -->
|
|
1363
|
+
<ry-section>
|
|
1364
|
+
<h2>Combobox</h2>
|
|
1365
|
+
<ry-example title="combobox">
|
|
1366
|
+
<template>
|
|
1367
|
+
<combobox placeholder="Search countries..." name="country">
|
|
1368
|
+
<option value="us">United States</option>
|
|
1369
|
+
<option value="uk">United Kingdom</option>
|
|
1370
|
+
<option value="ca">Canada</option>
|
|
1371
|
+
<option value="au">Australia</option>
|
|
1372
|
+
<option value="de">Germany</option>
|
|
1373
|
+
<option value="fr">France</option>
|
|
1374
|
+
<option value="jp">Japan</option>
|
|
1375
|
+
<option value="br">Brazil</option>
|
|
1376
|
+
</combobox>
|
|
1377
|
+
</template>
|
|
1378
|
+
<script slot="js" type="text/plain">
|
|
1379
|
+
const combobox = document.querySelector('ry-combobox');
|
|
1380
|
+
|
|
1381
|
+
// Listen for selection
|
|
1382
|
+
combobox.addEventListener('ry:change', (e) => {
|
|
1383
|
+
console.log(e.detail.value); // "us"
|
|
1384
|
+
console.log(e.detail.label); // "United States"
|
|
1385
|
+
});
|
|
1386
|
+
|
|
1387
|
+
// Get/set programmatically
|
|
1388
|
+
combobox.value; // "us"
|
|
1389
|
+
combobox.value = 'uk'; // Select United Kingdom
|
|
1390
|
+
|
|
1391
|
+
// Form integration
|
|
1392
|
+
const formData = new FormData(form);
|
|
1393
|
+
formData.get('country'); // "us"
|
|
1394
|
+
</script>
|
|
1395
|
+
</ry-example>
|
|
1396
|
+
<table>
|
|
1397
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
1398
|
+
<tbody>
|
|
1399
|
+
<tr><td><code>placeholder</code></td><td>string</td><td>Placeholder text for input</td></tr>
|
|
1400
|
+
<tr><td><code>name</code></td><td>string</td><td>Form field name</td></tr>
|
|
1401
|
+
<tr><td><code>value</code></td><td>string</td><td>Currently selected value</td></tr>
|
|
1402
|
+
<tr><td><code>disabled</code></td><td>boolean</td><td>Disable combobox</td></tr>
|
|
1403
|
+
</tbody>
|
|
1404
|
+
</table>
|
|
1405
|
+
</ry-section>
|
|
1406
|
+
|
|
1407
|
+
<!-- Code -->
|
|
1408
|
+
<ry-section>
|
|
1409
|
+
<h2>Code</h2>
|
|
1410
|
+
<ry-example title="ry-code">
|
|
1411
|
+
<template>
|
|
1412
|
+
<ry-code language="js" title="app.js">
|
|
1413
|
+
const greeting = "Hello!";
|
|
1414
|
+
console.log(greeting);
|
|
1415
|
+
</ry-code>
|
|
1416
|
+
</template>
|
|
1417
|
+
</ry-example>
|
|
1418
|
+
<table>
|
|
1419
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
1420
|
+
<tbody>
|
|
1421
|
+
<tr><td><code>language</code></td><td>js | css | html | json</td><td>Syntax highlighting</td></tr>
|
|
1422
|
+
<tr><td><code>title</code></td><td>string</td><td>Header title</td></tr>
|
|
1423
|
+
<tr><td><code>line-numbers</code></td><td>boolean</td><td>Show line numbers</td></tr>
|
|
1424
|
+
</tbody>
|
|
1425
|
+
</table>
|
|
1426
|
+
<p><em>Note: Use <code><ry-code></code> with prefix to avoid conflict with native <code><code></code> tag.</em></p>
|
|
1427
|
+
</ry-section>
|
|
1428
|
+
|
|
1429
|
+
<!-- Table -->
|
|
1430
|
+
<ry-section>
|
|
1431
|
+
<h2>Table</h2>
|
|
1432
|
+
<ry-example title="table">
|
|
1433
|
+
<template>
|
|
1434
|
+
<table>
|
|
1435
|
+
<thead>
|
|
1436
|
+
<tr>
|
|
1437
|
+
<th>Name</th>
|
|
1438
|
+
<th>Role</th>
|
|
1439
|
+
<th>Status</th>
|
|
1440
|
+
</tr>
|
|
1441
|
+
</thead>
|
|
1442
|
+
<tbody>
|
|
1443
|
+
<tr>
|
|
1444
|
+
<td>Alice Johnson</td>
|
|
1445
|
+
<td>Engineer</td>
|
|
1446
|
+
<td>Active</td>
|
|
1447
|
+
</tr>
|
|
1448
|
+
<tr>
|
|
1449
|
+
<td>Bob Smith</td>
|
|
1450
|
+
<td>Designer</td>
|
|
1451
|
+
<td>Active</td>
|
|
1452
|
+
</tr>
|
|
1453
|
+
<tr>
|
|
1454
|
+
<td>Carol White</td>
|
|
1455
|
+
<td>Manager</td>
|
|
1456
|
+
<td>Away</td>
|
|
1457
|
+
</tr>
|
|
1458
|
+
</tbody>
|
|
1459
|
+
</table>
|
|
1460
|
+
</template>
|
|
1461
|
+
</ry-example>
|
|
1462
|
+
<table>
|
|
1463
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
1464
|
+
<tbody>
|
|
1465
|
+
<tr><td><code>data-bordered</code></td><td>boolean</td><td>Add borders to all cells</td></tr>
|
|
1466
|
+
<tr><td><code>data-striped</code></td><td>boolean</td><td>Alternate row backgrounds</td></tr>
|
|
1467
|
+
</tbody>
|
|
1468
|
+
</table>
|
|
1469
|
+
</ry-section>
|
|
1470
|
+
|
|
1471
|
+
<!-- Tree -->
|
|
1472
|
+
<ry-section>
|
|
1473
|
+
<h2>Tree</h2>
|
|
1474
|
+
<ry-example title="tree" stacked>
|
|
1475
|
+
<template>
|
|
1476
|
+
<tree sortable>
|
|
1477
|
+
<tree-item label="src" open>
|
|
1478
|
+
<tree-item label="app" open>
|
|
1479
|
+
<tree-item label="layout.tsx"></tree-item>
|
|
1480
|
+
<tree-item label="page.tsx"></tree-item>
|
|
1481
|
+
</tree-item>
|
|
1482
|
+
<tree-item label="components" open>
|
|
1483
|
+
<tree-item label="ui" open>
|
|
1484
|
+
<tree-item label="button.tsx" selected></tree-item>
|
|
1485
|
+
</tree-item>
|
|
1486
|
+
<tree-item label="header.tsx"></tree-item>
|
|
1487
|
+
<tree-item label="footer.tsx"></tree-item>
|
|
1488
|
+
</tree-item>
|
|
1489
|
+
<tree-item label="lib" open>
|
|
1490
|
+
<tree-item label="utils.ts"></tree-item>
|
|
1491
|
+
</tree-item>
|
|
1492
|
+
</tree-item>
|
|
1493
|
+
</tree>
|
|
1494
|
+
</template>
|
|
1495
|
+
<script slot="js" type="text/plain">
|
|
1496
|
+
const tree = document.querySelector('ry-tree');
|
|
1497
|
+
|
|
1498
|
+
// Listen for file selection
|
|
1499
|
+
tree.addEventListener('ry:select', (e) => {
|
|
1500
|
+
console.log(e.detail.label); // "button.tsx"
|
|
1501
|
+
});
|
|
1502
|
+
|
|
1503
|
+
// Listen for folder toggle
|
|
1504
|
+
tree.addEventListener('ry:toggle', (e) => {
|
|
1505
|
+
console.log(e.detail.label, e.detail.open);
|
|
1506
|
+
});
|
|
1507
|
+
|
|
1508
|
+
// Listen for drag-and-drop moves
|
|
1509
|
+
tree.addEventListener('ry:move', (e) => {
|
|
1510
|
+
console.log(`Moved "${e.detail.item}" ${e.detail.position} "${e.detail.target}"`);
|
|
1511
|
+
|
|
1512
|
+
// Get the full new structure as JSON
|
|
1513
|
+
const state = tree.toJSON();
|
|
1514
|
+
console.log(JSON.stringify(state, null, 2));
|
|
1515
|
+
});
|
|
1516
|
+
|
|
1517
|
+
// Serialize current state
|
|
1518
|
+
tree.toJSON(); // [{ label: "src", open: true, children: [...] }]
|
|
1519
|
+
tree.value; // Same thing
|
|
1520
|
+
|
|
1521
|
+
// Create tree from JSON data
|
|
1522
|
+
const copy = RyTree.from(tree.toJSON());
|
|
1523
|
+
document.body.appendChild(copy);
|
|
1524
|
+
</script>
|
|
1525
|
+
</ry-example>
|
|
1526
|
+
<table>
|
|
1527
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
1528
|
+
<tbody>
|
|
1529
|
+
<tr><td><code>label</code></td><td>string</td><td>Item label (on tree-item)</td></tr>
|
|
1530
|
+
<tr><td><code>open</code></td><td>boolean</td><td>Initially expanded folder (on tree-item with children)</td></tr>
|
|
1531
|
+
<tr><td><code>selected</code></td><td>boolean</td><td>Initially selected file (on leaf tree-item)</td></tr>
|
|
1532
|
+
<tr><td><code>sortable</code></td><td>boolean</td><td>Enable drag-and-drop rearranging (on tree)</td></tr>
|
|
1533
|
+
<tr><td><code>no-animate</code></td><td>boolean</td><td>Disable expand/collapse animation (on tree)</td></tr>
|
|
1534
|
+
<tr><td><code>--ry-tree-duration</code></td><td>CSS time</td><td>Animation duration (default: 150ms)</td></tr>
|
|
1535
|
+
</tbody>
|
|
1536
|
+
</table>
|
|
1537
|
+
</ry-section>
|
|
1538
|
+
|
|
1539
|
+
<!-- Icon -->
|
|
1540
|
+
<ry-section>
|
|
1541
|
+
<h2>Icon</h2>
|
|
1542
|
+
<ry-example title="icon">
|
|
1543
|
+
<template>
|
|
1544
|
+
<cluster>
|
|
1545
|
+
<icon name="heart"></icon>
|
|
1546
|
+
<icon name="star"></icon>
|
|
1547
|
+
<icon name="search"></icon>
|
|
1548
|
+
<icon name="settings"></icon>
|
|
1549
|
+
<icon name="user"></icon>
|
|
1550
|
+
<icon name="check"></icon>
|
|
1551
|
+
</cluster>
|
|
1552
|
+
</template>
|
|
1553
|
+
</ry-example>
|
|
1554
|
+
<table>
|
|
1555
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
1556
|
+
<tbody>
|
|
1557
|
+
<tr><td><code>name</code></td><td>close | check | chevron-* | copy | sun | moon | info | warning | error | success | search | menu | plus | minus | settings | user | heart | star | trash | edit | external-link | download | upload</td><td>Icon name</td></tr>
|
|
1558
|
+
<tr><td><code>size</code></td><td>number</td><td>Size in pixels (default: 24)</td></tr>
|
|
1559
|
+
<tr><td><code>label</code></td><td>string</td><td>Accessible label</td></tr>
|
|
1560
|
+
</tbody>
|
|
1561
|
+
</table>
|
|
1562
|
+
</ry-section>
|
|
1563
|
+
|
|
1564
|
+
<!-- Tag -->
|
|
1565
|
+
<ry-section>
|
|
1566
|
+
<h2>Tag</h2>
|
|
1567
|
+
<ry-example title="tag" stacked>
|
|
1568
|
+
<template>
|
|
1569
|
+
<cluster>
|
|
1570
|
+
<tag>Default</tag>
|
|
1571
|
+
<tag variant="primary">Primary</tag>
|
|
1572
|
+
<tag variant="success">Success</tag>
|
|
1573
|
+
<tag variant="warning">Warning</tag>
|
|
1574
|
+
<tag variant="danger">Danger</tag>
|
|
1575
|
+
<tag removable>Removable</tag>
|
|
1576
|
+
<tag variant="primary" removable>Remove me</tag>
|
|
1577
|
+
<tag size="sm">Small</tag>
|
|
1578
|
+
<tag size="lg">Large</tag>
|
|
1579
|
+
</cluster>
|
|
1580
|
+
</template>
|
|
1581
|
+
</ry-example>
|
|
1582
|
+
<table>
|
|
1583
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
1584
|
+
<tbody>
|
|
1585
|
+
<tr><td><code>variant</code></td><td>default | primary | success | warning | danger</td><td>Color variant</td></tr>
|
|
1586
|
+
<tr><td><code>size</code></td><td>sm | md | lg</td><td>Size</td></tr>
|
|
1587
|
+
<tr><td><code>removable</code></td><td>boolean</td><td>Show close button</td></tr>
|
|
1588
|
+
<tr><td><code>data-value</code></td><td>string</td><td>Value included in ry:remove event</td></tr>
|
|
1589
|
+
</tbody>
|
|
1590
|
+
</table>
|
|
1591
|
+
</ry-section>
|
|
1592
|
+
|
|
1593
|
+
<!-- Tag Input -->
|
|
1594
|
+
<ry-section>
|
|
1595
|
+
<h2>Tag Input</h2>
|
|
1596
|
+
<ry-example title="tag-input" stacked>
|
|
1597
|
+
<template>
|
|
1598
|
+
<tag-input placeholder="Add tags (comma separated)..." value="JavaScript,TypeScript,CSS"></tag-input>
|
|
1599
|
+
</template>
|
|
1600
|
+
</ry-example>
|
|
1601
|
+
<table>
|
|
1602
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
1603
|
+
<tbody>
|
|
1604
|
+
<tr><td><code>placeholder</code></td><td>string</td><td>Input placeholder</td></tr>
|
|
1605
|
+
<tr><td><code>delimiter</code></td><td>string</td><td>Delimiter character (default ",")</td></tr>
|
|
1606
|
+
<tr><td><code>max-tags</code></td><td>number</td><td>Max number of tags</td></tr>
|
|
1607
|
+
<tr><td><code>value</code></td><td>string</td><td>Initial comma-separated values</td></tr>
|
|
1608
|
+
<tr><td><code>name</code></td><td>string</td><td>Form field name</td></tr>
|
|
1609
|
+
</tbody>
|
|
1610
|
+
</table>
|
|
1611
|
+
</ry-section>
|
|
1612
|
+
|
|
1613
|
+
<!-- Hero -->
|
|
1614
|
+
<ry-section>
|
|
1615
|
+
<h2>Hero</h2>
|
|
1616
|
+
<ry-example title="hero" stacked>
|
|
1617
|
+
<template>
|
|
1618
|
+
<hero align="center">
|
|
1619
|
+
<h1>Build apps faster</h1>
|
|
1620
|
+
<p>Framework-agnostic, Light DOM web components. CSS is the source of truth.</p>
|
|
1621
|
+
<cluster>
|
|
1622
|
+
<button>Get Started</button>
|
|
1623
|
+
<button variant="outline">Learn More</button>
|
|
1624
|
+
</cluster>
|
|
1625
|
+
</hero>
|
|
1626
|
+
</template>
|
|
1627
|
+
</ry-example>
|
|
1628
|
+
<table>
|
|
1629
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
1630
|
+
<tbody>
|
|
1631
|
+
<tr><td><code>align</code></td><td>center | left</td><td>Text alignment</td></tr>
|
|
1632
|
+
<tr><td><code>size</code></td><td>sm | md | lg</td><td>Padding size</td></tr>
|
|
1633
|
+
<tr><td><code>full-bleed</code></td><td>boolean</td><td>Remove max-width</td></tr>
|
|
1634
|
+
</tbody>
|
|
1635
|
+
</table>
|
|
1636
|
+
</ry-section>
|
|
1637
|
+
|
|
1638
|
+
<!-- Stat -->
|
|
1639
|
+
<ry-section>
|
|
1640
|
+
<h2>Stat</h2>
|
|
1641
|
+
<ry-example title="stat">
|
|
1642
|
+
<template>
|
|
1643
|
+
<grid cols="3">
|
|
1644
|
+
<stat trend="up">
|
|
1645
|
+
<span slot="value">2,847</span>
|
|
1646
|
+
<span slot="label">Active Users</span>
|
|
1647
|
+
</stat>
|
|
1648
|
+
<stat trend="down">
|
|
1649
|
+
<span slot="value">1.2%</span>
|
|
1650
|
+
<span slot="label">Bounce Rate</span>
|
|
1651
|
+
</stat>
|
|
1652
|
+
<stat>
|
|
1653
|
+
<span slot="value">$12,340</span>
|
|
1654
|
+
<span slot="label">Revenue</span>
|
|
1655
|
+
</stat>
|
|
1656
|
+
</grid>
|
|
1657
|
+
</template>
|
|
1658
|
+
</ry-example>
|
|
1659
|
+
<table>
|
|
1660
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
1661
|
+
<tbody>
|
|
1662
|
+
<tr><td><code>trend</code></td><td>up | down</td><td>Trend arrow direction</td></tr>
|
|
1663
|
+
<tr><td><code>size</code></td><td>sm | md | lg</td><td>Value text size</td></tr>
|
|
1664
|
+
<tr><td><code>align</code></td><td>left | center</td><td>Alignment</td></tr>
|
|
1665
|
+
</tbody>
|
|
1666
|
+
</table>
|
|
1667
|
+
</ry-section>
|
|
1668
|
+
|
|
1669
|
+
<!-- Feature Grid -->
|
|
1670
|
+
<ry-section>
|
|
1671
|
+
<h2>Feature Grid</h2>
|
|
1672
|
+
<ry-example title="feature-grid" stacked>
|
|
1673
|
+
<template>
|
|
1674
|
+
<feature-grid cols="3">
|
|
1675
|
+
<feature icon="settings" align="center">
|
|
1676
|
+
<h3>Easy Setup</h3>
|
|
1677
|
+
<p>One line of code to get started. No build step required.</p>
|
|
1678
|
+
</feature>
|
|
1679
|
+
<feature icon="heart" align="center">
|
|
1680
|
+
<h3>Developer Friendly</h3>
|
|
1681
|
+
<p>Clean API, great docs, and TypeScript support.</p>
|
|
1682
|
+
</feature>
|
|
1683
|
+
<feature icon="star" align="center">
|
|
1684
|
+
<h3>Lightweight</h3>
|
|
1685
|
+
<p>Under 10KB gzipped. No dependencies.</p>
|
|
1686
|
+
</feature>
|
|
1687
|
+
</feature-grid>
|
|
1688
|
+
</template>
|
|
1689
|
+
</ry-example>
|
|
1690
|
+
<table>
|
|
1691
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
1692
|
+
<tbody>
|
|
1693
|
+
<tr><td><code>cols</code> (grid)</td><td>2 | 3 | 4</td><td>Number of columns</td></tr>
|
|
1694
|
+
<tr><td><code>icon</code> (feature)</td><td>icon name</td><td>Icon from registry</td></tr>
|
|
1695
|
+
<tr><td><code>align</code> (feature)</td><td>left | center</td><td>Content alignment</td></tr>
|
|
1696
|
+
</tbody>
|
|
1697
|
+
</table>
|
|
1698
|
+
</ry-section>
|
|
1699
|
+
|
|
1700
|
+
<!-- Pricing -->
|
|
1701
|
+
<ry-section>
|
|
1702
|
+
<h2>Pricing</h2>
|
|
1703
|
+
<ry-example title="pricing" stacked>
|
|
1704
|
+
<template>
|
|
1705
|
+
<pricing>
|
|
1706
|
+
<pricing-card>
|
|
1707
|
+
<h3>Free</h3>
|
|
1708
|
+
<div slot="price">$0<span>/mo</span></div>
|
|
1709
|
+
<ul class="ry-check-list">
|
|
1710
|
+
<li>5 projects</li>
|
|
1711
|
+
<li>Community support</li>
|
|
1712
|
+
<li>Basic analytics</li>
|
|
1713
|
+
</ul>
|
|
1714
|
+
<button variant="outline">Get Started</button>
|
|
1715
|
+
</pricing-card>
|
|
1716
|
+
<pricing-card featured>
|
|
1717
|
+
<h3>Pro</h3>
|
|
1718
|
+
<div slot="price">$29<span>/mo</span></div>
|
|
1719
|
+
<ul class="ry-check-list">
|
|
1720
|
+
<li>Unlimited projects</li>
|
|
1721
|
+
<li>Priority support</li>
|
|
1722
|
+
<li>Advanced analytics</li>
|
|
1723
|
+
</ul>
|
|
1724
|
+
<button>Choose Pro</button>
|
|
1725
|
+
</pricing-card>
|
|
1726
|
+
<pricing-card>
|
|
1727
|
+
<h3>Enterprise</h3>
|
|
1728
|
+
<div slot="price">$99<span>/mo</span></div>
|
|
1729
|
+
<ul class="ry-check-list">
|
|
1730
|
+
<li>Everything in Pro</li>
|
|
1731
|
+
<li>SLA guarantee</li>
|
|
1732
|
+
<li>Custom integrations</li>
|
|
1733
|
+
</ul>
|
|
1734
|
+
<button variant="outline">Contact Us</button>
|
|
1735
|
+
</pricing-card>
|
|
1736
|
+
</pricing>
|
|
1737
|
+
</template>
|
|
1738
|
+
</ry-example>
|
|
1739
|
+
<table>
|
|
1740
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
1741
|
+
<tbody>
|
|
1742
|
+
<tr><td><code>featured</code></td><td>boolean</td><td>Highlight this card</td></tr>
|
|
1743
|
+
</tbody>
|
|
1744
|
+
</table>
|
|
1745
|
+
</ry-section>
|
|
1746
|
+
|
|
1747
|
+
<!-- Testimonial -->
|
|
1748
|
+
<ry-section>
|
|
1749
|
+
<h2>Testimonial</h2>
|
|
1750
|
+
<ry-example title="testimonial">
|
|
1751
|
+
<template>
|
|
1752
|
+
<ry>
|
|
1753
|
+
<grid cols="3">
|
|
1754
|
+
<testimonial stars="5">
|
|
1755
|
+
<img slot="avatar" src="https://i.pravatar.cc/128?img=1" alt="Sarah Chen">
|
|
1756
|
+
<blockquote>This library changed how we build UIs. Everything just works.</blockquote>
|
|
1757
|
+
<span slot="name">Sarah Chen</span>
|
|
1758
|
+
<span slot="role">CTO, Acme Corp</span>
|
|
1759
|
+
</testimonial>
|
|
1760
|
+
<testimonial stars="5">
|
|
1761
|
+
<img slot="avatar" src="https://i.pravatar.cc/128?img=3" alt="Marcus Johnson">
|
|
1762
|
+
<blockquote>Clean, fast, and framework-agnostic. Exactly what we needed.</blockquote>
|
|
1763
|
+
<span slot="name">Marcus Johnson</span>
|
|
1764
|
+
<span slot="role">Lead Engineer, StartupCo</span>
|
|
1765
|
+
</testimonial>
|
|
1766
|
+
<testimonial stars="4">
|
|
1767
|
+
<img slot="avatar" src="https://i.pravatar.cc/128?img=5" alt="Emily Park">
|
|
1768
|
+
<blockquote>We shipped our entire dashboard in half the time.</blockquote>
|
|
1769
|
+
<span slot="name">Emily Park</span>
|
|
1770
|
+
<span slot="role">Product Manager, BigCo</span>
|
|
1771
|
+
</testimonial>
|
|
1772
|
+
</grid>
|
|
1773
|
+
</ry>
|
|
1774
|
+
</template>
|
|
1775
|
+
</ry-example>
|
|
1776
|
+
<table>
|
|
1777
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
1778
|
+
<tbody>
|
|
1779
|
+
<tr><td><code>stars</code></td><td>1–5</td><td>Star rating display</td></tr>
|
|
1780
|
+
<tr><td><code>slot="avatar"</code></td><td>img element</td><td>Avatar photo</td></tr>
|
|
1781
|
+
<tr><td><code>slot="name"</code></td><td>text</td><td>Person's name</td></tr>
|
|
1782
|
+
<tr><td><code>slot="role"</code></td><td>text</td><td>Title / company</td></tr>
|
|
1783
|
+
</tbody>
|
|
1784
|
+
</table>
|
|
1785
|
+
</ry-section>
|
|
1786
|
+
|
|
1787
|
+
<!-- Carousel -->
|
|
1788
|
+
<ry-section>
|
|
1789
|
+
<h2>Carousel</h2>
|
|
1790
|
+
<ry-example title="carousel" stacked>
|
|
1791
|
+
<template>
|
|
1792
|
+
<carousel arrows dots loop>
|
|
1793
|
+
<div style="padding: var(--ry-space-8); text-align: center; background: var(--ry-color-bg-subtle); border-radius: var(--ry-radius-lg);">
|
|
1794
|
+
<h3>Slide 1</h3>
|
|
1795
|
+
<p>First slide content</p>
|
|
1796
|
+
</div>
|
|
1797
|
+
<div style="padding: var(--ry-space-8); text-align: center; background: var(--ry-color-bg-muted); border-radius: var(--ry-radius-lg);">
|
|
1798
|
+
<h3>Slide 2</h3>
|
|
1799
|
+
<p>Second slide content</p>
|
|
1800
|
+
</div>
|
|
1801
|
+
<div style="padding: var(--ry-space-8); text-align: center; background: var(--ry-color-bg-subtle); border-radius: var(--ry-radius-lg);">
|
|
1802
|
+
<h3>Slide 3</h3>
|
|
1803
|
+
<p>Third slide content</p>
|
|
1804
|
+
</div>
|
|
1805
|
+
</carousel>
|
|
1806
|
+
</template>
|
|
1807
|
+
</ry-example>
|
|
1808
|
+
<table>
|
|
1809
|
+
<thead><tr><th>Attribute</th><th>Values</th><th>Description</th></tr></thead>
|
|
1810
|
+
<tbody>
|
|
1811
|
+
<tr><td><code>arrows</code></td><td>boolean</td><td>Show prev/next arrows</td></tr>
|
|
1812
|
+
<tr><td><code>dots</code></td><td>boolean</td><td>Show dot indicators</td></tr>
|
|
1813
|
+
<tr><td><code>loop</code></td><td>boolean</td><td>Loop back to start</td></tr>
|
|
1814
|
+
<tr><td><code>autoplay</code></td><td>boolean</td><td>Auto-advance slides</td></tr>
|
|
1815
|
+
<tr><td><code>interval</code></td><td>number</td><td>Autoplay interval in ms (default 5000)</td></tr>
|
|
1816
|
+
<tr><td><code>pause-on-hover</code></td><td>boolean</td><td>Pause autoplay on hover</td></tr>
|
|
1817
|
+
</tbody>
|
|
1818
|
+
</table>
|
|
1819
|
+
</ry-section>
|
|
1820
|
+
|
|
1821
|
+
</ry-main>
|
|
1822
|
+
|
|
1823
|
+
<ry-footer>
|
|
1824
|
+
<p>ry-ui • Framework-agnostic Light DOM components</p>
|
|
1825
|
+
</ry-footer>
|
|
1826
|
+
|
|
1827
|
+
</ry-page>
|