@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
@@ -1,92 +1,9 @@
1
1
  /**
2
- * ry-ui Dark Theme
2
+ * ry-ui Dark Theme — DEPRECATED
3
+ *
4
+ * Dark mode is now built into ry-tokens.css via light-dark().
5
+ * To force dark mode: <html data-ry-theme="dark">
6
+ * To respect OS preference: omit data-ry-theme (default behavior).
7
+ *
8
+ * This file is kept for backward compatibility but has no effect.
3
9
  */
4
-
5
- [data-ry-theme="dark"] {
6
- /* Colors */
7
- --ry-color-primary: #60a5fa;
8
- --ry-color-primary-hover: #3b82f6;
9
- --ry-color-primary-active: #2563eb;
10
-
11
- --ry-color-secondary: #94a3b8;
12
- --ry-color-secondary-hover: #cbd5e1;
13
- --ry-color-secondary-active: #e2e8f0;
14
-
15
- /* Text */
16
- --ry-color-text: #f1f5f9;
17
- --ry-color-text-muted: #94a3b8;
18
- --ry-color-text-inverse: #0f172a;
19
-
20
- /* Background */
21
- --ry-color-bg: #0f172a;
22
- --ry-color-bg-subtle: #1e293b;
23
- --ry-color-bg-muted: #334155;
24
-
25
- /* Border */
26
- --ry-color-border: #334155;
27
- --ry-color-border-strong: #475569;
28
-
29
- /* Overlay */
30
- --ry-color-overlay: rgba(0, 0, 0, 0.7);
31
-
32
- /* Shadows (more subtle in dark mode) */
33
- --ry-shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.3);
34
- --ry-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.4);
35
- --ry-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.4);
36
- --ry-shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.5);
37
-
38
- /* Focus */
39
- --ry-focus-ring: 0 0 0 3px rgba(96, 165, 250, 0.5);
40
-
41
- /* Code block - Vibrant (using theme colors) */
42
- --ry-code-bg: #0f172a;
43
- --ry-code-header-bg: #1e293b;
44
- --ry-code-text-color: #f1f5f9;
45
- --ry-code-title-color: #94a3b8;
46
- --ry-code-icon-color: #64748b;
47
- --ry-code-icon-hover-bg: #334155;
48
- --ry-code-icon-hover-color: #f1f5f9;
49
- --ry-code-line-number-color: rgba(71, 85, 105, 0.6);
50
- --ry-code-line-border-color: #334155;
51
- --ry-code-color-preview-border: rgba(241, 245, 249, 0.3);
52
- /* Syntax - theme button colors */
53
- --ry-code-keyword: #ef4444;
54
- --ry-code-property: #60a5fa;
55
- --ry-code-value: #f59e0b;
56
- --ry-code-string: #22c55e;
57
- --ry-code-number: #f59e0b;
58
- --ry-code-comment: #94a3b8;
59
- --ry-code-selector: #06b6d4;
60
- --ry-code-punctuation: #94a3b8;
61
- --ry-code-tag: #06b6d4;
62
- --ry-code-attribute: #60a5fa;
63
- }
64
-
65
- /* Alert overrides for dark mode */
66
- [data-ry-theme="dark"] .ry-alert--info,
67
- [data-ry-theme="dark"] ry-alert[type="info"] {
68
- background-color: #164e63;
69
- border-color: #06b6d4;
70
- color: #a5f3fc;
71
- }
72
-
73
- [data-ry-theme="dark"] .ry-alert--success,
74
- [data-ry-theme="dark"] ry-alert[type="success"] {
75
- background-color: #14532d;
76
- border-color: #22c55e;
77
- color: #bbf7d0;
78
- }
79
-
80
- [data-ry-theme="dark"] .ry-alert--warning,
81
- [data-ry-theme="dark"] ry-alert[type="warning"] {
82
- background-color: #78350f;
83
- border-color: #f59e0b;
84
- color: #fef3c7;
85
- }
86
-
87
- [data-ry-theme="dark"] .ry-alert--danger,
88
- [data-ry-theme="dark"] ry-alert[type="danger"] {
89
- background-color: #7f1d1d;
90
- border-color: #ef4444;
91
- color: #fecaca;
92
- }
@@ -1,38 +1,9 @@
1
1
  /**
2
- * ry-ui Light Theme
2
+ * ry-ui Light Theme — DEPRECATED
3
3
  *
4
- * This is the default theme.
5
- * Most values inherit from ry-tokens.css.
4
+ * Light mode is the default in ry-tokens.css via light-dark().
5
+ * To force light mode: <html data-ry-theme="light">
6
+ * To respect OS preference: omit data-ry-theme (default behavior).
7
+ *
8
+ * This file is kept for backward compatibility but has no effect.
6
9
  */
7
-
8
- [data-ry-theme="light"] {
9
- /* Light theme is the default, so minimal overrides needed */
10
- --ry-color-bg: #ffffff;
11
- --ry-color-bg-subtle: #f8fafc;
12
- --ry-color-bg-muted: #f1f5f9;
13
- --ry-color-text: #1e293b;
14
- --ry-color-text-muted: #64748b;
15
-
16
- /* Code block - Cool/Minimal (GitHub style) */
17
- --ry-code-bg: #f6f8fa;
18
- --ry-code-header-bg: #eaeef2;
19
- --ry-code-text-color: #24292f;
20
- --ry-code-title-color: #57606a;
21
- --ry-code-icon-color: #8c959f;
22
- --ry-code-icon-hover-bg: #d0d7de;
23
- --ry-code-icon-hover-color: #24292f;
24
- --ry-code-line-number-color: rgba(140, 149, 159, 0.6);
25
- --ry-code-line-border-color: #d0d7de;
26
- --ry-code-color-preview-border: rgba(36, 41, 47, 0.3);
27
- /* Syntax */
28
- --ry-code-keyword: #cf222e;
29
- --ry-code-property: #0550ae;
30
- --ry-code-value: #0a3069;
31
- --ry-code-string: #0a3069;
32
- --ry-code-number: #0550ae;
33
- --ry-code-comment: #6e7781;
34
- --ry-code-selector: #116329;
35
- --ry-code-punctuation: #24292f;
36
- --ry-code-tag: #116329;
37
- --ry-code-attribute: #0550ae;
38
- }
@@ -6,43 +6,39 @@
6
6
 
7
7
  [data-ry-theme="ocean"] {
8
8
  /* Primary - ocean blues */
9
- --ry-color-primary: #0ea5e9;
10
- --ry-color-primary-hover: #0284c7;
11
- --ry-color-primary-active: #0369a1;
9
+ --ry-color-primary: oklch(0.685 0.148 237.3);
10
+ --ry-color-primary-hover: oklch(0.588 0.139 242);
11
+ --ry-color-primary-active: oklch(0.5 0.119 242.8);
12
12
 
13
13
  /* Secondary - teal */
14
- --ry-color-secondary: #06b6d4;
15
- --ry-color-secondary-hover: #0891b2;
16
- --ry-color-secondary-active: #0e7490;
14
+ --ry-color-secondary: oklch(0.715 0.126 215.2);
15
+ --ry-color-secondary-hover: oklch(0.609 0.111 221.7);
16
+ --ry-color-secondary-active: oklch(0.52 0.094 223.1);
17
17
 
18
18
  /* Text */
19
- --ry-color-text: #0c4a6e;
20
- --ry-color-text-muted: #64748b;
21
- --ry-color-text-inverse: #ffffff;
19
+ --ry-color-text: oklch(0.391 0.085 240.9);
20
+ --ry-color-text-muted: oklch(0.554 0.041 257.4);
21
+ --ry-color-text-inverse: oklch(1 0 0);
22
22
 
23
23
  /* Background - light blues */
24
- --ry-color-bg: #f0f9ff;
25
- --ry-color-bg-subtle: #e0f2fe;
26
- --ry-color-bg-muted: #bae6fd;
24
+ --ry-color-bg: oklch(0.977 0.013 236.8);
25
+ --ry-color-bg-subtle: oklch(0.951 0.025 236.9);
26
+ --ry-color-bg-muted: oklch(0.901 0.056 230.9);
27
27
 
28
28
  /* Border */
29
- --ry-color-border: #7dd3fc;
30
- --ry-color-border-strong: #38bdf8;
29
+ --ry-color-border: oklch(0.828 0.101 230.3);
30
+ --ry-color-border-strong: oklch(0.753 0.139 232.7);
31
31
 
32
32
  /* Shadows with blue tint */
33
- --ry-shadow-sm: 0 1px 2px 0 rgba(14, 165, 233, 0.1);
34
- --ry-shadow-md: 0 4px 6px -1px rgba(14, 165, 233, 0.15);
35
- --ry-shadow-lg: 0 10px 15px -3px rgba(14, 165, 233, 0.15);
36
- --ry-shadow-xl: 0 20px 25px -5px rgba(14, 165, 233, 0.2);
33
+ --ry-shadow-sm: 0 1px 2px 0 oklch(0.685 0.148 237.3 / 0.1);
34
+ --ry-shadow-md: 0 4px 6px -1px oklch(0.685 0.148 237.3 / 0.15);
35
+ --ry-shadow-lg: 0 10px 15px -3px oklch(0.685 0.148 237.3 / 0.15);
36
+ --ry-shadow-xl: 0 20px 25px -5px oklch(0.685 0.148 237.3 / 0.2);
37
37
 
38
38
  /* Focus */
39
- --ry-focus-ring: 0 0 0 3px rgba(14, 165, 233, 0.5);
40
- }
39
+ --ry-focus-ring: 0 0 0 3px oklch(0.685 0.148 237.3 / 0.5);
41
40
 
42
- /* Alert overrides */
43
- [data-ry-theme="ocean"] .ry-alert--info,
44
- [data-ry-theme="ocean"] ry-alert[type="info"] {
45
- background-color: #e0f2fe;
46
- border-color: #0ea5e9;
47
- color: #0369a1;
41
+ /* Alerts */
42
+ --ry-color-info-bg: oklch(0.951 0.025 236.9);
43
+ --ry-color-info-text: oklch(0.5 0.119 242.8);
48
44
  }
@@ -0,0 +1,31 @@
1
+ # Accordion
2
+
3
+ ## `<ry-accordion>`
4
+
5
+ | Attribute (on accordion-item) | Values | Description |
6
+ |-------------------------------|--------|-------------|
7
+ | `title` | string | Header text |
8
+ | `open` | boolean | Initially expanded |
9
+
10
+ Events: `ry:toggle` on item — `e.detail.open` (boolean)
11
+
12
+ ```html
13
+ <ry-accordion>
14
+ <ry-accordion-item title="Section 1" open>Content here.</ry-accordion-item>
15
+ <ry-accordion-item title="Section 2">More content.</ry-accordion-item>
16
+ </ry-accordion>
17
+ ```
18
+
19
+ JS:
20
+ ```js
21
+ const item = document.querySelector('ry-accordion-item');
22
+
23
+ item.addEventListener('ry:toggle', (e) => {
24
+ console.log(e.detail.open); // true or false
25
+ });
26
+
27
+ // Programmatic
28
+ item.open = true;
29
+ item.open = false;
30
+ item.toggle();
31
+ ```
@@ -0,0 +1,65 @@
1
+ # Button
2
+
3
+ ## `<ry-button>`
4
+
5
+ | Attribute | Values | Description |
6
+ |-----------|--------|-------------|
7
+ | `variant` | primary \| secondary \| outline \| ghost \| danger | Style (default: primary) |
8
+ | `size` | sm \| md \| lg | Size |
9
+ | `modal` | string | Opens modal with this ID |
10
+ | `drawer` | string | Opens drawer with this ID |
11
+ | `disabled` | boolean | Disable |
12
+
13
+ ```html
14
+ <ry-button>Primary</ry-button>
15
+ <ry-button variant="outline">Outline</ry-button>
16
+ <ry-button variant="danger" size="sm">Delete</ry-button>
17
+ <ry-button modal="confirm">Open Modal</ry-button>
18
+ <ry-button drawer="nav">Open Drawer</ry-button>
19
+ ```
20
+
21
+ ## `<ry-toggle-button>`
22
+
23
+ Selectable button. Same-name buttons form a radio group (only one pressed).
24
+
25
+ | Attribute | Values | Description |
26
+ |-----------|--------|-------------|
27
+ | `name` | string | Group name (same name = single selection) |
28
+ | `value` | string | Value when selected |
29
+ | `pressed` | boolean | Currently pressed |
30
+ | `block` | boolean | Full-width |
31
+ | `size` | sm \| md \| lg | Size |
32
+ | `disabled` | boolean | Disable |
33
+
34
+ Events: `ry:change` — `e.detail.pressed`, `e.detail.value`
35
+
36
+ ```html
37
+ <ry-cluster>
38
+ <ry-toggle-button name="size" value="s">S</ry-toggle-button>
39
+ <ry-toggle-button name="size" value="m" pressed>M</ry-toggle-button>
40
+ <ry-toggle-button name="size" value="l">L</ry-toggle-button>
41
+ </ry-cluster>
42
+ ```
43
+
44
+ Full-width card-style selection:
45
+
46
+ ```html
47
+ <ry-grid cols="3">
48
+ <ry-toggle-button name="plan" value="free" block>
49
+ <strong>Free</strong><br><b>$0</b>/month
50
+ </ry-toggle-button>
51
+ <ry-toggle-button name="plan" value="pro" block pressed>
52
+ <strong>Pro</strong><br><b>$10</b>/month
53
+ </ry-toggle-button>
54
+ </ry-grid>
55
+ ```
56
+
57
+ JS:
58
+ ```js
59
+ // Get selected value from a group
60
+ const selected = document.querySelector('ry-toggle-button[name="plan"][pressed]');
61
+ selected?.value; // "pro"
62
+
63
+ // Set programmatically
64
+ button.pressed = true;
65
+ ```
@@ -0,0 +1,84 @@
1
+ # Color Components
2
+
3
+ ## `<ry-color-picker>`
4
+
5
+ Full color picker with saturation/hue panel.
6
+
7
+ | Attribute | Values | Description |
8
+ |-----------|--------|-------------|
9
+ | `value` | color string | Initial color (hex, rgb, hsl) |
10
+ | `format` | hex \| rgb \| hsl | Output format (default: hex) |
11
+ | `inline` | boolean | Always visible (no dropdown) |
12
+ | `opacity` | boolean | Enable alpha channel |
13
+ | `swatches` | string | Preset colors separated by `;` |
14
+ | `disabled` | boolean | Disable |
15
+
16
+ Events: `ry:input` (during drag), `ry:change` (on release)
17
+ API: `.value`, `.rgb`, `.hsl`, `.hsv`, `.setColor(str)`
18
+
19
+ ```html
20
+ <ry-color-picker value="#3b82f6"></ry-color-picker>
21
+ <ry-color-picker value="#3b82f6" opacity inline swatches="#ef4444;#22c55e;#3b82f6"></ry-color-picker>
22
+ ```
23
+
24
+ JS:
25
+ ```js
26
+ const picker = document.querySelector('ry-color-picker');
27
+
28
+ picker.addEventListener('ry:input', (e) => {
29
+ console.log(e.detail.value); // "#3b82f6"
30
+ console.log(e.detail.rgb); // { r: 59, g: 130, b: 246 }
31
+ console.log(e.detail.hsv); // { h: 217, s: 76, v: 96 }
32
+ });
33
+
34
+ picker.value = '#ff0000';
35
+ picker.setColor('hsl(200, 100%, 50%)');
36
+ picker.rgb; // { r, g, b }
37
+ picker.hsl; // { h, s, l }
38
+ ```
39
+
40
+ ## `<ry-color-input>`
41
+
42
+ Compact swatch + editable hex input.
43
+
44
+ | Attribute | Values | Description |
45
+ |-----------|--------|-------------|
46
+ | `value` | color string | Initial color |
47
+ | `format` | hex \| rgb \| hsl | Output format |
48
+ | `opacity` | boolean | Enable alpha |
49
+ | `disabled` | boolean | Disable |
50
+
51
+ Events: `ry:change` — `e.detail.value`
52
+
53
+ ```html
54
+ <ry-color-input value="#3b82f6"></ry-color-input>
55
+ <ry-color-input value="rgba(139, 92, 246, 0.8)" opacity></ry-color-input>
56
+ ```
57
+
58
+ ## `<ry-gradient-picker>`
59
+
60
+ CSS gradient editor with draggable color stops.
61
+
62
+ | Attribute | Values | Description |
63
+ |-----------|--------|-------------|
64
+ | `value` | CSS gradient string | Initial gradient |
65
+ | `output` | boolean | Show CSS output |
66
+ | `disabled` | boolean | Disable |
67
+
68
+ Events: `ry:input`, `ry:change` — `e.detail.value`, `e.detail.stops`, `e.detail.type`, `e.detail.angle`
69
+ API: `.value`, `.type`, `.angle`, `.stops`, `.addStop(color, pos)`, `.removeStop(id)`
70
+
71
+ ```html
72
+ <ry-gradient-picker value="linear-gradient(90deg, #3b82f6 0%, #8b5cf6 100%)"></ry-gradient-picker>
73
+ <ry-gradient-picker value="radial-gradient(circle, #fbbf24 0%, #dc2626 100%)"></ry-gradient-picker>
74
+ ```
75
+
76
+ JS:
77
+ ```js
78
+ const picker = document.querySelector('ry-gradient-picker');
79
+ picker.value; // "linear-gradient(90deg, ...)"
80
+ picker.type; // "linear" | "radial"
81
+ picker.angle; // 0-360
82
+ picker.stops; // [{ id, color, position }, ...]
83
+ picker.addStop('#ff00ff', 50);
84
+ ```
@@ -0,0 +1,69 @@
1
+ # Display Components
2
+
3
+ ## `<ry-badge>`
4
+
5
+ | Attribute | Values | Description |
6
+ |-----------|--------|-------------|
7
+ | `variant` | default \| primary \| success \| warning \| danger | Color |
8
+
9
+ ```html
10
+ <ry-badge>Default</ry-badge>
11
+ <ry-badge variant="success">Active</ry-badge>
12
+ <ry-badge variant="danger">Offline</ry-badge>
13
+ ```
14
+
15
+ ## `<ry-alert>`
16
+
17
+ | Attribute | Values | Description |
18
+ |-----------|--------|-------------|
19
+ | `type` | info \| success \| warning \| danger | Style |
20
+ | `title` | string | Heading |
21
+
22
+ ```html
23
+ <ry-alert type="info" title="Info">Informational message.</ry-alert>
24
+ <ry-alert type="danger" title="Error">Something went wrong.</ry-alert>
25
+ ```
26
+
27
+ ## `<ry-icon>`
28
+
29
+ | Attribute | Values | Description |
30
+ |-----------|--------|-------------|
31
+ | `name` | close, check, chevron-down, chevron-up, chevron-left, chevron-right, copy, sun, moon, info, warning, error, success, search, menu, plus, minus, settings, user, heart, star, trash, edit, external-link, download, upload | Icon |
32
+ | `size` | number | Pixels (default: 24) |
33
+ | `label` | string | Accessible label |
34
+
35
+ ```html
36
+ <ry-icon name="heart" size="16"></ry-icon>
37
+ <ry-icon name="settings"></ry-icon>
38
+ ```
39
+
40
+ ## `<ry-code>`
41
+
42
+ Use `<ry-code>` with prefix even inside `<ry>` to avoid conflict with native `<code>`.
43
+
44
+ | Attribute | Values | Description |
45
+ |-----------|--------|-------------|
46
+ | `language` | js \| css \| html \| json | Highlighting |
47
+ | `title` | string | Header |
48
+ | `line-numbers` | boolean | Show line numbers |
49
+
50
+ ```html
51
+ <ry-code language="js" title="app.js">
52
+ const x = 1;
53
+ console.log(x);
54
+ </ry-code>
55
+ ```
56
+
57
+ ## Table (native HTML)
58
+
59
+ Standard `<table>` elements are styled automatically by the ry-ui theme.
60
+
61
+ ```html
62
+ <table>
63
+ <thead><tr><th>Name</th><th>Role</th></tr></thead>
64
+ <tbody>
65
+ <tr><td>Alice</td><td>Engineer</td></tr>
66
+ <tr><td>Bob</td><td>Designer</td></tr>
67
+ </tbody>
68
+ </table>
69
+ ```
@@ -0,0 +1,36 @@
1
+ # Drawer
2
+
3
+ ## `<ry-drawer>`
4
+
5
+ | Attribute | Values | Description |
6
+ |-----------|--------|-------------|
7
+ | `id` | string | Identifier (match button's `drawer` attr) |
8
+ | `side` | left \| right \| bottom | Slide direction |
9
+
10
+ Events: `ry:open`, `ry:close`
11
+ API: `.open()`, `.close()`, `.state`
12
+
13
+ ```html
14
+ <ry-button drawer="nav">Menu</ry-button>
15
+
16
+ <ry-drawer id="nav" side="left">
17
+ <h3>Navigation</h3>
18
+ <ry-stack>
19
+ <a href="/">Home</a>
20
+ <a href="/about">About</a>
21
+ </ry-stack>
22
+ </ry-drawer>
23
+ ```
24
+
25
+ JS:
26
+ ```js
27
+ const drawer = document.querySelector('ry-drawer');
28
+
29
+ drawer.addEventListener('ry:open', () => console.log('opened'));
30
+ drawer.addEventListener('ry:close', () => console.log('closed'));
31
+
32
+ // Programmatic
33
+ drawer.open();
34
+ drawer.close();
35
+ drawer.state; // "open" or "closed"
36
+ ```
@@ -0,0 +1,33 @@
1
+ # Dropdown
2
+
3
+ ## `<ry-dropdown>`
4
+
5
+ Use `slot="trigger"` on the trigger element. Menu items go inside `<ry-menu>`.
6
+
7
+ Events: `ry:select` — `e.detail.value`
8
+ API: `.open()`, `.close()`
9
+
10
+ ```html
11
+ <ry-dropdown>
12
+ <ry-button slot="trigger">Options</ry-button>
13
+ <ry-menu>
14
+ <ry-menu-item>Edit</ry-menu-item>
15
+ <ry-menu-item>Duplicate</ry-menu-item>
16
+ <ry-divider></ry-divider>
17
+ <ry-menu-item>Delete</ry-menu-item>
18
+ </ry-menu>
19
+ </ry-dropdown>
20
+ ```
21
+
22
+ JS:
23
+ ```js
24
+ const dropdown = document.querySelector('ry-dropdown');
25
+
26
+ dropdown.addEventListener('ry:select', (e) => {
27
+ console.log(e.detail.value); // "Edit", "Delete", etc.
28
+ });
29
+
30
+ // Programmatic
31
+ dropdown.open();
32
+ dropdown.close();
33
+ ```
@@ -0,0 +1,86 @@
1
+ # Form Components
2
+
3
+ ## `<ry-field>`
4
+
5
+ Wraps native `<input>` / `<textarea>` with label and optional error.
6
+
7
+ | Attribute | Values | Description |
8
+ |-----------|--------|-------------|
9
+ | `label` | string | Label text |
10
+ | `error` | string | Error message |
11
+
12
+ ```html
13
+ <ry-field label="Email">
14
+ <input type="email" placeholder="you@example.com">
15
+ </ry-field>
16
+ <ry-field label="Bio" error="Required">
17
+ <textarea rows="3"></textarea>
18
+ </ry-field>
19
+ ```
20
+
21
+ ## `<ry-select>`
22
+
23
+ | Attribute | Values | Description |
24
+ |-----------|--------|-------------|
25
+ | `placeholder` | string | Placeholder text |
26
+ | `name` | string | Form field name |
27
+
28
+ Events: `ry:change` — `e.detail.value`, `e.detail.label`
29
+ API: `.value`, `.open()`, `.close()`
30
+
31
+ ```html
32
+ <ry-select placeholder="Country" name="country">
33
+ <ry-option value="us">United States</ry-option>
34
+ <ry-option value="uk">United Kingdom</ry-option>
35
+ </ry-select>
36
+ ```
37
+
38
+ JS:
39
+ ```js
40
+ const select = document.querySelector('ry-select');
41
+ select.addEventListener('ry:change', (e) => {
42
+ console.log(e.detail.value); // "us"
43
+ console.log(e.detail.label); // "United States"
44
+ });
45
+ select.value = 'uk';
46
+ ```
47
+
48
+ ## `<ry-switch>`
49
+
50
+ | Attribute | Values | Description |
51
+ |-----------|--------|-------------|
52
+ | `name` | string | Form field name |
53
+ | `checked` | boolean | Initially on |
54
+ | `disabled` | boolean | Disable |
55
+
56
+ Events: `ry:change` — `e.detail.checked`, `e.detail.name`
57
+ API: `.checked`
58
+
59
+ ```html
60
+ <ry-switch name="notifications" checked>Email notifications</ry-switch>
61
+ ```
62
+
63
+ JS:
64
+ ```js
65
+ const sw = document.querySelector('ry-switch');
66
+ sw.addEventListener('ry:change', (e) => {
67
+ console.log(e.detail.checked); // true or false
68
+ });
69
+ sw.checked = false;
70
+ ```
71
+
72
+ ## Checkbox & Radio
73
+
74
+ Standard HTML, auto-styled by ry-ui theme. No custom elements needed.
75
+
76
+ ```html
77
+ <ry-stack gap="sm">
78
+ <label><input type="checkbox" checked> Accept terms</label>
79
+ <label><input type="checkbox"> Newsletter</label>
80
+ </ry-stack>
81
+
82
+ <ry-stack gap="sm">
83
+ <label><input type="radio" name="plan" value="free" checked> Free</label>
84
+ <label><input type="radio" name="plan" value="pro"> Pro</label>
85
+ </ry-stack>
86
+ ```
@@ -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
+ ```