@ryanhelsing/ry-ui 1.0.3 → 1.0.5

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.
@@ -0,0 +1,36 @@
1
+ # Button Group
2
+
3
+ ## `<ry-button-group>`
4
+
5
+ Segmented control with radio-group behavior. Only one child button can be selected at a time.
6
+
7
+ | Attribute | Values | Description |
8
+ |-----------|--------|-------------|
9
+ | `name` | string | Optional group name |
10
+ | `value` | string | Currently selected button value |
11
+
12
+ Events: `ry:change` — `e.detail.value`
13
+
14
+ Child buttons must have a `value` attribute to participate. Clicking a button sets `pressed` + `aria-pressed="true"` on it and clears the others.
15
+
16
+ ```html
17
+ <ry-button-group name="billing" value="monthly">
18
+ <ry-button value="monthly">Monthly</ry-button>
19
+ <ry-button value="annually">Annually</ry-button>
20
+ </ry-button-group>
21
+
22
+ <ry-button-group name="mode" value="terminal">
23
+ <ry-button value="direct">Direct</ry-button>
24
+ <ry-button value="terminal">Terminal</ry-button>
25
+ <ry-button value="release">Release</ry-button>
26
+ </ry-button-group>
27
+ ```
28
+
29
+ JS:
30
+ ```js
31
+ const group = document.querySelector('ry-button-group');
32
+ group.addEventListener('ry:change', (e) => {
33
+ console.log(e.detail.value); // "monthly" | "annually"
34
+ });
35
+ group.value = 'annually'; // programmatic selection
36
+ ```
@@ -2,20 +2,24 @@
2
2
 
3
3
  ## `<ry-field>`
4
4
 
5
- Wraps native `<input>` / `<textarea>` with label and optional error.
5
+ Wraps native `<input>` / `<textarea>` / `<select>` with auto-generated label, error, and hint. Handles accessibility linking (aria-describedby, aria-invalid) automatically.
6
6
 
7
7
  | Attribute | Values | Description |
8
8
  |-----------|--------|-------------|
9
9
  | `label` | string | Label text |
10
- | `error` | string | Error message |
10
+ | `error` | string | Error message (hides hint when set) |
11
+ | `hint` | string | Helper text shown below input |
11
12
 
12
13
  ```html
13
- <ry-field label="Email">
14
+ <ry-field label="Email" hint="We'll never share your email">
14
15
  <input type="email" placeholder="you@example.com">
15
16
  </ry-field>
16
- <ry-field label="Bio" error="Required">
17
- <textarea rows="3"></textarea>
17
+
18
+ <ry-field label="Password" error="Must be at least 8 characters">
19
+ <input type="password">
18
20
  </ry-field>
21
+
22
+ <!-- Setting error="" clears the error and shows hint again -->
19
23
  ```
20
24
 
21
25
  ## `<ry-select>`
@@ -75,9 +75,17 @@ Horizontal flex, wraps.
75
75
 
76
76
  ## `<ry-card>`
77
77
 
78
- Content container with padding and border. Use `<ry-actions>` inside for button groups.
78
+ Content container with padding and border. All cards lift subtly on hover. Add `interactive` for clickable cards.
79
+
80
+ | Attribute | Values | Description |
81
+ |-----------|--------|-------------|
82
+ | `interactive` | boolean | Clickable card — cursor pointer, stronger hover lift, primary border, keyboard support |
83
+ | `href` | URL | Navigate on click (requires `interactive`) |
84
+
85
+ Events: `ry:click` (interactive cards only)
79
86
 
80
87
  ```html
88
+ <!-- Static card -->
81
89
  <ry-card>
82
90
  <h3>Title</h3>
83
91
  <p>Content.</p>
@@ -86,8 +94,25 @@ Content container with padding and border. Use `<ry-actions>` inside for button
86
94
  <ry-button variant="ghost">Cancel</ry-button>
87
95
  </ry-actions>
88
96
  </ry-card>
97
+
98
+ <!-- Interactive card with navigation -->
99
+ <ry-card interactive href="/demos/goap">
100
+ <h3>GOAP</h3>
101
+ <p>Goal-Oriented Action Planning</p>
102
+ </ry-card>
103
+
104
+ <!-- Interactive card with event -->
105
+ <ry-card interactive>
106
+ <h3>Click Me</h3>
107
+ <p>Emits ry:click. Tab + Enter for keyboard.</p>
108
+ </ry-card>
89
109
  ```
90
110
 
111
+ Hover behavior:
112
+ - **All cards**: subtle lift (-2px) + border/shadow bump
113
+ - **Interactive**: stronger lift (-3px), primary-colored border, snaps back on click
114
+ - Clicks on child `<a>`, `<button>`, `<ry-button>` elements pass through normally
115
+
91
116
  ## `<ry-section>`
92
117
 
93
118
  Content section block. Adds bottom margin between sections, removed on last child.
@@ -112,15 +137,43 @@ Sidebar / secondary content block.
112
137
 
113
138
  ## `<ry-split>`
114
139
 
115
- Two-pane layout: content (flexible) + sidebar (300px). Stacks vertically on mobile (<768px).
140
+ Two-pane layout: content (flexible) + sidebar (fixed). Stacks vertically on mobile (<768px).
141
+
142
+ | Attribute | Values | Description |
143
+ |-----------|--------|-------------|
144
+ | `resizable` | boolean | Enables drag handle between panes |
145
+ | `persist` | string | localStorage key — saves/restores width as `ry-split:{key}` |
146
+
147
+ CSS custom properties:
148
+
149
+ | Property | Default | Description |
150
+ |----------|---------|-------------|
151
+ | `--ry-split-width` | `300px` | Sidebar width |
152
+ | `--ry-split-min-width` | `100px` | Minimum width during resize |
153
+ | `--ry-split-max-width` | `80%` | Maximum width during resize |
154
+
155
+ Events: `ry:resize` — `e.detail.width`
116
156
 
117
157
  ```html
158
+ <!-- Basic -->
118
159
  <ry-split>
119
160
  <div>Main content (flex: 1)</div>
120
161
  <div>Sidebar (300px)</div>
121
162
  </ry-split>
163
+
164
+ <!-- Resizable with persistence -->
165
+ <ry-split resizable persist="sidebar" style="--ry-split-width: 400px">
166
+ <main>Content</main>
167
+ <aside>Resizable sidebar</aside>
168
+ </ry-split>
122
169
  ```
123
170
 
171
+ Resize interaction:
172
+ - **Drag** handle between panes (mouse + touch)
173
+ - **Arrow keys** ±10px, **Shift+Arrow** ±50px
174
+ - **Home/End** jump to min/max
175
+ - **Double-click** handle to reset to default
176
+
124
177
  ## `<ry-center>`
125
178
 
126
179
  Centers content both horizontally and vertically.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ryanhelsing/ry-ui",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
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,6 +16,7 @@
16
16
  },
17
17
  "files": [
18
18
  "dist",
19
+ "AGENT.md",
19
20
  "AGENTS.md",
20
21
  "docs/components",
21
22
  "docs/theming.md"
@@ -26,7 +27,8 @@
26
27
  "build:types": "tsc --emitDeclarationOnly",
27
28
  "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/",
28
29
  "preview": "vite preview",
29
- "typecheck": "tsc --noEmit"
30
+ "typecheck": "tsc --noEmit",
31
+ "release": "npm run build && git add -A && git diff-index --quiet HEAD || git commit -m 'new build' && npm version patch && npm publish --access public"
30
32
  },
31
33
  "devDependencies": {
32
34
  "typescript": "^5.7.2",