@kerfjs/ui 5.0.0-beta.62 → 5.0.0-beta.63
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 +4 -0
- package/ai/component-catalog-extension.schema.json +13 -0
- package/ai/component-catalog.json +8 -2
- package/ai/component-composition.json +9 -2
- package/ai/components/list-item.md +1 -1
- package/ai/components/workbench.md +3 -2
- package/ai/public-api-signatures-v1.md +136 -38
- package/ai/skill.md +9 -5
- package/ai/webawesome-jsx-signatures-v1.md +1 -1
- package/analyzer/index.mjs +3 -2
- package/catalog-projection-cli.mjs +96 -0
- package/catalog-projection.d.mts +55 -0
- package/catalog-projection.mjs +62 -0
- package/dist/browser/catalog.js +1 -1
- package/dist/browser/collapsible-panel.js +2 -0
- package/dist/browser/nav-stack.js +1 -0
- package/dist/browser/split-view.js +1 -0
- package/dist/browser/toolbar-control-group.js +1 -0
- package/dist/browser/workbench.js +1 -0
- package/dist/catalog-resources.d.ts +1 -1
- package/dist/catalog.d.ts +1 -1
- package/dist/catalog.js +11 -10
- package/dist/catalog.js.map +1 -1
- package/dist/chip.d.ts +9 -3
- package/dist/chip.js +1 -1
- package/dist/{chunk-OD2VXAPL.js → chunk-3BYFWTP3.js} +4 -3
- package/dist/chunk-3BYFWTP3.js.map +1 -0
- package/dist/{chunk-5Q3N6EV7.js → chunk-5IJ6UGNZ.js} +3 -3
- package/dist/{chunk-5Q3N6EV7.js.map → chunk-5IJ6UGNZ.js.map} +1 -1
- package/dist/chunk-7AKGPBCC.js +76 -0
- package/dist/chunk-7AKGPBCC.js.map +1 -0
- package/dist/{chunk-KROD7KZK.js → chunk-AUVG54KC.js} +2 -2
- package/dist/{chunk-KROD7KZK.js.map → chunk-AUVG54KC.js.map} +1 -1
- package/dist/{chunk-AUKT3KMG.js → chunk-CQHN45XR.js} +17 -2
- package/dist/chunk-CQHN45XR.js.map +1 -0
- package/dist/{chunk-SWVW56CV.js → chunk-EN4LDR5Y.js} +2 -2
- package/dist/{chunk-SWVW56CV.js.map → chunk-EN4LDR5Y.js.map} +1 -1
- package/dist/{chunk-4MG3KXJM.js → chunk-F7OCOBTG.js} +2 -2
- package/dist/{chunk-4MG3KXJM.js.map → chunk-F7OCOBTG.js.map} +1 -1
- package/dist/{chunk-KYDDCJXU.js → chunk-HXCMWANP.js} +4 -4
- package/dist/{chunk-KYDDCJXU.js.map → chunk-HXCMWANP.js.map} +1 -1
- package/dist/{chunk-ENGVYQPG.js → chunk-IA4D5XNT.js} +60 -10
- package/dist/chunk-IA4D5XNT.js.map +1 -0
- package/dist/{chunk-F4QMLOXJ.js → chunk-IAOAZUOO.js} +2 -2
- package/dist/{chunk-F4QMLOXJ.js.map → chunk-IAOAZUOO.js.map} +1 -1
- package/dist/{chunk-X6ADHJNI.js → chunk-KFYANKJI.js} +25 -6
- package/dist/chunk-KFYANKJI.js.map +1 -0
- package/dist/chunk-MOSIE4Z2.js +51 -0
- package/dist/chunk-MOSIE4Z2.js.map +1 -0
- package/dist/{chunk-7JUBXOIV.js → chunk-NXWE5S57.js} +25 -6
- package/dist/chunk-NXWE5S57.js.map +1 -0
- package/dist/{chunk-NNMLEDMD.js → chunk-OBAFAH5B.js} +36 -8
- package/dist/chunk-OBAFAH5B.js.map +1 -0
- package/dist/{chunk-A3CKOW2R.js → chunk-R75GGNWY.js} +123 -20
- package/dist/chunk-R75GGNWY.js.map +1 -0
- package/dist/chunk-RGS4WX2M.js +44 -0
- package/dist/chunk-RGS4WX2M.js.map +1 -0
- package/dist/{chunk-RRB26JRJ.js → chunk-RTJNJTG3.js} +2 -2
- package/dist/{chunk-RRB26JRJ.js.map → chunk-RTJNJTG3.js.map} +1 -1
- package/dist/{chunk-EAC4CDY7.js → chunk-SMZGAPCU.js} +15 -2
- package/dist/chunk-SMZGAPCU.js.map +1 -0
- package/dist/{chunk-6ZXOQEAN.js → chunk-WF75U3V4.js} +7 -1
- package/dist/chunk-WF75U3V4.js.map +1 -0
- package/dist/{chunk-VCBTX62E.js → chunk-ZRWXFDDS.js} +2 -2
- package/dist/chunk-ZRWXFDDS.js.map +1 -0
- package/dist/collapsible-panel.d.ts +18 -7
- package/dist/collapsible-panel.js +19 -3
- package/dist/collapsible-panel.js.map +1 -1
- package/dist/content-item.d.ts +36 -5
- package/dist/content-item.js +1 -1
- package/dist/disclosure-arrow.js +2 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +19 -19
- package/dist/list-action-row.js +1 -1
- package/dist/list-header.js +1 -1
- package/dist/list-item.js +1 -1
- package/dist/lucide-icon.d.ts +5 -2
- package/dist/lucide-icon.js +2 -1
- package/dist/nav-stack.js +2 -1
- package/dist/pane.d.ts +2 -1
- package/dist/pane.js +1 -1
- package/dist/{panel-toolbar-DqwtBxQL.d.ts → panel-toolbar-DDKh4uKd.d.ts} +11 -2
- package/dist/popup-menu-register.js +38 -1
- package/dist/popup-menu-register.js.map +1 -1
- package/dist/popup-menu.d.ts +2 -2
- package/dist/popup-menu.js +1 -1
- package/dist/select.js +1 -1
- package/dist/split-view.js +2 -1
- package/dist/split-view.js.map +1 -1
- package/dist/styles/chip.css +14 -0
- package/dist/styles/content-item.css +36 -0
- package/dist/styles/list-action-row.css +4 -3
- package/dist/styles/list-header.css +4 -3
- package/dist/styles/list-item.css +21 -11
- package/dist/styles/lucide-icon.css +5 -0
- package/dist/styles/pane.css +3 -2
- package/dist/styles/popup-menu.css +15 -10
- package/dist/styles/select.css +11 -0
- package/dist/styles/sunken-panel.css +7 -0
- package/dist/styles/text.css +29 -0
- package/dist/styles/token-search-field.css +29 -6
- package/dist/styles/toolbar-control-group.css +35 -0
- package/dist/styles/workbench.css +148 -2
- package/dist/sunken-panel.d.ts +6 -1
- package/dist/sunken-panel.js +1 -1
- package/dist/text.d.ts +14 -3
- package/dist/text.js +1 -1
- package/dist/token-search-field.js +2 -1
- package/dist/toolbar-control-group.d.ts +5 -1
- package/dist/toolbar-control-group.js +2 -1
- package/dist/toolbar.d.ts +5 -2
- package/dist/toolbar.js +1 -1
- package/dist/wire-catalog.js +1 -1
- package/dist/wire-content-items.d.ts +9 -0
- package/dist/wire-content-items.js +62 -0
- package/dist/wire-content-items.js.map +1 -0
- package/dist/wire-token-search-fields.js +2 -1
- package/dist/wire-workbench.d.ts +7 -0
- package/dist/wire-workbench.js +1 -1
- package/dist/workbench.d.ts +24 -8
- package/dist/workbench.js +2 -1
- package/docs/accessibility.md +21 -5
- package/docs/catalog.md +36 -0
- package/docs/collapsible-panel.md +8 -1
- package/docs/component-contract.md +10 -4
- package/docs/component-selection.md +39 -8
- package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -1
- package/docs/design/templates/toolbar/title-and-actions.svg +1 -1
- package/docs/design/templates/toolbar-dark.svg +1 -1
- package/docs/design/templates/toolbar.svg +1 -1
- package/docs/examples/component-catalog-extension.json +6 -0
- package/docs/layout.md +30 -3
- package/docs/sunken-panel.md +22 -0
- package/docs/ui-analyzer.md +4 -0
- package/docs/workbench.md +38 -4
- package/llms.txt +9 -5
- package/package.json +16 -2
- package/scripts/component-catalog-extension-validation.mjs +28 -0
- package/dist/chunk-4R777DUZ.js +0 -34
- package/dist/chunk-4R777DUZ.js.map +0 -1
- package/dist/chunk-6ZXOQEAN.js.map +0 -1
- package/dist/chunk-7JUBXOIV.js.map +0 -1
- package/dist/chunk-A3CKOW2R.js.map +0 -1
- package/dist/chunk-AUKT3KMG.js.map +0 -1
- package/dist/chunk-EAC4CDY7.js.map +0 -1
- package/dist/chunk-ENGVYQPG.js.map +0 -1
- package/dist/chunk-MA73TA6D.js +0 -42
- package/dist/chunk-MA73TA6D.js.map +0 -1
- package/dist/chunk-N2DRU35S.js +0 -45
- package/dist/chunk-N2DRU35S.js.map +0 -1
- package/dist/chunk-NNMLEDMD.js.map +0 -1
- package/dist/chunk-OD2VXAPL.js.map +0 -1
- package/dist/chunk-VCBTX62E.js.map +0 -1
- package/dist/chunk-X6ADHJNI.js.map +0 -1
|
@@ -568,6 +568,25 @@
|
|
|
568
568
|
inset-block-end: 0;
|
|
569
569
|
}
|
|
570
570
|
|
|
571
|
+
/* Optional shared backdrop sits over work-area controls and restores, below
|
|
572
|
+
the overlay drawer and rails. It is last in document order so an equal-z
|
|
573
|
+
restore control cannot receive the outside press. */
|
|
574
|
+
.kui-workbench__backdrop {
|
|
575
|
+
position: absolute;
|
|
576
|
+
z-index: calc(var(--kui-workbench-overlay-z, 41) - 2);
|
|
577
|
+
display: none;
|
|
578
|
+
inset: 0;
|
|
579
|
+
background: var(--kui-color-scrim, rgb(0 0 0 / 32%));
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
.kui-workbench[data-overlay-backdrop="true"]:is(
|
|
583
|
+
[data-rail-overlay-expanded="true"],
|
|
584
|
+
[data-drawer-overlay-expanded="true"]
|
|
585
|
+
)
|
|
586
|
+
> .kui-workbench__backdrop {
|
|
587
|
+
display: block;
|
|
588
|
+
}
|
|
589
|
+
|
|
571
590
|
/* A collapsed overlay keeps its box for the slide-out, so it drops its surface
|
|
572
591
|
and shadow; the sliding content carries the surface instead. */
|
|
573
592
|
.kui-workbench__rail[data-presentation="overlay"][data-collapsed="true"],
|
|
@@ -609,7 +628,108 @@
|
|
|
609
628
|
container: kui-workbench / inline-size;
|
|
610
629
|
}
|
|
611
630
|
|
|
631
|
+
/* A numeric pixel threshold is measured by wireWorkbench and marked on the
|
|
632
|
+
panel. Keep its overlay geometry and covered work area in step with that
|
|
633
|
+
single mark, including when the app changes the threshold at render time. */
|
|
634
|
+
.kui-workbench__rail[data-responsive-overlay-active="true"] {
|
|
635
|
+
position: absolute;
|
|
636
|
+
z-index: var(--kui-workbench-overlay-z, 41);
|
|
637
|
+
width: var(--_kui-workbench-rail-extent);
|
|
638
|
+
max-width: var(--kui-workbench-overlay-max-width, 85vw);
|
|
639
|
+
inset-block: 0;
|
|
640
|
+
box-shadow: var(--kui-shadow-l);
|
|
641
|
+
clip-path: none;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
.kui-workbench__rail--left[data-responsive-overlay-active="true"] {
|
|
645
|
+
inset-inline-start: 0;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
.kui-workbench__rail--right[data-responsive-overlay-active="true"] {
|
|
649
|
+
inset-inline-end: 0;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
.kui-workbench__rail[data-responsive-overlay-active="true"][data-collapsed="true"],
|
|
653
|
+
.kui-workbench__drawer[data-responsive-overlay-active="true"][data-collapsed="true"] {
|
|
654
|
+
background: transparent;
|
|
655
|
+
box-shadow: none;
|
|
656
|
+
pointer-events: none;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
.kui-workbench__rail[data-responsive-overlay-active="true"]
|
|
660
|
+
> .kui-workbench__panel-content {
|
|
661
|
+
width: 100%;
|
|
662
|
+
background: var(--kui-color-surface);
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
.kui-workbench__rail[data-responsive-overlay-active="true"]
|
|
666
|
+
> .kui-workbench__handle,
|
|
667
|
+
.kui-workbench__drawer[data-responsive-overlay-active="true"]
|
|
668
|
+
> .kui-workbench__handle {
|
|
669
|
+
display: none;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
.kui-workbench:has(
|
|
673
|
+
> .kui-workbench__rail--left[data-responsive-overlay-active="true"]
|
|
674
|
+
)
|
|
675
|
+
> .kui-workbench__center {
|
|
676
|
+
--kui-edge-inset-inline-start: var(--_kui-workbench-safe-inline-start);
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
.kui-workbench:has(
|
|
680
|
+
> .kui-workbench__rail--right[data-responsive-overlay-active="true"]
|
|
681
|
+
)
|
|
682
|
+
> .kui-workbench__center {
|
|
683
|
+
--kui-edge-inset-inline-end: var(--_kui-workbench-safe-inline-end);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
.kui-workbench__drawer[data-responsive-overlay-active="true"] {
|
|
687
|
+
position: absolute;
|
|
688
|
+
anchor-name: none;
|
|
689
|
+
z-index: calc(var(--kui-workbench-overlay-z, 41) - 1);
|
|
690
|
+
height: var(--_kui-workbench-drawer-extent);
|
|
691
|
+
max-height: var(--kui-workbench-overlay-max-height, 85vh);
|
|
692
|
+
inset-inline: 0;
|
|
693
|
+
inset-block-end: 0;
|
|
694
|
+
box-shadow: var(--kui-shadow-l);
|
|
695
|
+
clip-path: none;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
.kui-workbench__drawer[data-responsive-overlay-active="true"]
|
|
699
|
+
> .kui-workbench__panel-content {
|
|
700
|
+
height: 100%;
|
|
701
|
+
background: var(--kui-color-surface);
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
.kui-workbench__main:has(
|
|
705
|
+
+ .kui-workbench__drawer[data-responsive-overlay-active="true"]
|
|
706
|
+
) {
|
|
707
|
+
--_kui-workbench-content-edge-block-end: var(--_kui-workbench-safe-block-end);
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
.kui-workbench[data-overlay-backdrop="true"]:has(
|
|
711
|
+
> .kui-workbench__rail[data-responsive-overlay-active="true"]:not(
|
|
712
|
+
[data-collapsed="true"]
|
|
713
|
+
),
|
|
714
|
+
> .kui-workbench__center
|
|
715
|
+
> .kui-workbench__drawer[data-responsive-overlay-active="true"]:not(
|
|
716
|
+
[data-collapsed="true"]
|
|
717
|
+
)
|
|
718
|
+
)
|
|
719
|
+
> .kui-workbench__backdrop {
|
|
720
|
+
display: block;
|
|
721
|
+
}
|
|
722
|
+
|
|
612
723
|
@container kui-workbench (max-width: 44rem) {
|
|
724
|
+
.kui-workbench[data-overlay-backdrop="true"]:is(
|
|
725
|
+
[data-left-responsive-expanded="narrow"],
|
|
726
|
+
[data-right-responsive-expanded="narrow"],
|
|
727
|
+
[data-drawer-responsive-expanded="narrow"]
|
|
728
|
+
)
|
|
729
|
+
> .kui-workbench__backdrop {
|
|
730
|
+
display: block;
|
|
731
|
+
}
|
|
732
|
+
|
|
613
733
|
.kui-workbench__rail[data-responsive-overlay-at="narrow"] {
|
|
614
734
|
position: absolute;
|
|
615
735
|
z-index: var(--kui-workbench-overlay-z, 41);
|
|
@@ -692,6 +812,15 @@
|
|
|
692
812
|
}
|
|
693
813
|
|
|
694
814
|
@container kui-workbench (max-width: 28rem) {
|
|
815
|
+
.kui-workbench[data-overlay-backdrop="true"]:is(
|
|
816
|
+
[data-left-responsive-expanded="compact"],
|
|
817
|
+
[data-right-responsive-expanded="compact"],
|
|
818
|
+
[data-drawer-responsive-expanded="compact"]
|
|
819
|
+
)
|
|
820
|
+
> .kui-workbench__backdrop {
|
|
821
|
+
display: block;
|
|
822
|
+
}
|
|
823
|
+
|
|
695
824
|
.kui-workbench__rail[data-responsive-overlay-at="compact"] {
|
|
696
825
|
position: absolute;
|
|
697
826
|
z-index: var(--kui-workbench-overlay-z, 41);
|
|
@@ -895,6 +1024,15 @@
|
|
|
895
1024
|
--_kui-workbench-covered: hidden;
|
|
896
1025
|
}
|
|
897
1026
|
|
|
1027
|
+
.kui-workbench:has(
|
|
1028
|
+
> .kui-workbench__rail[data-responsive-overlay-active="true"]:not(
|
|
1029
|
+
[data-collapsed="true"]
|
|
1030
|
+
)
|
|
1031
|
+
)
|
|
1032
|
+
> :is(.kui-workbench__center, .kui-workbench__restore) {
|
|
1033
|
+
--_kui-workbench-covered: hidden;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
898
1036
|
@container kui-workbench (max-width: 44rem) {
|
|
899
1037
|
.kui-workbench:is(
|
|
900
1038
|
[data-left-responsive-expanded="narrow"],
|
|
@@ -926,14 +1064,22 @@
|
|
|
926
1064
|
closes it (the wiring's outside press); `compactOverlay: "full"` fills the
|
|
927
1065
|
Workbench. The rail's resize and configured size stop applying there. */
|
|
928
1066
|
@container kui-workbench (max-width: 28rem) {
|
|
929
|
-
.kui-workbench__rail
|
|
1067
|
+
.kui-workbench__rail:is(
|
|
1068
|
+
[data-responsive-overlay-at="narrow"],
|
|
1069
|
+
[data-responsive-overlay-at="compact"],
|
|
1070
|
+
[data-responsive-overlay-active="true"]
|
|
1071
|
+
) {
|
|
930
1072
|
width: calc(
|
|
931
1073
|
100% - var(--kui-workbench-overlay-dismiss-margin, 2.75rem)
|
|
932
1074
|
);
|
|
933
1075
|
max-width: none;
|
|
934
1076
|
}
|
|
935
1077
|
|
|
936
|
-
.kui-workbench__rail
|
|
1078
|
+
.kui-workbench__rail:is(
|
|
1079
|
+
[data-responsive-overlay-at="narrow"],
|
|
1080
|
+
[data-responsive-overlay-at="compact"],
|
|
1081
|
+
[data-responsive-overlay-active="true"]
|
|
1082
|
+
)[data-compact-overlay="full"] {
|
|
937
1083
|
width: 100%;
|
|
938
1084
|
}
|
|
939
1085
|
}
|
package/dist/sunken-panel.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as kerfjs from 'kerfjs';
|
|
2
|
+
import { CssFlexKeyword, CssFlex } from './css-values.js';
|
|
2
3
|
import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
|
|
3
4
|
|
|
4
5
|
type SunkenPanelShape = 'rounded' | 'square';
|
|
@@ -8,6 +9,10 @@ interface SunkenPanelProps {
|
|
|
8
9
|
ariaLabel?: string;
|
|
9
10
|
/** Corner shape: a rounded rectangle (default) or square corners. */
|
|
10
11
|
shape?: SunkenPanelShape;
|
|
12
|
+
/** Grow or shrink within a flex parent, using Grid's typed flex contract. */
|
|
13
|
+
flex?: boolean | CssFlexKeyword | CssFlex;
|
|
14
|
+
/** Fill a parent with a definite height; use flex inside a flex layout. */
|
|
15
|
+
fill?: boolean;
|
|
11
16
|
className?: string;
|
|
12
17
|
/** Native named-slot assignment when composed inside a web component. */
|
|
13
18
|
slot?: string;
|
|
@@ -17,6 +22,6 @@ interface SunkenPanelProps {
|
|
|
17
22
|
* stack. The panel owns its background and padding; children own their own
|
|
18
23
|
* borders and internal geometry.
|
|
19
24
|
*/
|
|
20
|
-
declare function SunkenPanel({ children, ariaLabel, shape, className, slot, }: SunkenPanelProps): kerfjs.SafeHtml;
|
|
25
|
+
declare function SunkenPanel({ children, ariaLabel, shape, flex, fill, className, slot, }: SunkenPanelProps): kerfjs.SafeHtml;
|
|
21
26
|
|
|
22
27
|
export { SunkenPanel, type SunkenPanelProps, type SunkenPanelShape };
|
package/dist/sunken-panel.js
CHANGED
package/dist/text.d.ts
CHANGED
|
@@ -8,8 +8,9 @@ type TextSize = 'compact' | 'default' | 'large' | 'xlarge';
|
|
|
8
8
|
type TextFont = 'default' | 'monospace';
|
|
9
9
|
type TextBorder = 'transparent' | 'none';
|
|
10
10
|
type TextLineHeight = 'default' | 'tight';
|
|
11
|
+
type TextWrap = 'normal' | 'anywhere' | 'nowrap' | 'truncate';
|
|
11
12
|
type TextContent = KerfUiContent | string | number | readonly TextContent[];
|
|
12
|
-
type
|
|
13
|
+
type TextCommonProps = Omit<KerfBaseAttrs, 'children' | 'class' | 'className'> & {
|
|
13
14
|
/** Native heading, paragraph, or inline span element to render. Defaults to `p`. */
|
|
14
15
|
variant?: TextVariant;
|
|
15
16
|
/** Semantic foreground treatment. Defaults to the inherited foreground. */
|
|
@@ -28,11 +29,21 @@ type TextProps = Omit<KerfBaseAttrs, 'children' | 'class' | 'className'> & {
|
|
|
28
29
|
class?: string;
|
|
29
30
|
className?: string;
|
|
30
31
|
};
|
|
32
|
+
type TextProps = TextCommonProps & ({
|
|
33
|
+
/** Wrap normally or break long unbroken strings. Defaults to normal. */
|
|
34
|
+
wrap?: 'normal' | 'anywhere';
|
|
35
|
+
/** Cap wrapped text to this positive number of lines. */
|
|
36
|
+
maxLines?: number;
|
|
37
|
+
} | {
|
|
38
|
+
/** Keep one line, with or without an ellipsis. */
|
|
39
|
+
wrap: 'nowrap' | 'truncate';
|
|
40
|
+
maxLines?: never;
|
|
41
|
+
});
|
|
31
42
|
/**
|
|
32
43
|
* Semantic heading, paragraph, or inline text. Block variants use the standard
|
|
33
44
|
* content-item padding; `span` adds no box geometry.
|
|
34
45
|
* All ordinary native heading/paragraph attributes pass through to the element.
|
|
35
46
|
*/
|
|
36
|
-
declare function Text({ variant: Variant, tone, size, font, border, flush, lineHeight, children, class: classValue, className, ...attributes }: TextProps): kerfjs.SafeHtml;
|
|
47
|
+
declare function Text({ variant: Variant, tone, size, font, border, flush, lineHeight, wrap, maxLines, children, class: classValue, className, ...attributes }: TextProps): kerfjs.SafeHtml;
|
|
37
48
|
|
|
38
|
-
export { Text, type TextBorder, type TextContent, type TextFont, type TextLineHeight, type TextProps, type TextSize, type TextTone, type TextVariant };
|
|
49
|
+
export { Text, type TextBorder, type TextContent, type TextFont, type TextLineHeight, type TextProps, type TextSize, type TextTone, type TextVariant, type TextWrap };
|
package/dist/text.js
CHANGED
|
@@ -60,6 +60,10 @@ interface ToolbarControlGroupProps {
|
|
|
60
60
|
relocateOnCollapse?: boolean;
|
|
61
61
|
/** Add contrast behind photo-backed avatar content. */
|
|
62
62
|
scrim?: boolean;
|
|
63
|
+
/** Block the group's controls and show a spinner without changing its dimensions. */
|
|
64
|
+
busy?: boolean;
|
|
65
|
+
/** Announced status while busy; defaults to “Working”. */
|
|
66
|
+
busyLabel?: string;
|
|
63
67
|
/**
|
|
64
68
|
* Avatar image URL. A single-control group paints it on the group; a
|
|
65
69
|
* multi-control group paints it only on the pressed selection highlight.
|
|
@@ -68,6 +72,6 @@ interface ToolbarControlGroupProps {
|
|
|
68
72
|
/** Native named-slot assignment when composed inside a web component. */
|
|
69
73
|
slot?: string;
|
|
70
74
|
}
|
|
71
|
-
declare function ToolbarControlGroup({ children, label, className, expanded, single, appearance, tone, buttonAppearance, shape, size, density, content, focusRing, selectedChrome, selectedTone, nestedDropdown, menuInset, overflow, visibility, relocateOnCollapse, scrim, avatarImage, slot, }: ToolbarControlGroupProps): kerfjs.SafeHtml;
|
|
75
|
+
declare function ToolbarControlGroup({ children, label, className, expanded, single, appearance, tone, buttonAppearance, shape, size, density, content, focusRing, selectedChrome, selectedTone, nestedDropdown, menuInset, overflow, visibility, relocateOnCollapse, scrim, busy, busyLabel, avatarImage, slot, }: ToolbarControlGroupProps): kerfjs.SafeHtml;
|
|
72
76
|
|
|
73
77
|
export { ToolbarActionLink, type ToolbarActionLinkProps, ToolbarControlGroup, type ToolbarControlGroupAppearance, type ToolbarControlGroupButtonAppearance, type ToolbarControlGroupContent, type ToolbarControlGroupDensity, type ToolbarControlGroupFocusRing, type ToolbarControlGroupMenuInset, type ToolbarControlGroupOverflow, type ToolbarControlGroupProps, type ToolbarControlGroupSelectedChrome, type ToolbarControlGroupSelectedTone, type ToolbarControlGroupShape, type ToolbarControlGroupSize, type ToolbarControlGroupTone, type ToolbarControlGroupVisibility };
|
package/dist/toolbar.d.ts
CHANGED
|
@@ -3,11 +3,14 @@ import { PaneSeparatorSide } from './pane.js';
|
|
|
3
3
|
import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
|
|
4
4
|
import { S as Sides } from './sides-BPSWde0A.js';
|
|
5
5
|
|
|
6
|
+
type ToolbarPosition = 'header' | 'footer';
|
|
6
7
|
interface ToolbarProps {
|
|
7
8
|
leading?: KerfUiContent;
|
|
8
9
|
center?: KerfUiContent;
|
|
9
10
|
trailing?: KerfUiContent;
|
|
10
11
|
label?: string;
|
|
12
|
+
/** Use footer semantics for a bottom toolbar; defaults to header. */
|
|
13
|
+
position?: ToolbarPosition;
|
|
11
14
|
/**
|
|
12
15
|
* Physical divider edges in canonical top/right/bottom/left order, drawn
|
|
13
16
|
* always. Defaults to none: a toolbar pinned over or under scrolling content
|
|
@@ -57,6 +60,6 @@ interface ToolbarProps {
|
|
|
57
60
|
* toolbar) forwards, so the app configures that toolbar instead of styling it.
|
|
58
61
|
*/
|
|
59
62
|
type ToolbarConfig = Pick<ToolbarProps, 'dividerSides' | 'centerAlign' | 'responsive' | 'responsiveAt' | 'safeAreaEdges'>;
|
|
60
|
-
declare function Toolbar({ leading, center, trailing, label, dividerSides, centerAlign, responsive, responsiveAt, safeAreaEdges, className, slot, }: ToolbarProps): kerfjs.SafeHtml;
|
|
63
|
+
declare function Toolbar({ leading, center, trailing, label, position, dividerSides, centerAlign, responsive, responsiveAt, safeAreaEdges, className, slot, }: ToolbarProps): kerfjs.SafeHtml;
|
|
61
64
|
|
|
62
|
-
export { Sides, Toolbar, type ToolbarConfig, type ToolbarProps };
|
|
65
|
+
export { Sides, Toolbar, type ToolbarConfig, type ToolbarPosition, type ToolbarProps };
|
package/dist/toolbar.js
CHANGED
package/dist/wire-catalog.js
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Give interactive ContentItems native-like Enter/Space activation with one
|
|
3
|
+
* delegated listener pair. Space activates on release and is cancelled if
|
|
4
|
+
* focus moves; the item's own `data-action` still goes through the app's
|
|
5
|
+
* ordinary delegated click handler. Returns a disposer.
|
|
6
|
+
*/
|
|
7
|
+
declare function wireContentItems(root: HTMLElement): () => void;
|
|
8
|
+
|
|
9
|
+
export { wireContentItems };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// src/wire-content-items.ts
|
|
2
|
+
var ITEM_SELECTOR = '[data-component="content-item"][data-interactive="true"]';
|
|
3
|
+
var NESTED_CONTROL_SELECTOR = 'button, a[href], input, select, textarea, [contenteditable="true"], [role="button"]';
|
|
4
|
+
function actionItem(root, target) {
|
|
5
|
+
if (!(target instanceof Element)) return null;
|
|
6
|
+
const item = target.closest(ITEM_SELECTOR);
|
|
7
|
+
if (!item || !root.contains(item) || item.dataset.disabled === "true")
|
|
8
|
+
return null;
|
|
9
|
+
const nested = target.closest(NESTED_CONTROL_SELECTOR);
|
|
10
|
+
if (nested && nested !== item && item.contains(nested)) return null;
|
|
11
|
+
return item;
|
|
12
|
+
}
|
|
13
|
+
function wireContentItems(root) {
|
|
14
|
+
let pendingSpace = null;
|
|
15
|
+
const clearSpace = () => {
|
|
16
|
+
pendingSpace?.removeAttribute("data-kui-pressed");
|
|
17
|
+
pendingSpace = null;
|
|
18
|
+
};
|
|
19
|
+
const keydown = (event) => {
|
|
20
|
+
if (event.defaultPrevented || event.altKey || event.ctrlKey || event.metaKey)
|
|
21
|
+
return;
|
|
22
|
+
const item = actionItem(root, event.target);
|
|
23
|
+
if (!item) return;
|
|
24
|
+
if (event.key === "Enter") {
|
|
25
|
+
event.preventDefault();
|
|
26
|
+
item.click();
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (event.key === " " || event.key === "Spacebar") {
|
|
30
|
+
event.preventDefault();
|
|
31
|
+
if (event.repeat) return;
|
|
32
|
+
clearSpace();
|
|
33
|
+
pendingSpace = item;
|
|
34
|
+
item.setAttribute("data-kui-pressed", "true");
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
const keyup = (event) => {
|
|
38
|
+
if (event.key !== " " && event.key !== "Spacebar") return;
|
|
39
|
+
const item = pendingSpace;
|
|
40
|
+
if (!item) return;
|
|
41
|
+
event.preventDefault();
|
|
42
|
+
clearSpace();
|
|
43
|
+
if (item === actionItem(root, event.target) && item.ownerDocument.activeElement === item)
|
|
44
|
+
item.click();
|
|
45
|
+
};
|
|
46
|
+
const focusout = (event) => {
|
|
47
|
+
if (event.target === pendingSpace) clearSpace();
|
|
48
|
+
};
|
|
49
|
+
root.addEventListener("keydown", keydown);
|
|
50
|
+
root.addEventListener("keyup", keyup);
|
|
51
|
+
root.addEventListener("focusout", focusout);
|
|
52
|
+
return () => {
|
|
53
|
+
clearSpace();
|
|
54
|
+
root.removeEventListener("keydown", keydown);
|
|
55
|
+
root.removeEventListener("keyup", keyup);
|
|
56
|
+
root.removeEventListener("focusout", focusout);
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export { wireContentItems };
|
|
61
|
+
|
|
62
|
+
//# sourceMappingURL=wire-content-items.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/wire-content-items.ts"],"names":[],"mappings":"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","file":"wire-content-items.js","sourcesContent":["const ITEM_SELECTOR =\n '[data-component=\"content-item\"][data-interactive=\"true\"]';\nconst NESTED_CONTROL_SELECTOR =\n 'button, a[href], input, select, textarea, [contenteditable=\"true\"], [role=\"button\"]';\n\nfunction actionItem(root: HTMLElement, target: EventTarget | null) {\n if (!(target instanceof Element)) return null;\n const item = target.closest<HTMLElement>(ITEM_SELECTOR);\n if (!item || !root.contains(item) || item.dataset.disabled === 'true')\n return null;\n const nested = target.closest(NESTED_CONTROL_SELECTOR);\n if (nested && nested !== item && item.contains(nested)) return null;\n return item;\n}\n\n/**\n * Give interactive ContentItems native-like Enter/Space activation with one\n * delegated listener pair. Space activates on release and is cancelled if\n * focus moves; the item's own `data-action` still goes through the app's\n * ordinary delegated click handler. Returns a disposer.\n */\nexport function wireContentItems(root: HTMLElement): () => void {\n let pendingSpace: HTMLElement | null = null;\n\n const clearSpace = () => {\n pendingSpace?.removeAttribute('data-kui-pressed');\n pendingSpace = null;\n };\n\n const keydown = (event: KeyboardEvent) => {\n if (\n event.defaultPrevented ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey\n )\n return;\n const item = actionItem(root, event.target);\n if (!item) return;\n if (event.key === 'Enter') {\n event.preventDefault();\n item.click();\n return;\n }\n if (event.key === ' ' || event.key === 'Spacebar') {\n event.preventDefault();\n if (event.repeat) return;\n clearSpace();\n pendingSpace = item;\n item.setAttribute('data-kui-pressed', 'true');\n }\n };\n\n const keyup = (event: KeyboardEvent) => {\n if (event.key !== ' ' && event.key !== 'Spacebar') return;\n const item = pendingSpace;\n if (!item) return;\n event.preventDefault();\n clearSpace();\n if (\n item === actionItem(root, event.target) &&\n item.ownerDocument.activeElement === item\n )\n item.click();\n };\n\n const focusout = (event: FocusEvent) => {\n if (event.target === pendingSpace) clearSpace();\n };\n\n root.addEventListener('keydown', keydown);\n root.addEventListener('keyup', keyup);\n root.addEventListener('focusout', focusout);\n return () => {\n clearSpace();\n root.removeEventListener('keydown', keydown);\n root.removeEventListener('keyup', keyup);\n root.removeEventListener('focusout', focusout);\n };\n}\n"]}
|
package/dist/wire-workbench.d.ts
CHANGED
|
@@ -32,6 +32,13 @@ interface WireWorkbenchPanel {
|
|
|
32
32
|
* keeps Tab inside it, and it closes on Escape or a press outside it.
|
|
33
33
|
*/
|
|
34
34
|
collapsed?: Signal<boolean>;
|
|
35
|
+
/**
|
|
36
|
+
* Treat presses in a portal surface launched by this panel (for example a
|
|
37
|
+
* body-level menu or dialog) as inside it. The predicate receives each Node
|
|
38
|
+
* in the press's composed path; return true for the portal root. Ordinary
|
|
39
|
+
* presses outside the panel and its allowed surfaces still dismiss it.
|
|
40
|
+
*/
|
|
41
|
+
keepOpenOn?: (target: Node) => boolean;
|
|
35
42
|
}
|
|
36
43
|
/** A resize the user made, after `wireWorkbench` wrote it to the size signal. */
|
|
37
44
|
interface WorkbenchResize {
|
package/dist/wire-workbench.js
CHANGED
package/dist/workbench.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { ListConfig } from './list.js';
|
|
|
3
3
|
import { PaneConfig } from './pane.js';
|
|
4
4
|
import { ResizableRegionSeparator, ResizableRegionCollapseMotion, ResizableRegionContentOverflow, ResizableRegionPresentation, ResizableRegionRestorePosition } from './resizable-region.js';
|
|
5
5
|
import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
|
|
6
|
-
import { a as PanelToolbar, b as PanelToggle } from './panel-toolbar-
|
|
6
|
+
import { a as PanelToolbar, b as PanelChromePlacement, c as PanelBottomToolbar, d as PanelToggle } from './panel-toolbar-DDKh4uKd.js';
|
|
7
7
|
import { ToolbarConfig } from './toolbar.js';
|
|
8
8
|
import './css-values.js';
|
|
9
9
|
import './flex-alignment-4ms8ZbV8.js';
|
|
@@ -22,6 +22,7 @@ type WorkbenchPanelToggle = PanelToggle;
|
|
|
22
22
|
* `FloatingToolbar` in the work area's bottom-end corner.
|
|
23
23
|
*/
|
|
24
24
|
type WorkbenchPanelToolbar = PanelToolbar;
|
|
25
|
+
type WorkbenchPanelBottomToolbar = PanelBottomToolbar;
|
|
25
26
|
/**
|
|
26
27
|
* The work area's top toolbar; collapsed rails add their groups to it. Its
|
|
27
28
|
* configuration forwards to its `Toolbar`. It draws no divider of its own by
|
|
@@ -57,7 +58,7 @@ interface WorkbenchMainBottomToolbar extends ToolbarConfig {
|
|
|
57
58
|
* the Pane's `chromePlacement="auto"`; it applies to the pinned header and
|
|
58
59
|
* footer together).
|
|
59
60
|
*/
|
|
60
|
-
type WorkbenchChromePlacement =
|
|
61
|
+
type WorkbenchChromePlacement = PanelChromePlacement;
|
|
61
62
|
|
|
62
63
|
/**
|
|
63
64
|
* The Workbench container breakpoint below which a panel presents as an
|
|
@@ -65,7 +66,7 @@ type WorkbenchChromePlacement = 'fixed' | 'scroll' | 'auto';
|
|
|
65
66
|
* breakpoints as `ResizableRegion`'s `responsiveFillAt` — or `never` to keep
|
|
66
67
|
* it inline at every width.
|
|
67
68
|
*/
|
|
68
|
-
type WorkbenchResponsiveOverlayAt = 'compact' | 'narrow' | 'never';
|
|
69
|
+
type WorkbenchResponsiveOverlayAt = 'compact' | 'narrow' | 'never' | number;
|
|
69
70
|
/**
|
|
70
71
|
* How wide a rail's overlay is in a compact (448px or less) Workbench: `inset`
|
|
71
72
|
* fills the Workbench less a dismiss margin on the side away from the rail's
|
|
@@ -88,8 +89,20 @@ interface WorkbenchPanel {
|
|
|
88
89
|
* collapsed. With it, `content` renders in a `Pane` below the toolbar.
|
|
89
90
|
*/
|
|
90
91
|
toolbar?: WorkbenchPanelToolbar;
|
|
91
|
-
/**
|
|
92
|
+
/** Fixed content below a toolbar panel's top toolbar, above its scroll region. */
|
|
93
|
+
header?: KerfUiContent;
|
|
94
|
+
/** List layout for `header`; omitted fields keep List defaults. */
|
|
95
|
+
headerList?: ListConfig;
|
|
96
|
+
/** Placement of the top toolbar and header together; default `fixed`. */
|
|
97
|
+
headerPlacement?: WorkbenchChromePlacement;
|
|
98
|
+
/** Fixed content above a toolbar panel's bottom toolbar. */
|
|
92
99
|
footer?: KerfUiContent;
|
|
100
|
+
/** List layout for `footer`; omitted fields keep List defaults. */
|
|
101
|
+
footerList?: ListConfig;
|
|
102
|
+
/** Fixed toolbar below `footer`, using footer semantics. */
|
|
103
|
+
bottomToolbar?: WorkbenchPanelBottomToolbar;
|
|
104
|
+
/** Placement of the footer and bottom toolbar together; default `fixed`. */
|
|
105
|
+
footerPlacement?: WorkbenchChromePlacement;
|
|
93
106
|
/**
|
|
94
107
|
* Configuration for a `toolbar` panel's `Pane` (`contentElement`,
|
|
95
108
|
* `contentLabel`, `separators`, `safeAreaEdges`, `chromeDividers`) — for example
|
|
@@ -121,8 +134,9 @@ interface WorkbenchPanel {
|
|
|
121
134
|
presentation?: ResizableRegionPresentation;
|
|
122
135
|
/**
|
|
123
136
|
* Present the panel as an overlay, without a separator, below a Workbench
|
|
124
|
-
* container breakpoint, and inline above it
|
|
125
|
-
*
|
|
137
|
+
* container breakpoint, and inline above it. `compact` and `narrow` use
|
|
138
|
+
* CSS container queries; a positive number is a pixel threshold measured
|
|
139
|
+
* by `wireWorkbench` and requires a `collapsed` signal. A rail overlays from its side at full
|
|
126
140
|
* height, over the work area and an open drawer; the bottom drawer
|
|
127
141
|
* overlays the bottom of the work-area column. Rails default to `narrow`
|
|
128
142
|
* (pass `never` to keep one inline); the drawer defaults to inline.
|
|
@@ -222,6 +236,8 @@ interface WorkbenchProps {
|
|
|
222
236
|
* shorter. Workbenches without a drawer ignore it.
|
|
223
237
|
*/
|
|
224
238
|
mainMinHeight?: number;
|
|
239
|
+
/** Dim the work area below any open overlay and absorb outside presses; off by default. */
|
|
240
|
+
overlayBackdrop?: boolean;
|
|
225
241
|
className?: string;
|
|
226
242
|
/** Native named-slot assignment when composed inside a web component. */
|
|
227
243
|
slot?: string;
|
|
@@ -239,6 +255,6 @@ interface WorkbenchProps {
|
|
|
239
255
|
* lives outside it and stays reachable). A panel may opt in to drag and keyboard resizing with
|
|
240
256
|
* `resizable`, which `wireWorkbench` drives. See `docs/23-app-layouts.md` §3.3.
|
|
241
257
|
*/
|
|
242
|
-
declare function Workbench({ id, label, main, leftRail, rightRail, bottomDrawer, mainToolbar, mainHeader, mainFooter, mainBottomToolbar, mainHeaderPlacement, mainFooterPlacement, mainPane, mainHeaderList, mainFooterList, mainMinSize, mainMinHeight, className, slot, }: WorkbenchProps): SafeHtml;
|
|
258
|
+
declare function Workbench({ id, label, main, leftRail, rightRail, bottomDrawer, mainToolbar, mainHeader, mainFooter, mainBottomToolbar, mainHeaderPlacement, mainFooterPlacement, mainPane, mainHeaderList, mainFooterList, mainMinSize, mainMinHeight, overlayBackdrop, className, slot, }: WorkbenchProps): SafeHtml;
|
|
243
259
|
|
|
244
|
-
export { Workbench, type WorkbenchChromePlacement, type WorkbenchCompactOverlay, type WorkbenchMainBottomToolbar, type WorkbenchMainToolbar, type WorkbenchPanel, type WorkbenchPanelResizable, type WorkbenchPanelToggle, type WorkbenchPanelToolbar, type WorkbenchProps, type WorkbenchResponsiveOverlayAt };
|
|
260
|
+
export { Workbench, type WorkbenchChromePlacement, type WorkbenchCompactOverlay, type WorkbenchMainBottomToolbar, type WorkbenchMainToolbar, type WorkbenchPanel, type WorkbenchPanelBottomToolbar, type WorkbenchPanelResizable, type WorkbenchPanelToggle, type WorkbenchPanelToolbar, type WorkbenchProps, type WorkbenchResponsiveOverlayAt };
|
package/dist/workbench.js
CHANGED
package/docs/accessibility.md
CHANGED
|
@@ -5,7 +5,7 @@ These are normative contracts for package components and consuming applications.
|
|
|
5
5
|
## Shared rules
|
|
6
6
|
|
|
7
7
|
- All controls have accessible names and visible `:focus-visible` treatment.
|
|
8
|
-
- Decorative `LucideIcon` output is `aria-hidden`; pass `label` only when the SVG itself conveys meaning.
|
|
8
|
+
- Decorative `LucideIcon` output is `aria-hidden`; pass `label` only when the SVG itself conveys meaning. `size="xs|s|m|l|xl"` selects the 12/16/20/24/32px root-scaled icon steps, and a positive numeric `size` converts pixels to rem; omitting `size` keeps 1em. Size changes the visual only, never the owning control's hit target or accessible name.
|
|
9
9
|
- `ListItem` uses native button Enter/Space behavior. `selected` maps to `aria-current="page"`; `pressed` maps to `aria-pressed`. Selected rows keep the normal foreground over their brand-tinted fill so text retains WCAG AA contrast in light and dark themes. Its leading icon visual is 18px while the row retains its 44px minimum target; multiline icons align to the first text line. Its `trailing` content is dormant and must not contain controls. Its `rootAttributes` slot accepts only application `data-*` metadata and deliberately cannot emit `role="menuitem"` in isolation—a true ARIA menu must own arrow, Home/End, Escape, and focus behavior as one widget.
|
|
10
10
|
- `ListItemLink` shares that row content and geometry but uses native anchor Enter behavior and requires `href`. It has no `action` or `pressed` state. `external` opens a new tab with `rel="noopener noreferrer"`; the default accessible name announces the new tab for a string label, so an explicit `accessibleLabel` should do the same. Disabled and loading links omit `href`, expose `aria-disabled`, and leave the tab order. Its trailing content remains dormant.
|
|
11
11
|
- `ListHeader` owns action naming, disabled state, and disclosure `aria-expanded`. Toggle mode supplies one decorative 18px `DisclosureArrow` when `actionIcon` is omitted; it mirrors `expanded` while the native button's accessible name stays stable. The application must update that controlled state and reveal or hide real content. A valid `count` is visually rendered in an `aria-hidden` neutral pill while the required localized `countLabel` becomes part of the owning heading or disclosure button's accessible name; zero remains a real count. Its narrow `triggerAttributes` slot may describe a native popover or controlled-content relationship with `popoverTarget`, `popoverTargetAction`, `aria-controls`, and `aria-haspopup`; the application owns the target surface and its focus/dismissal behavior.
|
|
@@ -13,9 +13,12 @@ These are normative contracts for package components and consuming applications.
|
|
|
13
13
|
- `wireNavStack` moves focus into every newly active top view and remembers the last focused descendant of each mounted view for pop restoration. Mark a preferred initial heading or control with `data-nav-focus` (and `tabindex="-1"` when it is not normally tabbable); otherwise the helper uses the first enabled focusable descendant, then a programmatically focusable view-container fallback.
|
|
14
14
|
- In any `.kui-pane`, menu rows, `ListHeader` actions, and toolbar groups keep a minimum 44px target in both dimensions. A `ListHeader` fills the available inline width and keeps that action at the logical end, including in RTL. Its action visual defaults to 18px through `--kui-list-header-action-icon-size` inside a fitted 36px hover square; a transparent hit layer extends the pointer target to at least 44 × 44 around that square without moving layout or enlarging the painted surface. Compact headers are 36px tall like the rest of the compact List family, so their action target is 44px wide and clamped to the 36px header height instead of reaching into a neighboring row. Do not reduce the target to the visible icon, and do not force the button itself to 44px.
|
|
15
15
|
- `LoadingSpinner` is either labeled (`role="img"`) or hidden. Its rotation stops for reduced motion.
|
|
16
|
+
- A busy `ToolbarControlGroup` makes its controls inert and exposes `aria-busy`; its `busyLabel` is announced by an adjacent status node outside the inert group. Clear `busy` when the operation finishes so the controls rejoin the focus order.
|
|
17
|
+
- A bottom `Toolbar` uses `position="footer"` for footer semantics; top toolbars keep the default `header`. Workbench's main bottom toolbar sets this automatically.
|
|
18
|
+
- Interactive `ContentItem` cards have a keyboard reachable button or option role. Set `selectionMode="toggle"` for `aria-pressed`, or `selectionMode="single"` inside a listbox for `aria-selected`; wire `wireContentItems` once so Enter and Space activate their delegated action. Disabled cards expose `aria-disabled` and leave the Tab order.
|
|
16
19
|
- An unlabeled `Skeleton` (including the value slots a component's `placeholder` prop renders) is decorative loading chrome: it is `aria-hidden`, conveys no information a user needs to act on, and is deliberately exempt from the WCAG 3:1 non-text-contrast target. Inside a solid `Badge` it stays subtle (about 2.1–4.4:1 in light, 2.4–2.8:1 in dark, depending on tone); `tests/browser/tone-contrast.spec.ts` holds those values as a regression floor rather than an accessibility threshold. Announce loading through a labeled `Skeleton`, `LoadingSpinner`, or `aria-busy` on the owning region, never through the skeleton's visibility.
|
|
17
20
|
- `StateBanner` defaults to polite `role="status"`; use `urgency="alert"` only for an attention-requiring failure. Its optional `badge` is persistent inline status/count content beside the title and is announced as part of the banner; keep it terse and do not rely on color alone for its meaning.
|
|
18
|
-
- A removable `Chip` has a native button with a specific `removeLabel`, such as "Remove Urgent tag". The button is absent for a plain chip and disabled for a disabled chip. Tag text remains visible because tone does not convey meaning alone.
|
|
21
|
+
- A removable `Chip` has a native button with a specific `removeLabel`, such as "Remove Urgent tag". The button is absent for a plain chip and disabled for a disabled chip. Its leading `icon` is decorative; the visible label names the tag. `truncate` retains the full plain-text label as a native tooltip. Tag text remains visible because tone does not convey meaning alone.
|
|
19
22
|
- `EmptyState` reports busy state through `aria-busy` and never relies on an illustration as its label.
|
|
20
23
|
- `Select` follows the Web Awesome host's standard `input`/`change` events. Application tests verify the live `value`, focus, and events—not attributes alone. Its decorative option icons and value-dependent selected content remain present after controlled rerenders, so the visible choice does not silently lose its non-text cue.
|
|
21
24
|
- `DisclosureArrow` is an 18px root-scaled decorative visual by default, not an interaction target. Its owning native control supplies a stable accessible name, pointer and keyboard interaction, and `aria-expanded`; multiple arrows keep independently controlled state. Consumers may resize it with the typed `size` prop without changing that ownership. Configured directions animate over the shortest path; a 180-degree closed-to-open tie uses counterclockwise rotation.
|
|
@@ -205,7 +208,9 @@ open popup. A disabled item stays in the menu but cannot be
|
|
|
205
208
|
chosen; disable the whole trigger only when every command is unavailable.
|
|
206
209
|
Nested items use Web Awesome's submenu pointer and Left/Right arrow routing;
|
|
207
210
|
headings and dividers can separate nested groups without becoming keyboard
|
|
208
|
-
choices.
|
|
211
|
+
choices. A rapid ArrowDown or ArrowUp after opening a submenu keeps the chosen
|
|
212
|
+
item focused when its show animation finishes. Set `checked` to `true` or `false` for checkbox menu semantics; omit it
|
|
213
|
+
for a plain command. `details` supplies optional
|
|
209
214
|
trailing visual content without changing a command's accessible label. A
|
|
210
215
|
`context` menu's invisible anchor is outside the accessibility tree and normal
|
|
211
216
|
Tab order; opening the menu moves focus into its commands and Escape dismisses
|
|
@@ -443,10 +448,21 @@ remove actions, and suggestions are managed. Arrow Down moves from the editor
|
|
|
443
448
|
to suggestions, arrow keys move between suggestions, Enter selects one, and
|
|
444
449
|
Escape returns focus to the editor. The application still announces results
|
|
445
450
|
when needed and can supply an `evaluate` callback to compute them. Omitting the
|
|
446
|
-
model leaves the manual behavior above intact.
|
|
451
|
+
model leaves the manual behavior above intact. After a chip commit, suggestion
|
|
452
|
+
choice, chip edit, or Backspace/Delete chip removal, focus restoration runs at
|
|
453
|
+
the controlled render checkpoint and keeps the query-relative caret offset;
|
|
454
|
+
it leaves focus on a different control if the user moved there in the meantime.
|
|
455
|
+
Suggestions use Floating UI positioning, following the same viewport-aware
|
|
456
|
+
popup behavior as the Web Awesome controls behind Select and PopupMenu. They
|
|
457
|
+
follow the field while scrolling, flip above it at the bottom edge, and shift
|
|
458
|
+
within narrow viewports without growing its toolbar row. One
|
|
459
|
+
suggestion keeps a pill outline; lists with multiple choices use the standard
|
|
460
|
+
rounded surface and scroll once they reach 240px. The clear button's hover and focus
|
|
461
|
+
highlight follows the field's pill shape or its toolbar group's rounded shape.
|
|
447
462
|
|
|
448
463
|
Managed clear captures the action before application handlers run, keeps the adopted
|
|
449
|
-
expanded signal open
|
|
464
|
+
expanded signal open for a collapsible field, and restores the editor focus for
|
|
465
|
+
both collapsible and plain model fields at the actual
|
|
450
466
|
mutation checkpoint before the next input task. It also returns keyboard activation
|
|
451
467
|
from the clear button to a surviving editor immediately. No animation frame owns
|
|
452
468
|
clear focus, so fast typing cannot escape to page shortcuts or lose its first letter. The app still owns clearing query/tokens and emptying
|