wally-ui 1.5.1 → 1.6.0
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/package.json +1 -1
- package/playground/showcase/src/app/components/breadcrumb/breadcrumb.html +16 -12
- package/playground/showcase/src/app/components/button/button.html +9 -1
- package/playground/showcase/src/app/components/button/button.ts +5 -0
- package/playground/showcase/src/app/components/input/input.html +3 -3
- package/playground/showcase/src/app/pages/documentation/components/button-docs/button-docs.examples.ts +20 -0
- package/playground/showcase/src/app/pages/documentation/components/button-docs/button-docs.html +72 -10
- package/playground/showcase/src/app/pages/documentation/components/button-docs/button-docs.ts +9 -0
package/package.json
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
|
-
<nav class="">
|
|
2
|
-
<
|
|
1
|
+
<nav class="transition duration-200 ease-in-out" aria-label="Breadcrumb">
|
|
2
|
+
<ol class="flex items-center flex-wrap gap-x-2 gap-y-1 text-sm text-neutral-500 dark:text-neutral-400 antialiased">
|
|
3
3
|
@for (item of items(); track item.label; let isLast = $last) {
|
|
4
4
|
@if (!isLast && item.url) {
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
<li class="flex items-center gap-2">
|
|
6
|
+
<a
|
|
7
|
+
[routerLink]="item.url"
|
|
8
|
+
class="hover:text-blue-500 transition-colors">
|
|
9
|
+
{{ item.label }}
|
|
10
|
+
</a>
|
|
11
|
+
<span class="text-neutral-500 dark:text-neutral-500" aria-hidden="true">/</span>
|
|
12
|
+
</li>
|
|
11
13
|
} @else {
|
|
12
|
-
<
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
<li>
|
|
15
|
+
<span class="text-[#0a0a0a] dark:text-white font-medium" [attr.aria-current]="isLast ? 'page' : null">
|
|
16
|
+
{{ item.label }}
|
|
17
|
+
</span>
|
|
18
|
+
</li>
|
|
15
19
|
}
|
|
16
20
|
}
|
|
17
|
-
</
|
|
21
|
+
</ol>
|
|
18
22
|
</nav>
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
<button
|
|
1
|
+
<button
|
|
2
|
+
[type]="type()"
|
|
3
|
+
[disabled]="disabled() || loading()"
|
|
4
|
+
[attr.aria-label]="ariaLabel() || null"
|
|
5
|
+
[attr.aria-describedby]="ariaDescribedBy() || null"
|
|
6
|
+
[attr.aria-pressed]="ariaPressed()"
|
|
7
|
+
[attr.aria-busy]="loading()"
|
|
8
|
+
(click)="handleClick()"
|
|
9
|
+
class="
|
|
2
10
|
group
|
|
3
11
|
relative
|
|
4
12
|
w-full
|
|
@@ -15,6 +15,11 @@ export class Button {
|
|
|
15
15
|
loading: InputSignal<boolean> = input<boolean>(false);
|
|
16
16
|
showNotification: InputSignal<boolean> = input<boolean>(false);
|
|
17
17
|
|
|
18
|
+
// Accessibility properties
|
|
19
|
+
ariaLabel: InputSignal<string> = input<string>('');
|
|
20
|
+
ariaDescribedBy: InputSignal<string> = input<string>('');
|
|
21
|
+
ariaPressed: InputSignal<boolean | undefined> = input<boolean | undefined>(undefined);
|
|
22
|
+
|
|
18
23
|
click: OutputEmitterRef<void> = output<void>();
|
|
19
24
|
|
|
20
25
|
handleClick(): void {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
@if (label()) {
|
|
2
|
-
<div class="py-2">
|
|
2
|
+
<div class="py-2 antialiased">
|
|
3
3
|
<label [for]="inputId" class="block text-sm font-medium text-[#0a0a0a] dark:text-white">
|
|
4
4
|
{{ label() }}
|
|
5
5
|
</label>
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
focus:outline-none focus:ring-2 focus:ring-neutral-300
|
|
20
20
|
bg-gray-100
|
|
21
21
|
dark:bg-[#1b1b1b] dark:text-white dark:placeholder:text-neutral-500 dark:focus:ring-neutral-700
|
|
22
|
-
disabled:opacity-70 disabled:pointer-events-none disabled:cursor-not-allowed
|
|
22
|
+
disabled:opacity-70 disabled:pointer-events-none disabled:cursor-not-allowed antialiased
|
|
23
23
|
transition duration-200 ease-in-out
|
|
24
24
|
py-4 px-4" [ngClass]="{
|
|
25
25
|
'pe-12': type() === 'password',
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
|
|
65
65
|
@if (errorMessage()) {
|
|
66
66
|
<div class="py-1" [id]="inputId + '-error'">
|
|
67
|
-
<span class="text-sm text-red-500 font-medium">
|
|
67
|
+
<span class="text-sm text-red-500 font-medium antialiased">
|
|
68
68
|
{{ errorMessage() }}
|
|
69
69
|
</span>
|
|
70
70
|
</div>
|
|
@@ -47,9 +47,29 @@ export const ButtonCodeExamples = {
|
|
|
47
47
|
</svg>
|
|
48
48
|
</wally-button>`,
|
|
49
49
|
|
|
50
|
+
// Accessibility
|
|
51
|
+
ariaLabel: `<wally-button ariaLabel="Save document">
|
|
52
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
|
53
|
+
stroke-width="1.5" stroke="currentColor" class="size-5">
|
|
54
|
+
<path stroke-linecap="round" stroke-linejoin="round"
|
|
55
|
+
d="M17.593 3.322c1.1.128 1.907 1.077 1.907 2.185V21L12 17.25 4.5 21V5.507c0-1.108.806-2.057 1.907-2.185a48.507 48.507 0 0111.186 0z" />
|
|
56
|
+
</svg>
|
|
57
|
+
</wally-button>`,
|
|
58
|
+
|
|
59
|
+
ariaPressed: `<wally-button [ariaPressed]="isToggled">
|
|
60
|
+
Toggle Setting
|
|
61
|
+
</wally-button>`,
|
|
62
|
+
|
|
63
|
+
ariaBusy: `<wally-button [loading]="true">
|
|
64
|
+
Processing...
|
|
65
|
+
</wally-button>`,
|
|
66
|
+
|
|
50
67
|
// Properties
|
|
51
68
|
propertyType: `type: string = 'button';`,
|
|
52
69
|
propertyDisabled: `disabled: boolean = false;`,
|
|
53
70
|
propertyLoading: `loading: boolean = false;`,
|
|
54
71
|
propertyShowNotification: `showNotification: boolean = false;`,
|
|
72
|
+
propertyAriaLabel: `ariaLabel: string = '';`,
|
|
73
|
+
propertyAriaPressed: `ariaPressed: boolean | undefined = undefined;`,
|
|
74
|
+
propertyAriaDescribedBy: `ariaDescribedBy: string = '';`,
|
|
55
75
|
};
|
package/playground/showcase/src/app/pages/documentation/components/button-docs/button-docs.html
CHANGED
|
@@ -274,6 +274,57 @@
|
|
|
274
274
|
</div>
|
|
275
275
|
</section>
|
|
276
276
|
|
|
277
|
+
<!-- Accessibility -->
|
|
278
|
+
<section class="mb-8">
|
|
279
|
+
<h2 class="text-lg font-semibold mb-4 text-[#0a0a0a] dark:text-white">Accessibility</h2>
|
|
280
|
+
|
|
281
|
+
<div class="space-y-8">
|
|
282
|
+
<!-- ARIA Label -->
|
|
283
|
+
<div>
|
|
284
|
+
<h3 class="text-md font-medium mb-3 text-[#0a0a0a] dark:text-white">ARIA Label for Icon-Only Buttons</h3>
|
|
285
|
+
<div class="bg-gray-200 dark:bg-[#121212] p-4 rounded-lg mb-4">
|
|
286
|
+
<pre><code [innerHTML]="ariaLabelCode" class="text-sm text-[#0a0a0a] dark:text-white"></code></pre>
|
|
287
|
+
</div>
|
|
288
|
+
<div class="p-6 border rounded-lg bg-white dark:bg-[#121212]">
|
|
289
|
+
<wally-button ariaLabel="Save document">
|
|
290
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
|
291
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M17.593 3.322c1.1.128 1.907 1.077 1.907 2.185V21L12 17.25 4.5 21V5.507c0-1.108.806-2.057 1.907-2.185a48.507 48.507 0 0111.186 0z" />
|
|
292
|
+
</svg>
|
|
293
|
+
</wally-button>
|
|
294
|
+
</div>
|
|
295
|
+
</div>
|
|
296
|
+
|
|
297
|
+
<!-- Toggle Button -->
|
|
298
|
+
<div>
|
|
299
|
+
<h3 class="text-md font-medium mb-3 text-[#0a0a0a] dark:text-white">Toggle Button with ARIA Pressed</h3>
|
|
300
|
+
<div class="bg-gray-200 dark:bg-[#121212] p-4 rounded-lg mb-4">
|
|
301
|
+
<pre><code [innerHTML]="ariaPressedCode" class="text-sm text-[#0a0a0a] dark:text-white"></code></pre>
|
|
302
|
+
</div>
|
|
303
|
+
<div class="p-6 border rounded-lg bg-white dark:bg-[#121212]">
|
|
304
|
+
<wally-button [ariaPressed]="toggleState()">
|
|
305
|
+
Toggle Setting
|
|
306
|
+
</wally-button>
|
|
307
|
+
</div>
|
|
308
|
+
</div>
|
|
309
|
+
|
|
310
|
+
<!-- Loading State -->
|
|
311
|
+
<div>
|
|
312
|
+
<h3 class="text-md font-medium mb-3 text-[#0a0a0a] dark:text-white">Loading State with ARIA Busy</h3>
|
|
313
|
+
<div class="bg-gray-200 dark:bg-[#121212] p-4 rounded-lg mb-4">
|
|
314
|
+
<pre><code [innerHTML]="ariaBusyCode" class="text-sm text-[#0a0a0a] dark:text-white"></code></pre>
|
|
315
|
+
</div>
|
|
316
|
+
<div class="p-6 border rounded-lg bg-white dark:bg-[#121212]">
|
|
317
|
+
<wally-button [loading]="true">
|
|
318
|
+
Processing...
|
|
319
|
+
</wally-button>
|
|
320
|
+
</div>
|
|
321
|
+
<p class="text-sm text-gray-600 dark:text-gray-400 mt-2">
|
|
322
|
+
Automatically sets <code class="bg-gray-200 dark:bg-[#121212] px-1 py-0.5 rounded text-xs">aria-busy="true"</code> when loading
|
|
323
|
+
</p>
|
|
324
|
+
</div>
|
|
325
|
+
</div>
|
|
326
|
+
</section>
|
|
327
|
+
|
|
277
328
|
<!-- Properties -->
|
|
278
329
|
<section class="mb-8">
|
|
279
330
|
<h2 class="text-lg font-semibold mb-4 text-[#0a0a0a] dark:text-white">Properties</h2>
|
|
@@ -306,6 +357,27 @@
|
|
|
306
357
|
</div>
|
|
307
358
|
<p class="text-sm text-gray-700 dark:text-gray-400">Shows notification badge when true</p>
|
|
308
359
|
</div>
|
|
360
|
+
|
|
361
|
+
<div class="space-y-2">
|
|
362
|
+
<div class="bg-gray-200 dark:bg-[#121212] p-4 rounded-lg">
|
|
363
|
+
<pre><code [innerHTML]="propertyAriaLabelCode" class="text-sm text-[#0a0a0a] dark:text-white"></code></pre>
|
|
364
|
+
</div>
|
|
365
|
+
<p class="text-sm text-gray-700 dark:text-gray-400">Accessible label for screen readers (essential for icon-only buttons)</p>
|
|
366
|
+
</div>
|
|
367
|
+
|
|
368
|
+
<div class="space-y-2">
|
|
369
|
+
<div class="bg-gray-200 dark:bg-[#121212] p-4 rounded-lg">
|
|
370
|
+
<pre><code [innerHTML]="propertyAriaPressedCode" class="text-sm text-[#0a0a0a] dark:text-white"></code></pre>
|
|
371
|
+
</div>
|
|
372
|
+
<p class="text-sm text-gray-700 dark:text-gray-400">Indicates pressed state for toggle buttons</p>
|
|
373
|
+
</div>
|
|
374
|
+
|
|
375
|
+
<div class="space-y-2">
|
|
376
|
+
<div class="bg-gray-200 dark:bg-[#121212] p-4 rounded-lg">
|
|
377
|
+
<pre><code [innerHTML]="propertyAriaDescribedByCode" class="text-sm text-[#0a0a0a] dark:text-white"></code></pre>
|
|
378
|
+
</div>
|
|
379
|
+
<p class="text-sm text-gray-700 dark:text-gray-400">References element(s) that describe the button</p>
|
|
380
|
+
</div>
|
|
309
381
|
</div>
|
|
310
382
|
</section>
|
|
311
383
|
|
|
@@ -324,16 +396,6 @@
|
|
|
324
396
|
</p>
|
|
325
397
|
</div>
|
|
326
398
|
|
|
327
|
-
<div class="bg-gray-200 dark:bg-[#121212] p-4 rounded-lg">
|
|
328
|
-
<div class="flex items-center gap-2 mb-2">
|
|
329
|
-
<h3 class="text-md font-medium text-[#0a0a0a] dark:text-white">Accessibility</h3>
|
|
330
|
-
<span class="text-xs bg-yellow-500 text-black px-2 py-1 rounded">Under Construction</span>
|
|
331
|
-
</div>
|
|
332
|
-
<p class="text-sm text-gray-700 dark:text-gray-400">
|
|
333
|
-
ARIA labels, keyboard navigation, and screen reader support for better accessibility.
|
|
334
|
-
</p>
|
|
335
|
-
</div>
|
|
336
|
-
|
|
337
399
|
<div class="bg-gray-200 dark:bg-[#121212] p-4 rounded-lg">
|
|
338
400
|
<div class="flex items-center gap-2 mb-2">
|
|
339
401
|
<h3 class="text-md font-medium text-[#0a0a0a] dark:text-white">Ripple Effect</h3>
|
package/playground/showcase/src/app/pages/documentation/components/button-docs/button-docs.ts
CHANGED
|
@@ -38,13 +38,22 @@ export class ButtonDocs {
|
|
|
38
38
|
iconCode = getFormattedCode(ButtonCodeExamples.iconWithText, 'html');
|
|
39
39
|
iconNotificationCode = getFormattedCode(ButtonCodeExamples.iconOnly, 'html');
|
|
40
40
|
|
|
41
|
+
// Accessibility
|
|
42
|
+
ariaLabelCode = getFormattedCode(ButtonCodeExamples.ariaLabel, 'html');
|
|
43
|
+
ariaPressedCode = getFormattedCode(ButtonCodeExamples.ariaPressed, 'html');
|
|
44
|
+
ariaBusyCode = getFormattedCode(ButtonCodeExamples.ariaBusy, 'html');
|
|
45
|
+
|
|
41
46
|
// Properties
|
|
42
47
|
propertyTypeCode = getFormattedCode(ButtonCodeExamples.propertyType, 'typescript');
|
|
43
48
|
propertyDisabledCode = getFormattedCode(ButtonCodeExamples.propertyDisabled, 'typescript');
|
|
44
49
|
propertyLoadingCode = getFormattedCode(ButtonCodeExamples.propertyLoading, 'typescript');
|
|
45
50
|
propertyShowNotificationCode = getFormattedCode(ButtonCodeExamples.propertyShowNotification, 'typescript');
|
|
51
|
+
propertyAriaLabelCode = getFormattedCode(ButtonCodeExamples.propertyAriaLabel, 'typescript');
|
|
52
|
+
propertyAriaPressedCode = getFormattedCode(ButtonCodeExamples.propertyAriaPressed, 'typescript');
|
|
53
|
+
propertyAriaDescribedByCode = getFormattedCode(ButtonCodeExamples.propertyAriaDescribedBy, 'typescript');
|
|
46
54
|
|
|
47
55
|
clickMessage: WritableSignal<string> = signal<string>('');
|
|
56
|
+
toggleState: WritableSignal<boolean> = signal<boolean>(false);
|
|
48
57
|
|
|
49
58
|
constructor(
|
|
50
59
|
private aiPromptService: AiPromptService
|