@treeui/mcp 0.5.0 → 0.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/dist/{chunk-TRJAXZUC.js → chunk-ITEC3SEF.js} +2097 -377
- package/dist/cli.cjs +2097 -377
- package/dist/cli.js +1 -1
- package/dist/index.cjs +2114 -374
- package/dist/index.d.cts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +22 -2
- package/package.json +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// src/generated/treeui.catalog.json
|
|
2
2
|
var treeui_catalog_default = {
|
|
3
|
-
generatedAt: "2026-07-
|
|
3
|
+
generatedAt: "2026-07-21T19:17:20.408Z",
|
|
4
4
|
packageName: "@treeui/vue",
|
|
5
|
-
packageVersion: "0.
|
|
5
|
+
packageVersion: "0.19.0",
|
|
6
6
|
decisionGuides: [
|
|
7
7
|
{
|
|
8
8
|
id: "single-choice",
|
|
@@ -53,6 +53,14 @@ var treeui_catalog_default = {
|
|
|
53
53
|
"The options are hierarchical."
|
|
54
54
|
],
|
|
55
55
|
notes: []
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
use: "TLanguageSelect",
|
|
59
|
+
when: [
|
|
60
|
+
"The value is the application language or locale.",
|
|
61
|
+
"Each language should show a country flag beside its name."
|
|
62
|
+
],
|
|
63
|
+
notes: []
|
|
56
64
|
}
|
|
57
65
|
]
|
|
58
66
|
},
|
|
@@ -365,6 +373,32 @@ var treeui_catalog_default = {
|
|
|
365
373
|
"Prefer `TAppShell` (recipe `app-shell`) when you also need full-viewport sizing and a responsive mobile drawer."
|
|
366
374
|
]
|
|
367
375
|
},
|
|
376
|
+
{
|
|
377
|
+
id: "nav-menu-icons",
|
|
378
|
+
name: "Icons on navigation items",
|
|
379
|
+
useWhen: [
|
|
380
|
+
"Navigation items each carry an icon.",
|
|
381
|
+
"The navigation collapses to an icon-only rail, so the icon is the only thing left identifying a section.",
|
|
382
|
+
"Some of the icons the app needs are not TreeUI built-ins."
|
|
383
|
+
],
|
|
384
|
+
compose: [
|
|
385
|
+
"TNavMenu",
|
|
386
|
+
"TIcon",
|
|
387
|
+
"registerTreeIcons",
|
|
388
|
+
"resetTreeIcons"
|
|
389
|
+
],
|
|
390
|
+
notes: [
|
|
391
|
+
"Set `icon` on the item, as a registered NAME: `{ label: 'Dashboard', value: 'dashboard', icon: 'layout-dashboard' }`. Do not import an icon component per item, and do not put a `TIcon` in the `#item` slot just to get an icon \u2014 the item renders it for you.",
|
|
392
|
+
"`TNavMenuItem.icon` is `TIconInput`, so a component is accepted too. Prefer the name: `items` normally lives in a `ref`, a `computed`, or a route config, and a string is never made reactive \u2014 a component object there needs `markRaw` or Vue warns.",
|
|
393
|
+
"An item with no icon (or an unregistered name) falls back to a letter marker, and a `console.warn` lists the valid names \u2014 once per name, in production builds too. Give every item an icon before shipping a collapsible rail, or the collapsed state is a column of letters.",
|
|
394
|
+
"Icons the app needs but TreeUI does not ship are REGISTERED, not worked around: one `registerTreeIcons` call in `main.ts` and they are usable by name everywhere. Never hand-roll an `<svg>` \u2014 without the `absoluteStrokeWidth` correction its stroke scales with the icon (1.67px at size 20, 4px at 48), so it looks bolder than its neighbours at every size above 24.",
|
|
395
|
+
"Check the name is not already taken before registering it \u2014 `hasTreeIcon(name)` answers that. Registering one of the 364 built-in names replaces that built-in everywhere, silently, which is a supported swap but never what you want when the goal was adding an icon.",
|
|
396
|
+
"Keep the icon vocabulary consistent: built-ins use TreeUI's descriptive kebab-case names, so register custom ones with the same convention.",
|
|
397
|
+
"Icon registration is process-wide state. In component tests that register icons, call `resetTreeIcons()` in an `afterEach` so one case's icons do not leak into the next.",
|
|
398
|
+
"Set `to` for the route target on each item \u2014 `TNavMenuItem` has no `href` and no `id`; identity is `value`.",
|
|
399
|
+
"This recipe covers the icons only; the surrounding layout is its own recipe (`app-shell` or `sidebar-shell`)."
|
|
400
|
+
]
|
|
401
|
+
},
|
|
368
402
|
{
|
|
369
403
|
id: "stat-grid",
|
|
370
404
|
name: "Dashboard metric grid",
|
|
@@ -538,6 +572,148 @@ var treeui_catalog_default = {
|
|
|
538
572
|
notes: [
|
|
539
573
|
'Use `selectionMode="multiple"` when permissions or tag assignment spans nested nodes.'
|
|
540
574
|
]
|
|
575
|
+
},
|
|
576
|
+
{
|
|
577
|
+
id: "language-switcher",
|
|
578
|
+
name: "Application language switcher",
|
|
579
|
+
useWhen: [
|
|
580
|
+
"The app lets the user pick a language or locale, with an optional flag per option."
|
|
581
|
+
],
|
|
582
|
+
compose: [
|
|
583
|
+
"TFormField",
|
|
584
|
+
"TLanguageSelect"
|
|
585
|
+
],
|
|
586
|
+
notes: [
|
|
587
|
+
"The app owns the language list: TreeUI ships no locale dataset, so pass `options` with your own `label`, `value`, and optional `code` and `description`.",
|
|
588
|
+
"`TLanguageSelect` only emits the chosen `value` through `update:modelValue`; the app performs every locale side effect (i18n locale, persistence, `document.documentElement.lang`, route or API updates).",
|
|
589
|
+
"Set `code` only where a flag is meaningful \u2014 a language is not a country \u2014 and omit it to render that option without a flag.",
|
|
590
|
+
"Set `flagBaseUrl` once, at the switcher, when flag assets are self-hosted; it is forwarded to every nested `TFlag`.",
|
|
591
|
+
"Wrap with `TFormField` when the switcher sits in a form and needs a label, hint, or error text; drop the wrapper for a bare toolbar or header control."
|
|
592
|
+
]
|
|
593
|
+
}
|
|
594
|
+
],
|
|
595
|
+
practices: [
|
|
596
|
+
{
|
|
597
|
+
id: "interaction-feedback",
|
|
598
|
+
title: "Visual interaction feedback",
|
|
599
|
+
summary: "Every interaction answers back. Hover, focus, active, loading, and disabled are designed states \u2014 never afterthoughts left to the consumer.",
|
|
600
|
+
rules: [
|
|
601
|
+
"Interactive surfaces ship hover, active, and focus-visible treatments out of the box.",
|
|
602
|
+
"Loading states announce themselves (aria-busy, spinner) and block duplicate activation.",
|
|
603
|
+
"Disabled and loading elements never emit activation events.",
|
|
604
|
+
"Focus indicators stay visible in both light and dark themes."
|
|
605
|
+
],
|
|
606
|
+
components: [
|
|
607
|
+
"TButton",
|
|
608
|
+
"TLink",
|
|
609
|
+
"TInput",
|
|
610
|
+
"TSelect",
|
|
611
|
+
"TCheckbox",
|
|
612
|
+
"TSwitch",
|
|
613
|
+
"TTabs",
|
|
614
|
+
"TPagination",
|
|
615
|
+
"TDropdown",
|
|
616
|
+
"TSelectableList"
|
|
617
|
+
]
|
|
618
|
+
},
|
|
619
|
+
{
|
|
620
|
+
id: "accessible-by-default",
|
|
621
|
+
title: "Accessible by default",
|
|
622
|
+
summary: "Native semantics first, ARIA where the pattern requires it, full keyboard support, and focus management the consumer never has to write.",
|
|
623
|
+
rules: [
|
|
624
|
+
'Native elements before roles; role="dialog", aria-modal, aria-labelledby only where semantics require them.',
|
|
625
|
+
"Tab/Shift+Tab order, Escape to close, Enter/Space to activate, arrow keys where the pattern expects them.",
|
|
626
|
+
"Overlays trap focus while open and restore it on close.",
|
|
627
|
+
"Clickable targets stay at or above 44\xD744px."
|
|
628
|
+
],
|
|
629
|
+
components: [
|
|
630
|
+
"TModal",
|
|
631
|
+
"TDrawer",
|
|
632
|
+
"TConfirmDialog",
|
|
633
|
+
"TDropdown",
|
|
634
|
+
"TTooltip",
|
|
635
|
+
"TAccordion",
|
|
636
|
+
"TFormField",
|
|
637
|
+
"TTreeView",
|
|
638
|
+
"TToastProvider"
|
|
639
|
+
]
|
|
640
|
+
},
|
|
641
|
+
{
|
|
642
|
+
id: "predictable-api",
|
|
643
|
+
title: "One predictable API",
|
|
644
|
+
summary: "The same contracts everywhere: one size scale, one action-variant scale, v-model for form controls, open/close for overlays. Learn one component and you know them all.",
|
|
645
|
+
rules: [
|
|
646
|
+
"Sizes are sm | md | lg across the library.",
|
|
647
|
+
"Action variants come from one scale: solid, outline, ghost, soft, danger.",
|
|
648
|
+
"Form controls speak modelValue + update:modelValue (v-model).",
|
|
649
|
+
"Overlays speak open/defaultOpen + update:open/open-change."
|
|
650
|
+
],
|
|
651
|
+
components: [
|
|
652
|
+
"TButton",
|
|
653
|
+
"TInput",
|
|
654
|
+
"TSelect",
|
|
655
|
+
"TBadge",
|
|
656
|
+
"TTag",
|
|
657
|
+
"TCard",
|
|
658
|
+
"TModal"
|
|
659
|
+
]
|
|
660
|
+
},
|
|
661
|
+
{
|
|
662
|
+
id: "state-clarity",
|
|
663
|
+
title: "Empty, loading, and error are designed states",
|
|
664
|
+
summary: "Screens communicate status honestly: skeletons while loading, purposeful empty states, and status surfaces on one semantic tone scale.",
|
|
665
|
+
rules: [
|
|
666
|
+
"Default, hover, active, focus, disabled, loading, and error/empty states are designed and documented \u2014 not just the happy path.",
|
|
667
|
+
"Status tones map to semantic tokens (success, warning, error, info) and pass both themes.",
|
|
668
|
+
"Async feedback is immediate: skeleton or spinner first, toast or alert on completion."
|
|
669
|
+
],
|
|
670
|
+
components: [
|
|
671
|
+
"TSkeleton",
|
|
672
|
+
"TSpinner",
|
|
673
|
+
"TProgress",
|
|
674
|
+
"TEmptyState",
|
|
675
|
+
"TAlert",
|
|
676
|
+
"TToastProvider",
|
|
677
|
+
"TBadge"
|
|
678
|
+
]
|
|
679
|
+
},
|
|
680
|
+
{
|
|
681
|
+
id: "content-alignment",
|
|
682
|
+
title: "Alignment without custom CSS",
|
|
683
|
+
summary: "Layout primitives absorb spacing, alignment, and rhythm so product code never hand-rolls the same flexbox again.",
|
|
684
|
+
rules: [
|
|
685
|
+
"Spacing comes from the --tree-space-* scale, applied by layout components.",
|
|
686
|
+
"Compose TPage, TStack, TGrid, and TSplit before writing a custom layout div.",
|
|
687
|
+
"Forms align through TFormField + TStack + TGrid \u2014 labels, hints, and errors line up by contract.",
|
|
688
|
+
"Reading widths and page gutters come from TContainer/TPage, not local max-widths."
|
|
689
|
+
],
|
|
690
|
+
components: [
|
|
691
|
+
"TStack",
|
|
692
|
+
"TGrid",
|
|
693
|
+
"TSplit",
|
|
694
|
+
"TContainer",
|
|
695
|
+
"TSpacer",
|
|
696
|
+
"TPage",
|
|
697
|
+
"TPageHeader",
|
|
698
|
+
"TFormField"
|
|
699
|
+
]
|
|
700
|
+
},
|
|
701
|
+
{
|
|
702
|
+
id: "token-driven",
|
|
703
|
+
title: "Token-driven clarity",
|
|
704
|
+
summary: "No raw hex, px, or font values anywhere. Every visual decision references a --tree-* token, so light/dark and brand theming stay coherent by construction.",
|
|
705
|
+
rules: [
|
|
706
|
+
"Zero hardcoded colors, spacing, or typography in component code.",
|
|
707
|
+
"Light and dark are first-class themes; every state passes both.",
|
|
708
|
+
"Themes switch by attribute (data-tree-theme) with no component changes."
|
|
709
|
+
],
|
|
710
|
+
components: [
|
|
711
|
+
"TCard",
|
|
712
|
+
"TNavbar",
|
|
713
|
+
"TBadge",
|
|
714
|
+
"TTag",
|
|
715
|
+
"TChart"
|
|
716
|
+
]
|
|
541
717
|
}
|
|
542
718
|
],
|
|
543
719
|
setup: {
|
|
@@ -612,6 +788,43 @@ var treeui_catalog_default = {
|
|
|
612
788
|
"Use `maxVisibleTags` to control trigger density in compact layouts."
|
|
613
789
|
]
|
|
614
790
|
},
|
|
791
|
+
TFlag: {
|
|
792
|
+
required: [
|
|
793
|
+
"Pass `code` as an ISO 3166-1 alpha-2 country code. Matching is case-insensitive \u2014 the value is trimmed and lowercased internally.",
|
|
794
|
+
"Allow `https://flagcdn.com` in the app `Content-Security-Policy` `img-src` directive, or point `baseUrl` at a self-hosted mirror \u2014 flag images are fetched from a third-party CDN at runtime."
|
|
795
|
+
],
|
|
796
|
+
notes: [
|
|
797
|
+
"A mirror must serve `{baseUrl}/{segment}/{code}.png` for both steps of every size: 1x `h20` (sm), `h20` (md), `h24` (lg); 2x `h40` (sm), `h40` (md), `h60` (lg). The 2x asset is emitted through `srcset`.",
|
|
798
|
+
"Those fixed-height segments are part of the contract, and they are the CDN's flat artwork \u2014 a mirror must serve flat flags, not the waving ones.",
|
|
799
|
+
"Do not substitute the CDN's ratio-normalised width-by-height endpoints. They equalise aspect ratio only by switching to the waving artwork, which reads as decoration next to flat UI icons.",
|
|
800
|
+
"The fixed-height assets keep each flag's true proportions \u2014 Nepal is a pennant, Switzerland is square, Qatar is elongated. A shared height, not a shared ratio, is what aligns a column of flags.",
|
|
801
|
+
"CSS puts the image in a fixed 3:2 box (3:2 being the most common national flag ratio) with `object-fit: contain`, so outliers centre inside the box instead of being cropped or distorted.",
|
|
802
|
+
"Each retina segment is at least twice its box height \u2014 boxes are `--tree-size-icon-sm/md/lg` = 16px/20px/24px \u2014 so 2x screens never upscale.",
|
|
803
|
+
"`baseUrl` may be written with or without a trailing slash; trailing slashes are stripped before the path is built. An unknown `size` falls back to the `md` assets.",
|
|
804
|
+
"When the image cannot load \u2014 offline, blocked by CSP, unknown code \u2014 the component renders the uppercased `code` as text. Override that text with `fallbackText`.",
|
|
805
|
+
"The flag is `aria-hidden` by default. Pass `label` only when the flag carries meaning on its own; beside a visible country or language name it should stay decorative."
|
|
806
|
+
]
|
|
807
|
+
},
|
|
808
|
+
TLanguageSelect: {
|
|
809
|
+
required: [
|
|
810
|
+
"Pass `options` as `{ label, value, code?, description?, disabled? }[]`. TreeUI ships no language, locale, or country dataset \u2014 the app owns its language list.",
|
|
811
|
+
"Apply locale side effects (i18n locale, `lang` attribute, persistence) in the app layer; the component only reports the selected `value`.",
|
|
812
|
+
"Pass an `aria-label` whenever `iconOnly` is set \u2014 the visible language name is gone, so it is the control's only accessible name. It also labels the listbox."
|
|
813
|
+
],
|
|
814
|
+
notes: [
|
|
815
|
+
"`variant` is `field` (default) or `switcher`, typed as `TLanguageSelectVariant` and exported from `@treeui/vue`.",
|
|
816
|
+
'Use `variant="field"` inside a form, next to other inputs, or wrapped in `TFormField`: the flag leads the trigger, the trigger fills its container, and `width` applies. A visible field label already says what the control changes.',
|
|
817
|
+
'Use `variant="switcher"` for a page-level control in a navbar or app bar, where nothing nearby labels it. A translate icon (`TIcon name="languages"`) leads and the current flag trails before the chevron, so the control reads as "page language, now set to this" without an external label.',
|
|
818
|
+
"A switcher sizes to its content, so `width` does not apply, and its listbox aligns to the trigger's right edge.",
|
|
819
|
+
"`iconOnly` is switcher-only and drops the visible language name, leaving the translate icon and the current flag.",
|
|
820
|
+
"`value` is an opaque application key, typically a BCP-47 tag such as `pt-BR`. TreeUI never parses or validates it.",
|
|
821
|
+
"`code` is the ISO 3166-1 alpha-2 code used for the option flag. Omit it to render the option without a flag \u2014 a language is not a country, so many entries have no honest flag.",
|
|
822
|
+
"Use `description` for a secondary line such as the endonym.",
|
|
823
|
+
"Set `flagBaseUrl` once on the select rather than per option; it is forwarded to every nested `TFlag`.",
|
|
824
|
+
"Bind `modelValue` to a `string`, and use `v-model:open` when the app controls open state.",
|
|
825
|
+
"The CDN and Content-Security-Policy requirements under `TFlag` apply whenever any option carries a `code`."
|
|
826
|
+
]
|
|
827
|
+
},
|
|
615
828
|
TToggleGroup: {
|
|
616
829
|
required: [],
|
|
617
830
|
notes: [
|
|
@@ -661,7 +874,20 @@ var treeui_catalog_default = {
|
|
|
661
874
|
TNavMenu: {
|
|
662
875
|
required: [],
|
|
663
876
|
notes: [
|
|
664
|
-
"When nested inside `TSidebar` or `TAppShell`, `collapsed` can be inherited from the sidebar provider."
|
|
877
|
+
"When nested inside `TSidebar` or `TAppShell`, `collapsed` can be inherited from the sidebar provider.",
|
|
878
|
+
"Pass `items` as `{ label, value, icon?, to?, badge?, description?, shortLabel?, disabled?, exact? }[]`.",
|
|
879
|
+
"`icon` is `TIconInput` \u2014 a registered icon name (`icon: 'layout-dashboard'`) or a component. Use the name: it needs no import, and no `markRaw` when the item list is reactive.",
|
|
880
|
+
"An item with no icon, or with a name that is not registered, shows a letter marker instead. That marker is also all a collapsed rail can show, so give every item an icon when the sidebar collapses.",
|
|
881
|
+
"Register any icon the app needs beyond the built-ins first \u2014 see `icons` above."
|
|
882
|
+
]
|
|
883
|
+
},
|
|
884
|
+
TIcon: {
|
|
885
|
+
required: [
|
|
886
|
+
"Use a registered name: one of the built-ins, or one the app added with `registerTreeIcons`. See `icons` above."
|
|
887
|
+
],
|
|
888
|
+
notes: [
|
|
889
|
+
'`size` is a pixel count, not `sm | md | lg`. Passing `size="md"` renders an unsized svg.',
|
|
890
|
+
"The icon is `aria-hidden` by default. Pass `label` only when the icon carries meaning on its own; beside visible text it should stay decorative."
|
|
665
891
|
]
|
|
666
892
|
},
|
|
667
893
|
TTreeView: {
|
|
@@ -733,6 +959,7 @@ var treeui_catalog_default = {
|
|
|
733
959
|
],
|
|
734
960
|
commonCompositions: [
|
|
735
961
|
"TFormField + input-like control",
|
|
962
|
+
"TFormField + TLanguageSelect",
|
|
736
963
|
"TGrid + TStat",
|
|
737
964
|
"TStat + TSparkline",
|
|
738
965
|
"TCard + TChart",
|
|
@@ -756,15 +983,83 @@ var treeui_catalog_default = {
|
|
|
756
983
|
storyFile: "apps/docs/src/stories/Accordion.stories.ts",
|
|
757
984
|
storyTitle: "Components/Data Display/Accordion",
|
|
758
985
|
manifestFile: "docs/ai/COMPONENTS/accordion.yaml",
|
|
759
|
-
props: [
|
|
760
|
-
|
|
761
|
-
|
|
986
|
+
props: [
|
|
987
|
+
{
|
|
988
|
+
name: "type",
|
|
989
|
+
type: "'single' | 'multiple'",
|
|
990
|
+
default: "'single'",
|
|
991
|
+
values: [
|
|
992
|
+
"single",
|
|
993
|
+
"multiple"
|
|
994
|
+
],
|
|
995
|
+
description: "single \u2013 at most one item open at a time (opening one closes the rest). multiple \u2013 any number of items may be open simultaneously.\n"
|
|
996
|
+
},
|
|
997
|
+
{
|
|
998
|
+
name: "modelValue",
|
|
999
|
+
type: "string | string[] | undefined",
|
|
1000
|
+
default: "undefined",
|
|
1001
|
+
description: 'Controlled open state. For type="single" pass a string (the item value). For type="multiple" pass an array of strings. The accordion treats itself as controlled only while modelValue !== undefined; passing undefined leaves it uncontrolled and it falls back to its internal state.\n'
|
|
1002
|
+
},
|
|
1003
|
+
{
|
|
1004
|
+
name: "defaultValue",
|
|
1005
|
+
type: "string | string[] | undefined",
|
|
1006
|
+
default: "undefined",
|
|
1007
|
+
description: "Initial open state for uncontrolled usage. Read once when the accordion is created \u2014 changing it after mount has no effect. Ignored while modelValue is set. Do not combine it with modelValue: see notes.\n"
|
|
1008
|
+
},
|
|
1009
|
+
{
|
|
1010
|
+
name: "disabled",
|
|
1011
|
+
type: "boolean",
|
|
1012
|
+
default: "false",
|
|
1013
|
+
description: "Disables all items. OR-ed with each item's own disabled prop, so an item is disabled when either is true. Provided to items as a computed ref, so flipping it after mount updates every item.\n"
|
|
1014
|
+
},
|
|
1015
|
+
{
|
|
1016
|
+
name: "collapsible",
|
|
1017
|
+
type: "boolean",
|
|
1018
|
+
default: "false",
|
|
1019
|
+
description: 'Only applies when type="single". When true, the open item can be collapsed by clicking its trigger again, which emits undefined. When false, clicking the already-open trigger is a no-op and emits nothing. In type="multiple" any item can always be collapsed and this prop is ignored.\n'
|
|
1020
|
+
}
|
|
1021
|
+
],
|
|
1022
|
+
events: [
|
|
1023
|
+
{
|
|
1024
|
+
name: "update:modelValue",
|
|
1025
|
+
description: 'Emitted when the open state changes (v-model support). type="single" emits the open item value as a string, or undefined when it is collapsed. type="multiple" always emits a string[] of the open values.\n',
|
|
1026
|
+
payload: "string | string[] | undefined"
|
|
1027
|
+
}
|
|
1028
|
+
],
|
|
1029
|
+
slots: [
|
|
1030
|
+
{
|
|
1031
|
+
name: "default",
|
|
1032
|
+
description: "Accepts TAccordionItem children."
|
|
1033
|
+
}
|
|
1034
|
+
],
|
|
762
1035
|
a11y: [
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
1036
|
+
"container_is_a_plain_div_with_no_aria_role: true",
|
|
1037
|
+
"trigger_is_a_heading_wrapped_native_button: h3 > button",
|
|
1038
|
+
"aria_expanded_on_trigger_reflects_open_state: true",
|
|
1039
|
+
"aria_controls_on_trigger_references_panel_id: true",
|
|
1040
|
+
"panel_uses_role_region: true",
|
|
1041
|
+
"aria_labelledby_on_panel_references_trigger_id: true",
|
|
1042
|
+
"disabled_items_use_the_native_disabled_attribute: true",
|
|
1043
|
+
"chevron_icon_is_aria_hidden: true",
|
|
1044
|
+
"trigger_hit_area_is_at_least_44px: via the .t-accordion__trigger::after overlay",
|
|
1045
|
+
"enter_space_toggle_the_focused_item: native button activation",
|
|
1046
|
+
"arrow_down_focuses_next_enabled_trigger_wrapping_to_first: true",
|
|
1047
|
+
"arrow_up_focuses_previous_enabled_trigger_wrapping_to_last: true",
|
|
1048
|
+
"home_focuses_first_enabled_trigger: true",
|
|
1049
|
+
"end_focuses_last_enabled_trigger: true"
|
|
1050
|
+
],
|
|
1051
|
+
behavior: [
|
|
1052
|
+
"controlled_only_while_model_value_is_not_undefined: true",
|
|
1053
|
+
"default_value_seeds_uncontrolled_state_once: true",
|
|
1054
|
+
"single_mode_opening_an_item_closes_the_previous_one: true",
|
|
1055
|
+
"single_mode_collapsing_requires_collapsible: true",
|
|
1056
|
+
"multiple_mode_ignores_collapsible: true",
|
|
1057
|
+
"container_and_item_disabled_are_combined_with_or: true",
|
|
1058
|
+
"arrow_navigation_skips_disabled_triggers: true",
|
|
1059
|
+
"arrow_navigation_wraps_around: true",
|
|
1060
|
+
"trigger_order_follows_item_mount_order: true",
|
|
1061
|
+
"only_open_panels_are_rendered: true"
|
|
766
1062
|
],
|
|
767
|
-
behavior: [],
|
|
768
1063
|
selection: {
|
|
769
1064
|
keywords: [
|
|
770
1065
|
"accordion",
|
|
@@ -795,7 +1090,10 @@ var treeui_catalog_default = {
|
|
|
795
1090
|
required: [],
|
|
796
1091
|
notes: []
|
|
797
1092
|
},
|
|
798
|
-
recipes: []
|
|
1093
|
+
recipes: [],
|
|
1094
|
+
practices: [
|
|
1095
|
+
"accessible-by-default"
|
|
1096
|
+
]
|
|
799
1097
|
},
|
|
800
1098
|
{
|
|
801
1099
|
name: "TAlert",
|
|
@@ -812,14 +1110,15 @@ var treeui_catalog_default = {
|
|
|
812
1110
|
props: [
|
|
813
1111
|
{
|
|
814
1112
|
name: "variant",
|
|
815
|
-
type: "
|
|
1113
|
+
type: "TAlertVariant",
|
|
816
1114
|
default: "info",
|
|
817
1115
|
values: [
|
|
818
1116
|
"info",
|
|
819
1117
|
"success",
|
|
820
1118
|
"warning",
|
|
821
1119
|
"danger"
|
|
822
|
-
]
|
|
1120
|
+
],
|
|
1121
|
+
description: "Semantic tone. Sets the --tree-alert-* custom properties that colour the surface, border, icon, and dismiss button."
|
|
823
1122
|
},
|
|
824
1123
|
{
|
|
825
1124
|
name: "size",
|
|
@@ -829,42 +1128,55 @@ var treeui_catalog_default = {
|
|
|
829
1128
|
"sm",
|
|
830
1129
|
"md",
|
|
831
1130
|
"lg"
|
|
832
|
-
]
|
|
1131
|
+
],
|
|
1132
|
+
description: "Adjusts padding and font size only. md is the baseline defined on .t-alert itself."
|
|
833
1133
|
},
|
|
834
1134
|
{
|
|
835
1135
|
name: "dismissible",
|
|
836
1136
|
type: "boolean",
|
|
837
|
-
default: "false"
|
|
1137
|
+
default: "false",
|
|
1138
|
+
description: "Renders the trailing dismiss button. The button is the only thing gated by this prop; the alert never hides itself."
|
|
838
1139
|
}
|
|
839
1140
|
],
|
|
840
1141
|
events: [
|
|
841
1142
|
{
|
|
842
1143
|
name: "dismiss",
|
|
843
|
-
description: "Emitted when the dismiss button is clicked.",
|
|
1144
|
+
description: "Emitted when the dismiss button is clicked. TAlert is stateless \u2014 it does not hide, unmount, or animate itself out. The consumer owns removal (v-if, a list splice, or a store flag); without a handler the button is inert.\n",
|
|
844
1145
|
payload: "none"
|
|
845
1146
|
}
|
|
846
1147
|
],
|
|
847
1148
|
slots: [
|
|
848
1149
|
{
|
|
849
1150
|
name: "default",
|
|
850
|
-
description: "Alert message content."
|
|
1151
|
+
description: "Alert message content, rendered inside .t-alert__content."
|
|
851
1152
|
},
|
|
852
1153
|
{
|
|
853
1154
|
name: "icon",
|
|
854
|
-
description:
|
|
1155
|
+
description: 'Optional leading icon. The .t-alert__icon wrapper span is rendered only when the slot is provided (v-if="$slots.icon") and is marked aria-hidden, so the icon is decorative \u2014 never put meaning there that is not also in the message text. The wrapper inherits the variant colour via --tree-alert-accent.\n'
|
|
855
1156
|
},
|
|
856
1157
|
{
|
|
857
1158
|
name: "dismiss-icon",
|
|
858
|
-
description:
|
|
1159
|
+
description: 'Replaces the default 16x16 \xD7 SVG inside the dismiss button. Rendered only when dismissible is true, since the slot lives inside the button. Has a working default, so it is optional. The button keeps its aria-label="Dismiss" regardless of content.\n'
|
|
859
1160
|
}
|
|
860
1161
|
],
|
|
861
1162
|
a11y: [
|
|
862
1163
|
"role: alert",
|
|
1164
|
+
"role_is_on_root_element: true",
|
|
863
1165
|
"icon_slot_marked_aria_hidden: true",
|
|
1166
|
+
"default_dismiss_icon_marked_aria_hidden: true",
|
|
864
1167
|
"dismiss_button_aria_label: Dismiss",
|
|
865
|
-
"
|
|
1168
|
+
"dismiss_button_label_is_hardcoded: true",
|
|
1169
|
+
"dismiss_button_hit_area: 44x44 via a .t-alert__dismiss::after pseudo-element; the visible button is 1.5rem.",
|
|
1170
|
+
"keyboard: Tab to dismiss button, Enter/Space to activate",
|
|
1171
|
+
'live_region_caveat: role="alert" is an assertive live region. An alert that is already in the DOM on first paint is generally not announced \u2014 mount it dynamically (v-if / list insert) when you need the message read out.'
|
|
1172
|
+
],
|
|
1173
|
+
behavior: [
|
|
1174
|
+
"self_removes_on_dismiss: false",
|
|
1175
|
+
"icon_wrapper_rendered_only_when_icon_slot_provided: true",
|
|
1176
|
+
"dismiss_button_rendered_only_when_dismissible: true",
|
|
1177
|
+
"size_md_emits_class_without_css_rule: t-alert--md is always emitted but carries no CSS rule of its own; .t-alert is the md baseline and only --sm and --lg override padding and font size.",
|
|
1178
|
+
'variant_sets_local_custom_properties: ["--tree-alert-bg","--tree-alert-border","--tree-alert-text","--tree-alert-accent"]'
|
|
866
1179
|
],
|
|
867
|
-
behavior: [],
|
|
868
1180
|
selection: {
|
|
869
1181
|
keywords: [
|
|
870
1182
|
"alert",
|
|
@@ -895,7 +1207,10 @@ var treeui_catalog_default = {
|
|
|
895
1207
|
required: [],
|
|
896
1208
|
notes: []
|
|
897
1209
|
},
|
|
898
|
-
recipes: []
|
|
1210
|
+
recipes: [],
|
|
1211
|
+
practices: [
|
|
1212
|
+
"state-clarity"
|
|
1213
|
+
]
|
|
899
1214
|
},
|
|
900
1215
|
{
|
|
901
1216
|
name: "TAppShell",
|
|
@@ -913,7 +1228,8 @@ var treeui_catalog_default = {
|
|
|
913
1228
|
{
|
|
914
1229
|
name: "as",
|
|
915
1230
|
type: "string",
|
|
916
|
-
default: "div"
|
|
1231
|
+
default: "div",
|
|
1232
|
+
note: "Tag or component rendered as the shell root. The root is a plain `div` by default and is therefore not a landmark \u2014 the header/sidebar/main regions carry the semantics."
|
|
917
1233
|
},
|
|
918
1234
|
{
|
|
919
1235
|
name: "side",
|
|
@@ -927,164 +1243,254 @@ var treeui_catalog_default = {
|
|
|
927
1243
|
{
|
|
928
1244
|
name: "sidebarWidth",
|
|
929
1245
|
type: "string",
|
|
930
|
-
default: "17.5rem"
|
|
1246
|
+
default: "17.5rem",
|
|
1247
|
+
note: "Any CSS length. Sets `--tree-app-shell-sidebar-width` on the root, which drives the desktop rail track and also caps the mobile drawer at `min(100%, sidebarWidth)`."
|
|
931
1248
|
},
|
|
932
1249
|
{
|
|
933
1250
|
name: "collapsedWidth",
|
|
934
1251
|
type: "string",
|
|
935
|
-
default: "4.75rem"
|
|
1252
|
+
default: "4.75rem",
|
|
1253
|
+
note: "Any CSS length. Sets `--tree-app-shell-collapsed-width` on the root, but it only takes effect while the root carries `is-collapsed` (desktop + `collapsible` + collapsed)."
|
|
936
1254
|
},
|
|
937
1255
|
{
|
|
938
1256
|
name: "collapsible",
|
|
939
1257
|
type: "boolean",
|
|
940
|
-
default: "false"
|
|
1258
|
+
default: "false",
|
|
1259
|
+
note: "Master gate for the desktop rail. While false the root never gets `is-collapsed`, the built-in collapse toggle is not rendered, and `toggleCollapsed` is a no-op."
|
|
941
1260
|
},
|
|
942
1261
|
{
|
|
943
1262
|
name: "collapsed",
|
|
944
1263
|
type: "boolean",
|
|
945
|
-
default: "undefined"
|
|
1264
|
+
default: "undefined",
|
|
1265
|
+
note: "Controlled desktop rail state (v-model:collapsed). Leave undefined for uncontrolled. When set, the component only emits \u2014 the parent must apply the new value."
|
|
946
1266
|
},
|
|
947
1267
|
{
|
|
948
1268
|
name: "defaultCollapsed",
|
|
949
1269
|
type: "boolean",
|
|
950
|
-
default: "false"
|
|
1270
|
+
default: "false",
|
|
1271
|
+
note: "Initial value for uncontrolled use. Read once during setup; later changes to the prop are ignored."
|
|
951
1272
|
},
|
|
952
1273
|
{
|
|
953
1274
|
name: "mobile",
|
|
954
1275
|
type: "boolean",
|
|
955
|
-
default: "undefined"
|
|
1276
|
+
default: "undefined",
|
|
1277
|
+
note: "Forces mobile mode when explicitly true or false. Leave undefined to auto-detect from `breakpoint`."
|
|
956
1278
|
},
|
|
957
1279
|
{
|
|
958
1280
|
name: "breakpoint",
|
|
959
1281
|
type: "string",
|
|
960
|
-
default: "768px"
|
|
1282
|
+
default: "768px",
|
|
1283
|
+
note: "Any CSS length. Evaluated as `(max-width: <breakpoint>)` via matchMedia, and only consulted while `mobile` is undefined. Changing it tears down and rebuilds the media query listener."
|
|
961
1284
|
},
|
|
962
1285
|
{
|
|
963
1286
|
name: "sidebarOpen",
|
|
964
1287
|
type: "boolean",
|
|
965
|
-
default: "undefined"
|
|
1288
|
+
default: "undefined",
|
|
1289
|
+
note: "Controlled off-canvas drawer state (v-model:sidebarOpen). Mobile-only \u2014 the flag is tracked in desktop mode but nothing renders from it."
|
|
966
1290
|
},
|
|
967
1291
|
{
|
|
968
1292
|
name: "defaultSidebarOpen",
|
|
969
1293
|
type: "boolean",
|
|
970
|
-
default: "false"
|
|
1294
|
+
default: "false",
|
|
1295
|
+
note: "Initial value for uncontrolled use. Read once during setup."
|
|
1296
|
+
},
|
|
1297
|
+
{
|
|
1298
|
+
name: "immersive",
|
|
1299
|
+
type: "boolean",
|
|
1300
|
+
default: "undefined",
|
|
1301
|
+
note: "Controlled immersive state (v-model:immersive). Hides the header and sidebar so the content fills the viewport. The chrome is hidden with CSS rather than unmounted, so toggling never remounts the default slot. While immersive, the mobile drawer is not rendered."
|
|
1302
|
+
},
|
|
1303
|
+
{
|
|
1304
|
+
name: "defaultImmersive",
|
|
1305
|
+
type: "boolean",
|
|
1306
|
+
default: "false",
|
|
1307
|
+
note: "Initial value for uncontrolled use. Read once during setup."
|
|
971
1308
|
},
|
|
972
1309
|
{
|
|
973
1310
|
name: "closeOnEscape",
|
|
974
1311
|
type: "boolean",
|
|
975
|
-
default: "true"
|
|
1312
|
+
default: "true",
|
|
1313
|
+
note: "Drawer only. Escape is handled on the drawer surface, so it fires only while focus is inside the drawer."
|
|
976
1314
|
},
|
|
977
1315
|
{
|
|
978
1316
|
name: "closeOnOverlay",
|
|
979
1317
|
type: "boolean",
|
|
980
|
-
default: "true"
|
|
1318
|
+
default: "true",
|
|
1319
|
+
note: "Drawer only. Set false to keep the drawer open on backdrop clicks."
|
|
981
1320
|
},
|
|
982
1321
|
{
|
|
983
1322
|
name: "showMenuButton",
|
|
984
1323
|
type: "boolean",
|
|
985
|
-
default: "true"
|
|
1324
|
+
default: "true",
|
|
1325
|
+
note: "Renders the built-in hamburger in the header. Mobile only. Set false to supply your own trigger and call the `toggleSidebar` slot prop from the `header` or `header-start` slot."
|
|
986
1326
|
},
|
|
987
1327
|
{
|
|
988
1328
|
name: "showCollapseButton",
|
|
989
1329
|
type: "boolean",
|
|
990
1330
|
default: "true",
|
|
991
|
-
note: "Renders the built-in collapse toggle in the sidebar footer. Desktop only, and only when `collapsible` is set \u2014 no need to wire your own."
|
|
1331
|
+
note: "Renders the built-in collapse toggle in the sidebar footer. Desktop only, and only when `collapsible` is set \u2014 no need to wire your own. Never rendered in the mobile drawer."
|
|
992
1332
|
},
|
|
993
1333
|
{
|
|
994
1334
|
name: "collapseLabel",
|
|
995
1335
|
type: "string",
|
|
996
|
-
default: "Collapse sidebar"
|
|
1336
|
+
default: "Collapse sidebar",
|
|
1337
|
+
note: "aria-label of the collapse toggle while the rail is expanded."
|
|
997
1338
|
},
|
|
998
1339
|
{
|
|
999
1340
|
name: "expandLabel",
|
|
1000
1341
|
type: "string",
|
|
1001
|
-
default: "Expand sidebar"
|
|
1342
|
+
default: "Expand sidebar",
|
|
1343
|
+
note: "aria-label of the collapse toggle while the rail is collapsed."
|
|
1002
1344
|
},
|
|
1003
1345
|
{
|
|
1004
1346
|
name: "menuLabel",
|
|
1005
1347
|
type: "string",
|
|
1006
|
-
default: "Open menu"
|
|
1348
|
+
default: "Open menu",
|
|
1349
|
+
note: "aria-label of the built-in hamburger. Static \u2014 it does not swap to a close label while the drawer is open."
|
|
1007
1350
|
},
|
|
1008
1351
|
{
|
|
1009
1352
|
name: "closeLabel",
|
|
1010
1353
|
type: "string",
|
|
1011
|
-
default: "Close menu"
|
|
1354
|
+
default: "Close menu",
|
|
1355
|
+
note: "aria-label of the drawer's close button."
|
|
1012
1356
|
},
|
|
1013
1357
|
{
|
|
1014
1358
|
name: "sidebarLabel",
|
|
1015
1359
|
type: "string",
|
|
1016
|
-
default: "Sidebar"
|
|
1360
|
+
default: "Sidebar",
|
|
1361
|
+
note: "aria-label applied to both the desktop <aside> and the drawer <aside>."
|
|
1017
1362
|
}
|
|
1018
1363
|
],
|
|
1019
1364
|
events: [
|
|
1020
1365
|
{
|
|
1021
|
-
name: "update:collapsed"
|
|
1366
|
+
name: "update:collapsed",
|
|
1367
|
+
description: "Desktop rail collapsed state changed. Enables v-model:collapsed.",
|
|
1368
|
+
payload: "[value: boolean]"
|
|
1022
1369
|
},
|
|
1023
1370
|
{
|
|
1024
|
-
name: "collapse-change"
|
|
1371
|
+
name: "collapse-change",
|
|
1372
|
+
description: "Same change as update:collapsed, for non-v-model usage. Both always fire together.",
|
|
1373
|
+
payload: "[value: boolean]"
|
|
1374
|
+
},
|
|
1375
|
+
{
|
|
1376
|
+
name: "update:sidebarOpen",
|
|
1377
|
+
description: "Off-canvas drawer open state changed. Enables v-model:sidebarOpen.",
|
|
1378
|
+
payload: "[value: boolean]"
|
|
1025
1379
|
},
|
|
1026
1380
|
{
|
|
1027
|
-
name: "
|
|
1381
|
+
name: "sidebar-open-change",
|
|
1382
|
+
description: "Same change as update:sidebarOpen, for non-v-model usage. Both always fire together.",
|
|
1383
|
+
payload: "[value: boolean]"
|
|
1384
|
+
},
|
|
1385
|
+
{
|
|
1386
|
+
name: "update:immersive",
|
|
1387
|
+
description: "Immersive state changed. Enables v-model:immersive.",
|
|
1388
|
+
payload: "[value: boolean]"
|
|
1028
1389
|
},
|
|
1029
1390
|
{
|
|
1030
|
-
name: "
|
|
1391
|
+
name: "immersive-change",
|
|
1392
|
+
description: "Same change as update:immersive, for non-v-model usage. Both always fire together.",
|
|
1393
|
+
payload: "[value: boolean]"
|
|
1031
1394
|
}
|
|
1032
1395
|
],
|
|
1033
1396
|
slots: [
|
|
1034
1397
|
{
|
|
1035
|
-
name: "header"
|
|
1398
|
+
name: "header",
|
|
1399
|
+
description: "Main header region. Spans the full header width by default; once `header-start` is filled it is constrained to the content column so it lines up with the panel underneath. On mobile the header falls back to a single flex row either way.\n",
|
|
1400
|
+
note: "AppShellSlotProps \u2014 { mobile, collapsed, sidebarOpen, immersive, toggleSidebar, closeSidebar, toggleCollapsed, toggleImmersive }"
|
|
1036
1401
|
},
|
|
1037
1402
|
{
|
|
1038
|
-
name: "header-start"
|
|
1403
|
+
name: "header-start",
|
|
1404
|
+
description: "Header region sitting over the sidebar rail (typically the brand mark). Filling it adds `has-start` to the header, which switches the header to the shell's own two-column grid and tracks the rail width as it collapses.\n",
|
|
1405
|
+
note: "AppShellSlotProps"
|
|
1039
1406
|
},
|
|
1040
1407
|
{
|
|
1041
|
-
name: "sidebar-header"
|
|
1408
|
+
name: "sidebar-header",
|
|
1409
|
+
description: "Pinned above the sidebar body, inset to line up with nav item icons. Rendered in both the desktop aside and the mobile drawer.\n",
|
|
1410
|
+
note: "AppShellSlotProps"
|
|
1042
1411
|
},
|
|
1043
1412
|
{
|
|
1044
|
-
name: "sidebar"
|
|
1413
|
+
name: "sidebar",
|
|
1414
|
+
description: "Sidebar body \u2014 the natural home for a TNavMenu, which picks up the collapsed state through provide/inject. Rendered in both the desktop aside and the mobile drawer, and takes the vertical slack so the footer pins to the bottom.\n",
|
|
1415
|
+
note: "AppShellSlotProps"
|
|
1045
1416
|
},
|
|
1046
1417
|
{
|
|
1047
|
-
name: "sidebar-footer"
|
|
1418
|
+
name: "sidebar-footer",
|
|
1419
|
+
description: "Pinned to the bottom of the sidebar, inset to line up with nav item icons. In the desktop aside it shares one container with the built-in collapse toggle, which is rendered after the slot content; in the mobile drawer the container holds the slot content alone.\n",
|
|
1420
|
+
note: "AppShellSlotProps"
|
|
1048
1421
|
},
|
|
1049
1422
|
{
|
|
1050
|
-
name: "default"
|
|
1423
|
+
name: "default",
|
|
1424
|
+
description: "Main content area. Scrolls independently of the header and sidebar.",
|
|
1425
|
+
note: "{ mobile: boolean, collapsed: boolean, immersive: boolean, toggleImmersive: () => void } \u2014 a subset of AppShellSlotProps. toggleImmersive is included because immersive hides the chrome, so the content is the only place an exit control can live."
|
|
1051
1426
|
},
|
|
1052
1427
|
{
|
|
1053
|
-
name: "menu-icon"
|
|
1428
|
+
name: "menu-icon",
|
|
1429
|
+
description: "Replaces the default hamburger glyph inside the built-in menu button. Use `sidebarOpen` to swap the icon while the drawer is open. Renders inside the button, so it must be presentational only.\n",
|
|
1430
|
+
note: "{ sidebarOpen: boolean }"
|
|
1054
1431
|
},
|
|
1055
1432
|
{
|
|
1056
|
-
name: "collapse-icon"
|
|
1433
|
+
name: "collapse-icon",
|
|
1434
|
+
description: "Replaces the default glyph inside the built-in collapse toggle. Renders inside the button, so it must be presentational only.\n",
|
|
1435
|
+
note: "{ collapsed: boolean }"
|
|
1057
1436
|
}
|
|
1058
1437
|
],
|
|
1059
1438
|
a11y: [
|
|
1060
|
-
"
|
|
1439
|
+
"semantic_regions: <header>, <aside> and <main>; the shell root itself is a plain div and is not a landmark",
|
|
1440
|
+
"role: dialog \u2014 on the mobile drawer only",
|
|
1061
1441
|
"aria_modal: true",
|
|
1062
|
-
"focus_trap:
|
|
1063
|
-
"restores_focus_on_close:
|
|
1442
|
+
"focus_trap: Tab and Shift+Tab cycle inside the drawer; with no focusable descendant, focus is pinned to the drawer itself",
|
|
1443
|
+
"restores_focus_on_close: only when the drawer was opened through the built-in menu button or the toggleSidebar slot prop \u2014 those capture document.activeElement first",
|
|
1064
1444
|
"escape_closes_when_enabled: true",
|
|
1065
1445
|
"menu_button_aria_expanded: true",
|
|
1066
|
-
"menu_button_aria_controls_drawer:
|
|
1067
|
-
"
|
|
1446
|
+
"menu_button_aria_controls_drawer: aria-controls always points at the sidebar id, and on mobile that element exists only while the drawer is open",
|
|
1447
|
+
"collapse_button_aria_expanded: reflects the expanded rail, i.e. !collapsed",
|
|
1448
|
+
"collapse_button_aria_controls_sidebar: true",
|
|
1449
|
+
"collapse_button_label_swaps_by_state: collapseLabel while expanded, expandLabel while collapsed",
|
|
1450
|
+
"drawer_close_button_labelled_by_close_label: true",
|
|
1451
|
+
"sidebar_labelled_by_sidebar_label: true",
|
|
1452
|
+
"drawer_focusable_via_tabindex_minus_one: true",
|
|
1453
|
+
"backdrop_is_aria_hidden: true",
|
|
1454
|
+
"built_in_icons_are_aria_hidden: true",
|
|
1455
|
+
"menu_and_drawer_close_buttons_are_44px: true"
|
|
1068
1456
|
],
|
|
1069
1457
|
behavior: [
|
|
1070
1458
|
"fills_viewport_full_width_and_height: true",
|
|
1459
|
+
"resets_body_margin_while_a_shell_is_mounted: body:has(.t-app-shell) { margin: 0 } \u2014 a deliberate global rule, scoped so it only applies to pages that mount a shell",
|
|
1071
1460
|
"header_spans_full_width_above_sidebar_and_content: true",
|
|
1072
1461
|
"content_area_scrolls_independently: true",
|
|
1073
1462
|
"auto_switches_to_mobile_at_breakpoint_when_mobile_undefined: true",
|
|
1074
1463
|
"mobile_prop_forces_mobile_mode: true",
|
|
1075
1464
|
"mobile_sidebar_becomes_off_canvas_drawer: true",
|
|
1465
|
+
"desktop_sidebar_is_removed_from_the_dom_on_mobile: crossing the breakpoint unmounts and remounts the sidebar slot, so component state inside it is not preserved",
|
|
1466
|
+
"drawer_is_rendered_only_while_mobile_and_open: true",
|
|
1076
1467
|
"auto_menu_button_in_header_on_mobile: true",
|
|
1077
1468
|
"controlled_and_uncontrolled_collapsed_state: true",
|
|
1078
1469
|
"controlled_and_uncontrolled_sidebar_open_state: true",
|
|
1470
|
+
"controlled_and_uncontrolled_immersive_state: true",
|
|
1471
|
+
"immersive_hides_chrome_without_remounting_content: the header and sidebar are hidden with CSS and the grid collapses to a single `main` area, so the default slot keeps its component state across the toggle \u2014 unlike the mobile breakpoint, which does remount the sidebar slot",
|
|
1472
|
+
"immersive_suppresses_the_mobile_drawer: while immersive the overlay is not rendered, since the trigger that opens it lives in the hidden header",
|
|
1473
|
+
"controlled_mode_does_not_self_update: when collapsed, sidebarOpen or immersive is bound, the component only emits \u2014 the parent must apply the value",
|
|
1474
|
+
"no_emit_when_the_value_is_unchanged: true",
|
|
1475
|
+
"toggle_collapsed_is_a_noop_when_collapsible_is_false: true",
|
|
1476
|
+
"collapse_toggle_requires_desktop_and_collapsible_and_show_collapse_button: true",
|
|
1079
1477
|
"provides_collapsed_state_to_descendants: true",
|
|
1080
1478
|
"drawer_reports_collapsed_false_to_descendants_and_slots: true",
|
|
1081
1479
|
"left_and_right_variants: true",
|
|
1082
1480
|
"locks_body_scroll_while_drawer_open: true",
|
|
1481
|
+
"releases_the_scroll_lock_when_leaving_mobile_while_open: true",
|
|
1482
|
+
"rearms_the_overlay_when_reentering_mobile_while_open: true",
|
|
1083
1483
|
"overlay_click_closes_when_enabled: true",
|
|
1084
1484
|
"exposes_slot_props_with_mobile_collapsed_and_toggles: true",
|
|
1085
1485
|
"sidebar_footer_pinned_to_bottom: true",
|
|
1086
1486
|
"sidebar_header_and_footer_inset_to_align_with_nav_icons: true",
|
|
1087
|
-
"header_mirrors_shell_columns_when_header_start_is_used: true"
|
|
1487
|
+
"header_mirrors_shell_columns_when_header_start_is_used: true",
|
|
1488
|
+
"header_start_falls_back_to_a_single_flex_row_on_mobile: true",
|
|
1489
|
+
"animates_the_rail_width_via_grid_template_columns: true",
|
|
1490
|
+
"main_panel_has_a_rounded_inner_corner_on_the_sidebar_side_on_desktop: true",
|
|
1491
|
+
"drawer_width_is_capped_at_min_of_100_percent_and_sidebar_width: true",
|
|
1492
|
+
'root_data_attribute: data-mobile="true" | "false" on the shell root',
|
|
1493
|
+
"respects_prefers_reduced_motion: true"
|
|
1088
1494
|
],
|
|
1089
1495
|
selection: {
|
|
1090
1496
|
keywords: [
|
|
@@ -1131,14 +1537,15 @@ var treeui_catalog_default = {
|
|
|
1131
1537
|
},
|
|
1132
1538
|
recipes: [
|
|
1133
1539
|
"app-shell"
|
|
1134
|
-
]
|
|
1540
|
+
],
|
|
1541
|
+
practices: []
|
|
1135
1542
|
},
|
|
1136
1543
|
{
|
|
1137
1544
|
name: "TAvatar",
|
|
1138
1545
|
aliases: [],
|
|
1139
1546
|
package: "@treeui/vue",
|
|
1140
1547
|
category: "Data Display",
|
|
1141
|
-
description: "User image
|
|
1548
|
+
description: "User avatar that renders an image when `src` is set, otherwise initials derived from `alt`, plus an optional status indicator dot.",
|
|
1142
1549
|
sourceFile: "packages/vue/src/components/TAvatar.vue",
|
|
1143
1550
|
storyFile: "apps/docs/src/stories/Avatar.stories.ts",
|
|
1144
1551
|
storyTitle: "Components/Data Display/Avatar",
|
|
@@ -1148,19 +1555,19 @@ var treeui_catalog_default = {
|
|
|
1148
1555
|
name: "src",
|
|
1149
1556
|
type: "string",
|
|
1150
1557
|
required: false,
|
|
1151
|
-
description: "URL of the avatar image."
|
|
1558
|
+
description: "URL of the avatar image. When set, the `<img>` branch renders and the initials span is NOT in the DOM at all (`v-else`). If the image fails to load, the `<img>` is hidden via inline `display: none` \u2014 the component does NOT fall back to initials, leaving an empty circle. Pass no `src` if you want initials.\n"
|
|
1152
1559
|
},
|
|
1153
1560
|
{
|
|
1154
1561
|
name: "alt",
|
|
1155
1562
|
type: "string",
|
|
1156
1563
|
default: '""',
|
|
1157
|
-
description: "Accessible label for the avatar
|
|
1564
|
+
description: "Accessible label for the avatar and the `alt` attribute of the `<img>`. Also the source for derived initials when `initials` is not set. Defaults to an empty string, in which case no `aria-label` is rendered at all (`alt || undefined`) and derived initials are empty \u2014 always pass a meaningful `alt`.\n"
|
|
1158
1565
|
},
|
|
1159
1566
|
{
|
|
1160
1567
|
name: "initials",
|
|
1161
1568
|
type: "string",
|
|
1162
1569
|
required: false,
|
|
1163
|
-
description:
|
|
1570
|
+
description: 'Explicit initials, rendered only when `src` is unset. Takes precedence over initials derived from `alt`. When omitted, initials are derived from `alt` by splitting on spaces, taking the first character of the first two words, and uppercasing (e.g. "Jane Doe" -> "JD").\n'
|
|
1164
1571
|
},
|
|
1165
1572
|
{
|
|
1166
1573
|
name: "size",
|
|
@@ -1170,7 +1577,8 @@ var treeui_catalog_default = {
|
|
|
1170
1577
|
"sm",
|
|
1171
1578
|
"md",
|
|
1172
1579
|
"lg"
|
|
1173
|
-
]
|
|
1580
|
+
],
|
|
1581
|
+
description: "Fixed square dimensions \u2014 sm 2rem, md 2.5rem, lg 3.5rem \u2014 with matching font size for initials."
|
|
1174
1582
|
},
|
|
1175
1583
|
{
|
|
1176
1584
|
name: "status",
|
|
@@ -1182,20 +1590,23 @@ var treeui_catalog_default = {
|
|
|
1182
1590
|
"busy",
|
|
1183
1591
|
"away"
|
|
1184
1592
|
],
|
|
1185
|
-
description: "Shows a colored status dot on the avatar
|
|
1593
|
+
description: "Shows a colored status dot pinned to the bottom-right of the avatar bounding box. Renders alongside either branch (image or initials). The dot sits on the corner outside the circular mask, so `.t-avatar` deliberately has no `overflow: hidden`.\n"
|
|
1186
1594
|
}
|
|
1187
1595
|
],
|
|
1188
1596
|
events: [],
|
|
1189
1597
|
slots: [
|
|
1190
1598
|
{
|
|
1191
1599
|
name: "default",
|
|
1192
|
-
description:
|
|
1600
|
+
description: 'Optional overlay content, rendered inside the `.t-avatar` span after the image/initials and before the status dot. The parent is `position: relative`, so children can be absolutely positioned. Note the wrapper carries `role="img"`, which makes its subtree presentational to assistive technology \u2014 slot content is visual only and will not be announced.\n'
|
|
1193
1601
|
}
|
|
1194
1602
|
],
|
|
1195
1603
|
a11y: [
|
|
1196
|
-
"role: img",
|
|
1197
|
-
|
|
1198
|
-
|
|
1604
|
+
"role: img (always set on the root span, including when only initials render)",
|
|
1605
|
+
'aria-label: Set from `alt`. Omitted entirely when `alt` is empty (the default), which leaves the `role="img"` element without an accessible name.',
|
|
1606
|
+
'initials: Marked `aria-hidden="true"` \u2014 the name comes from `alt`, not the visible text.',
|
|
1607
|
+
"image: Receives the `alt` prop as its native `alt` attribute.",
|
|
1608
|
+
"status_dot: Carries `aria-label` with the status value, but the element is a bare `<span>` with no role, so the label is not exposed to assistive technology. Convey status in text if it matters.",
|
|
1609
|
+
'slot_content: Not announced \u2014 the `role="img"` root makes descendant content presentational.'
|
|
1199
1610
|
],
|
|
1200
1611
|
behavior: [],
|
|
1201
1612
|
selection: {
|
|
@@ -1208,7 +1619,8 @@ var treeui_catalog_default = {
|
|
|
1208
1619
|
required: [],
|
|
1209
1620
|
notes: []
|
|
1210
1621
|
},
|
|
1211
|
-
recipes: []
|
|
1622
|
+
recipes: [],
|
|
1623
|
+
practices: []
|
|
1212
1624
|
},
|
|
1213
1625
|
{
|
|
1214
1626
|
name: "TBadge",
|
|
@@ -1233,7 +1645,8 @@ var treeui_catalog_default = {
|
|
|
1233
1645
|
"ghost",
|
|
1234
1646
|
"soft",
|
|
1235
1647
|
"danger"
|
|
1236
|
-
]
|
|
1648
|
+
],
|
|
1649
|
+
description: "Surface treatment. Selects which --tree-badge-<variant>-* colour variables the badge consumes; danger is a surface style, not a semantic guarantee \u2014 its red palette is replaced when tone is success, warning, or info."
|
|
1237
1650
|
},
|
|
1238
1651
|
{
|
|
1239
1652
|
name: "tone",
|
|
@@ -1246,7 +1659,7 @@ var treeui_catalog_default = {
|
|
|
1246
1659
|
"danger",
|
|
1247
1660
|
"info"
|
|
1248
1661
|
],
|
|
1249
|
-
description: "
|
|
1662
|
+
description: "Semantic palette. Re-maps the --tree-badge-* colour variables that the chosen variant consumes, so it recolours the badge without changing its surface treatment. neutral keeps the brand palette."
|
|
1250
1663
|
},
|
|
1251
1664
|
{
|
|
1252
1665
|
name: "size",
|
|
@@ -1256,7 +1669,8 @@ var treeui_catalog_default = {
|
|
|
1256
1669
|
"sm",
|
|
1257
1670
|
"md",
|
|
1258
1671
|
"lg"
|
|
1259
|
-
]
|
|
1672
|
+
],
|
|
1673
|
+
description: "Changes min-height and font-size only; inline padding is constant across sizes."
|
|
1260
1674
|
}
|
|
1261
1675
|
],
|
|
1262
1676
|
events: [],
|
|
@@ -1269,10 +1683,19 @@ var treeui_catalog_default = {
|
|
|
1269
1683
|
}
|
|
1270
1684
|
],
|
|
1271
1685
|
a11y: [
|
|
1686
|
+
"semantic_element: span",
|
|
1272
1687
|
"interactive_by_default: false",
|
|
1273
|
-
"icon_slot_marked_aria_hidden: true"
|
|
1688
|
+
"icon_slot_marked_aria_hidden: true",
|
|
1689
|
+
"tone_conveys_meaning_by_color_only: No role or aria state is set, so put the status word in the badge text rather than relying on tone alone."
|
|
1690
|
+
],
|
|
1691
|
+
behavior: [
|
|
1692
|
+
"always_applies_one_modifier_per_prop: true",
|
|
1693
|
+
"tone_remaps_variant_color_variables: true",
|
|
1694
|
+
"tone_overrides_variant_danger_palette: true",
|
|
1695
|
+
"tone_neutral_has_no_stylesheet_rule: true",
|
|
1696
|
+
"icon_wrapper_rendered_only_when_slot_filled: true",
|
|
1697
|
+
"icon_renders_before_default_slot: true"
|
|
1274
1698
|
],
|
|
1275
|
-
behavior: [],
|
|
1276
1699
|
selection: {
|
|
1277
1700
|
keywords: [],
|
|
1278
1701
|
useWhen: [],
|
|
@@ -1285,6 +1708,11 @@ var treeui_catalog_default = {
|
|
|
1285
1708
|
},
|
|
1286
1709
|
recipes: [
|
|
1287
1710
|
"pricing-section"
|
|
1711
|
+
],
|
|
1712
|
+
practices: [
|
|
1713
|
+
"predictable-api",
|
|
1714
|
+
"state-clarity",
|
|
1715
|
+
"token-driven"
|
|
1288
1716
|
]
|
|
1289
1717
|
},
|
|
1290
1718
|
{
|
|
@@ -1304,23 +1732,32 @@ var treeui_catalog_default = {
|
|
|
1304
1732
|
name: "separator",
|
|
1305
1733
|
type: "string",
|
|
1306
1734
|
default: "/",
|
|
1307
|
-
description: "Character or string
|
|
1735
|
+
description: "Character or string shown between items. Applied as the inline CSS custom property --tree-breadcrumb-separator on the <ol>, wrapped in single quotes, and drawn by the .t-breadcrumb__item:not(:last-child)::after pseudo-element \u2014 it never enters the DOM as text. A value containing a single quote or a backslash produces an invalid CSS value and the separator stops rendering."
|
|
1308
1736
|
}
|
|
1309
1737
|
],
|
|
1310
1738
|
events: [],
|
|
1311
1739
|
slots: [
|
|
1312
1740
|
{
|
|
1313
|
-
name: "default"
|
|
1741
|
+
name: "default",
|
|
1742
|
+
description: "Breadcrumb trail content, rendered inside the <ol class='t-breadcrumb__list'>. Expects TBreadcrumbItem children so each entry becomes an <li>. No scoped props."
|
|
1314
1743
|
}
|
|
1315
1744
|
],
|
|
1316
1745
|
a11y: [
|
|
1317
1746
|
"element: nav",
|
|
1318
1747
|
"aria_label: Breadcrumb",
|
|
1748
|
+
"aria_label_hardcoded_but_overridable_via_fallthrough_attrs: true",
|
|
1319
1749
|
"current_page_aria_current: page",
|
|
1320
1750
|
"uses_ol_for_ordered_list: true",
|
|
1321
1751
|
"interactive_by_default: false"
|
|
1322
1752
|
],
|
|
1323
|
-
behavior: [
|
|
1753
|
+
behavior: [
|
|
1754
|
+
"link_target_precedence: to + resolvable RouterLink, then href, then string to",
|
|
1755
|
+
"string_to_without_router_renders_native_anchor: true",
|
|
1756
|
+
"object_to_without_router_renders_current_span: true",
|
|
1757
|
+
"current_state_is_not_positional: true",
|
|
1758
|
+
"separator_rendered_by_css_pseudo_element: true",
|
|
1759
|
+
"separator_ignores_pointer_events: true"
|
|
1760
|
+
],
|
|
1324
1761
|
selection: {
|
|
1325
1762
|
keywords: [],
|
|
1326
1763
|
useWhen: [],
|
|
@@ -1334,7 +1771,8 @@ var treeui_catalog_default = {
|
|
|
1334
1771
|
"Use `to` when the app has vue-router and breadcrumb items should render RouterLink."
|
|
1335
1772
|
]
|
|
1336
1773
|
},
|
|
1337
|
-
recipes: []
|
|
1774
|
+
recipes: [],
|
|
1775
|
+
practices: []
|
|
1338
1776
|
},
|
|
1339
1777
|
{
|
|
1340
1778
|
name: "TButton",
|
|
@@ -1352,7 +1790,8 @@ var treeui_catalog_default = {
|
|
|
1352
1790
|
{
|
|
1353
1791
|
name: "as",
|
|
1354
1792
|
type: "string",
|
|
1355
|
-
default: "button"
|
|
1793
|
+
default: "button",
|
|
1794
|
+
note: "Root tag rendered through `<component :is>`. Any value other than `button` switches the component onto the non-native accessibility path (see `a11y`) and stops the `type` attribute from being rendered."
|
|
1356
1795
|
},
|
|
1357
1796
|
{
|
|
1358
1797
|
name: "variant",
|
|
@@ -1376,23 +1815,50 @@ var treeui_catalog_default = {
|
|
|
1376
1815
|
"sm",
|
|
1377
1816
|
"md",
|
|
1378
1817
|
"lg"
|
|
1379
|
-
]
|
|
1818
|
+
],
|
|
1819
|
+
note: "`t-button--md` is emitted but carries no CSS rule of its own \u2014 md is the base sizing, and only sm/lg override height, padding, and font size."
|
|
1380
1820
|
},
|
|
1381
1821
|
{
|
|
1382
1822
|
name: "disabled",
|
|
1383
1823
|
type: "boolean",
|
|
1384
|
-
default: "false"
|
|
1824
|
+
default: "false",
|
|
1825
|
+
note: 'Applied as the native `disabled` attribute only when `as` is `button`; for any other tag the component falls back to `aria-disabled="true"` plus `tabindex="-1"`. Clicks are blocked in both cases.'
|
|
1385
1826
|
},
|
|
1386
1827
|
{
|
|
1387
1828
|
name: "loading",
|
|
1388
1829
|
type: "boolean",
|
|
1389
1830
|
default: "false",
|
|
1390
|
-
note: "loading implies disabled behavior"
|
|
1831
|
+
note: "loading implies disabled behavior \u2014 the effective disabled state is `disabled || loading`, so `loading` on its own disables the button and applies `is-disabled`."
|
|
1832
|
+
},
|
|
1833
|
+
{
|
|
1834
|
+
name: "loadingLabel",
|
|
1835
|
+
type: "string",
|
|
1836
|
+
default: "Loading",
|
|
1837
|
+
note: "Accessible announcement while loading, forwarded to the nested TSpinner's `label`. The default is English because TreeUI ships no i18n layer \u2014 pass the active locale's string to localize it (see DECISIONS.md \u2192 Locale Data)."
|
|
1838
|
+
},
|
|
1839
|
+
{
|
|
1840
|
+
name: "hideIconWhileLoading",
|
|
1841
|
+
type: "boolean",
|
|
1842
|
+
default: "true",
|
|
1843
|
+
note: "While loading, the `icon` slot is not rendered so the spinner replaces the icon instead of rendering beside it. Set to `false` to restore the pre-0.19 behavior of showing both."
|
|
1844
|
+
},
|
|
1845
|
+
{
|
|
1846
|
+
name: "iconOnly",
|
|
1847
|
+
type: "boolean",
|
|
1848
|
+
default: "false",
|
|
1849
|
+
note: "Square, icon-only button \u2014 collapses the inline padding to a 1:1 control matching the size token and suppresses the `t-button__label` wrapper. Requires an accessible name via `label` (or `aria-label`), since the icon slot is aria-hidden."
|
|
1850
|
+
},
|
|
1851
|
+
{
|
|
1852
|
+
name: "label",
|
|
1853
|
+
type: "string",
|
|
1854
|
+
default: "undefined",
|
|
1855
|
+
note: "Accessible name, rendered as `aria-label`. Required whenever `iconOnly` is set; ignored for ordinary buttons that already have visible text."
|
|
1391
1856
|
},
|
|
1392
1857
|
{
|
|
1393
1858
|
name: "type",
|
|
1394
1859
|
type: "button | submit | reset",
|
|
1395
|
-
default: "button"
|
|
1860
|
+
default: "button",
|
|
1861
|
+
note: 'Only forwarded when `as` is `button`; for any other tag no `type` attribute is rendered. Set `type="submit"` for the submit control of an enclosing form.'
|
|
1396
1862
|
},
|
|
1397
1863
|
{
|
|
1398
1864
|
name: "block",
|
|
@@ -1404,12 +1870,14 @@ var treeui_catalog_default = {
|
|
|
1404
1870
|
name: "align",
|
|
1405
1871
|
type: "start | center | end",
|
|
1406
1872
|
default: "center",
|
|
1407
|
-
note: "Content alignment; only meaningful together with `block`. Use `start` for left-aligned icon+label menu rows."
|
|
1873
|
+
note: "Content alignment; only meaningful once the button is wider than its content, which in practice means together with `block`, since the base rule is `min-width: max-content`. Use `start` for left-aligned icon+label menu rows. The default `center` emits no modifier class \u2014 it is the base rule."
|
|
1408
1874
|
}
|
|
1409
1875
|
],
|
|
1410
1876
|
events: [
|
|
1411
1877
|
{
|
|
1412
|
-
name: "click"
|
|
1878
|
+
name: "click",
|
|
1879
|
+
description: "Emitted on activation. Suppressed while disabled or loading: the internal handler calls preventDefault() and stopPropagation() and returns without emitting.",
|
|
1880
|
+
payload: "[event: MouseEvent]"
|
|
1413
1881
|
}
|
|
1414
1882
|
],
|
|
1415
1883
|
slots: [
|
|
@@ -1422,13 +1890,22 @@ var treeui_catalog_default = {
|
|
|
1422
1890
|
],
|
|
1423
1891
|
a11y: [
|
|
1424
1892
|
"native_button_by_default: true",
|
|
1893
|
+
"native_disabled_attr_only_when_button: true",
|
|
1425
1894
|
"aria_busy_when_loading: true",
|
|
1426
1895
|
"aria_disabled_for_non_button: true",
|
|
1427
|
-
"tabindex_minus_one_when_non_button_disabled: true"
|
|
1896
|
+
"tabindex_minus_one_when_non_button_disabled: true",
|
|
1897
|
+
"icon_slot_marked_aria_hidden: true",
|
|
1898
|
+
"loading_spinner_is_announced: The nested TSpinner carries role=\"status\" and a visually hidden label, so the button's accessible name gains that text while loading. The text comes from `loadingLabel`, so it follows the app's locale.",
|
|
1899
|
+
"icon_only_requires_an_accessible_name: With `iconOnly` there is no visible text and the icon slot is aria-hidden, so the name must come from `label` or `aria-label`. This is a documented requirement, not a runtime assertion \u2014 the package ships ESM+CJS with no dev-only build define, so there is no dev-stripped warning.",
|
|
1900
|
+
"touch_targets: 44\xD744px minimum via the .t-button::after overlay",
|
|
1901
|
+
"focus_visible: box-shadow focus ring on the root element"
|
|
1428
1902
|
],
|
|
1429
1903
|
behavior: [
|
|
1430
1904
|
"blocks_click_when_disabled_or_loading: true",
|
|
1431
|
-
"renders_spinner_when_loading: true"
|
|
1905
|
+
"renders_spinner_when_loading: true",
|
|
1906
|
+
"spinner_replaces_the_icon_slot_while_loading: The spinner takes the icon's leading position, so by default the icon slot is withheld while loading and the order is spinner, label. Set `hideIconWhileLoading: false` for the older spinner, icon, label order.",
|
|
1907
|
+
"icon_slot_wrapper_rendered_only_when_filled: true",
|
|
1908
|
+
"default_slot_wrapped_in_label_element_unless_icon_only: true"
|
|
1432
1909
|
],
|
|
1433
1910
|
selection: {
|
|
1434
1911
|
keywords: [],
|
|
@@ -1443,6 +1920,10 @@ var treeui_catalog_default = {
|
|
|
1443
1920
|
recipes: [
|
|
1444
1921
|
"confirm-destructive-action",
|
|
1445
1922
|
"pricing-section"
|
|
1923
|
+
],
|
|
1924
|
+
practices: [
|
|
1925
|
+
"interaction-feedback",
|
|
1926
|
+
"predictable-api"
|
|
1446
1927
|
]
|
|
1447
1928
|
},
|
|
1448
1929
|
{
|
|
@@ -1452,7 +1933,7 @@ var treeui_catalog_default = {
|
|
|
1452
1933
|
kind: "layout",
|
|
1453
1934
|
category: "Data Display",
|
|
1454
1935
|
status: "available",
|
|
1455
|
-
purpose: "Surface container with optional header and footer slots.",
|
|
1936
|
+
purpose: "Surface container with optional header, actions, and footer slots.",
|
|
1456
1937
|
sourceFile: "packages/vue/src/components/TCard.vue",
|
|
1457
1938
|
storyFile: "apps/docs/src/stories/Card.stories.ts",
|
|
1458
1939
|
storyTitle: "Components/Data Display/Card",
|
|
@@ -1461,7 +1942,8 @@ var treeui_catalog_default = {
|
|
|
1461
1942
|
{
|
|
1462
1943
|
name: "as",
|
|
1463
1944
|
type: "string",
|
|
1464
|
-
default: "section"
|
|
1945
|
+
default: "section",
|
|
1946
|
+
description: 'Tag or component used for the polymorphic root, rendered through `<component :is="as">`. Change it to `article`, `aside`, `li`, or `div` when the default `section` element is wrong for the surrounding document structure. It only swaps the element \u2014 classes, slots, and layout are unchanged.\n'
|
|
1465
1947
|
},
|
|
1466
1948
|
{
|
|
1467
1949
|
name: "variant",
|
|
@@ -1477,37 +1959,44 @@ var treeui_catalog_default = {
|
|
|
1477
1959
|
name: "size",
|
|
1478
1960
|
type: "TSize",
|
|
1479
1961
|
default: "md",
|
|
1480
|
-
|
|
1481
|
-
"sm",
|
|
1482
|
-
"md",
|
|
1483
|
-
"lg"
|
|
1484
|
-
]
|
|
1962
|
+
description: "Padding scale only \u2014 it does not change typography, border, or radius. `sm` uses --tree-space-3, `md` --tree-space-4, `lg` --tree-space-5.\n"
|
|
1485
1963
|
},
|
|
1486
1964
|
{
|
|
1487
1965
|
name: "title",
|
|
1488
1966
|
type: "string",
|
|
1489
1967
|
default: "undefined",
|
|
1490
|
-
description: "Optional card heading
|
|
1968
|
+
description: "Optional card heading. Rendered as the fallback content of the `header` slot inside a `span.t-card__title`, so supplying `#header` replaces it entirely. Setting it also forces the header element to render. Because it is declared as a prop it is consumed by the component and never reaches the root element as the native HTML `title` tooltip attribute.\n"
|
|
1491
1969
|
}
|
|
1492
1970
|
],
|
|
1493
1971
|
events: [],
|
|
1494
1972
|
slots: [
|
|
1495
1973
|
{
|
|
1496
|
-
name: "header"
|
|
1974
|
+
name: "header",
|
|
1975
|
+
description: "Replaces the `title` fallback inside `header.t-card__header`. When this slot is supplied the `title` prop renders nothing. Receives no slot props.\n"
|
|
1497
1976
|
},
|
|
1498
1977
|
{
|
|
1499
|
-
name: "actions"
|
|
1978
|
+
name: "actions",
|
|
1979
|
+
description: "Trailing controls wrapped in `span.t-card__actions`, rendered as a sibling after the header content inside the same `header.t-card__header`. Supplying it is enough to render the header on its own, with no `title` and no `header` slot. Receives no slot props.\n"
|
|
1500
1980
|
},
|
|
1501
1981
|
{
|
|
1502
|
-
name: "default"
|
|
1982
|
+
name: "default",
|
|
1983
|
+
description: "Card body. Always rendered, wrapped in `div.t-card__body`. Receives no slot props.\n"
|
|
1503
1984
|
},
|
|
1504
1985
|
{
|
|
1505
|
-
name: "footer"
|
|
1986
|
+
name: "footer",
|
|
1987
|
+
description: "Renders `footer.t-card__footer` only when the slot is supplied; there is no `footer` prop fallback. Receives no slot props.\n"
|
|
1506
1988
|
}
|
|
1507
1989
|
],
|
|
1508
|
-
a11y: [
|
|
1990
|
+
a11y: [
|
|
1991
|
+
"root_role: None applied by the component \u2014 semantics come entirely from `as` (default `section`).",
|
|
1992
|
+
"title_is_not_a_heading: `title` renders a `span.t-card__title`, styled at heading size and weight but carrying no heading semantics, so it does not enter the document outline. When the card must be reachable by heading navigation, put a real `<h2>`/`<h3>` in the `header` slot instead of using the prop.",
|
|
1993
|
+
"unnamed_section_root: The default `section` root has no accessible name, so assistive tech exposes it as generic rather than as a region. The component sets no `inheritAttrs: false` and has a single root, so `aria-label` / `aria-labelledby` passed by the consumer fall through to that root when a named region is wanted."
|
|
1994
|
+
],
|
|
1509
1995
|
behavior: [
|
|
1510
1996
|
"body_wrapper_class: t-card__body",
|
|
1997
|
+
"header_render_condition: The `header.t-card__header` element renders when ANY of the `header` slot, a truthy `title` prop, or the `actions` slot is present. All three branches are independent \u2014 actions alone still produces a header.",
|
|
1998
|
+
"footer_render_condition: The `footer.t-card__footer` element renders only when the `footer` slot is supplied.",
|
|
1999
|
+
"slot_props: None. No slot on this component is scoped; all four are plain content slots.",
|
|
1511
2000
|
'variant_effects: {"outline":"Base surface with a default border. The styling baseline \u2014 the `t-card--outline` class is emitted but carries no CSS rule of its own.","soft":"Subtle tinted surface (bg-subtle), same border and shadow as outline.","inset":"Same tinted surface as soft, but with no shadow, so it reads as recessed inside another surface."}',
|
|
1512
2001
|
"note: No card variant inverts its surface, so nested content inherits the normal color tokens. For a high-emphasis card, use a brand-colored border rather than an inverted background."
|
|
1513
2002
|
],
|
|
@@ -1542,6 +2031,10 @@ var treeui_catalog_default = {
|
|
|
1542
2031
|
},
|
|
1543
2032
|
recipes: [
|
|
1544
2033
|
"chart-surface"
|
|
2034
|
+
],
|
|
2035
|
+
practices: [
|
|
2036
|
+
"predictable-api",
|
|
2037
|
+
"token-driven"
|
|
1545
2038
|
]
|
|
1546
2039
|
},
|
|
1547
2040
|
{
|
|
@@ -1571,13 +2064,13 @@ var treeui_catalog_default = {
|
|
|
1571
2064
|
name: "series",
|
|
1572
2065
|
type: "TChartSeries[]",
|
|
1573
2066
|
default: "[]",
|
|
1574
|
-
note: "Each item is { name: string; data: number[]; color?: string }."
|
|
2067
|
+
note: "Each item is { name: string; data: number[]; color?: string }. Series with an empty data array are dropped before rendering \u2014 they never reach the plot, legend, tooltip, or a11y table."
|
|
1575
2068
|
},
|
|
1576
2069
|
{
|
|
1577
2070
|
name: "labels",
|
|
1578
2071
|
type: "string[]",
|
|
1579
2072
|
default: "[]",
|
|
1580
|
-
note: "X-axis categories, aligned index-for-index to each series' data."
|
|
2073
|
+
note: "X-axis categories, aligned index-for-index to each series' data. Labels past the longest series are ignored; a missing label falls back to '#<n>' in the tooltip and to an empty header cell in the a11y table."
|
|
1581
2074
|
},
|
|
1582
2075
|
{
|
|
1583
2076
|
name: "height",
|
|
@@ -1589,80 +2082,91 @@ var treeui_catalog_default = {
|
|
|
1589
2082
|
name: "smooth",
|
|
1590
2083
|
type: "boolean",
|
|
1591
2084
|
default: "false",
|
|
1592
|
-
note: "Curved line/area."
|
|
2085
|
+
note: "Curved line/area; ignored for bar."
|
|
1593
2086
|
},
|
|
1594
2087
|
{
|
|
1595
2088
|
name: "stacked",
|
|
1596
2089
|
type: "boolean",
|
|
1597
2090
|
default: "false",
|
|
1598
|
-
note: "Stacks bar series; ignored for line/area. Negative values are clamped to 0 in stacked mode (grouped mode renders them)."
|
|
2091
|
+
note: "Stacks bar series; ignored for line/area. Negative values are clamped to 0 in stacked mode (grouped mode renders them below the baseline). The tooltip always reports the raw per-series values, not the cumulative stack."
|
|
1599
2092
|
},
|
|
1600
2093
|
{
|
|
1601
2094
|
name: "showGrid",
|
|
1602
2095
|
type: "boolean",
|
|
1603
|
-
default: "true"
|
|
2096
|
+
default: "true",
|
|
2097
|
+
note: "Horizontal gridlines at the y ticks. Independent of showYAxis, which controls the tick text."
|
|
1604
2098
|
},
|
|
1605
2099
|
{
|
|
1606
2100
|
name: "showLegend",
|
|
1607
|
-
type: "boolean",
|
|
1608
|
-
default: "auto (true when more than one series)"
|
|
2101
|
+
type: "boolean | undefined",
|
|
2102
|
+
default: "auto (true when more than one series)",
|
|
2103
|
+
note: "The legend is suppressed whenever there is no data, even when set to true."
|
|
1609
2104
|
},
|
|
1610
2105
|
{
|
|
1611
2106
|
name: "showXAxis",
|
|
1612
2107
|
type: "boolean",
|
|
1613
|
-
default: "true"
|
|
2108
|
+
default: "true",
|
|
2109
|
+
note: "When false the category labels are skipped and the bottom margin collapses from 28px to 10px."
|
|
1614
2110
|
},
|
|
1615
2111
|
{
|
|
1616
2112
|
name: "showYAxis",
|
|
1617
2113
|
type: "boolean",
|
|
1618
|
-
default: "true"
|
|
2114
|
+
default: "true",
|
|
2115
|
+
note: "When false the tick text is skipped and the left margin collapses from 44px to 10px. Gridlines are unaffected."
|
|
1619
2116
|
},
|
|
1620
2117
|
{
|
|
1621
2118
|
name: "showTooltip",
|
|
1622
2119
|
type: "boolean",
|
|
1623
|
-
default: "true"
|
|
2120
|
+
default: "true",
|
|
2121
|
+
note: "Gates hover tracking as a whole: the crosshair, the tooltip panel, and the point-click event all stop when false."
|
|
1624
2122
|
},
|
|
1625
2123
|
{
|
|
1626
2124
|
name: "showPoints",
|
|
1627
2125
|
type: "boolean",
|
|
1628
2126
|
default: "false",
|
|
1629
|
-
note: "Always draw markers on line/area points."
|
|
2127
|
+
note: "Always draw markers on line/area points; ignored for bar."
|
|
1630
2128
|
},
|
|
1631
2129
|
{
|
|
1632
2130
|
name: "yTicks",
|
|
1633
2131
|
type: "number",
|
|
1634
|
-
default: "5"
|
|
2132
|
+
default: "5",
|
|
2133
|
+
note: "Target tick count handed to niceScale \u2014 the rendered count may differ once the bounds are rounded."
|
|
1635
2134
|
},
|
|
1636
2135
|
{
|
|
1637
2136
|
name: "valueFormat",
|
|
1638
2137
|
type: "(value: number) => string",
|
|
1639
|
-
default: "locale integers for |value| >= 1000"
|
|
2138
|
+
default: "locale integers for |value| >= 1000",
|
|
2139
|
+
note: "Applies to y-axis ticks, tooltip values, and the a11y table cells."
|
|
1640
2140
|
},
|
|
1641
2141
|
{
|
|
1642
2142
|
name: "minY",
|
|
1643
2143
|
type: "number",
|
|
1644
|
-
default: "auto"
|
|
2144
|
+
default: "auto (min(0, data min) for bar/area, data min for line)",
|
|
2145
|
+
note: "A hint, not a hard bound: niceScale rounds the low end down, so the rendered domain can start below it."
|
|
1645
2146
|
},
|
|
1646
2147
|
{
|
|
1647
2148
|
name: "maxY",
|
|
1648
2149
|
type: "number",
|
|
1649
|
-
default: "auto"
|
|
2150
|
+
default: "auto",
|
|
2151
|
+
note: "A hint, not a hard bound: niceScale rounds the high end up, so the rendered domain can extend above it."
|
|
1650
2152
|
},
|
|
1651
2153
|
{
|
|
1652
2154
|
name: "animated",
|
|
1653
2155
|
type: "boolean",
|
|
1654
2156
|
default: "true",
|
|
1655
|
-
note: "Draw-in animation; disabled under prefers-reduced-motion."
|
|
2157
|
+
note: "Draw-in animation via the is-animated root class; disabled under prefers-reduced-motion."
|
|
1656
2158
|
},
|
|
1657
2159
|
{
|
|
1658
2160
|
name: "loading",
|
|
1659
2161
|
type: "boolean",
|
|
1660
|
-
default: "false"
|
|
2162
|
+
default: "false",
|
|
2163
|
+
note: "Replaces the plot with five pulsing skeleton bars and adds the is-loading root class. Takes precedence over the empty state; the legend still renders when data is present."
|
|
1661
2164
|
},
|
|
1662
2165
|
{
|
|
1663
2166
|
name: "ariaLabel",
|
|
1664
2167
|
type: "string",
|
|
1665
|
-
default: "auto-generated summary"
|
|
2168
|
+
default: "auto-generated summary ('<type> chart with <n> series')",
|
|
2169
|
+
note: "Rendered as the <caption> of the visually-hidden data table \u2014 it is not applied as an aria-label attribute on the root."
|
|
1666
2170
|
}
|
|
1667
2171
|
],
|
|
1668
2172
|
events: [
|
|
@@ -1684,14 +2188,19 @@ var treeui_catalog_default = {
|
|
|
1684
2188
|
],
|
|
1685
2189
|
a11y: [
|
|
1686
2190
|
"SVG is aria-hidden; a visually-hidden <table> mirrors the series data for assistive tech.",
|
|
2191
|
+
"The table's <caption> carries ariaLabel (or the auto-generated summary); the root div itself has no role or accessible name.",
|
|
1687
2192
|
"Legend defaults on for multiple series so identity is not color-only.",
|
|
1688
|
-
"Provide a meaningful ariaLabel describing what the chart shows."
|
|
2193
|
+
"Provide a meaningful ariaLabel describing what the chart shows.",
|
|
2194
|
+
"point-click has no keyboard equivalent \u2014 do not make it the only way to reach a behavior."
|
|
1689
2195
|
],
|
|
1690
2196
|
behavior: [
|
|
1691
|
-
"colors_auto_assign_from_chart_palette: --tree-color-chart-1..8, cycling; per-series color overrides",
|
|
1692
|
-
"
|
|
1693
|
-
"
|
|
1694
|
-
"hover_shows_crosshair_and_tooltip: true"
|
|
2197
|
+
"colors_auto_assign_from_chart_palette: --tree-color-chart-1..8, cycling by series index; per-series color overrides",
|
|
2198
|
+
"zero_baseline_for_bar_and_area: the y domain is extended to include 0 for bar and area; line uses the data extent. minY overrides it.",
|
|
2199
|
+
"y_domain_uses_nice_ticks: every type runs through niceScale, which rounds the min down and the max up to round numbers",
|
|
2200
|
+
"hover_shows_crosshair_and_tooltip: only while showTooltip is true",
|
|
2201
|
+
"width_measured_with_resize_observer: falls back to 640px until the canvas is mounted and measured",
|
|
2202
|
+
"x_labels_decimate_when_crowded: keeps every max(2, floor(innerWidth / 52))-th label and hides the rest; the last category is always kept",
|
|
2203
|
+
"empty_state_when_no_series_has_data: true"
|
|
1695
2204
|
],
|
|
1696
2205
|
selection: {
|
|
1697
2206
|
keywords: [
|
|
@@ -1738,6 +2247,9 @@ var treeui_catalog_default = {
|
|
|
1738
2247
|
recipes: [
|
|
1739
2248
|
"chart-surface",
|
|
1740
2249
|
"metric-dashboard"
|
|
2250
|
+
],
|
|
2251
|
+
practices: [
|
|
2252
|
+
"token-driven"
|
|
1741
2253
|
]
|
|
1742
2254
|
},
|
|
1743
2255
|
{
|
|
@@ -1756,7 +2268,8 @@ var treeui_catalog_default = {
|
|
|
1756
2268
|
{
|
|
1757
2269
|
name: "modelValue",
|
|
1758
2270
|
type: "boolean",
|
|
1759
|
-
default: "false"
|
|
2271
|
+
default: "false",
|
|
2272
|
+
description: "Checked state. Fully controlled \u2014 the component holds no internal state and never mutates this prop; it emits update:modelValue and the parent must write the value back.\n"
|
|
1760
2273
|
},
|
|
1761
2274
|
{
|
|
1762
2275
|
name: "size",
|
|
@@ -1766,44 +2279,60 @@ var treeui_catalog_default = {
|
|
|
1766
2279
|
"sm",
|
|
1767
2280
|
"md",
|
|
1768
2281
|
"lg"
|
|
1769
|
-
]
|
|
2282
|
+
],
|
|
2283
|
+
description: "Control and label scale. Always rendered as a t-checkbox--<size> modifier."
|
|
1770
2284
|
},
|
|
1771
2285
|
{
|
|
1772
2286
|
name: "disabled",
|
|
1773
2287
|
type: "boolean",
|
|
1774
|
-
default: "false"
|
|
2288
|
+
default: "false",
|
|
2289
|
+
description: "Sets the native disabled attribute on the input and adds is-disabled to the root. No aria-disabled is emitted \u2014 the native attribute carries the state.\n"
|
|
1775
2290
|
},
|
|
1776
2291
|
{
|
|
1777
2292
|
name: "indeterminate",
|
|
1778
2293
|
type: "boolean",
|
|
1779
|
-
default: "false"
|
|
2294
|
+
default: "false",
|
|
2295
|
+
description: `Mixed state. Renders the dash icon and sets aria-checked="mixed", taking precedence over modelValue for both. Synced to the input's native indeterminate DOM property.
|
|
2296
|
+
`
|
|
1780
2297
|
},
|
|
1781
2298
|
{
|
|
1782
2299
|
name: "invalid",
|
|
1783
2300
|
type: "boolean",
|
|
1784
|
-
default: "false"
|
|
2301
|
+
default: "false",
|
|
2302
|
+
description: 'Adds is-invalid to the root and aria-invalid="true" to the input. When false the aria-invalid attribute is omitted entirely, not set to "false".\n'
|
|
1785
2303
|
}
|
|
1786
2304
|
],
|
|
1787
2305
|
events: [
|
|
1788
2306
|
{
|
|
1789
|
-
name: "update:modelValue"
|
|
2307
|
+
name: "update:modelValue",
|
|
2308
|
+
description: "Emitted on the native input's change event. The payload is always the negation of the current modelValue prop, not the DOM checked state. Enables v-model binding.\n",
|
|
2309
|
+
payload: "[value: boolean]"
|
|
1790
2310
|
}
|
|
1791
2311
|
],
|
|
1792
2312
|
slots: [
|
|
1793
2313
|
{
|
|
1794
|
-
name: "default"
|
|
2314
|
+
name: "default",
|
|
2315
|
+
description: 'Label content, wrapped in <span class="t-checkbox__label">. Rendered only when the slot is supplied (v-if="$slots.default"). The root element is a <label> that wraps the input, so slot text labels the control implicitly \u2014 no for/id pairing is needed.\n'
|
|
1795
2316
|
}
|
|
1796
2317
|
],
|
|
1797
2318
|
a11y: [
|
|
1798
2319
|
"role: native_checkbox",
|
|
2320
|
+
"accessible_name: From the default slot; absent when the slot is omitted \u2014 supply aria-label or aria-labelledby",
|
|
2321
|
+
"aria_checked_explicitly_bound: 'mixed' when indeterminate, otherwise the modelValue boolean",
|
|
1799
2322
|
"aria_checked_mixed_when_indeterminate: true",
|
|
1800
2323
|
"aria_invalid_when_invalid: true",
|
|
2324
|
+
"native_indeterminate_property_synced: true",
|
|
2325
|
+
"disabled_uses_native_attribute: true",
|
|
1801
2326
|
"focus_visible_on_control: true",
|
|
2327
|
+
"input_is_visually_hidden_but_focusable: clip-rect hidden input keeps native semantics and tab order; the focus ring is drawn on t-checkbox__control",
|
|
1802
2328
|
"clickable_target_44x44: true"
|
|
1803
2329
|
],
|
|
1804
2330
|
behavior: [
|
|
1805
2331
|
"update_payload_type: boolean",
|
|
2332
|
+
"controlled_only: No internal state; the checkbox does not change appearance until the parent updates modelValue",
|
|
2333
|
+
"indeterminate_precedence: indeterminate wins over modelValue for the rendered icon and for aria-checked; is-checked and is-indeterminate can both be present at once",
|
|
1806
2334
|
"indeterminate_clears_on_user_toggle: false",
|
|
2335
|
+
"indeterminate_is_parent_owned: The component never clears indeterminate \u2014 set it to false yourself when handling update:modelValue",
|
|
1807
2336
|
"label_click_toggles_checkbox: true"
|
|
1808
2337
|
],
|
|
1809
2338
|
selection: {
|
|
@@ -1836,7 +2365,10 @@ var treeui_catalog_default = {
|
|
|
1836
2365
|
required: [],
|
|
1837
2366
|
notes: []
|
|
1838
2367
|
},
|
|
1839
|
-
recipes: []
|
|
2368
|
+
recipes: [],
|
|
2369
|
+
practices: [
|
|
2370
|
+
"interaction-feedback"
|
|
2371
|
+
]
|
|
1840
2372
|
},
|
|
1841
2373
|
{
|
|
1842
2374
|
name: "TColorSwatch",
|
|
@@ -1855,19 +2387,19 @@ var treeui_catalog_default = {
|
|
|
1855
2387
|
name: "modelValue",
|
|
1856
2388
|
type: "string",
|
|
1857
2389
|
default: "undefined",
|
|
1858
|
-
note: "Selected colour as a hex string.
|
|
2390
|
+
note: "Selected colour as a hex string. Matched against `options[].value` by case-insensitive exact string comparison, so `#0969DA` matches `#0969da` but `#fff` never matches `#ffffff`. A value matching no preset leaves every swatch unselected and is still written to the custom input."
|
|
1859
2391
|
},
|
|
1860
2392
|
{
|
|
1861
2393
|
name: "options",
|
|
1862
2394
|
type: "TColorSwatchOption[]",
|
|
1863
2395
|
default: "[]",
|
|
1864
|
-
note: "Preset swatches, each `{ label, value }`. `label`
|
|
2396
|
+
note: "Preset swatches, each `{ label, value }`. `value` is applied raw as the button `background`, so any CSS colour renders, but keep it `#rrggbb` so matching and the custom input agree. `label` is the button's only accessible name \u2014 the button renders no text content. An empty array renders an empty group (only the custom input, when enabled)."
|
|
1865
2397
|
},
|
|
1866
2398
|
{
|
|
1867
2399
|
name: "allowCustom",
|
|
1868
2400
|
type: "boolean",
|
|
1869
2401
|
default: "false",
|
|
1870
|
-
note: 'Appends a native `<input type="color">` for values outside the
|
|
2402
|
+
note: 'Appends a native `<input type="color">` after the presets for values outside them. When false the input is not rendered at all and `customLabel` has no effect.'
|
|
1871
2403
|
},
|
|
1872
2404
|
{
|
|
1873
2405
|
name: "size",
|
|
@@ -1877,23 +2409,26 @@ var treeui_catalog_default = {
|
|
|
1877
2409
|
"sm",
|
|
1878
2410
|
"md",
|
|
1879
2411
|
"lg"
|
|
1880
|
-
]
|
|
2412
|
+
],
|
|
2413
|
+
note: "Drives `--tree-color-swatch-size` (sm 1.5rem, md 1.75rem, lg 2rem). Swatches are square; the custom input is one `--tree-space-2` wider."
|
|
1881
2414
|
},
|
|
1882
2415
|
{
|
|
1883
2416
|
name: "label",
|
|
1884
2417
|
type: "string",
|
|
1885
2418
|
default: "Color",
|
|
1886
|
-
note: 'Accessible label for the swatch group (`role="group"`).'
|
|
2419
|
+
note: 'Accessible label for the swatch group (`role="group"`). Rendered as `aria-label` on the root, so an `aria-label` passed by the consumer falls through to the same element and overrides it.'
|
|
1887
2420
|
},
|
|
1888
2421
|
{
|
|
1889
2422
|
name: "customLabel",
|
|
1890
2423
|
type: "string",
|
|
1891
|
-
default: "Custom color"
|
|
2424
|
+
default: "Custom color",
|
|
2425
|
+
note: "Accessible label (`aria-label`) for the native colour input, and its only accessible name. Applies only when `allowCustom` is set."
|
|
1892
2426
|
},
|
|
1893
2427
|
{
|
|
1894
2428
|
name: "disabled",
|
|
1895
2429
|
type: "boolean",
|
|
1896
|
-
default: "false"
|
|
2430
|
+
default: "false",
|
|
2431
|
+
note: "Sets the native `disabled` attribute on every preset button and on the custom input, so the group stops emitting and drops out of the Tab order. Not reflected on the wrapper, and there is no `is-disabled` class."
|
|
1897
2432
|
}
|
|
1898
2433
|
],
|
|
1899
2434
|
events: [
|
|
@@ -1903,14 +2438,21 @@ var treeui_catalog_default = {
|
|
|
1903
2438
|
],
|
|
1904
2439
|
slots: [],
|
|
1905
2440
|
a11y: [
|
|
1906
|
-
'Wrapper is `role="group"` labelled by `label`.',
|
|
1907
|
-
|
|
1908
|
-
"Selection is conveyed by an outline (not colour alone), since the swatch's own colour is the content."
|
|
2441
|
+
'Wrapper is `role="group"` labelled by `label` via `aria-label`.',
|
|
2442
|
+
'Each swatch is a native `<button type="button">` with `aria-pressed` reflecting selection and `aria-label` from the option label; it has no text content, so an option without a `label` is unnamed.',
|
|
2443
|
+
"Selection is conveyed by an outline (not colour alone), since the swatch's own colour is the content.",
|
|
2444
|
+
'The custom input is a native `<input type="color">` named only by `customLabel`.',
|
|
2445
|
+
"No roving focus and no arrow-key navigation \u2014 every swatch and the custom input is its own Tab stop."
|
|
1909
2446
|
],
|
|
1910
2447
|
behavior: [
|
|
2448
|
+
"update_payload_type: string",
|
|
1911
2449
|
"emits_on_preset_click: true",
|
|
1912
2450
|
"emits_on_custom_input: true",
|
|
1913
|
-
"blocks_interaction_when_disabled: true"
|
|
2451
|
+
"blocks_interaction_when_disabled: true",
|
|
2452
|
+
"selection_match_is_case_insensitive: true",
|
|
2453
|
+
"custom_input_rendered_only_when_allow_custom: true",
|
|
2454
|
+
"custom_input_emits_on_input_not_change: true",
|
|
2455
|
+
"fully_controlled_no_internal_selection_state: true"
|
|
1914
2456
|
],
|
|
1915
2457
|
selection: {
|
|
1916
2458
|
keywords: [],
|
|
@@ -1922,7 +2464,8 @@ var treeui_catalog_default = {
|
|
|
1922
2464
|
required: [],
|
|
1923
2465
|
notes: []
|
|
1924
2466
|
},
|
|
1925
|
-
recipes: []
|
|
2467
|
+
recipes: [],
|
|
2468
|
+
practices: []
|
|
1926
2469
|
},
|
|
1927
2470
|
{
|
|
1928
2471
|
name: "TCombobox",
|
|
@@ -1940,7 +2483,8 @@ var treeui_catalog_default = {
|
|
|
1940
2483
|
{
|
|
1941
2484
|
name: "modelValue",
|
|
1942
2485
|
type: "string",
|
|
1943
|
-
default: ""
|
|
2486
|
+
default: "",
|
|
2487
|
+
note: "The SELECTED option value, never the text in the input. The input renders an internal `query` string that is re-synced from the selected option's label whenever the listbox is closed. A `modelValue` with no matching entry in `options` resolves to an empty label."
|
|
1944
2488
|
},
|
|
1945
2489
|
{
|
|
1946
2490
|
name: "options",
|
|
@@ -1951,12 +2495,14 @@ var treeui_catalog_default = {
|
|
|
1951
2495
|
{
|
|
1952
2496
|
name: "open",
|
|
1953
2497
|
type: "boolean",
|
|
1954
|
-
default: "undefined"
|
|
2498
|
+
default: "undefined",
|
|
2499
|
+
note: "Controlled open state. Once a boolean is passed the component stops tracking open state internally \u2014 it only emits update:open / open-change and the consumer MUST write the value back, or the listbox never opens."
|
|
1955
2500
|
},
|
|
1956
2501
|
{
|
|
1957
2502
|
name: "defaultOpen",
|
|
1958
2503
|
type: "boolean",
|
|
1959
|
-
default: "false"
|
|
2504
|
+
default: "false",
|
|
2505
|
+
note: "Uncontrolled initial open state, read once on mount. Later changes to it are ignored."
|
|
1960
2506
|
},
|
|
1961
2507
|
{
|
|
1962
2508
|
name: "size",
|
|
@@ -1966,17 +2512,20 @@ var treeui_catalog_default = {
|
|
|
1966
2512
|
"sm",
|
|
1967
2513
|
"md",
|
|
1968
2514
|
"lg"
|
|
1969
|
-
]
|
|
2515
|
+
],
|
|
2516
|
+
note: "Sizes the control only. `md` has no CSS rule of its own \u2014 it is the base `.t-combobox__control` styling."
|
|
1970
2517
|
},
|
|
1971
2518
|
{
|
|
1972
2519
|
name: "disabled",
|
|
1973
2520
|
type: "boolean",
|
|
1974
|
-
default: "false"
|
|
2521
|
+
default: "false",
|
|
2522
|
+
note: 'Sets the native `disabled` attribute on the input, adds `is-disabled` to the root, and suppresses the listbox entirely (`v-if="isOpen && !disabled"`) \u2014 even while `open` is true. Also short-circuits opening, typing side effects, and keydown handling.'
|
|
1975
2523
|
},
|
|
1976
2524
|
{
|
|
1977
2525
|
name: "loading",
|
|
1978
2526
|
type: "boolean",
|
|
1979
|
-
default: "false"
|
|
2527
|
+
default: "false",
|
|
2528
|
+
note: 'Presentational only. Replaces the chevron indicator with `<TSpinner size="sm" label="Loading" />` and sets aria-busy; it never blocks typing, opening, filtering, or selection.'
|
|
1980
2529
|
},
|
|
1981
2530
|
{
|
|
1982
2531
|
name: "invalid",
|
|
@@ -1991,56 +2540,102 @@ var treeui_catalog_default = {
|
|
|
1991
2540
|
{
|
|
1992
2541
|
name: "emptyText",
|
|
1993
2542
|
type: "string",
|
|
1994
|
-
default: "No results found."
|
|
2543
|
+
default: "No results found.",
|
|
2544
|
+
note: "Fallback content of the `empty` slot \u2014 supplying that slot shadows this prop entirely."
|
|
1995
2545
|
}
|
|
1996
2546
|
],
|
|
1997
2547
|
events: [
|
|
1998
2548
|
{
|
|
1999
|
-
name: "update:modelValue"
|
|
2549
|
+
name: "update:modelValue",
|
|
2550
|
+
description: 'Emitted with the chosen option\'s `value` when an option is selected, and with `""` when the listbox closes while the input text is blank and a value was set (the clear-by-erasing path).',
|
|
2551
|
+
payload: '["string"]'
|
|
2000
2552
|
},
|
|
2001
2553
|
{
|
|
2002
|
-
name: "update:open"
|
|
2554
|
+
name: "update:open",
|
|
2555
|
+
description: "Emitted whenever the open state changes. Deduped \u2014 no emit when the next value equals the current one.",
|
|
2556
|
+
payload: '["boolean"]'
|
|
2003
2557
|
},
|
|
2004
2558
|
{
|
|
2005
|
-
name: "open-change"
|
|
2559
|
+
name: "open-change",
|
|
2560
|
+
description: "Emitted immediately after `update:open`, with the same payload. Alias for consumers that do not use v-model:open.",
|
|
2561
|
+
payload: '["boolean"]'
|
|
2006
2562
|
},
|
|
2007
2563
|
{
|
|
2008
|
-
name: "input-change"
|
|
2564
|
+
name: "input-change",
|
|
2565
|
+
description: "Emitted on every keystroke with the raw, untrimmed input text \u2014 the same string the `empty` slot receives as `query`. This is the only hook for server-side / async filtering; it does not replace or disable the built-in local filtering, so an async consumer must feed results back through `options`.",
|
|
2566
|
+
payload: '["string"]'
|
|
2009
2567
|
}
|
|
2010
2568
|
],
|
|
2011
2569
|
slots: [
|
|
2012
2570
|
{
|
|
2013
|
-
name: "prefix"
|
|
2571
|
+
name: "prefix",
|
|
2572
|
+
description: 'Leading content inside `.t-combobox__control`, before the input. Rendered only when the slot is supplied, wrapped in `<span class="t-combobox__slot t-combobox__slot--prefix">`. No scoped props.'
|
|
2014
2573
|
},
|
|
2015
2574
|
{
|
|
2016
|
-
name: "option"
|
|
2575
|
+
name: "option",
|
|
2576
|
+
description: 'Replaces the default option body (label, description, and the selected check icon). Renders INSIDE the row\'s `<li role="option">`, which owns the click and mouseenter handlers, so it must contain only presentational content. `selected` is `option.value === modelValue`; `active` is the keyboard-highlighted row, which is NOT DOM focus \u2014 focus stays on the input at all times.\n'
|
|
2017
2577
|
},
|
|
2018
2578
|
{
|
|
2019
|
-
name: "empty"
|
|
2579
|
+
name: "empty",
|
|
2580
|
+
description: 'Replaces `emptyText` inside `<li class="t-combobox__empty">` when the filter matches no option. `query` is the current raw input text, untrimmed and uncased. Passing both this slot and `emptyText` renders only the slot.'
|
|
2020
2581
|
}
|
|
2021
2582
|
],
|
|
2022
2583
|
a11y: [
|
|
2023
2584
|
"role: combobox",
|
|
2585
|
+
"combobox_element: input",
|
|
2586
|
+
"accessible_name: None is generated \u2014 there is no label element and no default slot. Pass aria-label or aria-labelledby (which also names the listbox), or pass `id` and wrap in TFormField with a matching `html-for`; TFormField does not link the label on its own.",
|
|
2024
2587
|
"trigger_aria_haspopup: listbox",
|
|
2025
2588
|
"trigger_aria_expanded: true",
|
|
2589
|
+
"trigger_aria_controls_when_open: true",
|
|
2026
2590
|
"aria_autocomplete: list",
|
|
2027
2591
|
"aria_activedescendant_on_active_option: true",
|
|
2592
|
+
"aria_activedescendant_cleared_while_closed: true",
|
|
2028
2593
|
"aria_invalid_when_invalid: true",
|
|
2029
2594
|
"aria_busy_when_loading: true",
|
|
2595
|
+
"listbox_role: listbox",
|
|
2596
|
+
"option_role: option",
|
|
2597
|
+
"listbox_mirrors_aria_label_and_aria_labelledby: true",
|
|
2030
2598
|
"aria_selected_on_options: true",
|
|
2031
2599
|
"aria_disabled_on_disabled_options: true",
|
|
2600
|
+
"focus_stays_on_the_input_options_are_never_focused: true",
|
|
2032
2601
|
"keyboard_arrow_navigation: true",
|
|
2602
|
+
"arrow_navigation_does_not_wrap_at_the_ends: true",
|
|
2603
|
+
"arrow_navigation_skips_disabled_options: true",
|
|
2033
2604
|
"escape_closes_and_restores_previous_selection: true",
|
|
2605
|
+
"escape_is_ignored_while_closed: true",
|
|
2034
2606
|
"enter_selects_active_option: true",
|
|
2607
|
+
"tab_closes_and_restores_previous_selection: true",
|
|
2035
2608
|
"home_end_navigation: true"
|
|
2036
2609
|
],
|
|
2037
2610
|
behavior: [
|
|
2038
2611
|
"update_payload_type: string",
|
|
2612
|
+
"input_text_is_internal_state_not_model_value: true",
|
|
2039
2613
|
"local_filtering_by_label_description_and_keywords: true",
|
|
2614
|
+
"filtering_is_case_insensitive_substring_on_a_trimmed_query: true",
|
|
2615
|
+
"empty_query_shows_all_options: true",
|
|
2616
|
+
"input_change_emits_the_raw_query_for_async_filtering: true",
|
|
2617
|
+
"async_results_are_fed_back_through_the_options_prop: true",
|
|
2040
2618
|
"loading_does_not_disable_by_itself: true",
|
|
2619
|
+
"spinner_replaces_the_chevron_when_loading: true",
|
|
2620
|
+
"chevron_rotates_when_open: true",
|
|
2621
|
+
"check_icon_on_selected_option: true",
|
|
2622
|
+
"focus_opens_the_listbox: true",
|
|
2623
|
+
"click_on_input_opens_the_listbox: true",
|
|
2624
|
+
"typing_opens_the_listbox: true",
|
|
2625
|
+
"arrow_down_opens_the_listbox_with_the_first_enabled_option_active: true",
|
|
2626
|
+
"arrow_up_opens_the_listbox_with_the_last_enabled_option_active: true",
|
|
2627
|
+
"active_option_defaults_to_the_current_selection_when_it_is_in_the_filtered_list: true",
|
|
2628
|
+
"disabled_options_cannot_be_activated_selected_or_hovered: true",
|
|
2629
|
+
"selecting_an_option_sets_the_input_text_to_its_label_and_closes_without_restoring: true",
|
|
2041
2630
|
"outside_click_closes_dropdown: true",
|
|
2631
|
+
"outside_click_is_detected_on_pointerdown_on_document: true",
|
|
2042
2632
|
"query_clears_selection_when_closed_empty: true",
|
|
2043
|
-
"selected_value_restores_when_search_is_abandoned: true"
|
|
2633
|
+
"selected_value_restores_when_search_is_abandoned: true",
|
|
2634
|
+
"external_model_value_and_options_changes_resync_the_input_text_only_while_closed: true",
|
|
2635
|
+
"active_option_is_revalidated_when_the_filtered_list_changes: true",
|
|
2636
|
+
"open_state_emits_are_deduped: true",
|
|
2637
|
+
"listbox_is_not_rendered_while_disabled: true",
|
|
2638
|
+
"listbox_renders_in_flow_with_no_portal_and_no_flip_positioning: true"
|
|
2044
2639
|
],
|
|
2045
2640
|
selection: {
|
|
2046
2641
|
keywords: [
|
|
@@ -2073,7 +2668,8 @@ var treeui_catalog_default = {
|
|
|
2073
2668
|
"Pass `options` as labeled items and keep labels human-readable because search matches visible fields."
|
|
2074
2669
|
]
|
|
2075
2670
|
},
|
|
2076
|
-
recipes: []
|
|
2671
|
+
recipes: [],
|
|
2672
|
+
practices: []
|
|
2077
2673
|
},
|
|
2078
2674
|
{
|
|
2079
2675
|
name: "TConfirmDialog",
|
|
@@ -2096,12 +2692,14 @@ var treeui_catalog_default = {
|
|
|
2096
2692
|
{
|
|
2097
2693
|
name: "defaultOpen",
|
|
2098
2694
|
type: "boolean",
|
|
2099
|
-
default: "false"
|
|
2695
|
+
default: "false",
|
|
2696
|
+
note: "Uncontrolled initial state. Read once on setup \u2014 later changes are ignored. Only meaningful when `open` is left undefined."
|
|
2100
2697
|
},
|
|
2101
2698
|
{
|
|
2102
2699
|
name: "disabled",
|
|
2103
2700
|
type: "boolean",
|
|
2104
|
-
default: "false"
|
|
2701
|
+
default: "false",
|
|
2702
|
+
note: "Only blocks opening from the `trigger` slot (the trigger wrapper gets `aria-disabled` and its click is swallowed). It does NOT block a programmatic open through `open`/`defaultOpen`, and it does not disable the confirm/cancel buttons \u2014 use `confirmDisabled`/`cancelDisabled` for those."
|
|
2105
2703
|
},
|
|
2106
2704
|
{
|
|
2107
2705
|
name: "size",
|
|
@@ -2111,47 +2709,63 @@ var treeui_catalog_default = {
|
|
|
2111
2709
|
"sm",
|
|
2112
2710
|
"md",
|
|
2113
2711
|
"lg"
|
|
2114
|
-
]
|
|
2712
|
+
],
|
|
2713
|
+
note: "Forwarded to TModal and applied as `t-modal__surface--<size>` \u2014 it sizes the dialog surface, not the confirm-dialog block, and it does not size the default footer buttons (those are always TButton `md`)."
|
|
2115
2714
|
},
|
|
2116
2715
|
{
|
|
2117
2716
|
name: "title",
|
|
2118
2717
|
type: "string",
|
|
2119
|
-
default: ""
|
|
2718
|
+
default: "",
|
|
2719
|
+
note: "Rendered by TModal as `t-modal__title` and referenced by `aria-labelledby`. TConfirmDialog does not expose TModal's `header` slot, so an empty title leaves the dialog without an accessible name."
|
|
2120
2720
|
},
|
|
2121
2721
|
{
|
|
2122
2722
|
name: "description",
|
|
2123
2723
|
type: "string",
|
|
2124
|
-
default: ""
|
|
2724
|
+
default: "",
|
|
2725
|
+
note: "Rendered by TModal as `t-modal__description` and referenced by `aria-describedby`. The default slot body is NOT part of the accessible description."
|
|
2125
2726
|
},
|
|
2126
2727
|
{
|
|
2127
2728
|
name: "confirmLabel",
|
|
2128
2729
|
type: "string",
|
|
2129
|
-
default: "Confirm"
|
|
2730
|
+
default: "Confirm",
|
|
2731
|
+
note: "Ignored when the `actions` slot is supplied."
|
|
2130
2732
|
},
|
|
2131
2733
|
{
|
|
2132
2734
|
name: "cancelLabel",
|
|
2133
2735
|
type: "string",
|
|
2134
|
-
default: "Cancel"
|
|
2736
|
+
default: "Cancel",
|
|
2737
|
+
note: "Ignored when the `actions` slot is supplied."
|
|
2135
2738
|
},
|
|
2136
2739
|
{
|
|
2137
2740
|
name: "confirmVariant",
|
|
2138
2741
|
type: "TVariant",
|
|
2139
|
-
default: "danger"
|
|
2742
|
+
default: "danger",
|
|
2743
|
+
values: [
|
|
2744
|
+
"solid",
|
|
2745
|
+
"outline",
|
|
2746
|
+
"ghost",
|
|
2747
|
+
"soft",
|
|
2748
|
+
"danger"
|
|
2749
|
+
],
|
|
2750
|
+
note: "Ignored when the `actions` slot is supplied."
|
|
2140
2751
|
},
|
|
2141
2752
|
{
|
|
2142
2753
|
name: "confirmDisabled",
|
|
2143
2754
|
type: "boolean",
|
|
2144
|
-
default: "false"
|
|
2755
|
+
default: "false",
|
|
2756
|
+
note: "Disables the default confirm button AND short-circuits the confirm handler \u2014 no `confirm` emit and no close, including when the handler is invoked from the `actions` slot scope."
|
|
2145
2757
|
},
|
|
2146
2758
|
{
|
|
2147
2759
|
name: "cancelDisabled",
|
|
2148
2760
|
type: "boolean",
|
|
2149
|
-
default: "false"
|
|
2761
|
+
default: "false",
|
|
2762
|
+
note: "Disables the default cancel button AND short-circuits the cancel handler \u2014 no `cancel` emit and no close, including when the handler is invoked from the `actions` slot scope."
|
|
2150
2763
|
},
|
|
2151
2764
|
{
|
|
2152
2765
|
name: "loading",
|
|
2153
2766
|
type: "boolean",
|
|
2154
|
-
default: "false"
|
|
2767
|
+
default: "false",
|
|
2768
|
+
note: "Puts the default confirm button into its spinner state (TButton adds `is-loading`, `aria-busy`, and the native `disabled` attribute) and short-circuits the confirm handler exactly like `confirmDisabled`. It does not affect the cancel button. Also passed to the `actions` slot scope so a custom footer can mirror the state."
|
|
2155
2769
|
},
|
|
2156
2770
|
{
|
|
2157
2771
|
name: "closeOnEscape",
|
|
@@ -2161,27 +2775,32 @@ var treeui_catalog_default = {
|
|
|
2161
2775
|
{
|
|
2162
2776
|
name: "closeOnOverlay",
|
|
2163
2777
|
type: "boolean",
|
|
2164
|
-
default: "false"
|
|
2778
|
+
default: "false",
|
|
2779
|
+
note: "Deliberately opt-in \u2014 TModal defaults this to true, TConfirmDialog flips it to false so a confirmation is not dismissed by a stray backdrop click."
|
|
2165
2780
|
},
|
|
2166
2781
|
{
|
|
2167
2782
|
name: "showCloseButton",
|
|
2168
2783
|
type: "boolean",
|
|
2169
|
-
default: "false"
|
|
2784
|
+
default: "false",
|
|
2785
|
+
note: "Deliberately opt-in \u2014 TModal defaults this to true. Enabling it adds a header close button that dismisses without emitting `cancel`."
|
|
2170
2786
|
},
|
|
2171
2787
|
{
|
|
2172
2788
|
name: "closeLabel",
|
|
2173
2789
|
type: "string",
|
|
2174
|
-
default: "Close dialog"
|
|
2790
|
+
default: "Close dialog",
|
|
2791
|
+
note: "Accessible name of the header close button. Only rendered when `showCloseButton` is true."
|
|
2175
2792
|
},
|
|
2176
2793
|
{
|
|
2177
2794
|
name: "closeOnConfirm",
|
|
2178
2795
|
type: "boolean",
|
|
2179
|
-
default: "true"
|
|
2796
|
+
default: "true",
|
|
2797
|
+
note: "Set false for async confirmation: `confirm` fires but the dialog stays open, so the caller can hold it open with `loading` while the request resolves and then close it via `open`."
|
|
2180
2798
|
},
|
|
2181
2799
|
{
|
|
2182
2800
|
name: "closeOnCancel",
|
|
2183
2801
|
type: "boolean",
|
|
2184
|
-
default: "true"
|
|
2802
|
+
default: "true",
|
|
2803
|
+
note: "Set false to keep the dialog open after `cancel` \u2014 the caller then owns closing via `open`."
|
|
2185
2804
|
}
|
|
2186
2805
|
],
|
|
2187
2806
|
events: [
|
|
@@ -2200,16 +2819,20 @@ var treeui_catalog_default = {
|
|
|
2200
2819
|
],
|
|
2201
2820
|
slots: [
|
|
2202
2821
|
{
|
|
2203
|
-
name: "trigger"
|
|
2822
|
+
name: "trigger",
|
|
2823
|
+
description: "Element that opens the dialog on click. Omit for imperative use."
|
|
2204
2824
|
},
|
|
2205
2825
|
{
|
|
2206
|
-
name: "icon"
|
|
2826
|
+
name: "icon",
|
|
2827
|
+
description: "Decorative leading icon. Presence switches the block to the two-column icon layout."
|
|
2207
2828
|
},
|
|
2208
2829
|
{
|
|
2209
|
-
name: "default"
|
|
2830
|
+
name: "default",
|
|
2831
|
+
description: "Extra body content rendered under the description."
|
|
2210
2832
|
},
|
|
2211
2833
|
{
|
|
2212
|
-
name: "actions"
|
|
2834
|
+
name: "actions",
|
|
2835
|
+
description: "Replaces the whole footer. Scope gives you confirm(), cancel(), and loading."
|
|
2213
2836
|
}
|
|
2214
2837
|
],
|
|
2215
2838
|
a11y: [
|
|
@@ -2217,15 +2840,26 @@ var treeui_catalog_default = {
|
|
|
2217
2840
|
"aria_modal: true",
|
|
2218
2841
|
"focus_trap: inherited_from_modal",
|
|
2219
2842
|
"restores_focus_on_close: inherited_from_modal",
|
|
2843
|
+
"restore_focus_caveat: TModal only records the previously focused element when the dialog is opened by clicking its `trigger` slot. A dialog opened programmatically \u2014 by setting `open` from a row action, a menu item, or `defaultOpen` \u2014 has nothing recorded, so focus is not restored on close. Move focus back yourself in that case.",
|
|
2844
|
+
"accessible_name_source: `title` prop, via aria-labelledby; absent when `title` is empty",
|
|
2845
|
+
"accessible_description_source: `description` prop, via aria-describedby; the default slot body is not included",
|
|
2846
|
+
"initial_focus: First focusable element inside the dialog surface. With the default footer and `showCloseButton: false` that is the cancel button, which is the safe landing spot for a destructive confirmation. Enabling `showCloseButton` moves initial focus to the header close button instead. A `loading` or `confirmDisabled` confirm button carries the native `disabled` attribute and is skipped.",
|
|
2220
2847
|
"icon_slot_marked_aria_hidden: true"
|
|
2221
2848
|
],
|
|
2222
2849
|
behavior: [
|
|
2223
2850
|
"built_on_modal_contract: true",
|
|
2224
2851
|
"default_confirm_button_variant: danger",
|
|
2852
|
+
"default_cancel_button_variant: ghost",
|
|
2225
2853
|
"overlay_click_disabled_by_default: true",
|
|
2226
2854
|
"close_button_hidden_by_default: true",
|
|
2227
2855
|
"loading_state_applies_to_confirm_button: true",
|
|
2228
|
-
"
|
|
2856
|
+
"confirm_suppressed_when: confirmDisabled || loading \u2014 the handler returns before emitting, so neither `confirm` nor the close runs",
|
|
2857
|
+
"cancel_suppressed_when: cancelDisabled \u2014 the handler returns before emitting, so neither `cancel` nor the close runs",
|
|
2858
|
+
"closes_after_confirm_when: closeOnConfirm",
|
|
2859
|
+
"closes_after_cancel_when: closeOnCancel",
|
|
2860
|
+
"guards_and_auto_close_apply_to_actions_slot: true",
|
|
2861
|
+
"close_button_and_escape_do_not_emit_cancel: true",
|
|
2862
|
+
"inherits_teleport_scroll_lock_and_focus_trap_from_modal: true"
|
|
2229
2863
|
],
|
|
2230
2864
|
selection: {
|
|
2231
2865
|
keywords: [],
|
|
@@ -2239,6 +2873,9 @@ var treeui_catalog_default = {
|
|
|
2239
2873
|
},
|
|
2240
2874
|
recipes: [
|
|
2241
2875
|
"confirm-destructive-action"
|
|
2876
|
+
],
|
|
2877
|
+
practices: [
|
|
2878
|
+
"accessible-by-default"
|
|
2242
2879
|
]
|
|
2243
2880
|
},
|
|
2244
2881
|
{
|
|
@@ -2291,7 +2928,9 @@ var treeui_catalog_default = {
|
|
|
2291
2928
|
}
|
|
2292
2929
|
],
|
|
2293
2930
|
a11y: [
|
|
2294
|
-
"Acts as a structural wrapper only; semantics come from the `as` prop and child content."
|
|
2931
|
+
"Acts as a structural wrapper only; semantics come from the `as` prop and child content.",
|
|
2932
|
+
'Renders a non-semantic `div` by default. Pass `as` to make it a landmark (e.g. `as="main"`, `as="section"`, `as="header"`) \u2014 avoid nesting a second `main` inside an app shell or a TPage that already provides one.\n',
|
|
2933
|
+
"`aria-*` and `role` attributes fall through to the root element (see `forwards_attrs_to`)."
|
|
2295
2934
|
],
|
|
2296
2935
|
behavior: [
|
|
2297
2936
|
"semantic_element_controlled_by_as: true",
|
|
@@ -2335,6 +2974,9 @@ var treeui_catalog_default = {
|
|
|
2335
2974
|
},
|
|
2336
2975
|
recipes: [
|
|
2337
2976
|
"sidebar-shell"
|
|
2977
|
+
],
|
|
2978
|
+
practices: [
|
|
2979
|
+
"content-alignment"
|
|
2338
2980
|
]
|
|
2339
2981
|
},
|
|
2340
2982
|
{
|
|
@@ -2343,6 +2985,8 @@ var treeui_catalog_default = {
|
|
|
2343
2985
|
package: "@treeui/vue",
|
|
2344
2986
|
category: "Overlay",
|
|
2345
2987
|
status: "stable",
|
|
2988
|
+
description: "Right-click (contextmenu) menu teleported to body and positioned at the cursor. The component renders no chrome of its own \u2014 the root wrapper is `display: contents` and only wraps the slotted trigger area.\n",
|
|
2989
|
+
sourceFile: "packages/vue/src/components/TContextMenu.vue",
|
|
2346
2990
|
storyFile: "apps/docs/src/stories/ContextMenu.stories.ts",
|
|
2347
2991
|
storyTitle: "Components/Overlay/ContextMenu",
|
|
2348
2992
|
manifestFile: "docs/ai/COMPONENTS/context-menu.yaml",
|
|
@@ -2351,73 +2995,84 @@ var treeui_catalog_default = {
|
|
|
2351
2995
|
name: "items",
|
|
2352
2996
|
type: "TContextMenuItem[]",
|
|
2353
2997
|
default: "[]",
|
|
2354
|
-
description:
|
|
2998
|
+
description: 'Menu items to render, one `role="menuitem"` <li> each. An empty array is allowed and still opens an empty `role="menu"` list with nothing focused.\n'
|
|
2355
2999
|
},
|
|
2356
3000
|
{
|
|
2357
3001
|
name: "open",
|
|
2358
3002
|
type: "boolean | undefined",
|
|
2359
3003
|
default: "undefined",
|
|
2360
|
-
description: "Controlled open state (v-model:open)."
|
|
3004
|
+
description: "Controlled open state (v-model:open). When defined it wins over the internal state and `defaultOpen` is ignored; the component still emits and expects the parent to write the new value back. `disabled` overrides this \u2014 a disabled component renders no menu even while `open` is true.\n"
|
|
2361
3005
|
},
|
|
2362
3006
|
{
|
|
2363
3007
|
name: "defaultOpen",
|
|
2364
3008
|
type: "boolean",
|
|
2365
3009
|
default: "false",
|
|
2366
|
-
description: "Uncontrolled initial open state."
|
|
3010
|
+
description: "Uncontrolled initial open state. Read once during setup \u2014 later changes to this prop have no effect.\n"
|
|
2367
3011
|
},
|
|
2368
3012
|
{
|
|
2369
3013
|
name: "disabled",
|
|
2370
3014
|
type: "boolean",
|
|
2371
3015
|
default: "false",
|
|
2372
|
-
description: "Prevents the context menu from opening."
|
|
3016
|
+
description: "Prevents the context menu from opening, and hides it if it is already open. While disabled the component does not call preventDefault on `contextmenu`, so the native browser menu appears instead.\n"
|
|
2373
3017
|
},
|
|
2374
3018
|
{
|
|
2375
3019
|
name: "size",
|
|
2376
3020
|
type: "TSize",
|
|
2377
3021
|
default: "md",
|
|
2378
|
-
|
|
3022
|
+
values: [
|
|
3023
|
+
"sm",
|
|
3024
|
+
"md",
|
|
3025
|
+
"lg"
|
|
3026
|
+
],
|
|
3027
|
+
description: "Item sizing variant. The modifier class is applied to both the root and the teleported menu, but only the copy on the menu is effective (the root is teleport-detached from the menu subtree).\n"
|
|
2379
3028
|
}
|
|
2380
3029
|
],
|
|
2381
3030
|
events: [
|
|
2382
3031
|
{
|
|
2383
3032
|
name: "select",
|
|
2384
|
-
description: "Emitted when
|
|
3033
|
+
description: "Emitted with `item.value` when an enabled item is activated by click or Enter/Space. Disabled items emit nothing.\n",
|
|
2385
3034
|
payload: "[value: string]"
|
|
2386
3035
|
},
|
|
2387
3036
|
{
|
|
2388
3037
|
name: "update:open",
|
|
2389
|
-
description: "Emitted when open state changes (v-model support).",
|
|
3038
|
+
description: "Emitted when open state changes (v-model support). Only fires on an actual transition \u2014 setting the same value again is a no-op.\n",
|
|
2390
3039
|
payload: "[value: boolean]"
|
|
2391
3040
|
},
|
|
2392
3041
|
{
|
|
2393
3042
|
name: "open-change",
|
|
2394
|
-
description: "Emitted when open state changes.",
|
|
3043
|
+
description: "Emitted when open state changes. Always fires together with `update:open`, including in controlled mode.\n",
|
|
2395
3044
|
payload: "[value: boolean]"
|
|
2396
3045
|
}
|
|
2397
3046
|
],
|
|
2398
3047
|
slots: [
|
|
2399
3048
|
{
|
|
2400
3049
|
name: "default",
|
|
2401
|
-
description: "Content that acts as the right-click trigger area."
|
|
3050
|
+
description: "Content that acts as the right-click trigger area. It is rendered inside the root <div>, which is `display: contents` and therefore contributes no box of its own \u2014 the slotted content keeps its own layout, and the `contextmenu` handler still fires through event bubbling.\n"
|
|
2402
3051
|
},
|
|
2403
3052
|
{
|
|
2404
3053
|
name: "item",
|
|
2405
|
-
description:
|
|
3054
|
+
description: 'Custom rendering for each menu item; scoped props `{ item, index }`, falls back to `{{ item.label }}`. Rendered inside the `role="menuitem"` <li>, which already owns click, keydown, tabindex and aria-disabled \u2014 keep the content presentational, nested interactive controls are not reachable inside a menuitem.\n'
|
|
2406
3055
|
}
|
|
2407
3056
|
],
|
|
2408
3057
|
a11y: [
|
|
2409
|
-
"role: menu (on the floating list)",
|
|
3058
|
+
"role: menu (on the teleported floating list)",
|
|
2410
3059
|
"items_role: menuitem",
|
|
2411
|
-
'keyboard: ["Right-click / contextmenu event opens menu at cursor","ArrowDown / ArrowUp
|
|
2412
|
-
'aria: ["aria-disabled on disabled items","aria-label on menu element"]',
|
|
2413
|
-
'focus: ["First enabled item receives focus on open","Focus restored to trigger area on close"]'
|
|
3060
|
+
'keyboard: ["Right-click / contextmenu event opens menu at cursor","ArrowDown / ArrowUp move focus to the next / previous enabled item (clamped, no wrap)","Home / End jumps to first / last enabled item","Enter / Space selects focused item","Escape closes menu and restores focus","All key handling lives on the items \u2014 keys are only handled while an item has focus"]',
|
|
3061
|
+
'aria: ["aria-disabled on disabled items (omitted, not false, when enabled)","aria-label=\\"Context menu\\" on the menu element \u2014 hardcoded, not configurable or localizable","Menu id is generated with createId(\'t-context-menu\'); there is no `id` prop","tabindex 0 on enabled items, -1 on disabled items \u2014 no roving tabindex, every enabled item is tab-reachable"]',
|
|
3062
|
+
'focus: ["First enabled item receives focus on open","When every item is disabled, focus still goes to the first item; with an empty `items` array nothing is focused","Focus restored to trigger area on close from Escape or item selection","An outside click closes without restoring focus, leaving it where the pointer put it"]'
|
|
2414
3063
|
],
|
|
2415
3064
|
behavior: [
|
|
2416
|
-
"Opens at cursor position on right-click (contextmenu event).",
|
|
2417
|
-
"Uses Teleport to body to escape stacking contexts.",
|
|
2418
|
-
"
|
|
2419
|
-
"
|
|
2420
|
-
"
|
|
3065
|
+
"Opens at cursor position on right-click (contextmenu event), using event.clientX / clientY.",
|
|
3066
|
+
"Uses Teleport to body to escape stacking contexts; the menu is not a DOM descendant of the trigger.",
|
|
3067
|
+
"Uses position fixed at the raw cursor coordinates, stacked at var(--tree-z-dropdown).",
|
|
3068
|
+
"No collision detection or viewport clamping \u2014 a menu opened near the right or bottom edge overflows.",
|
|
3069
|
+
"Closes on pointerdown outside the menu (including on the trigger itself), Escape, or item selection.",
|
|
3070
|
+
"Right-clicking again inside the trigger area repositions the menu \u2014 the outside pointerdown closes it and the following contextmenu reopens it at the new coordinates.",
|
|
3071
|
+
"A document-level contextmenu listener covers keyboard-invoked menus (Shift+F10 / Menu key) raised outside the trigger.",
|
|
3072
|
+
"Prevents native browser context menu on trigger area, but only while not disabled.",
|
|
3073
|
+
'Exposes data-state="open" | "closed" on the root element for external styling.',
|
|
3074
|
+
"Document pointerdown / contextmenu listeners are attached only while open, and removed on close and before unmount.",
|
|
3075
|
+
"Menu enter / leave uses the shared t-fade transition (opacity plus scale 0.95)."
|
|
2421
3076
|
],
|
|
2422
3077
|
selection: {
|
|
2423
3078
|
keywords: [
|
|
@@ -2442,7 +3097,8 @@ var treeui_catalog_default = {
|
|
|
2442
3097
|
required: [],
|
|
2443
3098
|
notes: []
|
|
2444
3099
|
},
|
|
2445
|
-
recipes: []
|
|
3100
|
+
recipes: [],
|
|
3101
|
+
practices: []
|
|
2446
3102
|
},
|
|
2447
3103
|
{
|
|
2448
3104
|
name: "TDatePicker",
|
|
@@ -2460,17 +3116,20 @@ var treeui_catalog_default = {
|
|
|
2460
3116
|
{
|
|
2461
3117
|
name: "modelValue",
|
|
2462
3118
|
type: "string",
|
|
2463
|
-
default: ""
|
|
3119
|
+
default: "",
|
|
3120
|
+
note: "Parsed with `parseDateValue`, which accepts ONLY a strict `YYYY-MM-DD` string that resolves to a real calendar date. Anything else (empty, `2026-13-01`, an ISO datetime, a Date object stringified) resolves to null and the trigger falls back to `placeholder`. The hidden input, when present, still submits the raw prop verbatim \u2014 an unparseable value renders as the placeholder but is submitted as-is."
|
|
2464
3121
|
},
|
|
2465
3122
|
{
|
|
2466
3123
|
name: "open",
|
|
2467
3124
|
type: "boolean",
|
|
2468
|
-
default: "
|
|
3125
|
+
default: "undefined",
|
|
3126
|
+
note: "Controlled open state. Once a boolean is passed the component stops tracking open state internally \u2014 it only emits update:open / open-change and the consumer MUST write the value back, or the calendar never opens."
|
|
2469
3127
|
},
|
|
2470
3128
|
{
|
|
2471
3129
|
name: "defaultOpen",
|
|
2472
3130
|
type: "boolean",
|
|
2473
|
-
default: "false"
|
|
3131
|
+
default: "false",
|
|
3132
|
+
note: "Uncontrolled initial open state, read once on mount. Later changes to it are ignored. Opening this way skips `openCalendar`, so no day button receives DOM focus until the user tabs or arrows into the grid."
|
|
2474
3133
|
},
|
|
2475
3134
|
{
|
|
2476
3135
|
name: "size",
|
|
@@ -2480,41 +3139,48 @@ var treeui_catalog_default = {
|
|
|
2480
3139
|
"sm",
|
|
2481
3140
|
"md",
|
|
2482
3141
|
"lg"
|
|
2483
|
-
]
|
|
3142
|
+
],
|
|
3143
|
+
note: "Sizes the trigger only, never the popover. `md` has no CSS rule of its own \u2014 it is the base `.t-date-picker__trigger` styling \u2014 but the `t-date-picker--md` class is still rendered."
|
|
2484
3144
|
},
|
|
2485
3145
|
{
|
|
2486
3146
|
name: "disabled",
|
|
2487
3147
|
type: "boolean",
|
|
2488
|
-
default: "false"
|
|
3148
|
+
default: "false",
|
|
3149
|
+
note: 'Sets the native `disabled` attribute on the trigger, adds `is-disabled` to the root, short-circuits `openCalendar` and trigger keydown, makes `isDateDisabled` return true for every date, and suppresses the popover entirely (`v-if="isOpen && !disabled"`) even while `open` is true.'
|
|
2489
3150
|
},
|
|
2490
3151
|
{
|
|
2491
3152
|
name: "invalid",
|
|
2492
3153
|
type: "boolean",
|
|
2493
|
-
default: "false"
|
|
3154
|
+
default: "false",
|
|
3155
|
+
note: 'Adds `is-invalid` to the root and `aria-invalid="true"` to the trigger. Purely presentational \u2014 it does not block opening or selection.'
|
|
2494
3156
|
},
|
|
2495
3157
|
{
|
|
2496
3158
|
name: "placeholder",
|
|
2497
3159
|
type: "string",
|
|
2498
|
-
default: "Select date"
|
|
3160
|
+
default: "Select date",
|
|
3161
|
+
note: "Rendered inside `.t-date-picker__value` with a `data-placeholder` attribute whenever `modelValue` does not parse."
|
|
2499
3162
|
},
|
|
2500
3163
|
{
|
|
2501
3164
|
name: "locale",
|
|
2502
3165
|
type: "string",
|
|
2503
|
-
default: "en-US"
|
|
3166
|
+
default: "en-US",
|
|
3167
|
+
note: "BCP-47 tag passed to three separate `Intl.DateTimeFormat` calls: the trigger text (day numeric / month long / year numeric), the popover month caption (month long / year numeric), and the weekday header (weekday short). It does NOT localize the per-day `aria-label`, which is always the raw `YYYY-MM-DD` key."
|
|
2504
3168
|
},
|
|
2505
3169
|
{
|
|
2506
3170
|
name: "min",
|
|
2507
3171
|
type: "string",
|
|
2508
|
-
default: ""
|
|
3172
|
+
default: "",
|
|
3173
|
+
note: "Inclusive lower bound. Days before it get the native `disabled` attribute and cannot be selected or arrowed onto; the Previous-month nav button is disabled once the view reaches the min month. A value that fails `parseDateValue` is ignored, i.e. treated as no bound."
|
|
2509
3174
|
},
|
|
2510
3175
|
{
|
|
2511
3176
|
name: "max",
|
|
2512
3177
|
type: "string",
|
|
2513
|
-
default: ""
|
|
3178
|
+
default: "",
|
|
3179
|
+
note: "Inclusive upper bound, mirroring `min`: out-of-range days are disabled and the Next-month nav button is disabled once the view reaches the max month."
|
|
2514
3180
|
},
|
|
2515
3181
|
{
|
|
2516
3182
|
name: "weekStartsOn",
|
|
2517
|
-
type: "
|
|
3183
|
+
type: "0 | 1 | 2 | 3 | 4 | 5 | 6",
|
|
2518
3184
|
default: "0",
|
|
2519
3185
|
values: [
|
|
2520
3186
|
"0",
|
|
@@ -2524,46 +3190,90 @@ var treeui_catalog_default = {
|
|
|
2524
3190
|
"4",
|
|
2525
3191
|
"5",
|
|
2526
3192
|
"6"
|
|
2527
|
-
]
|
|
3193
|
+
],
|
|
3194
|
+
note: "0 = Sunday. Drives the weekday header order, the leading offset of the day grid, and the Home/End keys (which jump to the first/last day of the week as defined by this prop)."
|
|
2528
3195
|
},
|
|
2529
3196
|
{
|
|
2530
3197
|
name: "id",
|
|
2531
3198
|
type: "string",
|
|
2532
|
-
default: "auto"
|
|
3199
|
+
default: "auto",
|
|
3200
|
+
note: "Names the CALENDAR POPOVER, not the trigger. It becomes the popover's `id` (referenced by the trigger's `aria-controls` while open) and seeds the month caption id as `${id}-caption`. Read once at setup \u2014 later changes are ignored. Because `id` is a declared prop it never falls through to the trigger button, so the trigger has no id and a `<label for>` / `TFormField html-for` cannot target it; name the control with `aria-label` instead."
|
|
2533
3201
|
}
|
|
2534
3202
|
],
|
|
2535
3203
|
events: [
|
|
2536
3204
|
{
|
|
2537
|
-
name: "update:modelValue"
|
|
3205
|
+
name: "update:modelValue",
|
|
3206
|
+
description: 'Emitted with the chosen day as `YYYY-MM-DD` from `selectDate` only \u2014 a click or Enter/Space on an enabled day button. Nothing else in the component emits it; there is no clear affordance, so the value never becomes `""` on its own.',
|
|
3207
|
+
payload: '["string"]'
|
|
2538
3208
|
},
|
|
2539
3209
|
{
|
|
2540
|
-
name: "update:open"
|
|
3210
|
+
name: "update:open",
|
|
3211
|
+
description: "Emitted whenever the open state changes. Deduped \u2014 no emit when the next value equals the current one.",
|
|
3212
|
+
payload: '["boolean"]'
|
|
2541
3213
|
},
|
|
2542
3214
|
{
|
|
2543
|
-
name: "open-change"
|
|
3215
|
+
name: "open-change",
|
|
3216
|
+
description: "Emitted immediately after `update:open`, with the same payload. Alias for consumers that do not use v-model:open.",
|
|
3217
|
+
payload: '["boolean"]'
|
|
2544
3218
|
},
|
|
2545
3219
|
{
|
|
2546
|
-
name: "select"
|
|
3220
|
+
name: "select",
|
|
3221
|
+
description: "Emitted from `selectDate` immediately after `update:modelValue`, with the same `YYYY-MM-DD` payload. It is the user-intent signal: it fires only on an actual day activation and never when `modelValue` changes from outside, which is what distinguishes it from `update:modelValue`.",
|
|
3222
|
+
payload: '["string"]'
|
|
2547
3223
|
}
|
|
2548
3224
|
],
|
|
2549
3225
|
slots: [
|
|
2550
3226
|
{
|
|
2551
|
-
name: "prefix"
|
|
3227
|
+
name: "prefix",
|
|
3228
|
+
description: 'Leading content inside the trigger button, before the value text. Rendered only when the slot is supplied, wrapped in `<span class="t-date-picker__slot t-date-picker__slot--prefix">`. No scoped props. Content is inside a `<button>`, so it must be presentational only.'
|
|
2552
3229
|
},
|
|
2553
3230
|
{
|
|
2554
|
-
name: "suffix"
|
|
3231
|
+
name: "suffix",
|
|
3232
|
+
description: 'Trailing content inside the trigger button, in `<span class="t-date-picker__slot t-date-picker__slot--suffix">`. Unlike `prefix` the wrapper is always rendered; supplying the slot replaces the default calendar icon. No scoped props, and the same presentational-only restriction applies.'
|
|
2555
3233
|
}
|
|
2556
3234
|
],
|
|
2557
3235
|
a11y: [
|
|
3236
|
+
"role: dialog",
|
|
3237
|
+
"accessible_name: None is generated for the trigger beyond its own text content, which is the formatted date or the placeholder \u2014 that changes as the user picks, so it is not a stable label. Pass `aria-label` (see example). The `id` prop cannot be used to link an external <label>.",
|
|
2558
3238
|
"trigger_has_popup_dialog: true",
|
|
3239
|
+
"trigger_aria_expanded: true",
|
|
3240
|
+
"trigger_aria_controls_when_open: true",
|
|
3241
|
+
"aria_invalid_when_invalid: true",
|
|
2559
3242
|
"calendar_uses_grid_roles: true",
|
|
3243
|
+
"calendar_aria_modal: false",
|
|
3244
|
+
"calendar_labelled_by_month_caption: true",
|
|
3245
|
+
"weekday_header_is_aria_hidden: true",
|
|
3246
|
+
"aria_selected_rendered_on_every_gridcell: true",
|
|
3247
|
+
"aria_current_date_on_today: true",
|
|
3248
|
+
"day_aria_label_is_the_raw_iso_key: true",
|
|
3249
|
+
"nav_buttons_labelled_previous_month_and_next_month: true",
|
|
3250
|
+
"roving_tabindex_one_focusable_day: true",
|
|
2560
3251
|
"escape_closes: true",
|
|
2561
|
-
"returns_focus_to_trigger_after_selection: true"
|
|
3252
|
+
"returns_focus_to_trigger_after_selection: true",
|
|
3253
|
+
"returns_focus_to_trigger_on_escape_from_a_day: true",
|
|
3254
|
+
"focus_is_not_trapped_and_tab_leaves_the_open_calendar: true"
|
|
2562
3255
|
],
|
|
2563
3256
|
behavior: [
|
|
3257
|
+
"value_format: YYYY-MM-DD",
|
|
3258
|
+
"controlled_and_uncontrolled_open: true",
|
|
3259
|
+
"open_state_emits_are_deduped: true",
|
|
2564
3260
|
"selection_closes_popover: true",
|
|
2565
3261
|
"hidden_input_created_when_name_attr_present: true",
|
|
2566
|
-
"
|
|
3262
|
+
"hidden_input_submits_the_raw_unparsed_model_value: true",
|
|
3263
|
+
"out_of_range_dates_disabled: true",
|
|
3264
|
+
"min_and_max_also_disable_the_month_nav_buttons: true",
|
|
3265
|
+
"popover_is_not_rendered_while_disabled: true",
|
|
3266
|
+
"outside_click_closes_calendar: true",
|
|
3267
|
+
"outside_click_is_detected_on_pointerdown_on_document: true",
|
|
3268
|
+
"outside_click_and_trigger_toggle_close_without_restoring_focus: true",
|
|
3269
|
+
"grid_is_always_six_weeks_forty_two_days: true",
|
|
3270
|
+
"leading_and_trailing_days_render_muted_and_stay_selectable: true",
|
|
3271
|
+
"opening_syncs_the_view_to_the_selected_date_else_the_last_focused_date_else_today: true",
|
|
3272
|
+
"external_model_value_changes_move_the_view_and_the_focused_day: true",
|
|
3273
|
+
"clearing_the_model_value_resets_the_view_to_today_only_while_closed: true",
|
|
3274
|
+
"month_nav_moves_the_focused_day_to_the_first_of_the_new_month_and_focuses_it: true",
|
|
3275
|
+
"today_is_computed_once_at_setup_not_re_evaluated_across_midnight: true",
|
|
3276
|
+
"popover_renders_in_flow_with_no_portal_and_no_flip_positioning: true"
|
|
2567
3277
|
],
|
|
2568
3278
|
selection: {
|
|
2569
3279
|
keywords: [
|
|
@@ -2591,13 +3301,14 @@ var treeui_catalog_default = {
|
|
|
2591
3301
|
"Use `min` and `max` with the same format."
|
|
2592
3302
|
]
|
|
2593
3303
|
},
|
|
2594
|
-
recipes: []
|
|
3304
|
+
recipes: [],
|
|
3305
|
+
practices: []
|
|
2595
3306
|
},
|
|
2596
3307
|
{
|
|
2597
3308
|
name: "TDateTimePicker",
|
|
2598
3309
|
aliases: [],
|
|
2599
3310
|
package: "@treeui/vue",
|
|
2600
|
-
kind: "
|
|
3311
|
+
kind: "form_overlay",
|
|
2601
3312
|
category: "Data Entry",
|
|
2602
3313
|
status: "available",
|
|
2603
3314
|
purpose: "Date and time picker with a calendar grid, time selection, and overlay trigger.",
|
|
@@ -2610,7 +3321,7 @@ var treeui_catalog_default = {
|
|
|
2610
3321
|
name: "modelValue",
|
|
2611
3322
|
type: "string",
|
|
2612
3323
|
default: "",
|
|
2613
|
-
note: "
|
|
3324
|
+
note: "Always emitted as `YYYY-MM-DDTHH:mm`. On input it also parses `YYYY-MM-DD` (midnight) and `YYYY-MM-DDTHH:mm:ss`; anything else parses to null and renders the placeholder."
|
|
2614
3325
|
},
|
|
2615
3326
|
{
|
|
2616
3327
|
name: "open",
|
|
@@ -2630,17 +3341,20 @@ var treeui_catalog_default = {
|
|
|
2630
3341
|
"sm",
|
|
2631
3342
|
"md",
|
|
2632
3343
|
"lg"
|
|
2633
|
-
]
|
|
3344
|
+
],
|
|
3345
|
+
note: "Renders as `t-date-picker--<size>` on the root \u2014 there is no `t-date-time-picker--<size>` modifier."
|
|
2634
3346
|
},
|
|
2635
3347
|
{
|
|
2636
3348
|
name: "disabled",
|
|
2637
3349
|
type: "boolean",
|
|
2638
|
-
default: "false"
|
|
3350
|
+
default: "false",
|
|
3351
|
+
note: "Blocks opening via click/keyboard and suppresses the overlay entirely, even when `open` is true."
|
|
2639
3352
|
},
|
|
2640
3353
|
{
|
|
2641
3354
|
name: "loading",
|
|
2642
3355
|
type: "boolean",
|
|
2643
|
-
default: "false"
|
|
3356
|
+
default: "false",
|
|
3357
|
+
note: "Only swaps the default suffix icon for a TSpinner; the trigger stays enabled and interactive."
|
|
2644
3358
|
},
|
|
2645
3359
|
{
|
|
2646
3360
|
name: "invalid",
|
|
@@ -2655,33 +3369,38 @@ var treeui_catalog_default = {
|
|
|
2655
3369
|
{
|
|
2656
3370
|
name: "locale",
|
|
2657
3371
|
type: "string",
|
|
2658
|
-
default: "en-US"
|
|
3372
|
+
default: "en-US",
|
|
3373
|
+
note: "Feeds all four Intl.DateTimeFormat calls: trigger text, draft preview, month caption, weekday labels."
|
|
2659
3374
|
},
|
|
2660
3375
|
{
|
|
2661
3376
|
name: "min",
|
|
2662
3377
|
type: "string",
|
|
2663
|
-
default: ""
|
|
3378
|
+
default: "",
|
|
3379
|
+
note: "`YYYY-MM-DD` (resolved to 00:00 of that day) or `YYYY-MM-DDTHH:mm`."
|
|
2664
3380
|
},
|
|
2665
3381
|
{
|
|
2666
3382
|
name: "max",
|
|
2667
3383
|
type: "string",
|
|
2668
|
-
default: ""
|
|
3384
|
+
default: "",
|
|
3385
|
+
note: "`YYYY-MM-DD` (resolved to 23:59:59.999 of that day) or `YYYY-MM-DDTHH:mm`."
|
|
2669
3386
|
},
|
|
2670
3387
|
{
|
|
2671
3388
|
name: "weekStartsOn",
|
|
2672
3389
|
type: "0 | 1 | 2 | 3 | 4 | 5 | 6",
|
|
2673
|
-
default: "0"
|
|
3390
|
+
default: "0",
|
|
3391
|
+
note: "0 = Sunday. Reorders the weekday header labels, the grid start date, and Home/End day navigation."
|
|
2674
3392
|
},
|
|
2675
3393
|
{
|
|
2676
3394
|
name: "id",
|
|
2677
3395
|
type: "string",
|
|
2678
|
-
default: "auto"
|
|
3396
|
+
default: "auto",
|
|
3397
|
+
note: "Id of the overlay dialog only \u2014 not of the root or the trigger. Read once at setup, so later changes are ignored. The trigger points at it with aria-controls while open."
|
|
2679
3398
|
},
|
|
2680
3399
|
{
|
|
2681
3400
|
name: "step",
|
|
2682
3401
|
type: "number",
|
|
2683
3402
|
default: "60",
|
|
2684
|
-
note: "Seconds between
|
|
3403
|
+
note: "Seconds between minute options. Must be a positive multiple of 60 below 3600; any other value falls back to 1-minute options. Hours are always 0-23 regardless of step."
|
|
2685
3404
|
}
|
|
2686
3405
|
],
|
|
2687
3406
|
events: [
|
|
@@ -2701,12 +3420,28 @@ var treeui_catalog_default = {
|
|
|
2701
3420
|
name: "select"
|
|
2702
3421
|
}
|
|
2703
3422
|
],
|
|
2704
|
-
slots: [
|
|
3423
|
+
slots: [
|
|
3424
|
+
{
|
|
3425
|
+
name: "prefix"
|
|
3426
|
+
},
|
|
3427
|
+
{
|
|
3428
|
+
name: "suffix"
|
|
3429
|
+
}
|
|
3430
|
+
],
|
|
2705
3431
|
a11y: [
|
|
2706
3432
|
"role: dialog",
|
|
3433
|
+
"aria_modal: false \u2014 the overlay is non-modal and does not trap focus",
|
|
2707
3434
|
"trigger_aria_haspopup: dialog",
|
|
2708
3435
|
"trigger_aria_expanded: true",
|
|
2709
|
-
"
|
|
3436
|
+
"trigger_aria_controls_when_open: true",
|
|
3437
|
+
"overlay_labelled_by_month_caption: true",
|
|
3438
|
+
"calendar_uses_grid_roles: true",
|
|
3439
|
+
"day_buttons_use_roving_tabindex: true",
|
|
3440
|
+
"day_buttons_aria_pressed_when_selected: true",
|
|
3441
|
+
"gridcell_aria_selected: true",
|
|
3442
|
+
"weekday_row_aria_hidden: true",
|
|
3443
|
+
"time_selects_have_aria_labels: true",
|
|
3444
|
+
"focus_restores_on_close: Only when closing via Apply, Clear, or Escape from a day button. Closing by clicking the trigger, Escape on the trigger, or an outside pointerdown leaves focus where it is.",
|
|
2710
3445
|
"keyboard_calendar_navigation: true",
|
|
2711
3446
|
"escape_closes_overlay: true",
|
|
2712
3447
|
"aria_invalid_when_invalid: true",
|
|
@@ -2716,7 +3451,21 @@ var treeui_catalog_default = {
|
|
|
2716
3451
|
"controlled_and_uncontrolled_open: true",
|
|
2717
3452
|
"value_format: YYYY-MM-DDTHH:mm",
|
|
2718
3453
|
"min_and_max_limit_available_values: true",
|
|
2719
|
-
"time_options_generated_from_step: true"
|
|
3454
|
+
"time_options_generated_from_step: true",
|
|
3455
|
+
"draft_then_commit: Choosing a day and changing the Hour/Minute selects mutate an internal draft only. Nothing is emitted and the overlay does NOT close until Apply \u2014 unlike TDatePicker, where selecting a day commits and closes.",
|
|
3456
|
+
"apply_emit_order: update:modelValue, then change, then select \u2014 all carrying the same `YYYY-MM-DDTHH:mm` string.",
|
|
3457
|
+
"clear_emits_empty_string: Clear emits update:modelValue, change, and select with `''`, then closes.",
|
|
3458
|
+
"default_draft_when_value_is_empty: Now, rounded UP to the next `step` boundary (minimum 60s) with seconds zeroed, then clamped into min/max.",
|
|
3459
|
+
"draft_resyncs_from_model_value_only_while_closed: true",
|
|
3460
|
+
"draft_is_clamped_into_min_max_on_open_and_on_day_select: true",
|
|
3461
|
+
"minute_options_always_include_the_current_draft_minute: true",
|
|
3462
|
+
"hour_option_disabled_when_no_minute_in_that_hour_is_available: true",
|
|
3463
|
+
"month_nav_buttons_disabled_at_min_max_month: true",
|
|
3464
|
+
"out_of_range_days_disabled: true",
|
|
3465
|
+
"outside_pointerdown_closes: true",
|
|
3466
|
+
"overlay_is_not_rendered_while_disabled: true",
|
|
3467
|
+
"hidden_input_created_when_name_attr_present: true",
|
|
3468
|
+
"open_state_emits_are_deduped: true"
|
|
2720
3469
|
],
|
|
2721
3470
|
selection: {
|
|
2722
3471
|
keywords: [
|
|
@@ -2749,14 +3498,15 @@ var treeui_catalog_default = {
|
|
|
2749
3498
|
},
|
|
2750
3499
|
recipes: [
|
|
2751
3500
|
"date-range-form"
|
|
2752
|
-
]
|
|
3501
|
+
],
|
|
3502
|
+
practices: []
|
|
2753
3503
|
},
|
|
2754
3504
|
{
|
|
2755
3505
|
name: "TDivider",
|
|
2756
3506
|
aliases: [],
|
|
2757
3507
|
package: "@treeui/vue",
|
|
2758
3508
|
category: "Layout",
|
|
2759
|
-
description:
|
|
3509
|
+
description: 'Horizontal or vertical visual separator. Renders a single native <hr> and nothing else \u2014 there is no default slot, so the "text in the middle of a rule" pattern (an "OR" divider) is NOT supported; compose that yourself from a flex row plus TText. The `label` prop is an accessible name only, never visible text. There are no size, variant, tone, or spacing props.\n',
|
|
2760
3510
|
sourceFile: "packages/vue/src/components/TDivider.vue",
|
|
2761
3511
|
storyFile: "apps/docs/src/stories/Divider.stories.ts",
|
|
2762
3512
|
storyTitle: "Components/Layout/Divider",
|
|
@@ -2764,34 +3514,41 @@ var treeui_catalog_default = {
|
|
|
2764
3514
|
props: [
|
|
2765
3515
|
{
|
|
2766
3516
|
name: "orientation",
|
|
2767
|
-
type: "
|
|
3517
|
+
type: '"horizontal" | "vertical"',
|
|
2768
3518
|
default: "horizontal",
|
|
2769
3519
|
values: [
|
|
2770
3520
|
"horizontal",
|
|
2771
3521
|
"vertical"
|
|
2772
|
-
]
|
|
3522
|
+
],
|
|
3523
|
+
description: "Selects the `t-divider--{orientation}` modifier \u2014 the only class the component varies. `horizontal` spans the full inline width (width 100%, height 0) with `margin-block` spacing. `vertical` is a zero-width rule (width 0, height auto) that takes its height from `align-self: stretch`, so it is only visible inside a flex or grid row \u2014 in a plain block container it collapses to zero height and renders nothing.\n"
|
|
2773
3524
|
},
|
|
2774
3525
|
{
|
|
2775
3526
|
name: "decorative",
|
|
2776
3527
|
type: "boolean",
|
|
2777
3528
|
default: "true",
|
|
2778
|
-
description:
|
|
3529
|
+
description: 'When true (the default) renders `role="none"` and no ARIA attributes at all \u2014 purely visual, removed from the accessibility tree, and the `label` prop is dropped. When false renders `role="separator"` plus `aria-orientation`, and `aria-label` when `label` is set.\n'
|
|
2779
3530
|
},
|
|
2780
3531
|
{
|
|
2781
3532
|
name: "label",
|
|
2782
3533
|
type: "string",
|
|
2783
3534
|
required: false,
|
|
2784
|
-
description:
|
|
3535
|
+
description: 'Accessible name, applied as `aria-label` ONLY when `decorative` is false. Because `decorative` defaults to true, `<TDivider label="Section" />` on its own renders no label at all \u2014 pass `:decorative="false"` as well. Never rendered as visible text.\n'
|
|
2785
3536
|
}
|
|
2786
3537
|
],
|
|
2787
3538
|
events: [],
|
|
2788
3539
|
slots: [],
|
|
2789
3540
|
a11y: [
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
"aria-label: Set from `label` prop when non-decorative."
|
|
3541
|
+
'role: "none" when decorative (the default), "separator" when `decorative` is false.',
|
|
3542
|
+
'aria-orientation: Set to the `orientation` value only when `decorative` is false; omitted otherwise. Note that "horizontal" is already the implicit default for `role="separator"`, so it is redundant there but harmless.',
|
|
3543
|
+
"aria-label: Set from the `label` prop only when `decorative` is false. Omitted when `label` is unset, so a non-decorative divider without a label is an unnamed separator (valid \u2014 separators need no name).",
|
|
3544
|
+
'notes: The decorative default is the right one for most dividers: a purely visual rule should not be announced. Use `:decorative="false"` only when the rule genuinely separates two sections that assistive technology should perceive as distinct, and pair it with `label` when the sections need naming.'
|
|
3545
|
+
],
|
|
3546
|
+
behavior: [
|
|
3547
|
+
"Renders a native <hr> element as its single root node.",
|
|
3548
|
+
"Extra attrs and class/style fall through to that <hr> (attribute inheritance is not disabled).",
|
|
3549
|
+
"Applies exactly two classes; no state, size, or variant modifiers exist.",
|
|
3550
|
+
"A vertical divider needs a flex or grid parent to have any height."
|
|
2793
3551
|
],
|
|
2794
|
-
behavior: [],
|
|
2795
3552
|
selection: {
|
|
2796
3553
|
keywords: [],
|
|
2797
3554
|
useWhen: [],
|
|
@@ -2802,7 +3559,8 @@ var treeui_catalog_default = {
|
|
|
2802
3559
|
required: [],
|
|
2803
3560
|
notes: []
|
|
2804
3561
|
},
|
|
2805
|
-
recipes: []
|
|
3562
|
+
recipes: [],
|
|
3563
|
+
practices: []
|
|
2806
3564
|
},
|
|
2807
3565
|
{
|
|
2808
3566
|
name: "TDonutChart",
|
|
@@ -2821,67 +3579,73 @@ var treeui_catalog_default = {
|
|
|
2821
3579
|
name: "segments",
|
|
2822
3580
|
type: "TDonutSegment[]",
|
|
2823
3581
|
default: "[]",
|
|
2824
|
-
note: "Each item is { label: string; value: number; color?: string }.
|
|
3582
|
+
note: "Each item is { label: string; value: number; color?: string }. Values <= 0 are filtered out before anything renders \u2014 they reach neither the chart, the legend, nor the segment count in the auto aria-label. Because the palette cycles by *visible* index, dropping a non-positive item shifts the colors of every segment after it."
|
|
2825
3583
|
},
|
|
2826
3584
|
{
|
|
2827
3585
|
name: "size",
|
|
2828
3586
|
type: "number",
|
|
2829
3587
|
default: "200",
|
|
2830
|
-
note: "Square canvas in px."
|
|
3588
|
+
note: "Square canvas in px; applied to both the svg and the figure box. Donut geometry insets the ring by thickness/2 + 3px so the hover growth cannot clip; pie geometry uses a radius of size/2 - 2."
|
|
2831
3589
|
},
|
|
2832
3590
|
{
|
|
2833
3591
|
name: "thickness",
|
|
2834
3592
|
type: "number",
|
|
2835
3593
|
default: "26",
|
|
2836
|
-
note: "Ring thickness
|
|
3594
|
+
note: "Ring thickness in px. `0` switches the whole render mode: segments become filled wedges to the center (a pie) and the center block is not rendered at all. Hovering a donut segment temporarily draws it at thickness + 4."
|
|
2837
3595
|
},
|
|
2838
3596
|
{
|
|
2839
3597
|
name: "gap",
|
|
2840
3598
|
type: "number",
|
|
2841
3599
|
default: "2",
|
|
2842
|
-
note: "Gap between slices, in degrees."
|
|
3600
|
+
note: "Gap between slices, in degrees. In donut mode it is converted to arc length on the mid-radius circle and then floored \u2014 the effective gap is at least 2px, or at least thickness + 2px when rounded \u2014 so small values (including 0) still leave a visible seam. Forced to 0 whenever exactly one segment is visible."
|
|
2843
3601
|
},
|
|
2844
3602
|
{
|
|
2845
3603
|
name: "rounded",
|
|
2846
3604
|
type: "boolean",
|
|
2847
3605
|
default: "false",
|
|
2848
|
-
note: "Round the ends of donut segments (widens the gap to make room). Best with a thinner ring."
|
|
3606
|
+
note: "Round the ends of donut segments (widens the gap to make room). Best with a thinner ring. Donut only \u2014 stroke-linecap is not applied to pie wedges, so it is ignored when thickness is 0."
|
|
2849
3607
|
},
|
|
2850
3608
|
{
|
|
2851
3609
|
name: "showLegend",
|
|
2852
3610
|
type: "boolean",
|
|
2853
|
-
default: "true"
|
|
3611
|
+
default: "true",
|
|
3612
|
+
note: "The legend only renders when there is data \u2014 it is suppressed in the empty state even when true, but it is NOT suppressed while loading, so real values sit next to the skeleton. The has-legend root class tracks the prop alone, not whether the legend actually rendered."
|
|
2854
3613
|
},
|
|
2855
3614
|
{
|
|
2856
3615
|
name: "showPercent",
|
|
2857
3616
|
type: "boolean",
|
|
2858
|
-
default: "true"
|
|
3617
|
+
default: "true",
|
|
3618
|
+
note: "Legend only. Percentages are rounded to whole numbers, so they may not sum to exactly 100%."
|
|
2859
3619
|
},
|
|
2860
3620
|
{
|
|
2861
3621
|
name: "centerLabel",
|
|
2862
3622
|
type: "string",
|
|
2863
|
-
default: "
|
|
2864
|
-
note: "Donut only;
|
|
3623
|
+
default: "undefined",
|
|
3624
|
+
note: "Static label under the center value. Falls back to the literal string 'Total' when unset, and is replaced by the hovered segment's label while a segment is hovered. Donut only; the center block is not rendered for a pie."
|
|
2865
3625
|
},
|
|
2866
3626
|
{
|
|
2867
3627
|
name: "centerValue",
|
|
2868
3628
|
type: "string | number",
|
|
2869
|
-
default: "
|
|
3629
|
+
default: "undefined",
|
|
3630
|
+
note: "Overrides the auto total in the center readout; falls back to the formatted sum of the visible values. Interpolated as-is (no valueFormat). Lower precedence than hover: hovering a segment replaces it with that segment's formatted value. Donut only."
|
|
2870
3631
|
},
|
|
2871
3632
|
{
|
|
2872
3633
|
name: "valueFormat",
|
|
2873
3634
|
type: "(value: number) => string",
|
|
2874
|
-
default: "locale integers for |value| >= 1000"
|
|
3635
|
+
default: "locale integers for |value| >= 1000",
|
|
3636
|
+
note: "Applies to the legend values and to the center value. Not applied to percentages, nor to an explicitly supplied centerValue."
|
|
2875
3637
|
},
|
|
2876
3638
|
{
|
|
2877
3639
|
name: "loading",
|
|
2878
3640
|
type: "boolean",
|
|
2879
|
-
default: "false"
|
|
3641
|
+
default: "false",
|
|
3642
|
+
note: "Replaces the figure with a pulsing skeleton disc and adds the is-loading root class. Takes precedence over the empty state; the legend still renders when data is present."
|
|
2880
3643
|
},
|
|
2881
3644
|
{
|
|
2882
3645
|
name: "ariaLabel",
|
|
2883
3646
|
type: "string",
|
|
2884
|
-
default: "auto-generated summary"
|
|
3647
|
+
default: "auto-generated summary ('Donut chart with <n> segments' / 'Pie chart with <n> segments')",
|
|
3648
|
+
note: 'Applied to the inner <svg role="img">, which only exists in the data state \u2014 neither the loading nor the empty state carries it.'
|
|
2885
3649
|
}
|
|
2886
3650
|
],
|
|
2887
3651
|
events: [],
|
|
@@ -2894,13 +3658,20 @@ var treeui_catalog_default = {
|
|
|
2894
3658
|
}
|
|
2895
3659
|
],
|
|
2896
3660
|
a11y: [
|
|
2897
|
-
"
|
|
2898
|
-
"Legend + percentages give a non-visual reading of each slice."
|
|
3661
|
+
"The inner <svg> carries role=img plus the ariaLabel (or the auto-generated summary); the root div has no role or accessible name.",
|
|
3662
|
+
"Legend + percentages give a non-visual reading of each slice.",
|
|
3663
|
+
"The hover readout is pointer-only \u2014 segments are not focusable and there is no keyboard equivalent, so never make it the only way to reach a value. The legend already carries the same numbers.",
|
|
3664
|
+
"Legend swatches are aria-hidden, so color is never the only carrier of identity.",
|
|
3665
|
+
"Provide a meaningful ariaLabel describing what the chart shows."
|
|
2899
3666
|
],
|
|
2900
3667
|
behavior: [
|
|
2901
|
-
"colors_auto_assign_from_chart_palette: --tree-color-chart-1..8, cycling; per-segment color overrides",
|
|
2902
|
-
"hovering_a_slice_dims_the_rest_and_updates_center:
|
|
2903
|
-
"
|
|
3668
|
+
"colors_auto_assign_from_chart_palette: --tree-color-chart-1..8, cycling by visible-segment index; per-segment color overrides",
|
|
3669
|
+
"hovering_a_slice_dims_the_rest_and_updates_center: the other segments get is-dimmed, the hovered donut segment grows to thickness + 4, and its legend row gets is-active",
|
|
3670
|
+
"hovering_a_legend_row_drives_the_same_highlight: legend items carry the same pointerenter/pointerleave handlers as the segments",
|
|
3671
|
+
"center_readout_precedence: hovered segment > centerValue > formatted total; the label half is hovered segment label > centerLabel > 'Total'",
|
|
3672
|
+
"single_segment_drops_the_gap: with exactly one visible segment the gap is forced to 0 in both donut and pie mode, so the ring/disc closes",
|
|
3673
|
+
"empty_state_when_no_visible_segment_has_value: total <= 0 renders the empty slot instead of the svg; loading wins over it",
|
|
3674
|
+
"segments_fade_in_staggered: 70ms animation delay per segment index; removed under prefers-reduced-motion"
|
|
2904
3675
|
],
|
|
2905
3676
|
selection: {
|
|
2906
3677
|
keywords: [
|
|
@@ -2938,7 +3709,8 @@ var treeui_catalog_default = {
|
|
|
2938
3709
|
},
|
|
2939
3710
|
recipes: [
|
|
2940
3711
|
"metric-dashboard"
|
|
2941
|
-
]
|
|
3712
|
+
],
|
|
3713
|
+
practices: []
|
|
2942
3714
|
},
|
|
2943
3715
|
{
|
|
2944
3716
|
name: "TDrawer",
|
|
@@ -2956,17 +3728,20 @@ var treeui_catalog_default = {
|
|
|
2956
3728
|
{
|
|
2957
3729
|
name: "open",
|
|
2958
3730
|
type: "boolean",
|
|
2959
|
-
default: "controlled_optional"
|
|
3731
|
+
default: "controlled_optional",
|
|
3732
|
+
note: "Runtime default is `undefined`. While it holds anything other than `undefined` the drawer is fully controlled \u2014 the internal state is ignored and the panel only moves when the parent updates this prop."
|
|
2960
3733
|
},
|
|
2961
3734
|
{
|
|
2962
3735
|
name: "defaultOpen",
|
|
2963
3736
|
type: "boolean",
|
|
2964
|
-
default: "false"
|
|
3737
|
+
default: "false",
|
|
3738
|
+
note: "Uncontrolled initial state. Read once on setup \u2014 later changes are ignored. Only meaningful while `open` is undefined. Opening this way skips the on-open side effects; see behavior.initial_open_skips_open_side_effects."
|
|
2965
3739
|
},
|
|
2966
3740
|
{
|
|
2967
3741
|
name: "disabled",
|
|
2968
3742
|
type: "boolean",
|
|
2969
|
-
default: "false"
|
|
3743
|
+
default: "false",
|
|
3744
|
+
note: "Only blocks opening from the `trigger` slot \u2014 the trigger wrapper gets `aria-disabled` and its click is swallowed (preventDefault + stopPropagation). It does NOT block a programmatic open through `open`/`defaultOpen`, and it disables nothing inside the drawer."
|
|
2970
3745
|
},
|
|
2971
3746
|
{
|
|
2972
3747
|
name: "size",
|
|
@@ -2976,7 +3751,8 @@ var treeui_catalog_default = {
|
|
|
2976
3751
|
"sm",
|
|
2977
3752
|
"md",
|
|
2978
3753
|
"lg"
|
|
2979
|
-
]
|
|
3754
|
+
],
|
|
3755
|
+
note: "Applied as `t-drawer__surface--<size>`. Sizes the cross axis of the panel: width for `side: left | right`, height for `side: top | bottom`."
|
|
2980
3756
|
},
|
|
2981
3757
|
{
|
|
2982
3758
|
name: "side",
|
|
@@ -2987,42 +3763,50 @@ var treeui_catalog_default = {
|
|
|
2987
3763
|
"right",
|
|
2988
3764
|
"bottom",
|
|
2989
3765
|
"left"
|
|
2990
|
-
]
|
|
3766
|
+
],
|
|
3767
|
+
note: "Applied as `t-drawer__surface--<side>`. Also selects the slide-in translate direction and which corners are rounded."
|
|
2991
3768
|
},
|
|
2992
3769
|
{
|
|
2993
3770
|
name: "title",
|
|
2994
3771
|
type: "string",
|
|
2995
|
-
default: ""
|
|
3772
|
+
default: "",
|
|
3773
|
+
note: "Rendered as `t-drawer__title` inside the fallback content of the `header` slot. An empty title with no `header` slot removes the header block entirely and leaves `aria-labelledby` unset \u2014 the dialog then has no accessible name."
|
|
2996
3774
|
},
|
|
2997
3775
|
{
|
|
2998
3776
|
name: "description",
|
|
2999
3777
|
type: "string",
|
|
3000
|
-
default: ""
|
|
3778
|
+
default: "",
|
|
3779
|
+
note: "Rendered as `t-drawer__description` between the topbar and the body, and referenced by `aria-describedby`. Only rendered when non-empty. The `content`/`default` body is NOT part of the accessible description."
|
|
3001
3780
|
},
|
|
3002
3781
|
{
|
|
3003
3782
|
name: "closeOnEscape",
|
|
3004
3783
|
type: "boolean",
|
|
3005
|
-
default: "true"
|
|
3784
|
+
default: "true",
|
|
3785
|
+
note: "Escape is handled on the surface's own keydown, so it only fires while focus is inside the drawer. When enabled the handler also calls preventDefault."
|
|
3006
3786
|
},
|
|
3007
3787
|
{
|
|
3008
3788
|
name: "closeOnOverlay",
|
|
3009
3789
|
type: "boolean",
|
|
3010
|
-
default: "true"
|
|
3790
|
+
default: "true",
|
|
3791
|
+
note: "Applies to clicks on `t-drawer__backdrop` only. The backdrop is a sibling of the surface, not an ancestor, so clicks inside the panel never reach it regardless of this prop."
|
|
3011
3792
|
},
|
|
3012
3793
|
{
|
|
3013
3794
|
name: "showCloseButton",
|
|
3014
3795
|
type: "boolean",
|
|
3015
|
-
default: "true"
|
|
3796
|
+
default: "true",
|
|
3797
|
+
note: "The topbar renders when `title` or the `header` slot is present OR this is true. Setting it false with no title and no `header` slot collapses the topbar entirely."
|
|
3016
3798
|
},
|
|
3017
3799
|
{
|
|
3018
3800
|
name: "closeLabel",
|
|
3019
3801
|
type: "string",
|
|
3020
|
-
default: "Close drawer"
|
|
3802
|
+
default: "Close drawer",
|
|
3803
|
+
note: "Accessible name (aria-label) of the header close button, which is icon-only and has no text. Only rendered when `showCloseButton` is true. The component's only localisation hook."
|
|
3021
3804
|
},
|
|
3022
3805
|
{
|
|
3023
3806
|
name: "id",
|
|
3024
3807
|
type: "string",
|
|
3025
|
-
default: "auto"
|
|
3808
|
+
default: "auto",
|
|
3809
|
+
note: "Id of the dialog surface; seeds `<id>-title` and `<id>-description`. Read once on setup (not reactive). Auto-generated via `createId('t-drawer')` when omitted."
|
|
3026
3810
|
}
|
|
3027
3811
|
],
|
|
3028
3812
|
events: [
|
|
@@ -3035,34 +3819,53 @@ var treeui_catalog_default = {
|
|
|
3035
3819
|
],
|
|
3036
3820
|
slots: [
|
|
3037
3821
|
{
|
|
3038
|
-
name: "trigger"
|
|
3822
|
+
name: "trigger",
|
|
3823
|
+
description: "Element that opens the drawer on click. Omit for controlled or imperative use."
|
|
3039
3824
|
},
|
|
3040
3825
|
{
|
|
3041
|
-
name: "header"
|
|
3826
|
+
name: "header",
|
|
3827
|
+
description: "Replaces the default title heading in the topbar."
|
|
3042
3828
|
},
|
|
3043
3829
|
{
|
|
3044
|
-
name: "default"
|
|
3830
|
+
name: "default",
|
|
3831
|
+
description: "Drawer body content."
|
|
3045
3832
|
},
|
|
3046
3833
|
{
|
|
3047
|
-
name: "content"
|
|
3834
|
+
name: "content",
|
|
3835
|
+
description: "Drawer body content; takes precedence over the default slot."
|
|
3048
3836
|
},
|
|
3049
3837
|
{
|
|
3050
|
-
name: "footer"
|
|
3838
|
+
name: "footer",
|
|
3839
|
+
description: "Action row pinned under the body."
|
|
3051
3840
|
}
|
|
3052
3841
|
],
|
|
3053
3842
|
a11y: [
|
|
3054
3843
|
"role: dialog",
|
|
3055
3844
|
"aria_modal: true",
|
|
3056
3845
|
"focus_trap: true",
|
|
3057
|
-
|
|
3058
|
-
"escape_closes_when_enabled: true"
|
|
3846
|
+
'restores_focus_on_close: {"value":"partial","detail":"The previously focused element is recorded only in the trigger-click path. A drawer opened programmatically \u2014 by setting `open` from elsewhere, or by `defaultOpen` \u2014 records nothing, so focus is not restored on close. Move focus back yourself in that case.\\n"}',
|
|
3847
|
+
"escape_closes_when_enabled: true",
|
|
3848
|
+
"escape_scope: The keydown listener lives on the surface, so Escape only closes while focus is inside the drawer.",
|
|
3849
|
+
"accessible_name_source: the `t-drawer__header` div, via aria-labelledby; unset when `title` is empty and no `header` slot is supplied",
|
|
3850
|
+
"accessible_description_source: the `description` prop, via aria-describedby; the body slots are not included",
|
|
3851
|
+
'initial_focus: First focusable element inside the surface, else the surface itself (`tabindex=\\"-1\\"`, with a visible `:focus-visible` ring). Applied on the closed \u2192 open transition only.',
|
|
3852
|
+
"backdrop_marked_aria_hidden: true",
|
|
3853
|
+
"trigger_state_not_announced: The trigger wrapper gets no aria-haspopup, aria-expanded, or aria-controls, and no scoped props are exposed to build them. A trigger that needs to announce the drawer must wire those attributes from consumer state."
|
|
3059
3854
|
],
|
|
3060
3855
|
behavior: [
|
|
3061
3856
|
"uses_teleport_to_body: true",
|
|
3062
3857
|
"locks_body_scroll_while_open: true",
|
|
3063
3858
|
"overlay_click_closes_when_enabled: true",
|
|
3064
3859
|
"close_button_optional: true",
|
|
3065
|
-
"slides_in_from_side: true"
|
|
3860
|
+
"slides_in_from_side: true",
|
|
3861
|
+
"root_uses_display_contents_without_trigger: `t-drawer` is `display: inline-flex`, but a root with no `t-drawer__trigger` child switches to `display: contents` so the empty wrapper does not generate a line box and add stray height to the page.",
|
|
3862
|
+
"topbar_rendered_when: title is non-empty OR the `header` slot is supplied OR showCloseButton is true",
|
|
3863
|
+
"body_slot_precedence: content > default",
|
|
3864
|
+
"footer_rendered_when: the `footer` slot is supplied",
|
|
3865
|
+
'data_state_attribute: `data-state="open" | "closed"` on both the `t-drawer` root and the `t-drawer__portal`',
|
|
3866
|
+
"focus_trap_detail: Tab and Shift+Tab cycle within the surface. With no focusable descendants, Tab is swallowed and focus is pushed back to the surface itself.",
|
|
3867
|
+
'initial_open_skips_open_side_effects: {"value":true,"detail":"The on-open work \u2014 body scroll lock and initial focus \u2014 runs from a watcher on the open state that is not immediate, so a drawer that starts open via `defaultOpen: true` (or an `open` prop already true on first render) never locks scroll and never moves focus into the surface. Focus trap and Escape therefore stay dormant until the user tabs in. Start closed and open on the next tick if you need the full behavior.\\n"}',
|
|
3868
|
+
'body_scroll_lock_scope: {"value":"per_component_instance","detail":"The overlay counter and the saved `overflow` value are per instance, not shared across overlays. Two overlays open at once each restore what they individually saw, so closing the first-opened one while a second is still open unlocks page scroll early.\\n"}'
|
|
3066
3869
|
],
|
|
3067
3870
|
selection: {
|
|
3068
3871
|
keywords: [
|
|
@@ -3091,7 +3894,10 @@ var treeui_catalog_default = {
|
|
|
3091
3894
|
required: [],
|
|
3092
3895
|
notes: []
|
|
3093
3896
|
},
|
|
3094
|
-
recipes: []
|
|
3897
|
+
recipes: [],
|
|
3898
|
+
practices: [
|
|
3899
|
+
"accessible-by-default"
|
|
3900
|
+
]
|
|
3095
3901
|
},
|
|
3096
3902
|
{
|
|
3097
3903
|
name: "TDropdown",
|
|
@@ -3110,22 +3916,25 @@ var treeui_catalog_default = {
|
|
|
3110
3916
|
name: "items",
|
|
3111
3917
|
type: "TDropdownItem[]",
|
|
3112
3918
|
default: "[]",
|
|
3113
|
-
note:
|
|
3919
|
+
note: 'Array of { label: string; value: string; disabled?: boolean }. Each entry renders one `<li role="menuitem">`, keyed by `value` \u2014 values must be unique, because the internal element map that drives focus is also keyed by `value` and duplicates collide. With the default `[]` the component still renders an empty `<ul role="menu">` and focus stays on the trigger; there is no empty-state affordance (no `emptyText`, no `empty` slot), so guard on `items.length` yourself.'
|
|
3114
3920
|
},
|
|
3115
3921
|
{
|
|
3116
3922
|
name: "open",
|
|
3117
3923
|
type: "boolean",
|
|
3118
|
-
default: "undefined"
|
|
3924
|
+
default: "undefined",
|
|
3925
|
+
note: "Controlled open state. Once a boolean is passed the component stops tracking open state internally \u2014 it only emits update:open / open-change and the consumer MUST write the value back, or the menu never opens. Flipping it externally does not run the open routine: no item is focused and the outside-click listener is only attached from the transition, so an initially-`true` value opens the menu with focus untouched."
|
|
3119
3926
|
},
|
|
3120
3927
|
{
|
|
3121
3928
|
name: "defaultOpen",
|
|
3122
3929
|
type: "boolean",
|
|
3123
|
-
default: "false"
|
|
3930
|
+
default: "false",
|
|
3931
|
+
note: "Uncontrolled initial open state, read once on mount. Later changes to it are ignored. It renders the menu already open but does NOT focus the first item (focusedIndex stays -1, so no `is-focused` row) and does NOT arm the outside-click listener until the open state changes at least once \u2014 see behavior.outside_click_closes_menu."
|
|
3124
3932
|
},
|
|
3125
3933
|
{
|
|
3126
3934
|
name: "disabled",
|
|
3127
3935
|
type: "boolean",
|
|
3128
|
-
default: "false"
|
|
3936
|
+
default: "false",
|
|
3937
|
+
note: 'Sets the native `disabled` attribute on the built-in trigger button, adds `is-disabled` to the root, and suppresses the menu entirely (`v-if="isOpen && !disabled"`) \u2014 even while `open` is true. Also short-circuits openMenu, toggleMenu and the trigger keydown handler. It is bound only to the default button, so a custom `trigger` slot must render its own disabled state.'
|
|
3129
3938
|
},
|
|
3130
3939
|
{
|
|
3131
3940
|
name: "size",
|
|
@@ -3135,12 +3944,14 @@ var treeui_catalog_default = {
|
|
|
3135
3944
|
"sm",
|
|
3136
3945
|
"md",
|
|
3137
3946
|
"lg"
|
|
3138
|
-
]
|
|
3947
|
+
],
|
|
3948
|
+
note: "Sizes the trigger and the menu rows. `t-dropdown--md` is emitted but has no CSS rule of its own \u2014 it is the base `.t-dropdown__trigger` / `.t-dropdown__item` styling."
|
|
3139
3949
|
},
|
|
3140
3950
|
{
|
|
3141
3951
|
name: "label",
|
|
3142
3952
|
type: "string",
|
|
3143
|
-
default: ""
|
|
3953
|
+
default: "",
|
|
3954
|
+
note: 'Text of the built-in trigger button AND the menu\'s accessible name (`:aria-label="label || undefined"` on the `<ul role="menu">`). A custom `trigger` slot does not render `label`, but it still names the menu \u2014 keep passing it, or the menu has no accessible name at all.'
|
|
3144
3955
|
},
|
|
3145
3956
|
{
|
|
3146
3957
|
name: "align",
|
|
@@ -3150,18 +3961,30 @@ var treeui_catalog_default = {
|
|
|
3150
3961
|
"start",
|
|
3151
3962
|
"end"
|
|
3152
3963
|
],
|
|
3153
|
-
note: "Horizontal alignment of the menu relative to the trigger
|
|
3964
|
+
note: "Horizontal alignment of the menu relative to the trigger \u2014 `start` pins `left: 0`, `end` pins `right: 0`. Use `end` when the trigger sits near the right edge of a clipping container (e.g. a table actions column). There is no collision detection: the menu is a plain absolutely-positioned child of the root, so it never flips and is clipped by any ancestor with `overflow: hidden`."
|
|
3965
|
+
},
|
|
3966
|
+
{
|
|
3967
|
+
name: "id",
|
|
3968
|
+
type: "string",
|
|
3969
|
+
default: "undefined",
|
|
3970
|
+
note: "Custom id for the menu element. Auto-generated when omitted; also exposed to the `trigger` slot as `menuId` so a custom trigger can wire aria-controls. Resolved once during setup \u2014 it is NOT reactive, so changing `id` after mount has no effect."
|
|
3154
3971
|
}
|
|
3155
3972
|
],
|
|
3156
3973
|
events: [
|
|
3157
3974
|
{
|
|
3158
|
-
name: "select"
|
|
3975
|
+
name: "select",
|
|
3976
|
+
description: "Emitted with the chosen item's `value`. Disabled items never emit. Fires before the menu closes; the close that follows restores focus to the trigger.",
|
|
3977
|
+
payload: '[{"value":"string"}]'
|
|
3159
3978
|
},
|
|
3160
3979
|
{
|
|
3161
|
-
name: "update:open"
|
|
3980
|
+
name: "update:open",
|
|
3981
|
+
description: "Emitted whenever the open state changes. Deduped \u2014 no emit when the next value equals the current one.",
|
|
3982
|
+
payload: '["boolean"]'
|
|
3162
3983
|
},
|
|
3163
3984
|
{
|
|
3164
|
-
name: "open-change"
|
|
3985
|
+
name: "open-change",
|
|
3986
|
+
description: "Emitted immediately after `update:open`, with the same payload. Alias for consumers that do not use v-model:open.",
|
|
3987
|
+
payload: '["boolean"]'
|
|
3165
3988
|
}
|
|
3166
3989
|
],
|
|
3167
3990
|
slots: [
|
|
@@ -3174,23 +3997,39 @@ var treeui_catalog_default = {
|
|
|
3174
3997
|
],
|
|
3175
3998
|
a11y: [
|
|
3176
3999
|
"role: menu",
|
|
4000
|
+
"menu_accessible_name_comes_from_the_label_prop: true",
|
|
3177
4001
|
"trigger_aria_haspopup: menu",
|
|
3178
4002
|
"trigger_aria_expanded: true",
|
|
3179
4003
|
"trigger_aria_controls: menu id, while open",
|
|
4004
|
+
"custom_trigger_caveat: The three trigger_aria_* guarantees above describe the BUILT-IN trigger button only. A custom `trigger` slot replaces that button, so the consumer must bind them from the `isOpen` and `menuId` scoped props \u2014 see slots.trigger.",
|
|
4005
|
+
"item_role: menuitem",
|
|
3180
4006
|
"aria_disabled_on_disabled_items: true",
|
|
4007
|
+
"disabled_items_get_tabindex_minus_1_but_stay_programmatically_focusable: true",
|
|
3181
4008
|
"focus_visible_on_trigger: true",
|
|
4009
|
+
"items_receive_real_dom_focus_no_aria_activedescendant: true",
|
|
3182
4010
|
"keyboard_arrow_navigation: true",
|
|
4011
|
+
"arrow_navigation_skips_disabled_items: true",
|
|
4012
|
+
"arrow_navigation_does_not_wrap_at_the_ends: true",
|
|
4013
|
+
"arrow_down_or_arrow_up_on_the_trigger_both_open_at_the_first_enabled_item: true",
|
|
3183
4014
|
"escape_closes_menu: true",
|
|
3184
4015
|
"enter_space_selects_item: true",
|
|
3185
|
-
"home_end_navigation: true"
|
|
4016
|
+
"home_end_navigation: true",
|
|
4017
|
+
"no_typeahead: true",
|
|
4018
|
+
"tab_does_not_close_the_menu: true"
|
|
3186
4019
|
],
|
|
3187
4020
|
behavior: [
|
|
3188
|
-
|
|
4021
|
+
'outside_click_closes_menu: {"value":true,"detail":"Detected on a document `pointerdown` listener that is attached by a watcher on the open state. The watcher is not immediate, so a menu that is already open on mount \u2014 via `defaultOpen` or an initially-`true` `open` \u2014 has no listener until the open state changes at least once, and outside clicks do not close it.\\n"}',
|
|
3189
4022
|
"outside_click_restores_focus: false",
|
|
3190
4023
|
"chevron_rotates_when_open: true",
|
|
3191
4024
|
"menu_grows_to_fit_items_without_wrapping: true",
|
|
3192
|
-
"
|
|
3193
|
-
|
|
4025
|
+
"menu_scrolls_vertically_past_15rem: true",
|
|
4026
|
+
"menu_renders_in_flow_with_no_portal_and_no_flip_positioning: true",
|
|
4027
|
+
"menu_is_not_rendered_while_disabled: true",
|
|
4028
|
+
"open_state_emits_are_deduped: true",
|
|
4029
|
+
"controlled_open_requires_writing_the_value_back: true",
|
|
4030
|
+
'opening_focuses_first_enabled_item: {"value":true,"detail":"Applies to the open routine only \u2014 a click or Enter/Space/ArrowDown/ArrowUp on the trigger. `defaultOpen` and an externally driven `open` skip it, leaving focusedIndex at -1 with no row focused and no `is-focused` class. With an empty `items` array focus stays on the trigger; when every item is disabled, focus lands on the first (disabled) item.\\n"}',
|
|
4031
|
+
'keyboard_activation_on_the_trigger_never_closes_the_menu: {"value":true,"detail":"Clicking the trigger toggles, but Enter/Space/Arrow keys always call the open routine, so pressing them while the menu is open re-focuses the first enabled item instead of closing. Escape is the keyboard close.\\n"}',
|
|
4032
|
+
'focus_restores_on_close: {"value":true,"detail":"Focus returns to the trigger when the menu closes from inside it \u2014 selecting an item or pressing Escape on an item. Closing from the trigger itself (clicking it again, or Escape while the trigger holds focus) does not run the restore, because focus is already there. It deliberately does NOT move focus on an outside click, where the pointer has already placed focus elsewhere.\\n","applies_to_custom_trigger":true}'
|
|
3194
4033
|
],
|
|
3195
4034
|
selection: {
|
|
3196
4035
|
keywords: [
|
|
@@ -3219,7 +4058,11 @@ var treeui_catalog_default = {
|
|
|
3219
4058
|
required: [],
|
|
3220
4059
|
notes: []
|
|
3221
4060
|
},
|
|
3222
|
-
recipes: []
|
|
4061
|
+
recipes: [],
|
|
4062
|
+
practices: [
|
|
4063
|
+
"interaction-feedback",
|
|
4064
|
+
"accessible-by-default"
|
|
4065
|
+
]
|
|
3223
4066
|
},
|
|
3224
4067
|
{
|
|
3225
4068
|
name: "TEmptyState",
|
|
@@ -3311,7 +4154,10 @@ var treeui_catalog_default = {
|
|
|
3311
4154
|
required: [],
|
|
3312
4155
|
notes: []
|
|
3313
4156
|
},
|
|
3314
|
-
recipes: []
|
|
4157
|
+
recipes: [],
|
|
4158
|
+
practices: [
|
|
4159
|
+
"state-clarity"
|
|
4160
|
+
]
|
|
3315
4161
|
},
|
|
3316
4162
|
{
|
|
3317
4163
|
name: "TFileUpload",
|
|
@@ -3345,7 +4191,7 @@ var treeui_catalog_default = {
|
|
|
3345
4191
|
name: "disabled",
|
|
3346
4192
|
type: "boolean",
|
|
3347
4193
|
default: "false",
|
|
3348
|
-
description: "The ONLY prop that gates interaction. Disables the dropzone, the native input, Clear all, and every per-row Remove/Retry."
|
|
4194
|
+
description: "The ONLY prop that gates interaction. Disables the dropzone, the native input, Clear all, and every per-row Remove/Retry, and makes the paste and drop handlers early-return."
|
|
3349
4195
|
},
|
|
3350
4196
|
{
|
|
3351
4197
|
name: "loading",
|
|
@@ -3370,13 +4216,15 @@ var treeui_catalog_default = {
|
|
|
3370
4216
|
},
|
|
3371
4217
|
{
|
|
3372
4218
|
name: "maxFiles",
|
|
3373
|
-
type: "number",
|
|
3374
|
-
default: "
|
|
4219
|
+
type: "number | null",
|
|
4220
|
+
default: "null",
|
|
4221
|
+
description: "Cap on the TOTAL list size, not on one batch \u2014 remaining slots are counted against the files already selected. `multiple: false` overrides it with a hard cap of 1. Values below 0 are clamped to 0, which rejects everything."
|
|
3375
4222
|
},
|
|
3376
4223
|
{
|
|
3377
4224
|
name: "maxFileSize",
|
|
3378
|
-
type: "number",
|
|
3379
|
-
default: "
|
|
4225
|
+
type: "number | null",
|
|
4226
|
+
default: "null",
|
|
4227
|
+
description: "Per-file byte cap. Enforced only when it is a number greater than 0 \u2014 both `null` and `0` disable the check."
|
|
3380
4228
|
},
|
|
3381
4229
|
{
|
|
3382
4230
|
name: "label",
|
|
@@ -3550,19 +4398,144 @@ var treeui_catalog_default = {
|
|
|
3550
4398
|
"thumbnails_are_client_only: Object URLs are minted after mount and revoked on removal and unmount. SSR and the hydrating render both show the extension chip, so there is no mismatch."
|
|
3551
4399
|
],
|
|
3552
4400
|
selection: {
|
|
3553
|
-
keywords: [],
|
|
3554
|
-
useWhen: [],
|
|
3555
|
-
avoidWhen: [],
|
|
3556
|
-
alternatives: []
|
|
4401
|
+
keywords: [],
|
|
4402
|
+
useWhen: [],
|
|
4403
|
+
avoidWhen: [],
|
|
4404
|
+
alternatives: []
|
|
4405
|
+
},
|
|
4406
|
+
setup: {
|
|
4407
|
+
required: [],
|
|
4408
|
+
notes: [
|
|
4409
|
+
"Bind `modelValue` to `File[]`.",
|
|
4410
|
+
"Use `accept`, `multiple`, and size limits in the app layer to constrain uploads."
|
|
4411
|
+
]
|
|
4412
|
+
},
|
|
4413
|
+
recipes: [],
|
|
4414
|
+
practices: []
|
|
4415
|
+
},
|
|
4416
|
+
{
|
|
4417
|
+
name: "TFlag",
|
|
4418
|
+
aliases: [],
|
|
4419
|
+
package: "@treeui/vue",
|
|
4420
|
+
kind: "display",
|
|
4421
|
+
category: "Data Display",
|
|
4422
|
+
status: "available",
|
|
4423
|
+
purpose: "Render a flat country flag image from a CDN at a fixed height, centred in a 3:2 box, with a text fallback when the request fails.",
|
|
4424
|
+
sourceFile: "packages/vue/src/components/TFlag.vue",
|
|
4425
|
+
storyFile: "apps/docs/src/stories/Flag.stories.ts",
|
|
4426
|
+
storyTitle: "Components/Data Display/Flag",
|
|
4427
|
+
manifestFile: "docs/ai/COMPONENTS/flag.yaml",
|
|
4428
|
+
props: [
|
|
4429
|
+
{
|
|
4430
|
+
name: "code",
|
|
4431
|
+
type: "string",
|
|
4432
|
+
required: true,
|
|
4433
|
+
description: "ISO 3166-1 alpha-2 country code. Case-insensitive \u2014 trimmed and lowercased before the URL is built."
|
|
4434
|
+
},
|
|
4435
|
+
{
|
|
4436
|
+
name: "baseUrl",
|
|
4437
|
+
type: "string",
|
|
4438
|
+
default: "https://flagcdn.com",
|
|
4439
|
+
description: "Origin serving the flag assets. The component appends a fixed path built from the CDN's fixed-height segments, so a self-hosted mirror must reproduce it exactly: 1x is `${baseUrl}/h20/{code}.png` (sm), `${baseUrl}/h20/{code}.png` (md), `${baseUrl}/h24/{code}.png` (lg); the matching 2x asset is emitted via srcset as `${baseUrl}/h40/{code}.png` (sm), `${baseUrl}/h40/{code}.png` (md), `${baseUrl}/h60/{code}.png` (lg). A trailing slash is stripped, so `https://cdn.example.com/flags/` and `https://cdn.example.com/flags` behave identically."
|
|
4440
|
+
},
|
|
4441
|
+
{
|
|
4442
|
+
name: "size",
|
|
4443
|
+
type: "TSize",
|
|
4444
|
+
default: "md",
|
|
4445
|
+
values: [
|
|
4446
|
+
"sm",
|
|
4447
|
+
"md",
|
|
4448
|
+
"lg"
|
|
4449
|
+
],
|
|
4450
|
+
description: "Box height, taken from `--tree-size-icon-sm/md/lg` (16px / 20px / 24px); the box width is 3:2 of that height. Also selects which CDN asset pair is requested \u2014 see `baseUrl`."
|
|
4451
|
+
},
|
|
4452
|
+
{
|
|
4453
|
+
name: "label",
|
|
4454
|
+
type: "string",
|
|
4455
|
+
default: "undefined",
|
|
4456
|
+
description: 'Accessible label. When set, the flag becomes role="img" with aria-label; otherwise it is aria-hidden. An empty string counts as unset \u2014 the flag stays decorative.'
|
|
4457
|
+
},
|
|
4458
|
+
{
|
|
4459
|
+
name: "fallbackText",
|
|
4460
|
+
type: "string",
|
|
4461
|
+
default: "undefined",
|
|
4462
|
+
description: 'Text shown when the image cannot load. Defaults to the normalized `code` uppercased, so a padded `" br "` falls back to `BR`.'
|
|
4463
|
+
}
|
|
4464
|
+
],
|
|
4465
|
+
events: [],
|
|
4466
|
+
slots: [],
|
|
4467
|
+
a11y: [
|
|
4468
|
+
"decorative_by_default: true",
|
|
4469
|
+
"becomes_image_when_labeled: true",
|
|
4470
|
+
'image_alt_is_always_empty: The `<img>` always carries `alt=""`, so the accessible name comes only from `label` on the root span \u2014 never from the image itself.',
|
|
4471
|
+
'fallback_text_is_hidden_when_decorative: The fallback text renders inside the root span, so without `label` it inherits `aria-hidden="true"` and is not announced. It is a visual affordance, not an accessible name.',
|
|
4472
|
+
'consumer_aria_label_does_not_replace_label: Fallthrough attributes land on the same root span, so a consumer-supplied `aria-label` overrides the one built from `label` \u2014 but it does not set `role="img"` or clear `aria-hidden="true"`, leaving the flag hidden and the label unannounced. Use the `label` prop instead.',
|
|
4473
|
+
"rule: Provide `label` only when the flag carries meaning that is not already in adjacent text \u2014 inside a language option the label is redundant."
|
|
4474
|
+
],
|
|
4475
|
+
behavior: [
|
|
4476
|
+
"falls_back_to_text_when_image_fails: true",
|
|
4477
|
+
"failed_state_resets_when_resolved_src_changes: true",
|
|
4478
|
+
"code_is_trimmed_and_lowercased: true",
|
|
4479
|
+
"fixed_height_endpoints_serve_flat_artwork_at_true_proportions: The CDN's ratio-normalised (width-by-height) endpoints do force every flag into one box, but only by serving the WAVING artwork, which reads as decoration next to flat UI icons. The fixed-height endpoints used here (h20, h24, h40, h60) serve the flat artwork at each flag's true proportions instead: Nepal stays a pennant, Switzerland stays square, Qatar stays elongated.",
|
|
4480
|
+
"shared_height_not_shared_ratio_is_what_aligns_a_column: Within a size step every flag is requested at the same asset height, so a stacked list lines up even though the widths differ. CSS then places each flag in a fixed 3:2 box (3:2 being the most common national flag ratio) with `object-fit: contain`, so the majority fill the box and the outliers centre inside it rather than being cropped or distorted.",
|
|
4481
|
+
"retina_asset_is_at_least_twice_the_box_height: Box heights come from `--tree-size-icon-sm/md/lg` (16px / 20px / 24px) and the srcset asset is h40 (sm, md) or h60 (lg), so a 2x screen never upscales.",
|
|
4482
|
+
"size_outside_the_union_falls_back_to_md: A JS consumer can pass a size outside `TSize`; the asset lookup falls back to the md pair rather than throwing on an undefined entry.",
|
|
4483
|
+
"base_url_trailing_slash_is_normalised: Trailing slashes are stripped from `baseUrl` before the path is appended, so a self-hosted mirror cannot silently produce a double-slashed URL.",
|
|
4484
|
+
"sm_and_md_share_one_asset_pair: sm and md both request h20 (h40 at 2x); only lg differs (h24, h60 at 2x). Four distinct segments exist in total, not one pair per size step, so a mirror needs four directories per flag.",
|
|
4485
|
+
"path_template_is_public_contract: Changing `baseUrl` is a config change, not a breaking one, as long as the mirror serves the same fixed-height segments (h20, h24, h40, h60).",
|
|
4486
|
+
"image_element_is_removed_not_hidden_on_failure: The `<img>` is behind `v-if`, so a failed load takes it out of the DOM and swaps in the fallback span \u2014 it is not left in place with `display: none`.",
|
|
4487
|
+
"no_country_or_locale_dataset_is_shipped: TreeUI never maps a language or locale to a country code \u2014 the application owns that decision."
|
|
4488
|
+
],
|
|
4489
|
+
selection: {
|
|
4490
|
+
keywords: [
|
|
4491
|
+
"flag",
|
|
4492
|
+
"country flag",
|
|
4493
|
+
"country",
|
|
4494
|
+
"nationality",
|
|
4495
|
+
"region",
|
|
4496
|
+
"iso 3166",
|
|
4497
|
+
"alpha-2"
|
|
4498
|
+
],
|
|
4499
|
+
useWhen: [
|
|
4500
|
+
"You need a country flag rendered from an ISO 3166-1 alpha-2 code.",
|
|
4501
|
+
"Flags stacked in a list must share one height so rows stay aligned \u2014 the flat assets keep each flag's true proportions and centre inside a fixed 3:2 box.",
|
|
4502
|
+
"You want a text fallback when the flag asset cannot load."
|
|
4503
|
+
],
|
|
4504
|
+
avoidWhen: [
|
|
4505
|
+
"The flag would be the only carrier of meaning \u2014 always pair it with adjacent text such as the language or country name.",
|
|
4506
|
+
"You need an interface glyph rather than a country flag.",
|
|
4507
|
+
"You are treating the flag as a language identity \u2014 a flag names a country, not a language."
|
|
4508
|
+
],
|
|
4509
|
+
alternatives: [
|
|
4510
|
+
{
|
|
4511
|
+
component: "TIcon",
|
|
4512
|
+
when: "The graphic is a registered TreeUI icon, not a country flag."
|
|
4513
|
+
},
|
|
4514
|
+
{
|
|
4515
|
+
component: "TLanguageSelect",
|
|
4516
|
+
when: "The flag belongs to a language or locale picker rather than standing alone."
|
|
4517
|
+
}
|
|
4518
|
+
]
|
|
3557
4519
|
},
|
|
3558
4520
|
setup: {
|
|
3559
|
-
required: [
|
|
4521
|
+
required: [
|
|
4522
|
+
"Pass `code` as an ISO 3166-1 alpha-2 country code. Matching is case-insensitive \u2014 the value is trimmed and lowercased internally.",
|
|
4523
|
+
"Allow `https://flagcdn.com` in the app `Content-Security-Policy` `img-src` directive, or point `baseUrl` at a self-hosted mirror \u2014 flag images are fetched from a third-party CDN at runtime."
|
|
4524
|
+
],
|
|
3560
4525
|
notes: [
|
|
3561
|
-
"
|
|
3562
|
-
"
|
|
4526
|
+
"A mirror must serve `{baseUrl}/{segment}/{code}.png` for both steps of every size: 1x `h20` (sm), `h20` (md), `h24` (lg); 2x `h40` (sm), `h40` (md), `h60` (lg). The 2x asset is emitted through `srcset`.",
|
|
4527
|
+
"Those fixed-height segments are part of the contract, and they are the CDN's flat artwork \u2014 a mirror must serve flat flags, not the waving ones.",
|
|
4528
|
+
"Do not substitute the CDN's ratio-normalised width-by-height endpoints. They equalise aspect ratio only by switching to the waving artwork, which reads as decoration next to flat UI icons.",
|
|
4529
|
+
"The fixed-height assets keep each flag's true proportions \u2014 Nepal is a pennant, Switzerland is square, Qatar is elongated. A shared height, not a shared ratio, is what aligns a column of flags.",
|
|
4530
|
+
"CSS puts the image in a fixed 3:2 box (3:2 being the most common national flag ratio) with `object-fit: contain`, so outliers centre inside the box instead of being cropped or distorted.",
|
|
4531
|
+
"Each retina segment is at least twice its box height \u2014 boxes are `--tree-size-icon-sm/md/lg` = 16px/20px/24px \u2014 so 2x screens never upscale.",
|
|
4532
|
+
"`baseUrl` may be written with or without a trailing slash; trailing slashes are stripped before the path is built. An unknown `size` falls back to the `md` assets.",
|
|
4533
|
+
"When the image cannot load \u2014 offline, blocked by CSP, unknown code \u2014 the component renders the uppercased `code` as text. Override that text with `fallbackText`.",
|
|
4534
|
+
"The flag is `aria-hidden` by default. Pass `label` only when the flag carries meaning on its own; beside a visible country or language name it should stay decorative."
|
|
3563
4535
|
]
|
|
3564
4536
|
},
|
|
3565
|
-
recipes: []
|
|
4537
|
+
recipes: [],
|
|
4538
|
+
practices: []
|
|
3566
4539
|
},
|
|
3567
4540
|
{
|
|
3568
4541
|
name: "TFormField",
|
|
@@ -3691,7 +4664,12 @@ var treeui_catalog_default = {
|
|
|
3691
4664
|
"date-range-form",
|
|
3692
4665
|
"color-field",
|
|
3693
4666
|
"tag-input",
|
|
3694
|
-
"hierarchy-picker"
|
|
4667
|
+
"hierarchy-picker",
|
|
4668
|
+
"language-switcher"
|
|
4669
|
+
],
|
|
4670
|
+
practices: [
|
|
4671
|
+
"accessible-by-default",
|
|
4672
|
+
"content-alignment"
|
|
3695
4673
|
]
|
|
3696
4674
|
},
|
|
3697
4675
|
{
|
|
@@ -3793,6 +4771,9 @@ var treeui_catalog_default = {
|
|
|
3793
4771
|
"date-range-form",
|
|
3794
4772
|
"stat-grid",
|
|
3795
4773
|
"metric-dashboard"
|
|
4774
|
+
],
|
|
4775
|
+
practices: [
|
|
4776
|
+
"content-alignment"
|
|
3796
4777
|
]
|
|
3797
4778
|
},
|
|
3798
4779
|
{
|
|
@@ -3813,24 +4794,380 @@ var treeui_catalog_default = {
|
|
|
3813
4794
|
type: "TIconName",
|
|
3814
4795
|
required: true,
|
|
3815
4796
|
values: [
|
|
4797
|
+
"account",
|
|
4798
|
+
"activity",
|
|
4799
|
+
"ai-studio",
|
|
3816
4800
|
"alert-circle",
|
|
4801
|
+
"align-left",
|
|
4802
|
+
"app-window",
|
|
4803
|
+
"apps-grid",
|
|
4804
|
+
"archive",
|
|
4805
|
+
"archive-restore",
|
|
4806
|
+
"arrow-down",
|
|
4807
|
+
"arrow-left",
|
|
4808
|
+
"arrow-left-right",
|
|
4809
|
+
"arrow-right",
|
|
4810
|
+
"arrow-up",
|
|
4811
|
+
"arrow-up-right",
|
|
4812
|
+
"assistant",
|
|
4813
|
+
"automation-key",
|
|
4814
|
+
"automations",
|
|
4815
|
+
"badge",
|
|
4816
|
+
"badge-check",
|
|
4817
|
+
"badge-star",
|
|
4818
|
+
"ban",
|
|
4819
|
+
"bell",
|
|
4820
|
+
"book-open",
|
|
4821
|
+
"bookmark",
|
|
4822
|
+
"bot",
|
|
4823
|
+
"bot-badge",
|
|
4824
|
+
"bot-users",
|
|
4825
|
+
"boxes",
|
|
4826
|
+
"boxes-model",
|
|
4827
|
+
"braces",
|
|
4828
|
+
"brackets",
|
|
4829
|
+
"brain",
|
|
4830
|
+
"brain-circuit",
|
|
4831
|
+
"brain-lock",
|
|
4832
|
+
"browser",
|
|
4833
|
+
"brush",
|
|
4834
|
+
"brush-stroke",
|
|
4835
|
+
"bug",
|
|
4836
|
+
"building-2",
|
|
4837
|
+
"calculator",
|
|
3817
4838
|
"calendar",
|
|
4839
|
+
"calendar-clock",
|
|
4840
|
+
"calendar-day",
|
|
4841
|
+
"calendar-days",
|
|
4842
|
+
"calendar-dot",
|
|
4843
|
+
"calendar-plus",
|
|
4844
|
+
"calendar-range",
|
|
4845
|
+
"calendar-x",
|
|
4846
|
+
"carousel",
|
|
4847
|
+
"catalog",
|
|
4848
|
+
"chart-column",
|
|
4849
|
+
"chart-line",
|
|
4850
|
+
"chart-pie",
|
|
4851
|
+
"chat",
|
|
3818
4852
|
"check",
|
|
3819
|
-
"
|
|
4853
|
+
"check-circle",
|
|
4854
|
+
"check-square",
|
|
3820
4855
|
"chevron-down",
|
|
4856
|
+
"chevron-left",
|
|
3821
4857
|
"chevron-right",
|
|
4858
|
+
"chevron-up",
|
|
4859
|
+
"chevron-updown",
|
|
4860
|
+
"chevrons-up-down",
|
|
4861
|
+
"circle-alert",
|
|
4862
|
+
"circle-check",
|
|
4863
|
+
"circle-dot",
|
|
4864
|
+
"circle-help",
|
|
4865
|
+
"circle-x",
|
|
4866
|
+
"clipboard-list",
|
|
4867
|
+
"clock",
|
|
4868
|
+
"clock-alert",
|
|
4869
|
+
"clock-sparkles",
|
|
4870
|
+
"clock-x",
|
|
4871
|
+
"close",
|
|
4872
|
+
"cloud",
|
|
4873
|
+
"cloud-off",
|
|
4874
|
+
"code",
|
|
4875
|
+
"code-2",
|
|
4876
|
+
"code-api",
|
|
4877
|
+
"coins",
|
|
4878
|
+
"comment",
|
|
4879
|
+
"companion",
|
|
4880
|
+
"compass",
|
|
4881
|
+
"connections",
|
|
4882
|
+
"contentpilot",
|
|
4883
|
+
"copy",
|
|
4884
|
+
"cpu",
|
|
4885
|
+
"cpu-chip",
|
|
4886
|
+
"credit-card",
|
|
4887
|
+
"crosshair",
|
|
4888
|
+
"crown",
|
|
4889
|
+
"cube",
|
|
4890
|
+
"database",
|
|
4891
|
+
"developer-settings",
|
|
4892
|
+
"device-link",
|
|
4893
|
+
"dollar-circle",
|
|
4894
|
+
"dollar-limit",
|
|
4895
|
+
"download",
|
|
4896
|
+
"download-video",
|
|
4897
|
+
"draw",
|
|
4898
|
+
"droplet",
|
|
4899
|
+
"ellipsis",
|
|
4900
|
+
"ellipsis-vertical",
|
|
4901
|
+
"embed-code",
|
|
4902
|
+
"eraser",
|
|
4903
|
+
"extension",
|
|
4904
|
+
"external-link",
|
|
4905
|
+
"eye",
|
|
4906
|
+
"eye-off",
|
|
4907
|
+
"file",
|
|
4908
|
+
"file-archive",
|
|
4909
|
+
"file-audio",
|
|
4910
|
+
"file-code",
|
|
4911
|
+
"file-edit",
|
|
4912
|
+
"file-image",
|
|
4913
|
+
"file-pdf",
|
|
4914
|
+
"file-plus",
|
|
4915
|
+
"file-scan",
|
|
4916
|
+
"file-text",
|
|
4917
|
+
"file-video",
|
|
4918
|
+
"file-warning",
|
|
4919
|
+
"files",
|
|
4920
|
+
"film",
|
|
4921
|
+
"filter",
|
|
4922
|
+
"filter-capabilities",
|
|
4923
|
+
"fingerprint",
|
|
4924
|
+
"flag",
|
|
4925
|
+
"flask-play",
|
|
4926
|
+
"folder",
|
|
4927
|
+
"folder-input",
|
|
4928
|
+
"folder-kanban",
|
|
4929
|
+
"folder-open",
|
|
4930
|
+
"folder-plus",
|
|
4931
|
+
"folder-shared",
|
|
4932
|
+
"folder-tree",
|
|
4933
|
+
"folder-x",
|
|
4934
|
+
"folders",
|
|
4935
|
+
"gauge",
|
|
4936
|
+
"gauge-high",
|
|
4937
|
+
"gauge-low",
|
|
4938
|
+
"gauge-medium",
|
|
4939
|
+
"gavel",
|
|
4940
|
+
"git-branch",
|
|
4941
|
+
"git-fork",
|
|
4942
|
+
"globe",
|
|
4943
|
+
"globe-check",
|
|
4944
|
+
"grid",
|
|
4945
|
+
"grip-vertical",
|
|
4946
|
+
"hand-check",
|
|
4947
|
+
"hard-drive",
|
|
4948
|
+
"hard-drive-alert",
|
|
4949
|
+
"hard-drive-off",
|
|
4950
|
+
"hash",
|
|
4951
|
+
"heart",
|
|
4952
|
+
"heart-chart-up",
|
|
4953
|
+
"heart-pulse",
|
|
4954
|
+
"help",
|
|
4955
|
+
"hierarchy",
|
|
4956
|
+
"history",
|
|
4957
|
+
"home",
|
|
4958
|
+
"hourglass",
|
|
4959
|
+
"house",
|
|
4960
|
+
"human-lock",
|
|
4961
|
+
"id-badge",
|
|
4962
|
+
"image",
|
|
4963
|
+
"image-minus",
|
|
4964
|
+
"image-plus",
|
|
4965
|
+
"image-up",
|
|
4966
|
+
"inbox",
|
|
4967
|
+
"inbox-empty",
|
|
3822
4968
|
"info",
|
|
4969
|
+
"install",
|
|
4970
|
+
"journal",
|
|
4971
|
+
"key",
|
|
4972
|
+
"key-off",
|
|
4973
|
+
"key-round",
|
|
4974
|
+
"languages",
|
|
4975
|
+
"laptop",
|
|
4976
|
+
"laptop-bridge",
|
|
4977
|
+
"layers",
|
|
4978
|
+
"layout-dashboard",
|
|
4979
|
+
"layout-grid",
|
|
4980
|
+
"layout-kanban",
|
|
4981
|
+
"leaf",
|
|
4982
|
+
"library-books",
|
|
4983
|
+
"life-buoy",
|
|
4984
|
+
"lightbulb",
|
|
4985
|
+
"lightbulb-sparkles",
|
|
4986
|
+
"line-width",
|
|
4987
|
+
"link",
|
|
4988
|
+
"link-2",
|
|
4989
|
+
"link-off",
|
|
4990
|
+
"list",
|
|
4991
|
+
"list-checks",
|
|
4992
|
+
"list-ordered",
|
|
4993
|
+
"list-rule",
|
|
4994
|
+
"list-todo",
|
|
4995
|
+
"llm",
|
|
3823
4996
|
"loader-circle",
|
|
4997
|
+
"lock",
|
|
4998
|
+
"lock-keyhole",
|
|
4999
|
+
"log-in",
|
|
5000
|
+
"log-out",
|
|
5001
|
+
"log-out-all",
|
|
5002
|
+
"magic-wand",
|
|
5003
|
+
"mail",
|
|
5004
|
+
"mail-check",
|
|
5005
|
+
"mail-open",
|
|
5006
|
+
"mail-plus",
|
|
5007
|
+
"mail-warning",
|
|
5008
|
+
"mails",
|
|
5009
|
+
"market",
|
|
5010
|
+
"maximize-2",
|
|
5011
|
+
"megaphone",
|
|
5012
|
+
"memory-stick",
|
|
5013
|
+
"menu",
|
|
5014
|
+
"message-circle",
|
|
5015
|
+
"message-square",
|
|
5016
|
+
"message-square-plus",
|
|
5017
|
+
"messages-square",
|
|
5018
|
+
"mic",
|
|
5019
|
+
"microphone",
|
|
5020
|
+
"minimize-2",
|
|
5021
|
+
"minus",
|
|
5022
|
+
"minus-square",
|
|
5023
|
+
"monitor-home",
|
|
5024
|
+
"monitor-smartphone",
|
|
5025
|
+
"moon",
|
|
5026
|
+
"more-horizontal",
|
|
5027
|
+
"mouse-pointer-2",
|
|
5028
|
+
"move-horizontal",
|
|
5029
|
+
"network",
|
|
5030
|
+
"network-nodes",
|
|
5031
|
+
"newsletter",
|
|
5032
|
+
"newspaper",
|
|
5033
|
+
"octagon-x",
|
|
5034
|
+
"package",
|
|
5035
|
+
"package-download",
|
|
5036
|
+
"page-snapshot",
|
|
5037
|
+
"palette",
|
|
5038
|
+
"panel-left",
|
|
5039
|
+
"panel-right",
|
|
5040
|
+
"panels-top-left",
|
|
5041
|
+
"paper-plane",
|
|
5042
|
+
"paperclip",
|
|
5043
|
+
"pause",
|
|
5044
|
+
"pause-circle",
|
|
5045
|
+
"pencil",
|
|
5046
|
+
"persona",
|
|
5047
|
+
"piggy-bank",
|
|
5048
|
+
"pipette",
|
|
5049
|
+
"play",
|
|
5050
|
+
"play-circle",
|
|
5051
|
+
"plug",
|
|
5052
|
+
"plug-cloud",
|
|
5053
|
+
"plug-off",
|
|
5054
|
+
"plug-plus",
|
|
5055
|
+
"plugin",
|
|
5056
|
+
"plus",
|
|
5057
|
+
"price-tag",
|
|
5058
|
+
"publish",
|
|
5059
|
+
"quote",
|
|
5060
|
+
"radio",
|
|
5061
|
+
"radio-tower",
|
|
5062
|
+
"receipt",
|
|
5063
|
+
"refresh",
|
|
5064
|
+
"refresh-cw",
|
|
5065
|
+
"refresh-cw-off",
|
|
5066
|
+
"repeat",
|
|
5067
|
+
"repeat-2",
|
|
5068
|
+
"repeat-fallback",
|
|
5069
|
+
"repeat-interval",
|
|
5070
|
+
"responses-list",
|
|
5071
|
+
"rocket",
|
|
5072
|
+
"rotate-ccw",
|
|
5073
|
+
"rotate-cw",
|
|
5074
|
+
"route",
|
|
5075
|
+
"rss",
|
|
5076
|
+
"save",
|
|
5077
|
+
"scale",
|
|
5078
|
+
"scan",
|
|
3824
5079
|
"search",
|
|
3825
|
-
"x"
|
|
5080
|
+
"search-x",
|
|
5081
|
+
"send",
|
|
5082
|
+
"send-check",
|
|
5083
|
+
"send-request",
|
|
5084
|
+
"server",
|
|
5085
|
+
"server-api",
|
|
5086
|
+
"server-environment",
|
|
5087
|
+
"settings",
|
|
5088
|
+
"settings-2",
|
|
5089
|
+
"share",
|
|
5090
|
+
"share-nodes",
|
|
5091
|
+
"shield",
|
|
5092
|
+
"shield-check",
|
|
5093
|
+
"shield-lock",
|
|
5094
|
+
"shield-question",
|
|
5095
|
+
"shield-x",
|
|
5096
|
+
"shopping-basket",
|
|
5097
|
+
"shopping-cart",
|
|
5098
|
+
"shuffle",
|
|
5099
|
+
"signal",
|
|
5100
|
+
"signal-high",
|
|
5101
|
+
"signal-low",
|
|
5102
|
+
"signal-medium",
|
|
5103
|
+
"signal-off",
|
|
5104
|
+
"siren",
|
|
5105
|
+
"sliders-horizontal",
|
|
5106
|
+
"smartphone",
|
|
5107
|
+
"sparkles",
|
|
5108
|
+
"square",
|
|
5109
|
+
"square-check",
|
|
5110
|
+
"square-plus",
|
|
5111
|
+
"square-terminal",
|
|
5112
|
+
"star",
|
|
5113
|
+
"sticker",
|
|
5114
|
+
"storage",
|
|
5115
|
+
"store",
|
|
5116
|
+
"story",
|
|
5117
|
+
"sun",
|
|
5118
|
+
"support",
|
|
5119
|
+
"target",
|
|
5120
|
+
"target-choice",
|
|
5121
|
+
"tasks",
|
|
5122
|
+
"terminal",
|
|
5123
|
+
"ticket",
|
|
5124
|
+
"ticket-plus",
|
|
5125
|
+
"tickets",
|
|
5126
|
+
"timeline",
|
|
5127
|
+
"timer",
|
|
5128
|
+
"toggle-left",
|
|
5129
|
+
"toggle-right",
|
|
5130
|
+
"token-input",
|
|
5131
|
+
"token-output",
|
|
5132
|
+
"trail",
|
|
5133
|
+
"trash-2",
|
|
5134
|
+
"trend-up",
|
|
5135
|
+
"triangle-alert",
|
|
5136
|
+
"type",
|
|
5137
|
+
"unlink",
|
|
5138
|
+
"unplug",
|
|
5139
|
+
"upload",
|
|
5140
|
+
"upload-cloud",
|
|
5141
|
+
"user",
|
|
5142
|
+
"user-check",
|
|
5143
|
+
"user-cog",
|
|
5144
|
+
"user-minus",
|
|
5145
|
+
"user-plus",
|
|
5146
|
+
"user-round",
|
|
5147
|
+
"user-x",
|
|
5148
|
+
"users",
|
|
5149
|
+
"users-round",
|
|
5150
|
+
"vault",
|
|
5151
|
+
"volume-2",
|
|
5152
|
+
"wallet",
|
|
5153
|
+
"wand-sparkles",
|
|
5154
|
+
"warehouse",
|
|
5155
|
+
"workflow",
|
|
5156
|
+
"workspace",
|
|
5157
|
+
"wrench",
|
|
5158
|
+
"wrench-zap",
|
|
5159
|
+
"x",
|
|
5160
|
+
"zap"
|
|
3826
5161
|
],
|
|
3827
|
-
description: "Icon identifier from the @treeui/icons registry."
|
|
5162
|
+
description: "Icon identifier from the @treeui/icons registry. Widens as `TIconRegistry` is augmented, so registered app icons are valid values too.",
|
|
5163
|
+
note: "Names use TreeUI's descriptive kebab-case vocabulary. The catalog covers common application needs; anything missing is one `registerTreeIcons` call away, and `listTreeIcons()` returns the live list at runtime."
|
|
3828
5164
|
},
|
|
3829
5165
|
{
|
|
3830
5166
|
name: "size",
|
|
3831
5167
|
type: "number | string",
|
|
3832
5168
|
default: "20",
|
|
3833
|
-
description: "Pixel size for both width and height of the rendered svg."
|
|
5169
|
+
description: "Pixel size for both width and height of the rendered svg.",
|
|
5170
|
+
note: 'This is a PIXEL COUNT, not the sm | md | lg token scale used by nearly every\nother TreeUI component. `<TIcon size="md" />` does not fail loudly: it writes\nwidth="md" / height="md" onto the svg, which the browser discards, so the\nicon becomes unsized and stretches to fill its container. Pass a number\n(20, 32) or a numeric string ("20"). To size an icon from tokens, leave `size`\nalone and set width/height in CSS from the icon scale \u2014 --tree-size-icon-sm |\n-md | -lg | -xl | -2xl (1rem / 1.25rem / 1.5rem / 2rem / 3rem) \u2014 which is what\nTLanguageSelect\'s switcher variant does.\n'
|
|
3834
5171
|
},
|
|
3835
5172
|
{
|
|
3836
5173
|
name: "strokeWidth",
|
|
@@ -3857,33 +5194,60 @@ var treeui_catalog_default = {
|
|
|
3857
5194
|
"becomes_image_when_labeled: true",
|
|
3858
5195
|
"rule: Provide `label` only when the icon conveys meaning that is not already in adjacent text."
|
|
3859
5196
|
],
|
|
3860
|
-
behavior: [
|
|
5197
|
+
behavior: [
|
|
5198
|
+
"unknown_name_renders_nothing: An unregistered name makes `resolveTreeIcon` return `undefined`, and `TIcon`'s `v-if` then renders no element at all \u2014 no empty box, no placeholder, no error. A `console.warn` names the missing icon, suggests the `registerTreeIcons` call, and lists every valid name. It warns once per NAME (not per message \u2014 the message embeds the valid-name list, which changes on every registration), so a miss inside a render loop cannot flood the console. The warning is NOT gated on `process.env.NODE_ENV`: it fires in production builds too, deliberately, because a missing icon is a misconfiguration worth hearing about once and `process` is undefined in most browser bundles. Components with a marker fallback (TNavMenu) show that instead \u2014 see nav-menu.yaml.",
|
|
5199
|
+
'absolute_stroke_width_math: Icons draw on `viewBox="0 0 24 24"` with the svg sized to `size`, so painted pixels = (stroke-width attribute) * size / 24. With `absoluteStrokeWidth` (the default) the attribute is set to `(strokeWidth * 24) / size`, which cancels the scale: at the default `strokeWidth: 2` the attribute is 2.4 at size 20, 1.5 at 32, and 1.0 at 48 \u2014 a constant 2px painted at every size. That is the entire point of the correction: a 48px icon sits beside a 20px one at the same optical weight. A `size` of 0 or a non-numeric value keeps the nominal stroke rather than producing NaN/Infinity. Setting `absoluteStrokeWidth: false` pins the attribute at `strokeWidth`, which is the hand-rolled behaviour: the painted stroke then scales WITH the icon (1.67px at 20, 2.67px at 32, 4px at 48 \u2014 double the library weight).',
|
|
5200
|
+
"icons_are_built_lazily_and_cached: Geometry lives in a data registry; a component is created on first lookup and reused after that, so an unused icon stays as DATA instead of becoming a `defineComponent`. Note what this does not claim: the geometry for all 364 built-ins is retained by any import of the package (the registry copies `builtinTreeIconNodes` into a `Map` at module scope, so a live reference exists and nothing tree-shakes it away \u2014 `sideEffects: false` does not change that). The saving is component construction, not bundle bytes.",
|
|
5201
|
+
"resolved_per_render: TIcon resolves its name in a computed, not once at setup, so an icon registered after the component mounted still appears.",
|
|
5202
|
+
"migration_aliases: Twelve compatibility names resolve to the same geometry as their canonical names: grid \u2192 layout-grid, share \u2192 share-nodes, chevron-updown \u2192 chevrons-up-down, refresh \u2192 refresh-cw, comment/chat \u2192 message-circle, check-square \u2192 square-check, help \u2192 circle-help, automations \u2192 zap, connections \u2192 external-link, persona \u2192 user-round, and close \u2192 x.",
|
|
5203
|
+
"company_logos_are_app_owned: Company logos are not built-ins. When an application needs one, it imports the official SVG as its own component and passes or registers that component under an application-owned name."
|
|
5204
|
+
],
|
|
3861
5205
|
selection: {
|
|
3862
5206
|
keywords: [
|
|
3863
5207
|
"icon",
|
|
3864
5208
|
"svg",
|
|
3865
5209
|
"glyph",
|
|
3866
|
-
"pictogram"
|
|
5210
|
+
"pictogram",
|
|
5211
|
+
"register",
|
|
5212
|
+
"register icon",
|
|
5213
|
+
"custom icon",
|
|
5214
|
+
"icon registry",
|
|
5215
|
+
"registerTreeIcons",
|
|
5216
|
+
"createTreeIcon"
|
|
3867
5217
|
],
|
|
3868
5218
|
useWhen: [
|
|
3869
|
-
"You need to render
|
|
3870
|
-
|
|
5219
|
+
"You need to render an interface icon. `TIcon` is the way to render one \u2014 it resolves the name through the registry and applies the shared size, stroke, and a11y defaults.",
|
|
5220
|
+
'The icon is one of the built-ins: `<TIcon name="cpu" />`. `listTreeIcons()` returns every registered name at runtime.',
|
|
5221
|
+
"The icon is your own: register it once with `registerTreeIcons`, then use it by name exactly like a built-in. A missing icon is registered, not worked around."
|
|
3871
5222
|
],
|
|
3872
5223
|
avoidWhen: [
|
|
3873
|
-
"The
|
|
5224
|
+
"The graphic is a country flag \u2014 a flag names a country, not an interface concept.",
|
|
5225
|
+
"A slot already renders the icon for you (`#icon` on TAlert, TBadge, TButton, TConfirmDialog, TEmptyState, TFileUpload, TStat, TTag) \u2014 put the `TIcon` inside that slot rather than beside it. None of those components has an `icon` PROP; the slot is the whole interface."
|
|
3874
5226
|
],
|
|
3875
5227
|
alternatives: [
|
|
3876
5228
|
{
|
|
3877
|
-
component: "
|
|
3878
|
-
when: "You
|
|
5229
|
+
component: "a component passed straight to `TNavMenuItem.icon`, or rendered into an `#icon` slot",
|
|
5230
|
+
when: "You want the escape hatch with no registry entry \u2014 a one-off icon, an imported SVG component, or the result of `createTreeIcon(...)`. `TNavMenuItem.icon` is `TIconInput` and takes the component directly; everywhere else, render it inside the component's `#icon` slot. `TIcon` itself will not take a component \u2014 its `name` is `TIconName`. Prefer registering when the icon is used in more than one place."
|
|
5231
|
+
},
|
|
5232
|
+
{
|
|
5233
|
+
component: "TFlag",
|
|
5234
|
+
when: "The graphic is a country flag rendered from an ISO 3166-1 alpha-2 code."
|
|
3879
5235
|
}
|
|
3880
5236
|
]
|
|
3881
5237
|
},
|
|
3882
5238
|
setup: {
|
|
3883
|
-
required: [
|
|
3884
|
-
|
|
5239
|
+
required: [
|
|
5240
|
+
"Use a registered name: one of the built-ins, or one the app added with `registerTreeIcons`. See `icons` above."
|
|
5241
|
+
],
|
|
5242
|
+
notes: [
|
|
5243
|
+
'`size` is a pixel count, not `sm | md | lg`. Passing `size="md"` renders an unsized svg.',
|
|
5244
|
+
"The icon is `aria-hidden` by default. Pass `label` only when the icon carries meaning on its own; beside visible text it should stay decorative."
|
|
5245
|
+
]
|
|
3885
5246
|
},
|
|
3886
|
-
recipes: [
|
|
5247
|
+
recipes: [
|
|
5248
|
+
"nav-menu-icons"
|
|
5249
|
+
],
|
|
5250
|
+
practices: []
|
|
3887
5251
|
},
|
|
3888
5252
|
{
|
|
3889
5253
|
name: "TInput",
|
|
@@ -4009,6 +5373,10 @@ var treeui_catalog_default = {
|
|
|
4009
5373
|
recipes: [
|
|
4010
5374
|
"form-field-input",
|
|
4011
5375
|
"tag-input"
|
|
5376
|
+
],
|
|
5377
|
+
practices: [
|
|
5378
|
+
"interaction-feedback",
|
|
5379
|
+
"predictable-api"
|
|
4012
5380
|
]
|
|
4013
5381
|
},
|
|
4014
5382
|
{
|
|
@@ -4046,7 +5414,245 @@ var treeui_catalog_default = {
|
|
|
4046
5414
|
required: [],
|
|
4047
5415
|
notes: []
|
|
4048
5416
|
},
|
|
4049
|
-
recipes: []
|
|
5417
|
+
recipes: [],
|
|
5418
|
+
practices: []
|
|
5419
|
+
},
|
|
5420
|
+
{
|
|
5421
|
+
name: "TLanguageSelect",
|
|
5422
|
+
aliases: [],
|
|
5423
|
+
package: "@treeui/vue",
|
|
5424
|
+
kind: "form_overlay",
|
|
5425
|
+
category: "Data Entry",
|
|
5426
|
+
status: "available",
|
|
5427
|
+
purpose: "Language/locale picker with a listbox, a flag per option, and the shared overlay contract; controlled and uncontrolled via v-model and open/defaultOpen.",
|
|
5428
|
+
sourceFile: "packages/vue/src/components/TLanguageSelect.vue",
|
|
5429
|
+
storyFile: "apps/docs/src/stories/LanguageSelect.stories.ts",
|
|
5430
|
+
storyTitle: "Components/Data Entry/LanguageSelect",
|
|
5431
|
+
manifestFile: "docs/ai/COMPONENTS/language-select.yaml",
|
|
5432
|
+
props: [
|
|
5433
|
+
{
|
|
5434
|
+
name: "modelValue",
|
|
5435
|
+
type: "string",
|
|
5436
|
+
default: ""
|
|
5437
|
+
},
|
|
5438
|
+
{
|
|
5439
|
+
name: "options",
|
|
5440
|
+
type: "TLanguageOption[]",
|
|
5441
|
+
default: "[]",
|
|
5442
|
+
note: "Array of { label: string; value: string; code?: string; description?: string; disabled?: boolean }. `value` is an opaque application key (typically a BCP-47 tag) \u2014 never parsed or validated. `code` is an ISO 3166-1 alpha-2 country code for the flag; omit it to render the option without one. `description` is a secondary line, e.g. the endonym."
|
|
5443
|
+
},
|
|
5444
|
+
{
|
|
5445
|
+
name: "open",
|
|
5446
|
+
type: "boolean",
|
|
5447
|
+
default: "undefined"
|
|
5448
|
+
},
|
|
5449
|
+
{
|
|
5450
|
+
name: "defaultOpen",
|
|
5451
|
+
type: "boolean",
|
|
5452
|
+
default: "false"
|
|
5453
|
+
},
|
|
5454
|
+
{
|
|
5455
|
+
name: "size",
|
|
5456
|
+
type: "TSize",
|
|
5457
|
+
default: "md",
|
|
5458
|
+
values: [
|
|
5459
|
+
"sm",
|
|
5460
|
+
"md",
|
|
5461
|
+
"lg"
|
|
5462
|
+
]
|
|
5463
|
+
},
|
|
5464
|
+
{
|
|
5465
|
+
name: "variant",
|
|
5466
|
+
type: "TLanguageSelectVariant",
|
|
5467
|
+
default: "field",
|
|
5468
|
+
values: [
|
|
5469
|
+
"field",
|
|
5470
|
+
"switcher"
|
|
5471
|
+
],
|
|
5472
|
+
note: "`field` is a form control, sized and laid out like any other input. `switcher` is a page-level control for a navbar/appbar where nothing nearby labels it: it leads with a translate icon, trails the current flag, and sizes to its content."
|
|
5473
|
+
},
|
|
5474
|
+
{
|
|
5475
|
+
name: "iconOnly",
|
|
5476
|
+
type: "boolean",
|
|
5477
|
+
default: "false",
|
|
5478
|
+
note: "`switcher` only \u2014 ignored by `field`. Drops the visible language name, leaving the translate icon, the current flag, and the chevron. The trigger then has no text, so the consumer MUST pass an `aria-label`."
|
|
5479
|
+
},
|
|
5480
|
+
{
|
|
5481
|
+
name: "width",
|
|
5482
|
+
type: "TFieldWidth",
|
|
5483
|
+
default: "full",
|
|
5484
|
+
values: [
|
|
5485
|
+
"xs",
|
|
5486
|
+
"sm",
|
|
5487
|
+
"md",
|
|
5488
|
+
"lg",
|
|
5489
|
+
"xl",
|
|
5490
|
+
"full"
|
|
5491
|
+
],
|
|
5492
|
+
note: "Inline-size cap (max-inline-size). Fluid by default; use instead of an inline width style. Applies to `variant: field` only \u2014 a `switcher` sizes to its content and ignores it."
|
|
5493
|
+
},
|
|
5494
|
+
{
|
|
5495
|
+
name: "disabled",
|
|
5496
|
+
type: "boolean",
|
|
5497
|
+
default: "false"
|
|
5498
|
+
},
|
|
5499
|
+
{
|
|
5500
|
+
name: "loading",
|
|
5501
|
+
type: "boolean",
|
|
5502
|
+
default: "false"
|
|
5503
|
+
},
|
|
5504
|
+
{
|
|
5505
|
+
name: "invalid",
|
|
5506
|
+
type: "boolean",
|
|
5507
|
+
default: "false"
|
|
5508
|
+
},
|
|
5509
|
+
{
|
|
5510
|
+
name: "placeholder",
|
|
5511
|
+
type: "string",
|
|
5512
|
+
default: ""
|
|
5513
|
+
},
|
|
5514
|
+
{
|
|
5515
|
+
name: "flagBaseUrl",
|
|
5516
|
+
type: "string",
|
|
5517
|
+
default: "undefined",
|
|
5518
|
+
note: "Forwarded to every nested TFlag. When omitted, TFlag's own default origin applies. Set once here to self-host flag assets."
|
|
5519
|
+
},
|
|
5520
|
+
{
|
|
5521
|
+
name: "emptyText",
|
|
5522
|
+
type: "string",
|
|
5523
|
+
default: "No languages available."
|
|
5524
|
+
}
|
|
5525
|
+
],
|
|
5526
|
+
events: [
|
|
5527
|
+
{
|
|
5528
|
+
name: "update:modelValue"
|
|
5529
|
+
},
|
|
5530
|
+
{
|
|
5531
|
+
name: "update:open"
|
|
5532
|
+
},
|
|
5533
|
+
{
|
|
5534
|
+
name: "open-change"
|
|
5535
|
+
}
|
|
5536
|
+
],
|
|
5537
|
+
slots: [
|
|
5538
|
+
{
|
|
5539
|
+
name: "prefix",
|
|
5540
|
+
description: "Leading content inside the trigger, before everything else \u2014 the selected flag and label in `field`, the translate icon in `switcher`."
|
|
5541
|
+
},
|
|
5542
|
+
{
|
|
5543
|
+
name: "option",
|
|
5544
|
+
description: `Replaces the default option body (flag, label, description). Renders INSIDE the row's <li role="option">, so it must contain only presentational content.
|
|
5545
|
+
`
|
|
5546
|
+
},
|
|
5547
|
+
{
|
|
5548
|
+
name: "empty",
|
|
5549
|
+
description: "Replaces `emptyText` when `options` is empty."
|
|
5550
|
+
}
|
|
5551
|
+
],
|
|
5552
|
+
a11y: [
|
|
5553
|
+
"role: listbox",
|
|
5554
|
+
"trigger_aria_haspopup: listbox",
|
|
5555
|
+
"trigger_aria_expanded: true",
|
|
5556
|
+
"trigger_aria_controls_when_open: true",
|
|
5557
|
+
"aria_invalid_when_invalid: true",
|
|
5558
|
+
"aria_busy_when_loading: true",
|
|
5559
|
+
"aria_selected_on_options: true",
|
|
5560
|
+
"aria_disabled_on_disabled_options: true",
|
|
5561
|
+
"focus_visible_on_trigger: true",
|
|
5562
|
+
"keyboard_arrow_navigation: true",
|
|
5563
|
+
"escape_closes_dropdown: true",
|
|
5564
|
+
"enter_space_selects_option: true",
|
|
5565
|
+
"home_end_navigation: true",
|
|
5566
|
+
"home_end_target_first_last_enabled_option: true",
|
|
5567
|
+
"focus_restores_to_trigger_on_close: true",
|
|
5568
|
+
"icon_only_removes_the_visible_language_name: true",
|
|
5569
|
+
"icon_only_requires_a_consumer_supplied_aria_label_on_the_trigger: true",
|
|
5570
|
+
"translate_icon_and_flags_are_decorative_not_the_accessible_name: true"
|
|
5571
|
+
],
|
|
5572
|
+
behavior: [
|
|
5573
|
+
"update_payload_type: string",
|
|
5574
|
+
"loading_does_not_disable_by_itself: true",
|
|
5575
|
+
"placeholder_shown_as_muted_text: true",
|
|
5576
|
+
"chevron_rotates_when_open: true",
|
|
5577
|
+
"check_icon_on_selected_option: true",
|
|
5578
|
+
"outside_click_closes_dropdown: true",
|
|
5579
|
+
"listbox_flips_above_trigger_when_space_below_is_insufficient: true",
|
|
5580
|
+
"options_without_a_code_render_without_a_flag: true",
|
|
5581
|
+
"empty_options_render_the_empty_slot_or_empty_text: true",
|
|
5582
|
+
"field_variant_leads_the_trigger_with_the_selected_flag: true",
|
|
5583
|
+
"field_variant_trigger_fills_its_container: true",
|
|
5584
|
+
"switcher_variant_leads_the_trigger_with_a_translate_icon: true",
|
|
5585
|
+
"switcher_variant_trails_the_current_flag_before_the_chevron: true",
|
|
5586
|
+
"switcher_variant_trigger_sizes_to_its_content: true",
|
|
5587
|
+
"switcher_variant_ignores_the_width_prop: true",
|
|
5588
|
+
"switcher_listbox_aligns_to_the_trigger_right_edge: true",
|
|
5589
|
+
"switcher_listbox_may_be_wider_than_the_trigger: true",
|
|
5590
|
+
"icon_only_applies_to_the_switcher_variant_only: true",
|
|
5591
|
+
"root_classes: t-language-select--field | t-language-select--switcher, plus t-language-select--icon-only"
|
|
5592
|
+
],
|
|
5593
|
+
selection: {
|
|
5594
|
+
keywords: [
|
|
5595
|
+
"language select",
|
|
5596
|
+
"language picker",
|
|
5597
|
+
"locale",
|
|
5598
|
+
"locale picker",
|
|
5599
|
+
"i18n",
|
|
5600
|
+
"internationalization",
|
|
5601
|
+
"translation",
|
|
5602
|
+
"country flag"
|
|
5603
|
+
],
|
|
5604
|
+
useWhen: [
|
|
5605
|
+
"The user is picking the interface language or locale.",
|
|
5606
|
+
'The control is a labelled form field for the language value \u2014 `variant="field"` (the default), where the flag leads the trigger and `width` applies.',
|
|
5607
|
+
'The control is a page-level language switcher in a navbar or app bar, where nothing nearby says what it changes \u2014 `variant="switcher"` leads with a translate icon and trails the current flag, sizes to its content, and ignores `width`.',
|
|
5608
|
+
"A navbar switcher should shrink to icon and flag only \u2014 `iconOnly` drops the language name, so pass an `aria-label` to name the control.",
|
|
5609
|
+
"Each language should render with its country flag, and optionally an endonym as a second line.",
|
|
5610
|
+
"The app owns the language list and applies the locale side effects itself."
|
|
5611
|
+
],
|
|
5612
|
+
avoidWhen: [
|
|
5613
|
+
"The values are not languages or locales.",
|
|
5614
|
+
"The language list is long enough that the user must type to narrow it down.",
|
|
5615
|
+
"You expect TreeUI to supply the locale dataset \u2014 it ships none, so pass your own `options`."
|
|
5616
|
+
],
|
|
5617
|
+
alternatives: [
|
|
5618
|
+
{
|
|
5619
|
+
component: "TSelect",
|
|
5620
|
+
when: "The values are ordinary application data rather than languages or locales."
|
|
5621
|
+
},
|
|
5622
|
+
{
|
|
5623
|
+
component: "TCombobox",
|
|
5624
|
+
when: "The language list is long enough that typing to narrow it down is required."
|
|
5625
|
+
},
|
|
5626
|
+
{
|
|
5627
|
+
component: "TFlag",
|
|
5628
|
+
when: "You only need to render one country flag, without a picker around it."
|
|
5629
|
+
}
|
|
5630
|
+
]
|
|
5631
|
+
},
|
|
5632
|
+
setup: {
|
|
5633
|
+
required: [
|
|
5634
|
+
"Pass `options` as `{ label, value, code?, description?, disabled? }[]`. TreeUI ships no language, locale, or country dataset \u2014 the app owns its language list.",
|
|
5635
|
+
"Apply locale side effects (i18n locale, `lang` attribute, persistence) in the app layer; the component only reports the selected `value`.",
|
|
5636
|
+
"Pass an `aria-label` whenever `iconOnly` is set \u2014 the visible language name is gone, so it is the control's only accessible name. It also labels the listbox."
|
|
5637
|
+
],
|
|
5638
|
+
notes: [
|
|
5639
|
+
"`variant` is `field` (default) or `switcher`, typed as `TLanguageSelectVariant` and exported from `@treeui/vue`.",
|
|
5640
|
+
'Use `variant="field"` inside a form, next to other inputs, or wrapped in `TFormField`: the flag leads the trigger, the trigger fills its container, and `width` applies. A visible field label already says what the control changes.',
|
|
5641
|
+
'Use `variant="switcher"` for a page-level control in a navbar or app bar, where nothing nearby labels it. A translate icon (`TIcon name="languages"`) leads and the current flag trails before the chevron, so the control reads as "page language, now set to this" without an external label.',
|
|
5642
|
+
"A switcher sizes to its content, so `width` does not apply, and its listbox aligns to the trigger's right edge.",
|
|
5643
|
+
"`iconOnly` is switcher-only and drops the visible language name, leaving the translate icon and the current flag.",
|
|
5644
|
+
"`value` is an opaque application key, typically a BCP-47 tag such as `pt-BR`. TreeUI never parses or validates it.",
|
|
5645
|
+
"`code` is the ISO 3166-1 alpha-2 code used for the option flag. Omit it to render the option without a flag \u2014 a language is not a country, so many entries have no honest flag.",
|
|
5646
|
+
"Use `description` for a secondary line such as the endonym.",
|
|
5647
|
+
"Set `flagBaseUrl` once on the select rather than per option; it is forwarded to every nested `TFlag`.",
|
|
5648
|
+
"Bind `modelValue` to a `string`, and use `v-model:open` when the app controls open state.",
|
|
5649
|
+
"The CDN and Content-Security-Policy requirements under `TFlag` apply whenever any option carries a `code`."
|
|
5650
|
+
]
|
|
5651
|
+
},
|
|
5652
|
+
recipes: [
|
|
5653
|
+
"language-switcher"
|
|
5654
|
+
],
|
|
5655
|
+
practices: []
|
|
4050
5656
|
},
|
|
4051
5657
|
{
|
|
4052
5658
|
name: "TLink",
|
|
@@ -4147,7 +5753,10 @@ var treeui_catalog_default = {
|
|
|
4147
5753
|
required: [],
|
|
4148
5754
|
notes: []
|
|
4149
5755
|
},
|
|
4150
|
-
recipes: []
|
|
5756
|
+
recipes: [],
|
|
5757
|
+
practices: [
|
|
5758
|
+
"interaction-feedback"
|
|
5759
|
+
]
|
|
4151
5760
|
},
|
|
4152
5761
|
{
|
|
4153
5762
|
name: "TMarkdownEditor",
|
|
@@ -4256,7 +5865,8 @@ var treeui_catalog_default = {
|
|
|
4256
5865
|
required: [],
|
|
4257
5866
|
notes: []
|
|
4258
5867
|
},
|
|
4259
|
-
recipes: []
|
|
5868
|
+
recipes: [],
|
|
5869
|
+
practices: []
|
|
4260
5870
|
},
|
|
4261
5871
|
{
|
|
4262
5872
|
name: "TModal",
|
|
@@ -4404,7 +6014,11 @@ var treeui_catalog_default = {
|
|
|
4404
6014
|
"Use `v-model:open` for the idiomatic Vue controlled pattern."
|
|
4405
6015
|
]
|
|
4406
6016
|
},
|
|
4407
|
-
recipes: []
|
|
6017
|
+
recipes: [],
|
|
6018
|
+
practices: [
|
|
6019
|
+
"accessible-by-default",
|
|
6020
|
+
"predictable-api"
|
|
6021
|
+
]
|
|
4408
6022
|
},
|
|
4409
6023
|
{
|
|
4410
6024
|
name: "TMultiSelect",
|
|
@@ -4563,7 +6177,8 @@ var treeui_catalog_default = {
|
|
|
4563
6177
|
},
|
|
4564
6178
|
recipes: [
|
|
4565
6179
|
"searchable-multi-choice"
|
|
4566
|
-
]
|
|
6180
|
+
],
|
|
6181
|
+
practices: []
|
|
4567
6182
|
},
|
|
4568
6183
|
{
|
|
4569
6184
|
name: "TNavbar",
|
|
@@ -4661,6 +6276,9 @@ var treeui_catalog_default = {
|
|
|
4661
6276
|
},
|
|
4662
6277
|
recipes: [
|
|
4663
6278
|
"sidebar-shell"
|
|
6279
|
+
],
|
|
6280
|
+
practices: [
|
|
6281
|
+
"token-driven"
|
|
4664
6282
|
]
|
|
4665
6283
|
},
|
|
4666
6284
|
{
|
|
@@ -4753,10 +6371,13 @@ var treeui_catalog_default = {
|
|
|
4753
6371
|
keywords: [
|
|
4754
6372
|
"nav menu",
|
|
4755
6373
|
"sidebar nav",
|
|
4756
|
-
"section nav"
|
|
6374
|
+
"section nav",
|
|
6375
|
+
"nav icons",
|
|
6376
|
+
"sidebar rail"
|
|
4757
6377
|
],
|
|
4758
6378
|
useWhen: [
|
|
4759
|
-
"You need app-section navigation inside a shell or sidebar."
|
|
6379
|
+
"You need app-section navigation inside a shell or sidebar.",
|
|
6380
|
+
"Each section should carry an icon \u2014 set `icon` on the item to a registered name (`icon: 'layout-dashboard'`). Items with no icon fall back to a letter marker, which is also what a collapsed rail shows."
|
|
4760
6381
|
],
|
|
4761
6382
|
avoidWhen: [
|
|
4762
6383
|
"You need tabs for small panel switching."
|
|
@@ -4775,13 +6396,19 @@ var treeui_catalog_default = {
|
|
|
4775
6396
|
setup: {
|
|
4776
6397
|
required: [],
|
|
4777
6398
|
notes: [
|
|
4778
|
-
"When nested inside `TSidebar` or `TAppShell`, `collapsed` can be inherited from the sidebar provider."
|
|
6399
|
+
"When nested inside `TSidebar` or `TAppShell`, `collapsed` can be inherited from the sidebar provider.",
|
|
6400
|
+
"Pass `items` as `{ label, value, icon?, to?, badge?, description?, shortLabel?, disabled?, exact? }[]`.",
|
|
6401
|
+
"`icon` is `TIconInput` \u2014 a registered icon name (`icon: 'layout-dashboard'`) or a component. Use the name: it needs no import, and no `markRaw` when the item list is reactive.",
|
|
6402
|
+
"An item with no icon, or with a name that is not registered, shows a letter marker instead. That marker is also all a collapsed rail can show, so give every item an icon when the sidebar collapses.",
|
|
6403
|
+
"Register any icon the app needs beyond the built-ins first \u2014 see `icons` above."
|
|
4779
6404
|
]
|
|
4780
6405
|
},
|
|
4781
6406
|
recipes: [
|
|
4782
6407
|
"app-shell",
|
|
4783
|
-
"sidebar-shell"
|
|
4784
|
-
|
|
6408
|
+
"sidebar-shell",
|
|
6409
|
+
"nav-menu-icons"
|
|
6410
|
+
],
|
|
6411
|
+
practices: []
|
|
4785
6412
|
},
|
|
4786
6413
|
{
|
|
4787
6414
|
name: "TNumberInput",
|
|
@@ -4888,7 +6515,8 @@ var treeui_catalog_default = {
|
|
|
4888
6515
|
required: [],
|
|
4889
6516
|
notes: []
|
|
4890
6517
|
},
|
|
4891
|
-
recipes: []
|
|
6518
|
+
recipes: [],
|
|
6519
|
+
practices: []
|
|
4892
6520
|
},
|
|
4893
6521
|
{
|
|
4894
6522
|
name: "TPage",
|
|
@@ -4981,7 +6609,10 @@ var treeui_catalog_default = {
|
|
|
4981
6609
|
required: [],
|
|
4982
6610
|
notes: []
|
|
4983
6611
|
},
|
|
4984
|
-
recipes: []
|
|
6612
|
+
recipes: [],
|
|
6613
|
+
practices: [
|
|
6614
|
+
"content-alignment"
|
|
6615
|
+
]
|
|
4985
6616
|
},
|
|
4986
6617
|
{
|
|
4987
6618
|
name: "TPageHeader",
|
|
@@ -5075,7 +6706,10 @@ var treeui_catalog_default = {
|
|
|
5075
6706
|
required: [],
|
|
5076
6707
|
notes: []
|
|
5077
6708
|
},
|
|
5078
|
-
recipes: []
|
|
6709
|
+
recipes: [],
|
|
6710
|
+
practices: [
|
|
6711
|
+
"content-alignment"
|
|
6712
|
+
]
|
|
5079
6713
|
},
|
|
5080
6714
|
{
|
|
5081
6715
|
name: "TPagination",
|
|
@@ -5188,6 +6822,9 @@ var treeui_catalog_default = {
|
|
|
5188
6822
|
},
|
|
5189
6823
|
recipes: [
|
|
5190
6824
|
"data-listing"
|
|
6825
|
+
],
|
|
6826
|
+
practices: [
|
|
6827
|
+
"interaction-feedback"
|
|
5191
6828
|
]
|
|
5192
6829
|
},
|
|
5193
6830
|
{
|
|
@@ -5247,7 +6884,7 @@ var treeui_catalog_default = {
|
|
|
5247
6884
|
slots: [
|
|
5248
6885
|
{
|
|
5249
6886
|
name: "trigger",
|
|
5250
|
-
description: "Custom trigger element. Receives current open state
|
|
6887
|
+
description: "Custom trigger element. Receives the current open state and the id of the content panel, so aria-expanded and aria-controls can be wired by hand.\n"
|
|
5251
6888
|
},
|
|
5252
6889
|
{
|
|
5253
6890
|
name: "default",
|
|
@@ -5256,9 +6893,9 @@ var treeui_catalog_default = {
|
|
|
5256
6893
|
],
|
|
5257
6894
|
a11y: [
|
|
5258
6895
|
"role: dialog",
|
|
5259
|
-
'attrs: ["aria-haspopup=\\"dialog\\" on trigger","aria-expanded on trigger","aria-controls linking trigger to content","tabindex=\\"-1\\" on content for focus management"]',
|
|
6896
|
+
'attrs: ["aria-haspopup=\\"dialog\\" on the built-in trigger (custom triggers must supply it)","aria-expanded on the built-in trigger (custom triggers bind it from `isOpen`)","aria-controls linking trigger to content (custom triggers bind it from `contentId`)","tabindex=\\"-1\\" on content for focus management"]',
|
|
5260
6897
|
'keyboard: ["Click or Enter/Space on trigger toggles popover","Escape closes popover and restores focus to trigger","Tab navigates within popover content"]',
|
|
5261
|
-
'focus: ["On open, focuses first focusable element inside content (or content itself)","On Escape close, restores focus to trigger"]',
|
|
6898
|
+
'focus: ["On open, focuses first focusable element inside content (or content itself)","On Escape close, restores focus to trigger","Focus restore works with a custom trigger too: the ref lives on the `t-popover__anchor` wrapper, not on the built-in button, and focus returns to the first focusable element inside it.\\n"]',
|
|
5262
6899
|
'dismiss: ["Outside click closes popover","Escape key closes popover"]'
|
|
5263
6900
|
],
|
|
5264
6901
|
behavior: [],
|
|
@@ -5291,7 +6928,8 @@ var treeui_catalog_default = {
|
|
|
5291
6928
|
},
|
|
5292
6929
|
recipes: [
|
|
5293
6930
|
"anchored-help"
|
|
5294
|
-
]
|
|
6931
|
+
],
|
|
6932
|
+
practices: []
|
|
5295
6933
|
},
|
|
5296
6934
|
{
|
|
5297
6935
|
name: "TPricing",
|
|
@@ -5355,7 +6993,8 @@ var treeui_catalog_default = {
|
|
|
5355
6993
|
},
|
|
5356
6994
|
recipes: [
|
|
5357
6995
|
"pricing-section"
|
|
5358
|
-
]
|
|
6996
|
+
],
|
|
6997
|
+
practices: []
|
|
5359
6998
|
},
|
|
5360
6999
|
{
|
|
5361
7000
|
name: "TPricingCard",
|
|
@@ -5484,7 +7123,8 @@ var treeui_catalog_default = {
|
|
|
5484
7123
|
},
|
|
5485
7124
|
recipes: [
|
|
5486
7125
|
"pricing-section"
|
|
5487
|
-
]
|
|
7126
|
+
],
|
|
7127
|
+
practices: []
|
|
5488
7128
|
},
|
|
5489
7129
|
{
|
|
5490
7130
|
name: "TProgress",
|
|
@@ -5546,7 +7186,10 @@ var treeui_catalog_default = {
|
|
|
5546
7186
|
required: [],
|
|
5547
7187
|
notes: []
|
|
5548
7188
|
},
|
|
5549
|
-
recipes: []
|
|
7189
|
+
recipes: [],
|
|
7190
|
+
practices: [
|
|
7191
|
+
"state-clarity"
|
|
7192
|
+
]
|
|
5550
7193
|
},
|
|
5551
7194
|
{
|
|
5552
7195
|
name: "TRadio",
|
|
@@ -5614,7 +7257,8 @@ var treeui_catalog_default = {
|
|
|
5614
7257
|
required: [],
|
|
5615
7258
|
notes: []
|
|
5616
7259
|
},
|
|
5617
|
-
recipes: []
|
|
7260
|
+
recipes: [],
|
|
7261
|
+
practices: []
|
|
5618
7262
|
},
|
|
5619
7263
|
{
|
|
5620
7264
|
name: "TRadioGroup",
|
|
@@ -5689,7 +7333,8 @@ var treeui_catalog_default = {
|
|
|
5689
7333
|
required: [],
|
|
5690
7334
|
notes: []
|
|
5691
7335
|
},
|
|
5692
|
-
recipes: []
|
|
7336
|
+
recipes: [],
|
|
7337
|
+
practices: []
|
|
5693
7338
|
},
|
|
5694
7339
|
{
|
|
5695
7340
|
name: "TSelect",
|
|
@@ -5844,6 +7489,10 @@ var treeui_catalog_default = {
|
|
|
5844
7489
|
},
|
|
5845
7490
|
recipes: [
|
|
5846
7491
|
"chart-surface"
|
|
7492
|
+
],
|
|
7493
|
+
practices: [
|
|
7494
|
+
"interaction-feedback",
|
|
7495
|
+
"predictable-api"
|
|
5847
7496
|
]
|
|
5848
7497
|
},
|
|
5849
7498
|
{
|
|
@@ -5954,7 +7603,10 @@ var treeui_catalog_default = {
|
|
|
5954
7603
|
required: [],
|
|
5955
7604
|
notes: []
|
|
5956
7605
|
},
|
|
5957
|
-
recipes: []
|
|
7606
|
+
recipes: [],
|
|
7607
|
+
practices: [
|
|
7608
|
+
"interaction-feedback"
|
|
7609
|
+
]
|
|
5958
7610
|
},
|
|
5959
7611
|
{
|
|
5960
7612
|
name: "TSidebar",
|
|
@@ -6102,7 +7754,8 @@ var treeui_catalog_default = {
|
|
|
6102
7754
|
},
|
|
6103
7755
|
recipes: [
|
|
6104
7756
|
"sidebar-shell"
|
|
6105
|
-
]
|
|
7757
|
+
],
|
|
7758
|
+
practices: []
|
|
6106
7759
|
},
|
|
6107
7760
|
{
|
|
6108
7761
|
name: "TSkeleton",
|
|
@@ -6165,7 +7818,10 @@ var treeui_catalog_default = {
|
|
|
6165
7818
|
required: [],
|
|
6166
7819
|
notes: []
|
|
6167
7820
|
},
|
|
6168
|
-
recipes: []
|
|
7821
|
+
recipes: [],
|
|
7822
|
+
practices: [
|
|
7823
|
+
"state-clarity"
|
|
7824
|
+
]
|
|
6169
7825
|
},
|
|
6170
7826
|
{
|
|
6171
7827
|
name: "TSpacer",
|
|
@@ -6205,7 +7861,10 @@ var treeui_catalog_default = {
|
|
|
6205
7861
|
required: [],
|
|
6206
7862
|
notes: []
|
|
6207
7863
|
},
|
|
6208
|
-
recipes: []
|
|
7864
|
+
recipes: [],
|
|
7865
|
+
practices: [
|
|
7866
|
+
"content-alignment"
|
|
7867
|
+
]
|
|
6209
7868
|
},
|
|
6210
7869
|
{
|
|
6211
7870
|
name: "TSparkline",
|
|
@@ -6328,7 +7987,8 @@ var treeui_catalog_default = {
|
|
|
6328
7987
|
},
|
|
6329
7988
|
recipes: [
|
|
6330
7989
|
"metric-dashboard"
|
|
6331
|
-
]
|
|
7990
|
+
],
|
|
7991
|
+
practices: []
|
|
6332
7992
|
},
|
|
6333
7993
|
{
|
|
6334
7994
|
name: "TSpinner",
|
|
@@ -6377,7 +8037,10 @@ var treeui_catalog_default = {
|
|
|
6377
8037
|
required: [],
|
|
6378
8038
|
notes: []
|
|
6379
8039
|
},
|
|
6380
|
-
recipes: []
|
|
8040
|
+
recipes: [],
|
|
8041
|
+
practices: [
|
|
8042
|
+
"state-clarity"
|
|
8043
|
+
]
|
|
6381
8044
|
},
|
|
6382
8045
|
{
|
|
6383
8046
|
name: "TSplit",
|
|
@@ -6453,7 +8116,10 @@ var treeui_catalog_default = {
|
|
|
6453
8116
|
required: [],
|
|
6454
8117
|
notes: []
|
|
6455
8118
|
},
|
|
6456
|
-
recipes: []
|
|
8119
|
+
recipes: [],
|
|
8120
|
+
practices: [
|
|
8121
|
+
"content-alignment"
|
|
8122
|
+
]
|
|
6457
8123
|
},
|
|
6458
8124
|
{
|
|
6459
8125
|
name: "TStack",
|
|
@@ -6557,6 +8223,9 @@ var treeui_catalog_default = {
|
|
|
6557
8223
|
"tag-input",
|
|
6558
8224
|
"data-listing",
|
|
6559
8225
|
"chart-surface"
|
|
8226
|
+
],
|
|
8227
|
+
practices: [
|
|
8228
|
+
"content-alignment"
|
|
6560
8229
|
]
|
|
6561
8230
|
},
|
|
6562
8231
|
{
|
|
@@ -6631,7 +8300,8 @@ var treeui_catalog_default = {
|
|
|
6631
8300
|
required: [],
|
|
6632
8301
|
notes: []
|
|
6633
8302
|
},
|
|
6634
|
-
recipes: []
|
|
8303
|
+
recipes: [],
|
|
8304
|
+
practices: []
|
|
6635
8305
|
},
|
|
6636
8306
|
{
|
|
6637
8307
|
name: "TStat",
|
|
@@ -6753,7 +8423,8 @@ var treeui_catalog_default = {
|
|
|
6753
8423
|
recipes: [
|
|
6754
8424
|
"stat-grid",
|
|
6755
8425
|
"metric-dashboard"
|
|
6756
|
-
]
|
|
8426
|
+
],
|
|
8427
|
+
practices: []
|
|
6757
8428
|
},
|
|
6758
8429
|
{
|
|
6759
8430
|
name: "TSteps",
|
|
@@ -6857,7 +8528,8 @@ var treeui_catalog_default = {
|
|
|
6857
8528
|
"Pass explicit `status` per item only when the app should override the computed complete/current/upcoming logic."
|
|
6858
8529
|
]
|
|
6859
8530
|
},
|
|
6860
|
-
recipes: []
|
|
8531
|
+
recipes: [],
|
|
8532
|
+
practices: []
|
|
6861
8533
|
},
|
|
6862
8534
|
{
|
|
6863
8535
|
name: "TSwitch",
|
|
@@ -6946,7 +8618,10 @@ var treeui_catalog_default = {
|
|
|
6946
8618
|
required: [],
|
|
6947
8619
|
notes: []
|
|
6948
8620
|
},
|
|
6949
|
-
recipes: []
|
|
8621
|
+
recipes: [],
|
|
8622
|
+
practices: [
|
|
8623
|
+
"interaction-feedback"
|
|
8624
|
+
]
|
|
6950
8625
|
},
|
|
6951
8626
|
{
|
|
6952
8627
|
name: "TTable",
|
|
@@ -6986,6 +8661,13 @@ var treeui_catalog_default = {
|
|
|
6986
8661
|
type: "TTableSortState",
|
|
6987
8662
|
required: false,
|
|
6988
8663
|
description: "Controlled sort state. When provided, overrides internal sort tracking."
|
|
8664
|
+
},
|
|
8665
|
+
{
|
|
8666
|
+
name: "caption",
|
|
8667
|
+
type: "string",
|
|
8668
|
+
required: false,
|
|
8669
|
+
description: "Visible `<caption>` naming the table.",
|
|
8670
|
+
note: "For a name without visible text, pass `aria-label` / `aria-labelledby` instead \u2014 attribute inheritance is disabled and every non-class/style attr is forwarded to the `<table>`, so the name lands on the named element rather than the scroll wrapper."
|
|
6989
8671
|
}
|
|
6990
8672
|
],
|
|
6991
8673
|
events: [
|
|
@@ -7010,7 +8692,9 @@ var treeui_catalog_default = {
|
|
|
7010
8692
|
}
|
|
7011
8693
|
],
|
|
7012
8694
|
a11y: [
|
|
7013
|
-
"role:
|
|
8695
|
+
"role: table (native). No explicit role is emitted.",
|
|
8696
|
+
'why_not_grid: TTable previously set role="grid" without implementing the composite-widget keyboard model \u2014 no roving tabindex, no gridcell/row roles, no 2D arrow-key navigation. Screen readers switched to application/focus mode and offered cell navigation that did not exist. The role was removed so the component is honestly a reading table. An opt-in interactive grid mode is deliberately NOT offered until the keyboard model ships.',
|
|
8697
|
+
"accessible_name: Use `caption` for a visible name or `aria-label` / `aria-labelledby` for an invisible one. Both land on the `<table>`.",
|
|
7014
8698
|
"aria-sort: Set on sortable column headers (ascending, descending, none).",
|
|
7015
8699
|
"keyboard: Sortable headers are focusable and activated with Enter or Space.",
|
|
7016
8700
|
"scope: col on all th elements."
|
|
@@ -7047,7 +8731,8 @@ var treeui_catalog_default = {
|
|
|
7047
8731
|
},
|
|
7048
8732
|
recipes: [
|
|
7049
8733
|
"data-listing"
|
|
7050
|
-
]
|
|
8734
|
+
],
|
|
8735
|
+
practices: []
|
|
7051
8736
|
},
|
|
7052
8737
|
{
|
|
7053
8738
|
name: "TTabs",
|
|
@@ -7153,6 +8838,9 @@ var treeui_catalog_default = {
|
|
|
7153
8838
|
},
|
|
7154
8839
|
recipes: [
|
|
7155
8840
|
"router-backed-tabs"
|
|
8841
|
+
],
|
|
8842
|
+
practices: [
|
|
8843
|
+
"interaction-feedback"
|
|
7156
8844
|
]
|
|
7157
8845
|
},
|
|
7158
8846
|
{
|
|
@@ -7233,6 +8921,10 @@ var treeui_catalog_default = {
|
|
|
7233
8921
|
},
|
|
7234
8922
|
recipes: [
|
|
7235
8923
|
"tag-input"
|
|
8924
|
+
],
|
|
8925
|
+
practices: [
|
|
8926
|
+
"predictable-api",
|
|
8927
|
+
"token-driven"
|
|
7236
8928
|
]
|
|
7237
8929
|
},
|
|
7238
8930
|
{
|
|
@@ -7297,6 +8989,12 @@ var treeui_catalog_default = {
|
|
|
7297
8989
|
type: "boolean",
|
|
7298
8990
|
default: "false",
|
|
7299
8991
|
note: "Clip to a single line with an ellipsis."
|
|
8992
|
+
},
|
|
8993
|
+
{
|
|
8994
|
+
name: "preserveWhitespace",
|
|
8995
|
+
type: "boolean",
|
|
8996
|
+
default: "false",
|
|
8997
|
+
note: "Render authored line breaks and blank lines as written (`white-space: pre-wrap`) while still wrapping long lines. Use for plain-text output such as AI responses, so consumers never need a local `white-space: pre-wrap` class. Mutually exclusive with `truncate`, which needs `nowrap`; when both are set `truncate` wins and no `is-pre-wrap` class is emitted."
|
|
7300
8998
|
}
|
|
7301
8999
|
],
|
|
7302
9000
|
events: [],
|
|
@@ -7310,7 +9008,8 @@ var treeui_catalog_default = {
|
|
|
7310
9008
|
],
|
|
7311
9009
|
behavior: [
|
|
7312
9010
|
"semantic_element_controlled_by_as: true",
|
|
7313
|
-
"token_driven_size_tone_weight: true"
|
|
9011
|
+
"token_driven_size_tone_weight: true",
|
|
9012
|
+
"truncate_takes_precedence_over_preserve_whitespace: true"
|
|
7314
9013
|
],
|
|
7315
9014
|
selection: {
|
|
7316
9015
|
keywords: [],
|
|
@@ -7322,7 +9021,8 @@ var treeui_catalog_default = {
|
|
|
7322
9021
|
required: [],
|
|
7323
9022
|
notes: []
|
|
7324
9023
|
},
|
|
7325
|
-
recipes: []
|
|
9024
|
+
recipes: [],
|
|
9025
|
+
practices: []
|
|
7326
9026
|
},
|
|
7327
9027
|
{
|
|
7328
9028
|
name: "TTextarea",
|
|
@@ -7439,7 +9139,8 @@ var treeui_catalog_default = {
|
|
|
7439
9139
|
required: [],
|
|
7440
9140
|
notes: []
|
|
7441
9141
|
},
|
|
7442
|
-
recipes: []
|
|
9142
|
+
recipes: [],
|
|
9143
|
+
practices: []
|
|
7443
9144
|
},
|
|
7444
9145
|
{
|
|
7445
9146
|
name: "TTimeline",
|
|
@@ -7499,7 +9200,8 @@ var treeui_catalog_default = {
|
|
|
7499
9200
|
required: [],
|
|
7500
9201
|
notes: []
|
|
7501
9202
|
},
|
|
7502
|
-
recipes: []
|
|
9203
|
+
recipes: [],
|
|
9204
|
+
practices: []
|
|
7503
9205
|
},
|
|
7504
9206
|
{
|
|
7505
9207
|
name: "TToast",
|
|
@@ -7562,7 +9264,8 @@ var treeui_catalog_default = {
|
|
|
7562
9264
|
},
|
|
7563
9265
|
recipes: [
|
|
7564
9266
|
"confirm-destructive-action"
|
|
7565
|
-
]
|
|
9267
|
+
],
|
|
9268
|
+
practices: []
|
|
7566
9269
|
},
|
|
7567
9270
|
{
|
|
7568
9271
|
name: "TToggleGroup",
|
|
@@ -7679,7 +9382,8 @@ var treeui_catalog_default = {
|
|
|
7679
9382
|
'Use `selectionMode="multiple"` for small visible multi-choice sets.'
|
|
7680
9383
|
]
|
|
7681
9384
|
},
|
|
7682
|
-
recipes: []
|
|
9385
|
+
recipes: [],
|
|
9386
|
+
practices: []
|
|
7683
9387
|
},
|
|
7684
9388
|
{
|
|
7685
9389
|
name: "TTooltip",
|
|
@@ -7791,6 +9495,9 @@ var treeui_catalog_default = {
|
|
|
7791
9495
|
},
|
|
7792
9496
|
recipes: [
|
|
7793
9497
|
"anchored-help"
|
|
9498
|
+
],
|
|
9499
|
+
practices: [
|
|
9500
|
+
"accessible-by-default"
|
|
7794
9501
|
]
|
|
7795
9502
|
},
|
|
7796
9503
|
{
|
|
@@ -7803,7 +9510,7 @@ var treeui_catalog_default = {
|
|
|
7803
9510
|
purpose: "Hierarchical tree view with expansion, keyboard navigation, and single or multiple selection.",
|
|
7804
9511
|
sourceFile: "packages/vue/src/components/TTreeView.vue",
|
|
7805
9512
|
storyFile: "apps/docs/src/stories/TreeView.stories.ts",
|
|
7806
|
-
storyTitle: "Components/Navigation & Disclosure/
|
|
9513
|
+
storyTitle: "Components/Navigation & Disclosure/TreeView",
|
|
7807
9514
|
manifestFile: "docs/ai/COMPONENTS/tree-view.yaml",
|
|
7808
9515
|
props: [
|
|
7809
9516
|
{
|
|
@@ -7913,6 +9620,9 @@ var treeui_catalog_default = {
|
|
|
7913
9620
|
},
|
|
7914
9621
|
recipes: [
|
|
7915
9622
|
"hierarchy-picker"
|
|
9623
|
+
],
|
|
9624
|
+
practices: [
|
|
9625
|
+
"accessible-by-default"
|
|
7916
9626
|
]
|
|
7917
9627
|
}
|
|
7918
9628
|
],
|
|
@@ -9069,7 +10779,8 @@ var formatComponentSummary = (component) => {
|
|
|
9069
10779
|
"Setup",
|
|
9070
10780
|
[...component.setup.required, ...component.setup.notes]
|
|
9071
10781
|
),
|
|
9072
|
-
component.recipes.length > 0 ? `Recipes: ${component.recipes.join(", ")}` : void 0
|
|
10782
|
+
component.recipes.length > 0 ? `Recipes: ${component.recipes.join(", ")}` : void 0,
|
|
10783
|
+
component.practices.length > 0 ? `Practices: ${component.practices.join(", ")}` : void 0
|
|
9073
10784
|
].filter(Boolean);
|
|
9074
10785
|
return lines.join("\n");
|
|
9075
10786
|
};
|
|
@@ -9144,6 +10855,12 @@ var resourceList = [
|
|
|
9144
10855
|
description: "Reusable multi-component composition recipes.",
|
|
9145
10856
|
mimeType: "application/json"
|
|
9146
10857
|
},
|
|
10858
|
+
{
|
|
10859
|
+
uri: "treeui://practices",
|
|
10860
|
+
name: "TreeUI practices",
|
|
10861
|
+
description: "Named UX practices and the components that follow them.",
|
|
10862
|
+
mimeType: "application/json"
|
|
10863
|
+
},
|
|
9147
10864
|
{
|
|
9148
10865
|
uri: "treeui://tokens",
|
|
9149
10866
|
name: "TreeUI design tokens",
|
|
@@ -9177,6 +10894,9 @@ var readResourcePayload = (uri) => {
|
|
|
9177
10894
|
if (uri === "treeui://recipes") {
|
|
9178
10895
|
return catalog.recipes;
|
|
9179
10896
|
}
|
|
10897
|
+
if (uri === "treeui://practices") {
|
|
10898
|
+
return catalog.practices;
|
|
10899
|
+
}
|
|
9180
10900
|
if (uri === "treeui://tokens") {
|
|
9181
10901
|
return catalog.tokens;
|
|
9182
10902
|
}
|