@compa11y/web 0.1.0 → 0.1.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.
- package/README.md +608 -0
- package/dist/compa11y.iife.js +1126 -27
- package/dist/compa11y.js +3671 -716
- package/dist/components/button.d.ts +31 -0
- package/dist/components/checkbox.d.ts +159 -0
- package/dist/components/combobox.d.ts +2 -3
- package/dist/components/dialog.d.ts +2 -3
- package/dist/components/dialog.test.d.ts +0 -1
- package/dist/components/input.d.ts +40 -0
- package/dist/components/listbox.d.ts +85 -0
- package/dist/components/menu.d.ts +2 -3
- package/dist/components/menu.test.d.ts +0 -1
- package/dist/components/radio-group.d.ts +86 -0
- package/dist/components/select.d.ts +46 -0
- package/dist/components/switch.d.ts +2 -3
- package/dist/components/tabs.d.ts +2 -3
- package/dist/components/tabs.test.d.ts +0 -1
- package/dist/components/textarea.d.ts +40 -0
- package/dist/index.d.ts +8 -2
- package/dist/utils/base-element.d.ts +1 -2
- package/dist/utils/styles.d.ts +44 -1
- package/package.json +39 -3
- package/dist/compa11y.iife.js.map +0 -1
- package/dist/compa11y.js.map +0 -1
- package/dist/compa11y.umd.cjs +0 -533
- package/dist/compa11y.umd.cjs.map +0 -1
- package/dist/components/combobox.d.ts.map +0 -1
- package/dist/components/dialog.d.ts.map +0 -1
- package/dist/components/dialog.test.d.ts.map +0 -1
- package/dist/components/menu.d.ts.map +0 -1
- package/dist/components/menu.test.d.ts.map +0 -1
- package/dist/components/switch.d.ts.map +0 -1
- package/dist/components/tabs.d.ts.map +0 -1
- package/dist/components/tabs.test.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/utils/base-element.d.ts.map +0 -1
- package/dist/utils/styles.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -150,6 +150,508 @@ tabs.addEventListener('a11y-tabs-change', (e) => {
|
|
|
150
150
|
});
|
|
151
151
|
```
|
|
152
152
|
|
|
153
|
+
### Combobox
|
|
154
|
+
|
|
155
|
+
```html
|
|
156
|
+
<a11y-combobox
|
|
157
|
+
label="Choose a country"
|
|
158
|
+
placeholder="Search countries..."
|
|
159
|
+
></a11y-combobox>
|
|
160
|
+
|
|
161
|
+
<script>
|
|
162
|
+
const combobox = document.querySelector('a11y-combobox');
|
|
163
|
+
combobox.options = [
|
|
164
|
+
{ value: 'us', label: 'United States' },
|
|
165
|
+
{ value: 'uk', label: 'United Kingdom' },
|
|
166
|
+
{ value: 'ca', label: 'Canada' },
|
|
167
|
+
];
|
|
168
|
+
|
|
169
|
+
combobox.addEventListener('change', (e) => {
|
|
170
|
+
console.log('Selected:', e.detail.value);
|
|
171
|
+
});
|
|
172
|
+
</script>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
#### Attributes
|
|
176
|
+
|
|
177
|
+
| Attribute | Description | Default |
|
|
178
|
+
| --------------- | ------------------------------------- | -------------------- |
|
|
179
|
+
| `label` | Label text (required for a11y) | — |
|
|
180
|
+
| `placeholder` | Input placeholder | — |
|
|
181
|
+
| `value` | Currently selected value | — |
|
|
182
|
+
| `disabled` | Disable the combobox | `false` |
|
|
183
|
+
| `clearable` | Show clear button when value selected | `false` |
|
|
184
|
+
| `empty-message` | Message when no options match | `'No results found'` |
|
|
185
|
+
|
|
186
|
+
#### Properties
|
|
187
|
+
|
|
188
|
+
```js
|
|
189
|
+
const combobox = document.querySelector('a11y-combobox');
|
|
190
|
+
combobox.options = [...]; // Set options
|
|
191
|
+
combobox.value = 'us'; // Set value
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
#### Events
|
|
195
|
+
|
|
196
|
+
```js
|
|
197
|
+
combobox.addEventListener('change', (e) => {
|
|
198
|
+
console.log(e.detail.value, e.detail.option);
|
|
199
|
+
});
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Select
|
|
203
|
+
|
|
204
|
+
```html
|
|
205
|
+
<a11y-select aria-label="Choose a fruit" placeholder="Pick a fruit...">
|
|
206
|
+
<option value="apple">Apple</option>
|
|
207
|
+
<option value="banana">Banana</option>
|
|
208
|
+
<option value="cherry">Cherry</option>
|
|
209
|
+
<option value="dragonfruit" disabled>Dragon Fruit (unavailable)</option>
|
|
210
|
+
<option value="elderberry">Elderberry</option>
|
|
211
|
+
</a11y-select>
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
#### Attributes
|
|
215
|
+
|
|
216
|
+
| Attribute | Description | Default |
|
|
217
|
+
| ----------------- | ------------------------ | ----------------------- |
|
|
218
|
+
| `placeholder` | Trigger placeholder text | `'Select an option...'` |
|
|
219
|
+
| `value` | Currently selected value | — |
|
|
220
|
+
| `disabled` | Disable the select | `false` |
|
|
221
|
+
| `aria-label` | Accessible label | — |
|
|
222
|
+
| `aria-labelledby` | ID of labelling element | — |
|
|
223
|
+
|
|
224
|
+
#### Properties
|
|
225
|
+
|
|
226
|
+
```js
|
|
227
|
+
const select = document.querySelector('a11y-select');
|
|
228
|
+
select.value = 'apple'; // Set value programmatically
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
#### Methods
|
|
232
|
+
|
|
233
|
+
```js
|
|
234
|
+
const select = document.querySelector('a11y-select');
|
|
235
|
+
select.show(); // Open
|
|
236
|
+
select.close(); // Close
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
#### Events
|
|
240
|
+
|
|
241
|
+
```js
|
|
242
|
+
select.addEventListener('change', (e) => {
|
|
243
|
+
console.log('Value:', e.detail.value);
|
|
244
|
+
console.log('Label:', e.detail.label);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
select.addEventListener('a11y-select-change', (e) => {
|
|
248
|
+
console.log('Selected:', e.detail);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
select.addEventListener('a11y-select-open', () => {});
|
|
252
|
+
select.addEventListener('a11y-select-close', () => {});
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
#### Keyboard Navigation
|
|
256
|
+
|
|
257
|
+
| Key | Action |
|
|
258
|
+
| ----------------- | ----------------------------------------- |
|
|
259
|
+
| `Enter` / `Space` | Open listbox or select highlighted option |
|
|
260
|
+
| `ArrowDown` | Open listbox / move highlight down |
|
|
261
|
+
| `ArrowUp` | Open listbox / move highlight up |
|
|
262
|
+
| `Home` / `End` | Jump to first / last option |
|
|
263
|
+
| `Escape` | Close listbox |
|
|
264
|
+
| `Tab` | Close listbox and move focus |
|
|
265
|
+
| Type characters | Jump to matching option (type-ahead) |
|
|
266
|
+
|
|
267
|
+
### Switch
|
|
268
|
+
|
|
269
|
+
```html
|
|
270
|
+
<a11y-switch label="Enable notifications"></a11y-switch>
|
|
271
|
+
|
|
272
|
+
<!-- Checked by default -->
|
|
273
|
+
<a11y-switch checked label="Dark mode"></a11y-switch>
|
|
274
|
+
|
|
275
|
+
<!-- Disabled -->
|
|
276
|
+
<a11y-switch disabled label="Premium feature"></a11y-switch>
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
#### Attributes
|
|
280
|
+
|
|
281
|
+
| Attribute | Description | Default |
|
|
282
|
+
| ---------- | ------------------------- | ------- |
|
|
283
|
+
| `label` | Label text | — |
|
|
284
|
+
| `checked` | Whether switch is on | `false` |
|
|
285
|
+
| `disabled` | Disable the switch | `false` |
|
|
286
|
+
| `value` | Value for form submission | — |
|
|
287
|
+
| `name` | Name for form submission | — |
|
|
288
|
+
|
|
289
|
+
#### Properties
|
|
290
|
+
|
|
291
|
+
```js
|
|
292
|
+
const switchEl = document.querySelector('a11y-switch');
|
|
293
|
+
switchEl.checked = true; // Set checked state
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
#### Events
|
|
297
|
+
|
|
298
|
+
```js
|
|
299
|
+
switchEl.addEventListener('change', (e) => {
|
|
300
|
+
console.log('Checked:', e.detail.checked);
|
|
301
|
+
console.log('Value:', e.detail.value);
|
|
302
|
+
console.log('Name:', e.detail.name);
|
|
303
|
+
});
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### Listbox
|
|
307
|
+
|
|
308
|
+
```html
|
|
309
|
+
<!-- Single select -->
|
|
310
|
+
<a11y-listbox aria-label="Favorite fruit" value="apple">
|
|
311
|
+
<a11y-optgroup label="Citrus">
|
|
312
|
+
<a11y-option value="orange">Orange</a11y-option>
|
|
313
|
+
<a11y-option value="lemon">Lemon</a11y-option>
|
|
314
|
+
<a11y-option value="grapefruit">Grapefruit</a11y-option>
|
|
315
|
+
</a11y-optgroup>
|
|
316
|
+
<a11y-optgroup label="Berries">
|
|
317
|
+
<a11y-option value="strawberry">Strawberry</a11y-option>
|
|
318
|
+
<a11y-option value="blueberry">Blueberry</a11y-option>
|
|
319
|
+
<a11y-option value="raspberry" disabled>Raspberry (sold out)</a11y-option>
|
|
320
|
+
</a11y-optgroup>
|
|
321
|
+
<a11y-option value="apple">Apple</a11y-option>
|
|
322
|
+
<a11y-option value="banana">Banana</a11y-option>
|
|
323
|
+
</a11y-listbox>
|
|
324
|
+
|
|
325
|
+
<!-- Multi select -->
|
|
326
|
+
<a11y-listbox multiple aria-label="Pizza toppings" value="cheese,mushrooms">
|
|
327
|
+
<a11y-option value="cheese">Cheese</a11y-option>
|
|
328
|
+
<a11y-option value="pepperoni">Pepperoni</a11y-option>
|
|
329
|
+
<a11y-option value="mushrooms">Mushrooms</a11y-option>
|
|
330
|
+
<a11y-option value="onions">Onions</a11y-option>
|
|
331
|
+
<a11y-option value="pineapple" disabled>Pineapple (unavailable)</a11y-option>
|
|
332
|
+
</a11y-listbox>
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
#### Listbox Attributes
|
|
336
|
+
|
|
337
|
+
| Attribute | Description | Default |
|
|
338
|
+
| ----------------- | --------------------------------------------- | ---------- |
|
|
339
|
+
| `value` | Selected value(s) (comma-separated for multi) | — |
|
|
340
|
+
| `multiple` | Enable multi-select mode | `false` |
|
|
341
|
+
| `disabled` | Disable all options | `false` |
|
|
342
|
+
| `discoverable` | Keep disabled listbox in tab order | `true` |
|
|
343
|
+
| `orientation` | `horizontal` or `vertical` | `vertical` |
|
|
344
|
+
| `aria-label` | Accessible label | — |
|
|
345
|
+
| `aria-labelledby` | ID of labelling element | — |
|
|
346
|
+
|
|
347
|
+
#### Option Attributes
|
|
348
|
+
|
|
349
|
+
| Attribute | Description | Default |
|
|
350
|
+
| -------------- | --------------------------------- | ------- |
|
|
351
|
+
| `value` | Value for this option | — |
|
|
352
|
+
| `disabled` | Disable this option | `false` |
|
|
353
|
+
| `discoverable` | Keep disabled option in tab order | `true` |
|
|
354
|
+
|
|
355
|
+
#### Optgroup Attributes
|
|
356
|
+
|
|
357
|
+
| Attribute | Description | Default |
|
|
358
|
+
| ---------- | ------------------------------- | ------- |
|
|
359
|
+
| `label` | Group label (visible, required) | — |
|
|
360
|
+
| `disabled` | Disable all options in group | `false` |
|
|
361
|
+
|
|
362
|
+
#### Properties
|
|
363
|
+
|
|
364
|
+
```js
|
|
365
|
+
const listbox = document.querySelector('a11y-listbox');
|
|
366
|
+
listbox.value = 'apple'; // Set selected value (single)
|
|
367
|
+
listbox.value = 'cheese,onions'; // Set selected values (multi, comma-separated)
|
|
368
|
+
listbox.multiple = true; // Toggle multi-select mode
|
|
369
|
+
listbox.disabled = true; // Disable all options
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
#### Events
|
|
373
|
+
|
|
374
|
+
```js
|
|
375
|
+
listbox.addEventListener('change', (e) => {
|
|
376
|
+
console.log('Value:', e.detail.value);
|
|
377
|
+
console.log('Label:', e.detail.label);
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
listbox.addEventListener('a11y-listbox-change', (e) => {
|
|
381
|
+
console.log('Selected:', e.detail);
|
|
382
|
+
});
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
#### Keyboard Navigation
|
|
386
|
+
|
|
387
|
+
| Key | Single Select | Multi Select |
|
|
388
|
+
| ----------------------- | ---------------------------------- | ------------------------------- |
|
|
389
|
+
| `ArrowDown` / `ArrowUp` | Move focus and select | Move focus only |
|
|
390
|
+
| `Home` / `End` | First/last option and select | Move focus only |
|
|
391
|
+
| `Space` | — | Toggle focused option |
|
|
392
|
+
| `Shift+ArrowDown/Up` | — | Move focus and toggle selection |
|
|
393
|
+
| `Ctrl+Shift+Home/End` | — | Select range to first/last |
|
|
394
|
+
| `Ctrl+A` / `Cmd+A` | — | Toggle select all |
|
|
395
|
+
| Type characters | Jump to matching option and select | Jump to matching option |
|
|
396
|
+
|
|
397
|
+
#### CSS Custom Properties
|
|
398
|
+
|
|
399
|
+
```css
|
|
400
|
+
a11y-listbox {
|
|
401
|
+
--compa11y-listbox-bg: white;
|
|
402
|
+
--compa11y-listbox-border: 1px solid #ccc;
|
|
403
|
+
--compa11y-listbox-radius: 6px;
|
|
404
|
+
--compa11y-listbox-max-height: 300px;
|
|
405
|
+
--compa11y-listbox-padding: 4px;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
a11y-option {
|
|
409
|
+
--compa11y-option-padding: 0.5rem 0.75rem;
|
|
410
|
+
--compa11y-option-radius: 4px;
|
|
411
|
+
--compa11y-option-hover-bg: #f5f5f5;
|
|
412
|
+
--compa11y-option-focused-bg: #e6f0ff;
|
|
413
|
+
--compa11y-option-focused-border: #0066cc;
|
|
414
|
+
--compa11y-option-selected-bg: #e6f0ff;
|
|
415
|
+
--compa11y-option-selected-color: #0066cc;
|
|
416
|
+
--compa11y-option-check-color: #0066cc;
|
|
417
|
+
--compa11y-option-disabled-color: #999;
|
|
418
|
+
--compa11y-option-disabled-bg: transparent;
|
|
419
|
+
--compa11y-focus-color: #0066cc;
|
|
420
|
+
}
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### Input
|
|
424
|
+
|
|
425
|
+
```html
|
|
426
|
+
<a11y-input
|
|
427
|
+
label="Full Name"
|
|
428
|
+
hint="Enter your first and last name"
|
|
429
|
+
required
|
|
430
|
+
placeholder="John Doe"
|
|
431
|
+
type="text"
|
|
432
|
+
></a11y-input>
|
|
433
|
+
|
|
434
|
+
<!-- With error -->
|
|
435
|
+
<a11y-input
|
|
436
|
+
label="Email"
|
|
437
|
+
error="Please enter a valid email"
|
|
438
|
+
type="email"
|
|
439
|
+
></a11y-input>
|
|
440
|
+
|
|
441
|
+
<!-- Read-only -->
|
|
442
|
+
<a11y-input label="User ID" value="USR-12345" readonly></a11y-input>
|
|
443
|
+
|
|
444
|
+
<!-- Disabled -->
|
|
445
|
+
<a11y-input label="Organization" value="Compa11y Inc." disabled></a11y-input>
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
#### Attributes
|
|
449
|
+
|
|
450
|
+
| Attribute | Description | Default |
|
|
451
|
+
| ----------------- | ------------------------ | -------- |
|
|
452
|
+
| `label` | Visible label text | — |
|
|
453
|
+
| `hint` | Hint/description text | — |
|
|
454
|
+
| `error` | Error message text | — |
|
|
455
|
+
| `type` | Input type | `'text'` |
|
|
456
|
+
| `placeholder` | Placeholder text | — |
|
|
457
|
+
| `value` | Current value | — |
|
|
458
|
+
| `disabled` | Disable the input | `false` |
|
|
459
|
+
| `readonly` | Read-only input | `false` |
|
|
460
|
+
| `required` | Required field | `false` |
|
|
461
|
+
| `name` | Name for form submission | — |
|
|
462
|
+
| `aria-label` | Accessible label | — |
|
|
463
|
+
| `aria-labelledby` | ID of labelling element | — |
|
|
464
|
+
|
|
465
|
+
#### Properties
|
|
466
|
+
|
|
467
|
+
```js
|
|
468
|
+
const input = document.querySelector('a11y-input');
|
|
469
|
+
input.value = 'Hello'; // Set value
|
|
470
|
+
input.error = 'Required'; // Set error (shows role="alert")
|
|
471
|
+
input.error = ''; // Clear error
|
|
472
|
+
input.disabled = true; // Disable
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
#### Methods
|
|
476
|
+
|
|
477
|
+
```js
|
|
478
|
+
const input = document.querySelector('a11y-input');
|
|
479
|
+
input.focus(); // Focus the input
|
|
480
|
+
input.blur(); // Blur the input
|
|
481
|
+
input.select(); // Select all text
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
#### Events
|
|
485
|
+
|
|
486
|
+
```js
|
|
487
|
+
input.addEventListener('input', (e) => {
|
|
488
|
+
console.log('Value:', e.detail.value);
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
input.addEventListener('change', (e) => {
|
|
492
|
+
console.log('Final value:', e.detail.value);
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
input.addEventListener('a11y-input-focus', () => {});
|
|
496
|
+
input.addEventListener('a11y-input-blur', () => {});
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
### Textarea
|
|
500
|
+
|
|
501
|
+
```html
|
|
502
|
+
<a11y-textarea
|
|
503
|
+
label="Description"
|
|
504
|
+
hint="Provide at least 10 characters"
|
|
505
|
+
required
|
|
506
|
+
rows="4"
|
|
507
|
+
placeholder="Enter a description..."
|
|
508
|
+
></a11y-textarea>
|
|
509
|
+
|
|
510
|
+
<!-- With error -->
|
|
511
|
+
<a11y-textarea label="Bio" error="Bio is required" rows="5"></a11y-textarea>
|
|
512
|
+
|
|
513
|
+
<!-- Read-only -->
|
|
514
|
+
<a11y-textarea
|
|
515
|
+
label="Terms"
|
|
516
|
+
value="Read only content..."
|
|
517
|
+
readonly
|
|
518
|
+
rows="3"
|
|
519
|
+
></a11y-textarea>
|
|
520
|
+
|
|
521
|
+
<!-- Disabled -->
|
|
522
|
+
<a11y-textarea
|
|
523
|
+
label="Notes"
|
|
524
|
+
value="Disabled content"
|
|
525
|
+
disabled
|
|
526
|
+
rows="2"
|
|
527
|
+
></a11y-textarea>
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
#### Attributes
|
|
531
|
+
|
|
532
|
+
| Attribute | Description | Default |
|
|
533
|
+
| ----------------- | ------------------------ | ------------ |
|
|
534
|
+
| `label` | Visible label text | — |
|
|
535
|
+
| `hint` | Hint/description text | — |
|
|
536
|
+
| `error` | Error message text | — |
|
|
537
|
+
| `rows` | Number of visible rows | `3` |
|
|
538
|
+
| `resize` | Resize behavior | `'vertical'` |
|
|
539
|
+
| `placeholder` | Placeholder text | — |
|
|
540
|
+
| `value` | Current value | — |
|
|
541
|
+
| `disabled` | Disable the textarea | `false` |
|
|
542
|
+
| `readonly` | Read-only textarea | `false` |
|
|
543
|
+
| `required` | Required field | `false` |
|
|
544
|
+
| `name` | Name for form submission | — |
|
|
545
|
+
| `aria-label` | Accessible label | — |
|
|
546
|
+
| `aria-labelledby` | ID of labelling element | — |
|
|
547
|
+
|
|
548
|
+
#### Properties
|
|
549
|
+
|
|
550
|
+
```js
|
|
551
|
+
const textarea = document.querySelector('a11y-textarea');
|
|
552
|
+
textarea.value = 'Hello'; // Set value
|
|
553
|
+
textarea.error = 'Required'; // Set error (shows role="alert")
|
|
554
|
+
textarea.error = ''; // Clear error
|
|
555
|
+
textarea.disabled = true; // Disable
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
#### Methods
|
|
559
|
+
|
|
560
|
+
```js
|
|
561
|
+
const textarea = document.querySelector('a11y-textarea');
|
|
562
|
+
textarea.focus(); // Focus the textarea
|
|
563
|
+
textarea.blur(); // Blur the textarea
|
|
564
|
+
textarea.select(); // Select all text
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
#### Events
|
|
568
|
+
|
|
569
|
+
```js
|
|
570
|
+
textarea.addEventListener('input', (e) => {
|
|
571
|
+
console.log('Value:', e.detail.value);
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
textarea.addEventListener('change', (e) => {
|
|
575
|
+
console.log('Final value:', e.detail.value);
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
textarea.addEventListener('a11y-textarea-focus', () => {});
|
|
579
|
+
textarea.addEventListener('a11y-textarea-blur', () => {});
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
### Button
|
|
583
|
+
|
|
584
|
+
```html
|
|
585
|
+
<a11y-button variant="primary">Save</a11y-button>
|
|
586
|
+
<a11y-button variant="danger">Delete</a11y-button>
|
|
587
|
+
<a11y-button variant="outline">Cancel</a11y-button>
|
|
588
|
+
|
|
589
|
+
<!-- Loading state -->
|
|
590
|
+
<a11y-button variant="primary" loading>Saving...</a11y-button>
|
|
591
|
+
|
|
592
|
+
<!-- Disabled but discoverable (stays in tab order) -->
|
|
593
|
+
<a11y-button variant="primary" disabled discoverable>Unavailable</a11y-button>
|
|
594
|
+
|
|
595
|
+
<!-- Sizes -->
|
|
596
|
+
<a11y-button variant="primary" size="sm">Small</a11y-button>
|
|
597
|
+
<a11y-button variant="primary" size="md">Medium</a11y-button>
|
|
598
|
+
<a11y-button variant="primary" size="lg">Large</a11y-button>
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
#### Attributes
|
|
602
|
+
|
|
603
|
+
| Attribute | Description | Default |
|
|
604
|
+
| -------------- | ----------------------------------------------------------- | ------------- |
|
|
605
|
+
| `variant` | Visual variant (primary, secondary, danger, outline, ghost) | `'secondary'` |
|
|
606
|
+
| `size` | Size (sm, md, lg) | `'md'` |
|
|
607
|
+
| `type` | Button type (button, submit, reset) | `'button'` |
|
|
608
|
+
| `disabled` | Disable the button | `false` |
|
|
609
|
+
| `discoverable` | Keep disabled button in tab order | `false` |
|
|
610
|
+
| `loading` | Loading state (shows spinner, aria-busy) | `false` |
|
|
611
|
+
| `aria-label` | Accessible label | — |
|
|
612
|
+
|
|
613
|
+
#### Properties
|
|
614
|
+
|
|
615
|
+
```js
|
|
616
|
+
const btn = document.querySelector('a11y-button');
|
|
617
|
+
btn.disabled = true; // Disable
|
|
618
|
+
btn.loading = true; // Set loading
|
|
619
|
+
btn.variant = 'danger'; // Change variant
|
|
620
|
+
btn.size = 'lg'; // Change size
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
#### Methods
|
|
624
|
+
|
|
625
|
+
```js
|
|
626
|
+
const btn = document.querySelector('a11y-button');
|
|
627
|
+
btn.focus(); // Focus the button
|
|
628
|
+
btn.blur(); // Blur the button
|
|
629
|
+
btn.click(); // Programmatic click
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
#### Events
|
|
633
|
+
|
|
634
|
+
```js
|
|
635
|
+
btn.addEventListener('a11y-button-click', () => {
|
|
636
|
+
console.log('Button clicked');
|
|
637
|
+
});
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
#### CSS Custom Properties
|
|
641
|
+
|
|
642
|
+
```css
|
|
643
|
+
a11y-button {
|
|
644
|
+
--compa11y-button-radius: 4px;
|
|
645
|
+
--compa11y-button-font-weight: 500;
|
|
646
|
+
--compa11y-button-disabled-opacity: 0.5;
|
|
647
|
+
--compa11y-button-primary-bg: #0066cc;
|
|
648
|
+
--compa11y-button-primary-color: white;
|
|
649
|
+
--compa11y-button-danger-bg: #ef4444;
|
|
650
|
+
--compa11y-button-danger-color: white;
|
|
651
|
+
--compa11y-focus-color: #0066cc;
|
|
652
|
+
}
|
|
653
|
+
```
|
|
654
|
+
|
|
153
655
|
## Styling
|
|
154
656
|
|
|
155
657
|
Use CSS custom properties for theming:
|
|
@@ -182,6 +684,112 @@ a11y-tabs {
|
|
|
182
684
|
--compa11y-tab-active-color: #0066cc;
|
|
183
685
|
}
|
|
184
686
|
|
|
687
|
+
/* Combobox */
|
|
688
|
+
a11y-combobox {
|
|
689
|
+
--compa11y-combobox-width: 300px;
|
|
690
|
+
--compa11y-combobox-border: 1px solid #ccc;
|
|
691
|
+
--compa11y-combobox-radius: 4px;
|
|
692
|
+
--compa11y-combobox-option-hover-bg: #f5f5f5;
|
|
693
|
+
--compa11y-combobox-option-selected-bg: #e6f0ff;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
/* Select */
|
|
697
|
+
a11y-select {
|
|
698
|
+
--compa11y-select-width: 300px;
|
|
699
|
+
--compa11y-select-border: 1px solid #ccc;
|
|
700
|
+
--compa11y-select-radius: 4px;
|
|
701
|
+
--compa11y-select-bg: white;
|
|
702
|
+
--compa11y-select-placeholder-color: #999;
|
|
703
|
+
--compa11y-select-chevron-color: #666;
|
|
704
|
+
--compa11y-select-option-hover-bg: #f5f5f5;
|
|
705
|
+
--compa11y-select-option-selected-bg: #e6f0ff;
|
|
706
|
+
--compa11y-select-check-color: #0066cc;
|
|
707
|
+
--compa11y-select-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
/* Switch */
|
|
711
|
+
a11y-switch {
|
|
712
|
+
--compa11y-switch-bg: #d1d5db;
|
|
713
|
+
--compa11y-switch-checked-bg: #0066cc;
|
|
714
|
+
--compa11y-switch-thumb-bg: white;
|
|
715
|
+
--compa11y-switch-width: 2.75rem;
|
|
716
|
+
--compa11y-switch-height: 1.5rem;
|
|
717
|
+
--compa11y-switch-thumb-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
/* Input */
|
|
721
|
+
a11y-input {
|
|
722
|
+
--compa11y-input-border: 1px solid #ccc;
|
|
723
|
+
--compa11y-input-border-focus: #0066cc;
|
|
724
|
+
--compa11y-input-border-error: #ef4444;
|
|
725
|
+
--compa11y-input-bg: white;
|
|
726
|
+
--compa11y-input-radius: 4px;
|
|
727
|
+
--compa11y-input-padding: 0.5rem 0.75rem;
|
|
728
|
+
--compa11y-input-font-size: 0.875rem;
|
|
729
|
+
--compa11y-input-label-color: inherit;
|
|
730
|
+
--compa11y-input-label-size: 0.875rem;
|
|
731
|
+
--compa11y-input-label-weight: 500;
|
|
732
|
+
--compa11y-input-hint-color: #666;
|
|
733
|
+
--compa11y-input-hint-size: 0.8125rem;
|
|
734
|
+
--compa11y-input-error-color: #ef4444;
|
|
735
|
+
--compa11y-input-error-size: 0.8125rem;
|
|
736
|
+
--compa11y-input-required-color: #ef4444;
|
|
737
|
+
--compa11y-input-disabled-bg: #f5f5f5;
|
|
738
|
+
--compa11y-input-placeholder-color: #999;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
/* Textarea */
|
|
742
|
+
a11y-textarea {
|
|
743
|
+
--compa11y-textarea-border: 1px solid #ccc;
|
|
744
|
+
--compa11y-textarea-border-focus: #0066cc;
|
|
745
|
+
--compa11y-textarea-border-error: #ef4444;
|
|
746
|
+
--compa11y-textarea-bg: white;
|
|
747
|
+
--compa11y-textarea-radius: 4px;
|
|
748
|
+
--compa11y-textarea-padding: 0.5rem 0.75rem;
|
|
749
|
+
--compa11y-textarea-font-size: 0.875rem;
|
|
750
|
+
--compa11y-textarea-resize: vertical;
|
|
751
|
+
--compa11y-textarea-label-color: inherit;
|
|
752
|
+
--compa11y-textarea-label-size: 0.875rem;
|
|
753
|
+
--compa11y-textarea-label-weight: 500;
|
|
754
|
+
--compa11y-textarea-hint-color: #666;
|
|
755
|
+
--compa11y-textarea-hint-size: 0.8125rem;
|
|
756
|
+
--compa11y-textarea-error-color: #ef4444;
|
|
757
|
+
--compa11y-textarea-error-size: 0.8125rem;
|
|
758
|
+
--compa11y-textarea-required-color: #ef4444;
|
|
759
|
+
--compa11y-textarea-disabled-bg: #f5f5f5;
|
|
760
|
+
--compa11y-textarea-placeholder-color: #999;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
/* Button */
|
|
764
|
+
a11y-button {
|
|
765
|
+
--compa11y-button-radius: 4px;
|
|
766
|
+
--compa11y-button-font-weight: 500;
|
|
767
|
+
--compa11y-button-disabled-opacity: 0.5;
|
|
768
|
+
--compa11y-button-primary-bg: #0066cc;
|
|
769
|
+
--compa11y-button-primary-color: white;
|
|
770
|
+
--compa11y-button-danger-bg: #ef4444;
|
|
771
|
+
--compa11y-button-danger-color: white;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
/* Listbox */
|
|
775
|
+
a11y-listbox {
|
|
776
|
+
--compa11y-listbox-bg: white;
|
|
777
|
+
--compa11y-listbox-border: 1px solid #ccc;
|
|
778
|
+
--compa11y-listbox-radius: 6px;
|
|
779
|
+
--compa11y-listbox-max-height: 300px;
|
|
780
|
+
--compa11y-listbox-padding: 4px;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
a11y-option {
|
|
784
|
+
--compa11y-option-padding: 0.5rem 0.75rem;
|
|
785
|
+
--compa11y-option-radius: 4px;
|
|
786
|
+
--compa11y-option-hover-bg: #f5f5f5;
|
|
787
|
+
--compa11y-option-focused-bg: #e6f0ff;
|
|
788
|
+
--compa11y-option-selected-bg: #e6f0ff;
|
|
789
|
+
--compa11y-option-check-color: #0066cc;
|
|
790
|
+
--compa11y-option-disabled-color: #999;
|
|
791
|
+
}
|
|
792
|
+
|
|
185
793
|
/* Focus ring */
|
|
186
794
|
:root {
|
|
187
795
|
--compa11y-focus-color: #0066cc;
|