@ryanhelsing/ry-ui 1.0.2 → 1.0.3

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.
Files changed (51) hide show
  1. package/AGENTS.md +56 -0
  2. package/README.md +26 -1
  3. package/dist/components/ry-carousel.d.ts +21 -0
  4. package/dist/components/ry-carousel.d.ts.map +1 -0
  5. package/dist/components/ry-feature.d.ts +21 -0
  6. package/dist/components/ry-feature.d.ts.map +1 -0
  7. package/dist/components/ry-hero.d.ts +16 -0
  8. package/dist/components/ry-hero.d.ts.map +1 -0
  9. package/dist/components/ry-number-select.d.ts.map +1 -1
  10. package/dist/components/ry-pricing.d.ts +21 -0
  11. package/dist/components/ry-pricing.d.ts.map +1 -0
  12. package/dist/components/ry-select.d.ts +8 -1
  13. package/dist/components/ry-select.d.ts.map +1 -1
  14. package/dist/components/ry-stat.d.ts +17 -0
  15. package/dist/components/ry-stat.d.ts.map +1 -0
  16. package/dist/components/ry-tag-input.d.ts +18 -0
  17. package/dist/components/ry-tag-input.d.ts.map +1 -0
  18. package/dist/components/ry-tag.d.ts +19 -0
  19. package/dist/components/ry-tag.d.ts.map +1 -0
  20. package/dist/core/ry-transform.d.ts.map +1 -1
  21. package/dist/css/ry-structure.css +620 -148
  22. package/dist/css/ry-theme.css +456 -180
  23. package/dist/css/ry-tokens.css +112 -24
  24. package/dist/css/ry-ui.css +4708 -1059
  25. package/dist/ry-ui.d.ts +7 -0
  26. package/dist/ry-ui.d.ts.map +1 -1
  27. package/dist/ry-ui.js +1071 -713
  28. package/dist/ry-ui.js.map +1 -1
  29. package/dist/themes/dark.css +7 -90
  30. package/dist/themes/light.css +6 -35
  31. package/dist/themes/ocean.css +22 -26
  32. package/docs/components/accordion.md +31 -0
  33. package/docs/components/button.md +65 -0
  34. package/docs/components/color.md +84 -0
  35. package/docs/components/display.md +69 -0
  36. package/docs/components/drawer.md +36 -0
  37. package/docs/components/dropdown.md +33 -0
  38. package/docs/components/forms.md +86 -0
  39. package/docs/components/knob.md +42 -0
  40. package/docs/components/layout.md +189 -0
  41. package/docs/components/modal.md +38 -0
  42. package/docs/components/number-select.md +42 -0
  43. package/docs/components/slider.md +48 -0
  44. package/docs/components/tabs.md +30 -0
  45. package/docs/components/theme-toggle.md +36 -0
  46. package/docs/components/toast.md +27 -0
  47. package/docs/components/tooltip.md +14 -0
  48. package/docs/components/tree.md +46 -0
  49. package/docs/theming.md +182 -0
  50. package/package.json +5 -3
  51. package/USING_CDN.md +0 -591
@@ -0,0 +1,189 @@
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 (300px). Stacks vertically on mobile (<768px).
116
+
117
+ ```html
118
+ <ry-split>
119
+ <div>Main content (flex: 1)</div>
120
+ <div>Sidebar (300px)</div>
121
+ </ry-split>
122
+ ```
123
+
124
+ ## `<ry-center>`
125
+
126
+ Centers content both horizontally and vertically.
127
+
128
+ ```html
129
+ <ry-center>
130
+ <h1>Centered title</h1>
131
+ <p>Centered paragraph</p>
132
+ </ry-center>
133
+ ```
134
+
135
+ ## `<ry-nav>`
136
+
137
+ Horizontal navigation links. Use `aria-current="page"` to highlight the active link.
138
+
139
+ ```html
140
+ <ry-nav>
141
+ <a href="/" aria-current="page">Home</a>
142
+ <a href="/about">About</a>
143
+ <a href="/contact">Contact</a>
144
+ </ry-nav>
145
+ ```
146
+
147
+ ## `<ry-logo>`
148
+
149
+ Inline logo element. Bold, large text. Typically used inside `<ry-header>`.
150
+
151
+ ```html
152
+ <ry-header>
153
+ <ry-logo>My App</ry-logo>
154
+ <ry-nav>...</ry-nav>
155
+ </ry-header>
156
+ ```
157
+
158
+ ## `<ry-actions>`
159
+
160
+ Horizontal button group. Use inside cards, modals, or any container.
161
+
162
+ ```html
163
+ <ry-actions>
164
+ <ry-button>Primary</ry-button>
165
+ <ry-button variant="ghost">Cancel</ry-button>
166
+ </ry-actions>
167
+ ```
168
+
169
+ ## `<ry-divider>`
170
+
171
+ Horizontal or vertical separator line.
172
+
173
+ | Attribute | Values | Description |
174
+ |-----------|--------|-------------|
175
+ | `vertical` | boolean | Vertical orientation (for use inside flex rows) |
176
+
177
+ ```html
178
+ <ry-stack>
179
+ <p>Above</p>
180
+ <ry-divider></ry-divider>
181
+ <p>Below</p>
182
+ </ry-stack>
183
+
184
+ <ry-cluster>
185
+ <span>Left</span>
186
+ <ry-divider vertical></ry-divider>
187
+ <span>Right</span>
188
+ </ry-cluster>
189
+ ```
@@ -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
+ ```
@@ -0,0 +1,182 @@
1
+ # ry-ui Theming Guide
2
+
3
+ ## Built-in Themes
4
+
5
+ Set on `<html>`:
6
+ ```html
7
+ <html data-ry-theme="light"> <!-- light | dark | ocean -->
8
+ ```
9
+
10
+ Toggle at runtime:
11
+ ```html
12
+ <ry-theme-toggle themes="light,dark"></ry-theme-toggle>
13
+ ```
14
+
15
+ Or programmatically:
16
+ ```js
17
+ document.documentElement.setAttribute('data-ry-theme', 'dark');
18
+ ```
19
+
20
+ ## Dark Mode
21
+
22
+ Dark mode is built into the base bundle via `light-dark()` + `color-scheme`. No extra files needed.
23
+
24
+ ```html
25
+ <!-- This is all you need — dark mode works automatically -->
26
+ <link rel="stylesheet" href="https://unpkg.com/@ryanhelsing/ry-ui/css/ry-ui.css">
27
+ ```
28
+
29
+ Without a `data-ry-theme` attribute, the OS preference is respected automatically. Setting `data-ry-theme="dark"` forces dark mode.
30
+
31
+ ## Token Override (Quickest Customization)
32
+
33
+ Use the full bundle, override specific tokens:
34
+
35
+ ```css
36
+ :root {
37
+ --ry-color-primary: oklch(0.541 0.218 293);
38
+ --ry-color-primary-hover: oklch(0.491 0.234 292);
39
+ --ry-radius-md: 0;
40
+ --ry-radius-lg: 0;
41
+ }
42
+ ```
43
+
44
+ > **Note:** Tokens use `oklch()` color values. Hex still works for overrides but won't participate in `light-dark()` automatic switching. For dark-aware overrides, use `light-dark()`:
45
+ > ```css
46
+ > :root {
47
+ > --ry-color-primary: light-dark(oklch(0.541 0.218 293), oklch(0.65 0.2 293));
48
+ > }
49
+ > ```
50
+
51
+ ## Custom Theme (Full Control)
52
+
53
+ Load structure only, bring your own visuals:
54
+
55
+ ```html
56
+ <link rel="stylesheet" href="https://unpkg.com/@ryanhelsing/ry-ui/css/ry-structure.css">
57
+ <link rel="stylesheet" href="/your-tokens.css">
58
+ <link rel="stylesheet" href="/your-theme.css">
59
+ ```
60
+
61
+ Structure CSS has layout only — no colors, shadows, borders. Your theme provides all visuals.
62
+
63
+ ## Token Reference
64
+
65
+ ### Colors
66
+
67
+ All color tokens use `oklch()` and `light-dark()` for automatic dark mode:
68
+
69
+ ```css
70
+ --ry-color-primary: light-dark(oklch(0.623 0.188 259.8), oklch(0.714 0.143 254.6));
71
+ --ry-color-primary-hover: light-dark(oklch(0.546 0.215 262.9), oklch(0.623 0.188 259.8));
72
+ --ry-color-primary-active: light-dark(oklch(0.488 0.217 264.4), oklch(0.546 0.215 262.9));
73
+ --ry-color-secondary: light-dark(oklch(0.554 0.041 257.4), oklch(0.714 0.035 253.3));
74
+ --ry-color-success: light-dark(oklch(0.723 0.192 149.6), oklch(0.723 0.192 149.6));
75
+ --ry-color-warning: light-dark(oklch(0.769 0.165 70.1), oklch(0.769 0.165 70.1));
76
+ --ry-color-danger: light-dark(oklch(0.637 0.208 25.3), oklch(0.637 0.208 25.3));
77
+ --ry-color-info: light-dark(oklch(0.715 0.126 215.2), oklch(0.715 0.126 215.2));
78
+ --ry-color-text: light-dark(oklch(0.279 0.037 260), oklch(0.95 0.008 255));
79
+ --ry-color-text-muted: light-dark(oklch(0.554 0.041 257.4), oklch(0.714 0.035 253.3));
80
+ --ry-color-text-inverse: light-dark(oklch(1 0 0), oklch(0.279 0.037 260));
81
+ --ry-color-bg: light-dark(oklch(1 0 0), oklch(0.205 0.027 261));
82
+ --ry-color-bg-subtle: light-dark(oklch(0.984 0.003 248.2), oklch(0.249 0.03 261));
83
+ --ry-color-bg-muted: light-dark(oklch(0.968 0.007 248.1), oklch(0.279 0.033 261));
84
+ --ry-color-border: light-dark(oklch(0.929 0.013 255.6), oklch(0.372 0.039 257.3));
85
+ --ry-color-overlay: light-dark(oklch(0 0 0 / 0.5), oklch(0 0 0 / 0.7));
86
+ ```
87
+
88
+ ### Typography
89
+ ```css
90
+ --ry-font-sans: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
91
+ --ry-font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
92
+
93
+ /* Sizes */
94
+ --ry-text-xs: 0.75rem;
95
+ --ry-text-sm: 0.875rem;
96
+ --ry-text-base: 1rem;
97
+ --ry-text-lg: 1.125rem;
98
+ --ry-text-xl: 1.25rem;
99
+ --ry-text-2xl: 1.5rem;
100
+ --ry-text-3xl: 1.875rem;
101
+ --ry-text-4xl: 2.25rem;
102
+
103
+ /* Weights */
104
+ --ry-font-normal: 400;
105
+ --ry-font-medium: 500;
106
+ --ry-font-semibold: 600;
107
+ --ry-font-bold: 700;
108
+ ```
109
+
110
+ ### Spacing
111
+ ```css
112
+ --ry-space-0: 0;
113
+ --ry-space-1: 0.25rem;
114
+ --ry-space-2: 0.5rem;
115
+ --ry-space-3: 0.75rem;
116
+ --ry-space-4: 1rem;
117
+ --ry-space-5: 1.25rem;
118
+ --ry-space-6: 1.5rem;
119
+ --ry-space-8: 2rem;
120
+ --ry-space-10: 2.5rem;
121
+ --ry-space-12: 3rem;
122
+ --ry-space-16: 4rem;
123
+ --ry-space-20: 5rem;
124
+ ```
125
+
126
+ ### Border Radius
127
+ ```css
128
+ --ry-radius-none: 0;
129
+ --ry-radius-sm: 0.25rem;
130
+ --ry-radius-md: 0.375rem;
131
+ --ry-radius-lg: 0.5rem;
132
+ --ry-radius-xl: 0.75rem;
133
+ --ry-radius-2xl: 1rem;
134
+ --ry-radius-full: 9999px;
135
+ ```
136
+
137
+ ### Shadows
138
+
139
+ Shadows use sub-tokens for dark-mode-aware intensity:
140
+
141
+ ```css
142
+ --ry-shadow-color: light-dark(oklch(0 0 0 / 0.1), oklch(0 0 0 / 0.4));
143
+ --ry-shadow-sm: 0 1px 2px 0 var(--ry-shadow-color-sm);
144
+ --ry-shadow-md: 0 4px 6px -1px var(--ry-shadow-color), 0 2px 4px -2px var(--ry-shadow-color);
145
+ --ry-shadow-lg: 0 10px 15px -3px var(--ry-shadow-color), 0 4px 6px -4px var(--ry-shadow-color);
146
+ --ry-shadow-xl: 0 20px 25px -5px var(--ry-shadow-color), 0 8px 10px -6px var(--ry-shadow-color);
147
+ ```
148
+
149
+ ### Transitions
150
+ ```css
151
+ --ry-duration-fast: 100ms;
152
+ --ry-duration-normal: 200ms;
153
+ --ry-duration-slow: 300ms;
154
+ --ry-ease: cubic-bezier(0.4, 0, 0.2, 1);
155
+ --ry-ease-in: cubic-bezier(0.4, 0, 1, 1);
156
+ --ry-ease-out: cubic-bezier(0, 0, 0.2, 1);
157
+ ```
158
+
159
+ ### Z-Index Layers
160
+ ```css
161
+ --ry-z-dropdown: 1000;
162
+ --ry-z-sticky: 1020;
163
+ --ry-z-fixed: 1030;
164
+ --ry-z-modal-backdrop: 1040;
165
+ --ry-z-modal: 1050;
166
+ --ry-z-popover: 1060;
167
+ --ry-z-tooltip: 1070;
168
+ --ry-z-toast: 1080;
169
+ ```
170
+
171
+ ### Focus
172
+ ```css
173
+ --ry-focus-ring: 0 0 0 3px light-dark(oklch(0.623 0.188 259.8 / 0.5), oklch(0.714 0.143 254.6 / 0.5));
174
+ ```
175
+
176
+ ## Best Practices
177
+
178
+ - Always use `--ry-*` tokens instead of hardcoding values
179
+ - Use `var(--ry-color-text)` and `var(--ry-color-bg)` on your own elements to stay theme-consistent
180
+ - Semantic colors (`success`, `warning`, `danger`, `info`) are available as both `--ry-color-*` tokens and component `variant`/`type`/`color` attributes
181
+ - For inline styles, reference tokens: `style="color: var(--ry-color-text-muted); padding: var(--ry-space-4);"`
182
+ - Set `background: var(--ry-color-bg); color: var(--ry-color-text);` on `<body>` for full-page theme support
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ryanhelsing/ry-ui",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Framework-agnostic, Light DOM web components. CSS is the source of truth.",
5
5
  "type": "module",
6
6
  "main": "./dist/ry-ui.js",
@@ -16,13 +16,15 @@
16
16
  },
17
17
  "files": [
18
18
  "dist",
19
- "USING_CDN.md"
19
+ "AGENTS.md",
20
+ "docs/components",
21
+ "docs/theming.md"
20
22
  ],
21
23
  "scripts": {
22
24
  "dev": "vite",
23
25
  "build": "vite build && npm run build:types && npm run build:css",
24
26
  "build:types": "tsc --emitDeclarationOnly",
25
- "build:css": "mkdir -p dist/css && cp src/css/*.css dist/css/ && mkdir -p dist/themes && cp src/themes/*.css dist/themes/",
27
+ "build:css": "mkdir -p dist/css && node -e \"const fs=require('fs'); const files=['src/css/ry-tokens.css','src/css/ry-structure.css','src/css/ry-theme.css']; const out=files.map(f=>fs.readFileSync(f,'utf8')).join('\\n'); fs.writeFileSync('dist/css/ry-ui.css',out);\" && cp src/css/ry-tokens.css src/css/ry-structure.css src/css/ry-theme.css dist/css/ && mkdir -p dist/themes && cp src/themes/*.css dist/themes/",
26
28
  "preview": "vite preview",
27
29
  "typecheck": "tsc --noEmit"
28
30
  },