@ryanhelsing/ry-ui 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENT.md +460 -0
- package/AGENTS.md +57 -0
- package/README.md +45 -1
- package/dist/components/ry-button-group.d.ts +32 -0
- package/dist/components/ry-button-group.d.ts.map +1 -0
- package/dist/components/ry-carousel.d.ts +21 -0
- package/dist/components/ry-carousel.d.ts.map +1 -0
- package/dist/components/ry-feature.d.ts +21 -0
- package/dist/components/ry-feature.d.ts.map +1 -0
- package/dist/components/ry-field.d.ts +7 -1
- package/dist/components/ry-field.d.ts.map +1 -1
- package/dist/components/ry-hero.d.ts +16 -0
- package/dist/components/ry-hero.d.ts.map +1 -0
- package/dist/components/ry-number-select.d.ts.map +1 -1
- package/dist/components/ry-pricing.d.ts +21 -0
- package/dist/components/ry-pricing.d.ts.map +1 -0
- package/dist/components/ry-select.d.ts +8 -1
- package/dist/components/ry-select.d.ts.map +1 -1
- package/dist/components/ry-split.d.ts +28 -0
- package/dist/components/ry-split.d.ts.map +1 -0
- package/dist/components/ry-stat.d.ts +17 -0
- package/dist/components/ry-stat.d.ts.map +1 -0
- package/dist/components/ry-tag-input.d.ts +18 -0
- package/dist/components/ry-tag-input.d.ts.map +1 -0
- package/dist/components/ry-tag.d.ts +19 -0
- package/dist/components/ry-tag.d.ts.map +1 -0
- package/dist/core/ry-transform.d.ts.map +1 -1
- package/dist/css/ry-structure.css +739 -149
- package/dist/css/ry-theme.css +581 -180
- package/dist/css/ry-tokens.css +120 -24
- package/dist/css/ry-ui.css +4965 -1065
- package/dist/ry-ui.d.ts +9 -0
- package/dist/ry-ui.d.ts.map +1 -1
- package/dist/ry-ui.js +1309 -778
- package/dist/ry-ui.js.map +1 -1
- package/dist/themes/dark.css +7 -90
- package/dist/themes/light.css +6 -35
- package/dist/themes/ocean.css +22 -26
- package/docs/components/accordion.md +31 -0
- package/docs/components/button-group.md +36 -0
- package/docs/components/button.md +65 -0
- package/docs/components/color.md +84 -0
- package/docs/components/display.md +69 -0
- package/docs/components/drawer.md +36 -0
- package/docs/components/dropdown.md +33 -0
- package/docs/components/forms.md +90 -0
- package/docs/components/knob.md +42 -0
- package/docs/components/layout.md +217 -0
- package/docs/components/modal.md +38 -0
- package/docs/components/number-select.md +42 -0
- package/docs/components/slider.md +48 -0
- package/docs/components/tabs.md +30 -0
- package/docs/components/theme-toggle.md +36 -0
- package/docs/components/toast.md +27 -0
- package/docs/components/tooltip.md +14 -0
- package/docs/components/tree.md +46 -0
- package/docs/theming.md +182 -0
- package/package.json +8 -4
- package/USING_CDN.md +0 -591
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Knob
|
|
2
|
+
|
|
3
|
+
## `<ry-knob>`
|
|
4
|
+
|
|
5
|
+
Rotary dial control. Great for audio/settings UIs.
|
|
6
|
+
|
|
7
|
+
| Attribute | Values | Description |
|
|
8
|
+
|-----------|--------|-------------|
|
|
9
|
+
| `min` | number | Minimum (default: 0) |
|
|
10
|
+
| `max` | number | Maximum (default: 100) |
|
|
11
|
+
| `step` | number | Step (default: 0 = smooth) |
|
|
12
|
+
| `value` | number | Current value |
|
|
13
|
+
| `label` | string | Label below knob |
|
|
14
|
+
| `labels` | string | Comma-separated labels for discrete steps |
|
|
15
|
+
| `description` | string | Tooltip on hover |
|
|
16
|
+
| `color` | primary \| secondary \| success \| warning \| danger | Track color |
|
|
17
|
+
| `size` | sm \| lg | Size |
|
|
18
|
+
| `disabled` | boolean | Disable |
|
|
19
|
+
|
|
20
|
+
Events: `ry:input` (during drag), `ry:change` (on release)
|
|
21
|
+
|
|
22
|
+
```html
|
|
23
|
+
<ry-knob min="0" max="100" value="50" label="Volume"></ry-knob>
|
|
24
|
+
<ry-knob min="0" max="3" step="1" value="1" labels="Off,Low,Med,High" label="Mode"></ry-knob>
|
|
25
|
+
<ry-knob value="60" color="warning" label="Warning"></ry-knob>
|
|
26
|
+
<ry-knob size="sm" value="25" label="Small"></ry-knob>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
JS:
|
|
30
|
+
```js
|
|
31
|
+
const knob = document.querySelector('ry-knob');
|
|
32
|
+
|
|
33
|
+
knob.addEventListener('ry:input', (e) => {
|
|
34
|
+
updateVolume(e.detail.value); // fires during drag
|
|
35
|
+
});
|
|
36
|
+
knob.addEventListener('ry:change', (e) => {
|
|
37
|
+
saveSettings({ volume: e.detail.value }); // fires on release
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
knob.value; // 50
|
|
41
|
+
knob.value = 75;
|
|
42
|
+
```
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# Layout Components
|
|
2
|
+
|
|
3
|
+
CSS-only layout primitives. No JavaScript needed.
|
|
4
|
+
|
|
5
|
+
## `<ry-page>`
|
|
6
|
+
|
|
7
|
+
Top-level page shell. Contains header, main, footer.
|
|
8
|
+
|
|
9
|
+
```html
|
|
10
|
+
<ry-page>
|
|
11
|
+
<ry-header sticky>...</ry-header>
|
|
12
|
+
<ry-main>...</ry-main>
|
|
13
|
+
<ry-footer>...</ry-footer>
|
|
14
|
+
</ry-page>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## `<ry-header>`
|
|
18
|
+
|
|
19
|
+
| Attribute | Values | Description |
|
|
20
|
+
|-----------|--------|-------------|
|
|
21
|
+
| `sticky` | boolean | Sticks to top of viewport |
|
|
22
|
+
|
|
23
|
+
Horizontal flex with space-between. Two direct children = left and right.
|
|
24
|
+
|
|
25
|
+
```html
|
|
26
|
+
<ry-header sticky>
|
|
27
|
+
<ry-cluster><strong>App</strong></ry-cluster>
|
|
28
|
+
<ry-cluster><ry-theme-toggle themes="light,dark"></ry-theme-toggle></ry-cluster>
|
|
29
|
+
</ry-header>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## `<ry-grid>`
|
|
33
|
+
|
|
34
|
+
| Attribute | Values | Description |
|
|
35
|
+
|-----------|--------|-------------|
|
|
36
|
+
| `cols` | 1–6 | Number of columns |
|
|
37
|
+
|
|
38
|
+
```html
|
|
39
|
+
<ry-grid cols="3">
|
|
40
|
+
<ry-card>One</ry-card>
|
|
41
|
+
<ry-card>Two</ry-card>
|
|
42
|
+
<ry-card>Three</ry-card>
|
|
43
|
+
</ry-grid>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## `<ry-stack>`
|
|
47
|
+
|
|
48
|
+
Vertical flex layout.
|
|
49
|
+
|
|
50
|
+
| Attribute | Values | Description |
|
|
51
|
+
|-----------|--------|-------------|
|
|
52
|
+
| `gap` | sm \| md \| lg | Vertical spacing |
|
|
53
|
+
|
|
54
|
+
```html
|
|
55
|
+
<ry-stack gap="sm">
|
|
56
|
+
<p>Item 1</p>
|
|
57
|
+
<p>Item 2</p>
|
|
58
|
+
</ry-stack>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## `<ry-cluster>`
|
|
62
|
+
|
|
63
|
+
Horizontal flex, wraps.
|
|
64
|
+
|
|
65
|
+
| Attribute | Values | Description |
|
|
66
|
+
|-----------|--------|-------------|
|
|
67
|
+
| `gap` | sm \| md \| lg | Horizontal spacing |
|
|
68
|
+
|
|
69
|
+
```html
|
|
70
|
+
<ry-cluster>
|
|
71
|
+
<ry-badge>A</ry-badge>
|
|
72
|
+
<ry-badge>B</ry-badge>
|
|
73
|
+
</ry-cluster>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## `<ry-card>`
|
|
77
|
+
|
|
78
|
+
Content container with padding and border. Use `<ry-actions>` inside for button groups.
|
|
79
|
+
|
|
80
|
+
```html
|
|
81
|
+
<ry-card>
|
|
82
|
+
<h3>Title</h3>
|
|
83
|
+
<p>Content.</p>
|
|
84
|
+
<ry-actions>
|
|
85
|
+
<ry-button>Save</ry-button>
|
|
86
|
+
<ry-button variant="ghost">Cancel</ry-button>
|
|
87
|
+
</ry-actions>
|
|
88
|
+
</ry-card>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## `<ry-section>`
|
|
92
|
+
|
|
93
|
+
Content section block. Adds bottom margin between sections, removed on last child.
|
|
94
|
+
|
|
95
|
+
```html
|
|
96
|
+
<ry-main>
|
|
97
|
+
<ry-section><h2>Section 1</h2><p>Content.</p></ry-section>
|
|
98
|
+
<ry-section><h2>Section 2</h2><p>Content.</p></ry-section>
|
|
99
|
+
</ry-main>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## `<ry-aside>`
|
|
103
|
+
|
|
104
|
+
Sidebar / secondary content block.
|
|
105
|
+
|
|
106
|
+
```html
|
|
107
|
+
<ry-split>
|
|
108
|
+
<ry-main>Primary content</ry-main>
|
|
109
|
+
<ry-aside>Sidebar content</ry-aside>
|
|
110
|
+
</ry-split>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## `<ry-split>`
|
|
114
|
+
|
|
115
|
+
Two-pane layout: content (flexible) + sidebar (fixed). Stacks vertically on mobile (<768px).
|
|
116
|
+
|
|
117
|
+
| Attribute | Values | Description |
|
|
118
|
+
|-----------|--------|-------------|
|
|
119
|
+
| `resizable` | boolean | Enables drag handle between panes |
|
|
120
|
+
| `persist` | string | localStorage key — saves/restores width as `ry-split:{key}` |
|
|
121
|
+
|
|
122
|
+
CSS custom properties:
|
|
123
|
+
|
|
124
|
+
| Property | Default | Description |
|
|
125
|
+
|----------|---------|-------------|
|
|
126
|
+
| `--ry-split-width` | `300px` | Sidebar width |
|
|
127
|
+
| `--ry-split-min-width` | `100px` | Minimum width during resize |
|
|
128
|
+
| `--ry-split-max-width` | `80%` | Maximum width during resize |
|
|
129
|
+
|
|
130
|
+
Events: `ry:resize` — `e.detail.width`
|
|
131
|
+
|
|
132
|
+
```html
|
|
133
|
+
<!-- Basic -->
|
|
134
|
+
<ry-split>
|
|
135
|
+
<div>Main content (flex: 1)</div>
|
|
136
|
+
<div>Sidebar (300px)</div>
|
|
137
|
+
</ry-split>
|
|
138
|
+
|
|
139
|
+
<!-- Resizable with persistence -->
|
|
140
|
+
<ry-split resizable persist="sidebar" style="--ry-split-width: 400px">
|
|
141
|
+
<main>Content</main>
|
|
142
|
+
<aside>Resizable sidebar</aside>
|
|
143
|
+
</ry-split>
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Resize interaction:
|
|
147
|
+
- **Drag** handle between panes (mouse + touch)
|
|
148
|
+
- **Arrow keys** ±10px, **Shift+Arrow** ±50px
|
|
149
|
+
- **Home/End** jump to min/max
|
|
150
|
+
- **Double-click** handle to reset to default
|
|
151
|
+
|
|
152
|
+
## `<ry-center>`
|
|
153
|
+
|
|
154
|
+
Centers content both horizontally and vertically.
|
|
155
|
+
|
|
156
|
+
```html
|
|
157
|
+
<ry-center>
|
|
158
|
+
<h1>Centered title</h1>
|
|
159
|
+
<p>Centered paragraph</p>
|
|
160
|
+
</ry-center>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## `<ry-nav>`
|
|
164
|
+
|
|
165
|
+
Horizontal navigation links. Use `aria-current="page"` to highlight the active link.
|
|
166
|
+
|
|
167
|
+
```html
|
|
168
|
+
<ry-nav>
|
|
169
|
+
<a href="/" aria-current="page">Home</a>
|
|
170
|
+
<a href="/about">About</a>
|
|
171
|
+
<a href="/contact">Contact</a>
|
|
172
|
+
</ry-nav>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## `<ry-logo>`
|
|
176
|
+
|
|
177
|
+
Inline logo element. Bold, large text. Typically used inside `<ry-header>`.
|
|
178
|
+
|
|
179
|
+
```html
|
|
180
|
+
<ry-header>
|
|
181
|
+
<ry-logo>My App</ry-logo>
|
|
182
|
+
<ry-nav>...</ry-nav>
|
|
183
|
+
</ry-header>
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## `<ry-actions>`
|
|
187
|
+
|
|
188
|
+
Horizontal button group. Use inside cards, modals, or any container.
|
|
189
|
+
|
|
190
|
+
```html
|
|
191
|
+
<ry-actions>
|
|
192
|
+
<ry-button>Primary</ry-button>
|
|
193
|
+
<ry-button variant="ghost">Cancel</ry-button>
|
|
194
|
+
</ry-actions>
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## `<ry-divider>`
|
|
198
|
+
|
|
199
|
+
Horizontal or vertical separator line.
|
|
200
|
+
|
|
201
|
+
| Attribute | Values | Description |
|
|
202
|
+
|-----------|--------|-------------|
|
|
203
|
+
| `vertical` | boolean | Vertical orientation (for use inside flex rows) |
|
|
204
|
+
|
|
205
|
+
```html
|
|
206
|
+
<ry-stack>
|
|
207
|
+
<p>Above</p>
|
|
208
|
+
<ry-divider></ry-divider>
|
|
209
|
+
<p>Below</p>
|
|
210
|
+
</ry-stack>
|
|
211
|
+
|
|
212
|
+
<ry-cluster>
|
|
213
|
+
<span>Left</span>
|
|
214
|
+
<ry-divider vertical></ry-divider>
|
|
215
|
+
<span>Right</span>
|
|
216
|
+
</ry-cluster>
|
|
217
|
+
```
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Modal
|
|
2
|
+
|
|
3
|
+
## `<ry-modal>`
|
|
4
|
+
|
|
5
|
+
| Attribute | Values | Description |
|
|
6
|
+
|-----------|--------|-------------|
|
|
7
|
+
| `id` | string | Identifier (match button's `modal` attr) |
|
|
8
|
+
| `title` | string | Header title |
|
|
9
|
+
|
|
10
|
+
Put `close` attribute on any button inside to dismiss. Uses focus trapping.
|
|
11
|
+
|
|
12
|
+
Events: `ry:open`, `ry:close`
|
|
13
|
+
API: `.open()`, `.close()`, `.state`
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<ry-button modal="demo">Open</ry-button>
|
|
17
|
+
|
|
18
|
+
<ry-modal id="demo" title="Confirm">
|
|
19
|
+
<p>Are you sure?</p>
|
|
20
|
+
<ry-actions slot="footer">
|
|
21
|
+
<ry-button variant="ghost" close>Cancel</ry-button>
|
|
22
|
+
<ry-button>OK</ry-button>
|
|
23
|
+
</ry-actions>
|
|
24
|
+
</ry-modal>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
JS:
|
|
28
|
+
```js
|
|
29
|
+
const modal = document.querySelector('ry-modal');
|
|
30
|
+
|
|
31
|
+
modal.addEventListener('ry:open', () => console.log('opened'));
|
|
32
|
+
modal.addEventListener('ry:close', () => console.log('closed'));
|
|
33
|
+
|
|
34
|
+
// Programmatic
|
|
35
|
+
modal.open();
|
|
36
|
+
modal.close();
|
|
37
|
+
modal.state; // "open" or "closed"
|
|
38
|
+
```
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Number Select
|
|
2
|
+
|
|
3
|
+
## `<ry-number-select>`
|
|
4
|
+
|
|
5
|
+
Numeric stepper with increment/decrement buttons and optional drag-to-adjust.
|
|
6
|
+
|
|
7
|
+
| Attribute | Values | Description |
|
|
8
|
+
|-----------|--------|-------------|
|
|
9
|
+
| `min` | number | Minimum (default: 0) |
|
|
10
|
+
| `max` | number | Maximum (default: 100) |
|
|
11
|
+
| `step` | number | Step (default: 1) |
|
|
12
|
+
| `value` | number | Current value |
|
|
13
|
+
| `arrows` | both \| start \| end \| stacked \| stacked-end \| stacked-start \| none | Button placement |
|
|
14
|
+
| `icons` | plus-minus \| chevron \| arrow | Icon style |
|
|
15
|
+
| `drag` | x \| y \| none | Drag direction |
|
|
16
|
+
| `prefix` | string | Before value ("$") |
|
|
17
|
+
| `suffix` | string | After value ("°", "%") |
|
|
18
|
+
| `editable` | boolean | Allow typing directly |
|
|
19
|
+
| `wrap` | boolean | Wrap around min/max |
|
|
20
|
+
| `size` | xs \| sm \| lg | Size |
|
|
21
|
+
| `disabled` | boolean | Disable |
|
|
22
|
+
|
|
23
|
+
Events: `ry:input` (during drag), `ry:change` (on commit)
|
|
24
|
+
|
|
25
|
+
```html
|
|
26
|
+
<ry-number-select min="0" max="100" value="50"></ry-number-select>
|
|
27
|
+
<ry-number-select min="0" max="360" value="90" suffix="°" arrows="stacked" icons="chevron"></ry-number-select>
|
|
28
|
+
<ry-number-select min="0" max="1000" value="50" prefix="$" editable></ry-number-select>
|
|
29
|
+
<ry-number-select min="0" max="7" value="3" wrap></ry-number-select>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
JS:
|
|
33
|
+
```js
|
|
34
|
+
const ns = document.querySelector('ry-number-select');
|
|
35
|
+
|
|
36
|
+
ns.addEventListener('ry:input', (e) => console.log(e.detail.value));
|
|
37
|
+
ns.addEventListener('ry:change', (e) => console.log(e.detail.value));
|
|
38
|
+
|
|
39
|
+
ns.value; // 50
|
|
40
|
+
ns.value = 75;
|
|
41
|
+
ns.step = 5;
|
|
42
|
+
```
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Slider
|
|
2
|
+
|
|
3
|
+
## `<ry-slider>`
|
|
4
|
+
|
|
5
|
+
| Attribute | Values | Description |
|
|
6
|
+
|-----------|--------|-------------|
|
|
7
|
+
| `min` | number | Minimum (default: 0) |
|
|
8
|
+
| `max` | number | Maximum (default: 100) |
|
|
9
|
+
| `step` | number | Step (default: 1, 0 = smooth) |
|
|
10
|
+
| `value` | number | Current value (single mode) |
|
|
11
|
+
| `start` / `end` | number | Range values (with `range`) |
|
|
12
|
+
| `range` | boolean | Dual-handle mode |
|
|
13
|
+
| `labeled` | boolean | Show min/max labels |
|
|
14
|
+
| `ticked` | boolean | Show tick marks |
|
|
15
|
+
| `tooltip` | boolean | Show value on hover |
|
|
16
|
+
| `vertical` | boolean | Vertical orientation |
|
|
17
|
+
| `reversed` | boolean | Reverse direction |
|
|
18
|
+
| `color` | primary \| secondary \| success \| warning \| danger \| info | Track color |
|
|
19
|
+
| `size` | sm \| lg | Size |
|
|
20
|
+
| `disabled` | boolean | Disable |
|
|
21
|
+
|
|
22
|
+
Events: `ry:input` (during drag), `ry:change` (on release)
|
|
23
|
+
|
|
24
|
+
```html
|
|
25
|
+
<ry-slider min="0" max="100" value="50"></ry-slider>
|
|
26
|
+
<ry-slider min="0" max="100" start="25" end="75" range labeled></ry-slider>
|
|
27
|
+
<ry-slider min="0" max="10" step="1" value="5" ticked labeled tooltip></ry-slider>
|
|
28
|
+
<ry-slider min="0" max="100" value="60" color="success"></ry-slider>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
JS:
|
|
32
|
+
```js
|
|
33
|
+
const slider = document.querySelector('ry-slider');
|
|
34
|
+
|
|
35
|
+
slider.addEventListener('ry:input', (e) => {
|
|
36
|
+
console.log(e.detail.value); // fires during drag
|
|
37
|
+
});
|
|
38
|
+
slider.addEventListener('ry:change', (e) => {
|
|
39
|
+
saveValue(e.detail.value); // fires on release
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
slider.value; // 50
|
|
43
|
+
slider.value = 75;
|
|
44
|
+
|
|
45
|
+
// Range slider
|
|
46
|
+
rangeSlider.start; // 25
|
|
47
|
+
rangeSlider.end; // 75
|
|
48
|
+
```
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Tabs
|
|
2
|
+
|
|
3
|
+
## `<ry-tabs>`
|
|
4
|
+
|
|
5
|
+
| Attribute (on tab) | Values | Description |
|
|
6
|
+
|---------------------|--------|-------------|
|
|
7
|
+
| `title` | string | Tab label |
|
|
8
|
+
| `active` | boolean | Initially selected |
|
|
9
|
+
|
|
10
|
+
Events: `ry:change` — `e.detail.index`, `e.detail.title`
|
|
11
|
+
|
|
12
|
+
```html
|
|
13
|
+
<ry-tabs>
|
|
14
|
+
<ry-tab title="Overview" active><p>Overview content.</p></ry-tab>
|
|
15
|
+
<ry-tab title="Settings"><p>Settings content.</p></ry-tab>
|
|
16
|
+
</ry-tabs>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
JS:
|
|
20
|
+
```js
|
|
21
|
+
const tabs = document.querySelector('ry-tabs');
|
|
22
|
+
|
|
23
|
+
tabs.addEventListener('ry:change', (e) => {
|
|
24
|
+
console.log(e.detail.index); // 0, 1, 2...
|
|
25
|
+
console.log(e.detail.title); // "Overview"
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// Switch programmatically
|
|
29
|
+
tabs.activeIndex = 1;
|
|
30
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Theme Toggle
|
|
2
|
+
|
|
3
|
+
## `<ry-theme-toggle>`
|
|
4
|
+
|
|
5
|
+
Cycles through themes on click. Sets `data-ry-theme` on `<html>`.
|
|
6
|
+
|
|
7
|
+
| Attribute | Values | Description |
|
|
8
|
+
|-----------|--------|-------------|
|
|
9
|
+
| `themes` | string | Comma-separated theme names (default: "light,dark") |
|
|
10
|
+
|
|
11
|
+
Events: `ry:theme-change` — `e.detail.theme`
|
|
12
|
+
API: `.theme` (get/set), `.toggle()`
|
|
13
|
+
|
|
14
|
+
```html
|
|
15
|
+
<ry-theme-toggle themes="light,dark"></ry-theme-toggle>
|
|
16
|
+
<ry-theme-toggle themes="light,dark,ocean"></ry-theme-toggle>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
JS:
|
|
20
|
+
```js
|
|
21
|
+
const toggle = document.querySelector('ry-theme-toggle');
|
|
22
|
+
|
|
23
|
+
toggle.addEventListener('ry:theme-change', (e) => {
|
|
24
|
+
console.log(e.detail.theme); // "dark"
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Programmatic
|
|
28
|
+
toggle.theme; // "light"
|
|
29
|
+
toggle.theme = 'dark';
|
|
30
|
+
toggle.toggle(); // cycles to next
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Or skip the component and set the theme directly:
|
|
34
|
+
```js
|
|
35
|
+
document.documentElement.dataset.ryTheme = 'dark';
|
|
36
|
+
```
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Toast
|
|
2
|
+
|
|
3
|
+
## `RyToast` (programmatic API)
|
|
4
|
+
|
|
5
|
+
No HTML element needed. Call globally after ry-ui loads.
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
RyToast.success('Saved!');
|
|
9
|
+
RyToast.error('Something went wrong');
|
|
10
|
+
RyToast.warning('Please review');
|
|
11
|
+
RyToast.info('New update available');
|
|
12
|
+
|
|
13
|
+
// With options
|
|
14
|
+
RyToast.success('Done!', { duration: 5000 }); // default: 3000ms
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Common pattern:
|
|
18
|
+
```js
|
|
19
|
+
async function saveData() {
|
|
20
|
+
try {
|
|
21
|
+
await api.save(data);
|
|
22
|
+
RyToast.success('Saved!');
|
|
23
|
+
} catch (err) {
|
|
24
|
+
RyToast.error(err.message);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Tooltip
|
|
2
|
+
|
|
3
|
+
## `<ry-tooltip>`
|
|
4
|
+
|
|
5
|
+
| Attribute | Values | Description |
|
|
6
|
+
|-----------|--------|-------------|
|
|
7
|
+
| `content` | string | Tooltip text |
|
|
8
|
+
| `position` | top \| bottom \| left \| right | Position |
|
|
9
|
+
|
|
10
|
+
```html
|
|
11
|
+
<ry-tooltip content="Save changes" position="top">
|
|
12
|
+
<ry-button>Save</ry-button>
|
|
13
|
+
</ry-tooltip>
|
|
14
|
+
```
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Tree
|
|
2
|
+
|
|
3
|
+
## `<ry-tree>`
|
|
4
|
+
|
|
5
|
+
File-tree / nested list with expand/collapse and optional drag-and-drop.
|
|
6
|
+
|
|
7
|
+
| Attribute | Values | Description |
|
|
8
|
+
|-----------|--------|-------------|
|
|
9
|
+
| `sortable` | boolean | Enable drag-and-drop (on tree) |
|
|
10
|
+
| `no-animate` | boolean | Disable animation |
|
|
11
|
+
| `label` | string | Item label (on tree-item) |
|
|
12
|
+
| `open` | boolean | Expanded folder (on tree-item with children) |
|
|
13
|
+
| `selected` | boolean | Selected item (on leaf tree-item) |
|
|
14
|
+
|
|
15
|
+
Events: `ry:select` (file click), `ry:toggle` (folder expand/collapse), `ry:move` (drag-drop)
|
|
16
|
+
API: `.toJSON()`, `.value`, `RyTree.from(json)`
|
|
17
|
+
|
|
18
|
+
```html
|
|
19
|
+
<ry-tree sortable>
|
|
20
|
+
<ry-tree-item label="src" open>
|
|
21
|
+
<ry-tree-item label="app">
|
|
22
|
+
<ry-tree-item label="page.tsx"></ry-tree-item>
|
|
23
|
+
</ry-tree-item>
|
|
24
|
+
<ry-tree-item label="utils.ts"></ry-tree-item>
|
|
25
|
+
</ry-tree-item>
|
|
26
|
+
</ry-tree>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
JS:
|
|
30
|
+
```js
|
|
31
|
+
const tree = document.querySelector('ry-tree');
|
|
32
|
+
|
|
33
|
+
tree.addEventListener('ry:select', (e) => {
|
|
34
|
+
console.log(e.detail.label); // "page.tsx"
|
|
35
|
+
});
|
|
36
|
+
tree.addEventListener('ry:toggle', (e) => {
|
|
37
|
+
console.log(e.detail.label, e.detail.open);
|
|
38
|
+
});
|
|
39
|
+
tree.addEventListener('ry:move', (e) => {
|
|
40
|
+
console.log(`Moved "${e.detail.item}" ${e.detail.position} "${e.detail.target}"`);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Serialize/deserialize
|
|
44
|
+
tree.toJSON(); // [{ label: "src", open: true, children: [...] }]
|
|
45
|
+
const copy = RyTree.from(tree.toJSON());
|
|
46
|
+
```
|