@treeui/mcp 0.8.0 → 0.8.1

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/index.cjs CHANGED
@@ -50,9 +50,9 @@ module.exports = __toCommonJS(index_exports);
50
50
 
51
51
  // src/generated/treeui.catalog.json
52
52
  var treeui_catalog_default = {
53
- generatedAt: "0.30.0",
53
+ generatedAt: "0.32.0",
54
54
  packageName: "@treeui/vue",
55
- packageVersion: "0.30.0",
55
+ packageVersion: "0.32.0",
56
56
  decisionGuides: [
57
57
  {
58
58
  id: "single-choice",
@@ -175,7 +175,7 @@ var treeui_catalog_default = {
175
175
  ],
176
176
  notes: [
177
177
  "Editing, not display. For read-only key/value display use TDescriptionList.",
178
- "A write-only/sensitive mode (value never read back) is a closed contract on the queue, not yet shipped."
178
+ "A write-only/sensitive mode (value never read back) is a designed contract that is not yet shipped."
179
179
  ]
180
180
  },
181
181
  {
@@ -473,8 +473,8 @@ var treeui_catalog_default = {
473
473
  "Put the lockup in the `header-start` slot, not `header`. Filling `header-start` switches the header to the shell's own grid, so the mark tracks `--tree-app-shell-sidebar-width` and animates with the collapse \u2014 no local column math.",
474
474
  'The slot is scoped: use its `collapsed` binding to drop the wordmark and keep only the mark (`v-if="!collapsed"`), rather than hiding text with CSS.',
475
475
  'Logo is `TAvatar` (`size`, `alt`, `initials` fallback) or a plain `<img>` sized with `--tree-size-icon-*`; name and subtitle are `TText` (`weight`, `tone="muted"`, `truncate`) \u2014 never raw `<strong>`/`<span>` with a local class.',
476
- "TreeUI ships no `TBrand` component on purpose: the logo asset, the product name, and what survives collapse are product identity, which must stay in the consumer. See DECISIONS.md \u2192 Portability Boundary.",
477
- "Company and service logos (AWS, LocalStack, social networks) are brand assets and are not TreeUI icons \u2014 source them from the app's brand policy, not the icon registry."
476
+ "TreeUI ships no `TBrand` component on purpose: the logo asset, the product name, and what survives collapse are product identity, which must stay in the consuming application. See DECISIONS.md \u2192 Portability Boundary.",
477
+ "Company and service logos are brand assets, not TreeUI icons \u2014 source them from your own brand assets rather than the icon registry."
478
478
  ]
479
479
  },
480
480
  {
@@ -820,28 +820,38 @@ var treeui_catalog_default = {
820
820
  "Tab/Shift+Tab order, Escape to close, Enter/Space to activate, arrow keys where the pattern expects them.",
821
821
  "Overlays trap focus while open and restore it on close.",
822
822
  "Clickable targets stay at or above 44\xD744px.",
823
- "Form control boundaries clear 3:1 against every surface (WCAG 1.4.11); decorative edges are a separate token and are not held to it."
823
+ "Form control boundaries clear 3:1 against every surface (WCAG 1.4.11); decorative edges are a separate token and are not held to it.",
824
+ "A panel anchored to a trigger is rendered in a layer no ancestor can clip, and is pushed back inside the viewport \u2014 a control that is painted off-screen or behind a clip is not operable.",
825
+ "Every string a screen reader announces is a prop with a default, never a hard-coded literal; a control whose only name is English is unusable in any other language."
824
826
  ],
825
827
  components: [
826
- "TModal",
827
- "TDrawer",
828
- "TConfirmDialog",
829
- "TDropdown",
830
- "TTooltip",
831
828
  "TAccordion",
832
- "TFormField",
833
- "TTreeView",
834
- "TToastProvider",
829
+ "TAppShell",
835
830
  "TButton",
831
+ "TCanvasSurface",
832
+ "TCheckbox",
836
833
  "TCodeBlock",
834
+ "TConfirmDialog",
835
+ "TDatePicker",
836
+ "TDrawer",
837
+ "TDropdown",
838
+ "TFileUpload",
839
+ "TFormField",
840
+ "TImage",
837
841
  "TLinkTile",
838
842
  "TMenu",
843
+ "TModal",
839
844
  "TPopover",
840
- "TImage",
845
+ "TSelect",
841
846
  "TSkipLink",
842
- "TAppShell",
843
- "TCheckbox",
844
- "TText"
847
+ "TSteps",
848
+ "TTabs",
849
+ "TText",
850
+ "TToast",
851
+ "TToastProvider",
852
+ "TToggleGroup",
853
+ "TTooltip",
854
+ "TTreeView"
845
855
  ]
846
856
  },
847
857
  {
@@ -901,26 +911,42 @@ var treeui_catalog_default = {
901
911
  "Spacing comes from the --tree-space-* scale, applied by layout components.",
902
912
  "Compose TPage, TStack, TGrid, and TSplit before writing a custom layout div.",
903
913
  "Forms align through TFormField + TStack + TGrid \u2014 labels, hints, and errors line up by contract.",
904
- "Reading widths and page gutters come from TContainer/TPage, not local max-widths."
914
+ "Reading widths and page gutters come from TContainer/TPage, not local max-widths.",
915
+ "A surface takes its container's width: it never grows to the min-content of something inside it. Card, modal and timeline surfaces declare an explicit minmax(0, 1fr) track, and text that can lack a break opportunity wraps, so scrolling and truncation belong to the descendant that asked for them \u2014 never to every sibling on the surface."
905
916
  ],
906
917
  components: [
907
- "TStack",
908
- "TGrid",
909
- "TSplit",
910
- "TContainer",
911
- "TSpacer",
912
- "TPage",
913
- "TPageHeader",
914
- "TFormField",
918
+ "TAppShell",
919
+ "TBadge",
915
920
  "TBrandLockup",
916
- "TList",
921
+ "TCanvasSurface",
922
+ "TCard",
923
+ "TCodeBlock",
924
+ "TConfirmDialog",
925
+ "TContainer",
917
926
  "TDescriptionList",
918
- "TSection",
927
+ "TEmptyState",
928
+ "TFormField",
929
+ "TGrid",
919
930
  "THero",
931
+ "THide",
932
+ "TLinkTile",
933
+ "TList",
934
+ "TModal",
935
+ "TNavMenu",
936
+ "TPage",
937
+ "TPageHeader",
920
938
  "TPageSurface",
939
+ "TSection",
921
940
  "TShow",
922
- "THide",
923
- "TEmptyState"
941
+ "TSpacer",
942
+ "TSparkline",
943
+ "TSplit",
944
+ "TStack",
945
+ "TStat",
946
+ "TSteps",
947
+ "TTabs",
948
+ "TText",
949
+ "TTimeline"
924
950
  ]
925
951
  },
926
952
  {
@@ -967,6 +993,24 @@ var treeui_catalog_default = {
967
993
  "TTextarea",
968
994
  "TToast"
969
995
  ]
996
+ },
997
+ {
998
+ id: "branchline-icons",
999
+ title: "Icons drawn to a contract",
1000
+ summary: "Branchline is the drawing contract behind every shipped icon: one grid, one weight, one closed modifier vocabulary. It is checked rather than reviewed \u2014 the build renders each glyph and fails when two names look alike at 16px or when a shape draws nothing.",
1001
+ rules: [
1002
+ "One grid: a 24x24 canvas with geometry inside a 1.5-22.5 trim area, so a 2u stroke never clips; four keylines carry the set \u2014 square 17.5, circle 18.5 diameter, wide 18x14, tall 14x18 \u2014 and positions land on a 0.25u step.",
1003
+ "One weight: 2u stroke, round caps and joins, currentColor and fill=none, all declared on the root <svg>. A child that sets stroke or fill breaks absoluteStrokeWidth and fails the build.",
1004
+ "Legible at the size it ships at: every pair of canonical icons is rendered at 16px and must differ by at least 5% of its ink. The rule is measured by branchline.test.ts, not judged by eye.",
1005
+ "A modifier gets territory of its own, and the base keeps its size: it is drawn inside bases that enclose space (shield, file, folder, calendar, ticket, message, square, badge, search) and in a cleared corner otherwise, where the base is redrawn at full size with that corner interrupted so 5.5u of canvas stays clear around the mark.",
1006
+ "Every shape earns its place: each node is removed and re-rendered, and a node that changes less than 1% of the glyph's ink fails the build. Geometry is never derived from the icon's name.",
1007
+ "A family shares one base, drawn once and reused literally; a variant changes exactly one thing, in one place, by one rule.",
1008
+ "The metaphor is the conventional one \u2014 an icon is not the place to be original. A concept with no settled picture composes one from Branchline primitives, drawn deliberately rather than generated.",
1009
+ "One concept, one canonical name, one drawing. A synonym is an alias that shares its target's geometry byte for byte, so mic and microphone can never drift apart."
1010
+ ],
1011
+ components: [
1012
+ "TIcon"
1013
+ ]
970
1014
  }
971
1015
  ],
972
1016
  setup: {
@@ -1604,7 +1648,7 @@ var treeui_catalog_default = {
1604
1648
  name: "showCollapseButton",
1605
1649
  type: "boolean",
1606
1650
  default: "true",
1607
- 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."
1651
+ 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, and never inside the auto-rail band (between `breakpoint` and `railBreakpoint`): there the width decides the state, so the button could not change anything, did nothing when pressed, and announced the manual preference instead of what was on screen. Its `aria-expanded` and `aria-label` are derived from the EFFECTIVE collapsed state, as the glyph already was."
1608
1652
  },
1609
1653
  {
1610
1654
  name: "collapseLabel",
@@ -1688,7 +1732,7 @@ var treeui_catalog_default = {
1688
1732
  },
1689
1733
  {
1690
1734
  name: "header-end",
1691
- description: "Trailing header region for actions/controls, pinned to the far end of the row. Filling it adds `has-end`; in the plain flex header the content region's grow already pushes it to the end, and in the `has-start` grid it becomes a content-sized third column with the trailing padding. Replaces the consumer's own `TStack justify=flex-end` wrapper inside `#header`.\n",
1735
+ description: "Trailing header region for actions/controls, pinned to the far end of the row. Filling it adds `has-end`; in the plain flex header the content region's grow already pushes it to the end, and in the `has-start` grid it becomes a content-sized third column with the trailing padding. Trailing alignment is the shell's own job, so header actions need no `TStack justify=flex-end` wrapper around them.\n",
1692
1736
  note: "AppShellSlotProps"
1693
1737
  },
1694
1738
  {
@@ -1742,6 +1786,7 @@ var treeui_catalog_default = {
1742
1786
  "menu_and_drawer_close_buttons_are_44px: true"
1743
1787
  ],
1744
1788
  behavior: [
1789
+ "scroller_is_a_containing_block: `.t-app-shell__main` (and `.t-app-shell__sidebar-body`) carry `position: relative`. Without it an absolutely positioned descendant with auto insets \u2014 `.t-visually-hidden`, which this library itself uses for the TProgress label \u2014 anchored to the initial block instead of the panel: it was neither clipped nor scrolled with the panel, and it extended the DOCUMENT's scroll. The shell is `100dvh`, so the document is not supposed to scroll at all; it did, leaving an empty band below the shell.",
1745
1790
  "fills_viewport_full_width_and_height: true",
1746
1791
  "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",
1747
1792
  "header_spans_full_width_above_sidebar_and_content: true",
@@ -1829,7 +1874,8 @@ var treeui_catalog_default = {
1829
1874
  "brand-lockup"
1830
1875
  ],
1831
1876
  practices: [
1832
- "accessible-by-default"
1877
+ "accessible-by-default",
1878
+ "content-alignment"
1833
1879
  ]
1834
1880
  },
1835
1881
  {
@@ -2040,6 +2086,18 @@ var treeui_catalog_default = {
2040
2086
  "lg"
2041
2087
  ],
2042
2088
  description: "Changes min-height and font-size only; inline padding is constant across sizes."
2089
+ },
2090
+ {
2091
+ name: "truncate",
2092
+ type: "boolean",
2093
+ default: "false",
2094
+ description: "Keep the label on one line and clip it with an ellipsis. Opt-in: the default is to wrap, because a status pill that silently loses the end of its text is worse than a two-line pill. Pass `label` alongside it so the full text reaches the `title` tooltip."
2095
+ },
2096
+ {
2097
+ name: "label",
2098
+ type: "string",
2099
+ default: "undefined",
2100
+ description: "The badge text. Only needed with `truncate`, which puts it in `title`; otherwise use the default slot."
2043
2101
  }
2044
2102
  ],
2045
2103
  events: [],
@@ -2062,8 +2120,10 @@ var treeui_catalog_default = {
2062
2120
  "tone_remaps_variant_color_variables: true",
2063
2121
  "tone_overrides_variant_danger_palette: true",
2064
2122
  "tone_neutral_has_no_stylesheet_rule: true",
2123
+ 'tint_ink_is_the_on_soft_token: The `soft` and `danger` variants paint their label with the tone\'s `*-on-soft` colour, never the tone\'s full-strength colour. `*-on-soft` is derived to clear AA on that exact tint and deepens as the tint deepens; the full-strength tone on its own tint measured below AA for eight of the ten tone/theme pairs, including `variant="soft" tone="neutral"`, which is both defaults. The mapping is declared in `@treeui/tokens` as `NATIVE_BADGE_TONES` and the stylesheet is tested against it.',
2065
2124
  "icon_wrapper_rendered_only_when_slot_filled: true",
2066
- "icon_renders_before_default_slot: true"
2125
+ "icon_renders_before_default_slot: true",
2126
+ "never_wider_than_its_container: The badge carries `max-inline-size: 100%` and `min-inline-size: 0`, so a long label wraps inside the container instead of pushing it. Wrapped lines use the UI line height with block padding rather than `line-height: 1`, at which a second line's ascenders touched the pill's border."
2067
2127
  ],
2068
2128
  selection: {
2069
2129
  keywords: [],
@@ -2081,6 +2141,7 @@ var treeui_catalog_default = {
2081
2141
  practices: [
2082
2142
  "predictable-api",
2083
2143
  "state-clarity",
2144
+ "content-alignment",
2084
2145
  "token-driven"
2085
2146
  ]
2086
2147
  },
@@ -2271,7 +2332,7 @@ var treeui_catalog_default = {
2271
2332
  name: "href",
2272
2333
  type: "string",
2273
2334
  default: "undefined",
2274
- note: 'Anchor attributes (`href`, `target`, `rel`, `download`) are declared props and are only rendered when `as="a"`. They were fallthrough before, which typechecked as an error in a consumer\'s `strictTemplates` build even though a link button is the documented use of `as` (TREEUX-011, group 1).\n'
2335
+ note: 'Anchor attributes (`href`, `target`, `rel`, `download`) are declared props and are only rendered when `as="a"`. They were fallthrough before, which typechecked as an error in a consumer\'s `strictTemplates` build even though a link button is the documented use of `as`.\n'
2275
2336
  },
2276
2337
  {
2277
2338
  name: "target",
@@ -2686,6 +2747,116 @@ var treeui_catalog_default = {
2686
2747
  recipes: [],
2687
2748
  practices: []
2688
2749
  },
2750
+ {
2751
+ name: "TCanvasSurface",
2752
+ aliases: [],
2753
+ package: "@treeui/vue",
2754
+ kind: "data-display",
2755
+ category: "Data Display",
2756
+ status: "available",
2757
+ purpose: "A sized, repaintable, hit-testable canvas for a data-driven drawing \u2014 a diagram, a graph, a custom plot.",
2758
+ sourceFile: "packages/vue/src/components/TCanvasSurface.vue",
2759
+ storyFile: "apps/docs/src/stories/CanvasSurface.stories.ts",
2760
+ storyTitle: "Components/Data Display/Canvas Surface",
2761
+ manifestFile: "docs/ai/COMPONENTS/canvas-surface.yaml",
2762
+ props: [
2763
+ {
2764
+ name: "draw",
2765
+ type: "(frame: CanvasSurfaceFrame) => void",
2766
+ required: true,
2767
+ note: "Paints the whole surface. Called on mount, on resize and on every `redraw()`. The context arrives already scaled to CSS pixels, so the drawing never does device-ratio arithmetic; it is expected to clear what it does not repaint.\n"
2768
+ },
2769
+ {
2770
+ name: "height",
2771
+ type: "number | string",
2772
+ default: "320",
2773
+ note: "Number is px, string is any CSS length. A diagram has no intrinsic height, so it is declared."
2774
+ },
2775
+ {
2776
+ name: "cursor",
2777
+ type: "string",
2778
+ default: "undefined",
2779
+ note: "Pointer over the surface. This cannot come from a stylesheet: the sensitive area is a rectangle inside the bitmap and no selector knows where it is. Bind it to whatever the consumer's hit-test just decided.\n"
2780
+ },
2781
+ {
2782
+ name: "maxPixelRatio",
2783
+ type: "number",
2784
+ default: "2"
2785
+ },
2786
+ {
2787
+ name: "ariaLabel",
2788
+ type: "string",
2789
+ default: "undefined",
2790
+ note: "Sets role=img. A bitmap says nothing on its own."
2791
+ },
2792
+ {
2793
+ name: "redrawKey",
2794
+ type: "unknown",
2795
+ default: "undefined",
2796
+ note: "Repaint whenever this changes \u2014 pass the data, a version counter, or the theme. Deep-watched."
2797
+ }
2798
+ ],
2799
+ events: [],
2800
+ slots: [
2801
+ {
2802
+ name: "default",
2803
+ description: "The long form of the drawing \u2014 a list, a table, the same data as markup. It lives inside the `<canvas>` element, which the browser exposes to assistive technology and never paints.\n"
2804
+ }
2805
+ ],
2806
+ a11y: [
2807
+ "Give it an ariaLabel; a canvas is opaque to assistive technology.",
2808
+ "Put the same information in the default slot as markup \u2014 it is the accessible form, not a fallback.",
2809
+ "Anything clickable inside the drawing needs a real control elsewhere, or a keyboard user cannot reach it."
2810
+ ],
2811
+ behavior: [
2812
+ "repaints_on_demand_not_on_a_clock: true",
2813
+ "backing_store_follows_the_element: true",
2814
+ "pointer_events_reach_the_canvas: true",
2815
+ "ssr_safe: Nothing touches the DOM outside onMounted."
2816
+ ],
2817
+ selection: {
2818
+ keywords: [
2819
+ "canvas",
2820
+ "diagram",
2821
+ "graph",
2822
+ "node and edge",
2823
+ "custom drawing",
2824
+ "plot",
2825
+ "topology",
2826
+ "map",
2827
+ "hit testing"
2828
+ ],
2829
+ useWhen: [
2830
+ "The drawing is data-driven and no chart primitive expresses it \u2014 nodes and edges, a topology, a custom plot.",
2831
+ "Parts of the drawing are click or hover targets.",
2832
+ "It must repaint when the data, the locale or the theme changes."
2833
+ ],
2834
+ avoidWhen: [
2835
+ "A line, area or bar chart says it \u2014 use TChart, which brings axes, legend, tooltip and an accessible table.",
2836
+ "The drawing is ornament \u2014 use useDecorativeCanvas, which gates the loop on visibility and reduced motion.",
2837
+ "The shape is an inline trend \u2014 use TSparkline."
2838
+ ],
2839
+ alternatives: [
2840
+ {
2841
+ component: "TChart",
2842
+ when: "The data fits axes and categories."
2843
+ },
2844
+ {
2845
+ component: "useDecorativeCanvas",
2846
+ when: "It is decoration, not information."
2847
+ }
2848
+ ]
2849
+ },
2850
+ setup: {
2851
+ required: [],
2852
+ notes: []
2853
+ },
2854
+ recipes: [],
2855
+ practices: [
2856
+ "accessible-by-default",
2857
+ "content-alignment"
2858
+ ]
2859
+ },
2689
2860
  {
2690
2861
  name: "TCard",
2691
2862
  aliases: [],
@@ -2759,6 +2930,9 @@ var treeui_catalog_default = {
2759
2930
  "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."
2760
2931
  ],
2761
2932
  behavior: [
2933
+ "surface_never_inflated_by_a_descendant: The surface and its body declare `grid-template-columns: minmax(0, 1fr)`. An implicit `auto` track takes its minimum from the min-content of its items, so one unbreakable descendant \u2014 a table, a code block, a machine string \u2014 behind any wrapper widened the whole surface and laid every sibling out past the border: `TText truncate` never engaged, the TTable wrapper's `overflow-x` never scrolled, and anything aligned to the end was painted outside the surface or over the neighbouring card.",
2934
+ "title_wraps_instead_of_widening_the_card: `.t-card__title` carries `overflow-wrap: anywhere`. A title without spaces used to set the card's min-content width, and the `#header` slot was no way out because the same track was still `auto`.",
2935
+ "actions_shrink_and_wrap: `.t-card__actions` is `flex-shrink: 1; min-inline-size: 0; flex-wrap: wrap`. It was `flex-shrink: 0`, so in a narrow card the controls were laid out past the border instead of moving to the next line \u2014 the header already wraps, and the actions now follow it.",
2762
2936
  "body_wrapper_class: t-card__body",
2763
2937
  "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.",
2764
2938
  "footer_render_condition: The `footer.t-card__footer` element renders only when the `footer` slot is supplied.",
@@ -2801,6 +2975,7 @@ var treeui_catalog_default = {
2801
2975
  practices: [
2802
2976
  "interaction-feedback",
2803
2977
  "predictable-api",
2978
+ "content-alignment",
2804
2979
  "token-driven"
2805
2980
  ]
2806
2981
  },
@@ -2817,6 +2992,12 @@ var treeui_catalog_default = {
2817
2992
  storyTitle: "Components/Data Display/Chart",
2818
2993
  manifestFile: "docs/ai/COMPONENTS/chart.yaml",
2819
2994
  props: [
2995
+ {
2996
+ name: "yAxisWidth",
2997
+ type: "number",
2998
+ default: "undefined",
2999
+ description: "Fix the space reserved for the y-axis labels, in pixels. Left unset, the chart MEASURES the formatted ticks and reserves what they need \u2014 the margin used to be a flat 44px, which clipped a formatted `1,234,567`. Set it to line several charts up on a shared gutter."
3000
+ },
2820
3001
  {
2821
3002
  name: "type",
2822
3003
  type: "TChartType",
@@ -2987,7 +3168,7 @@ var treeui_catalog_default = {
2987
3168
  ],
2988
3169
  avoidWhen: [
2989
3170
  "A single value tells the story \u2014 use TStat.",
2990
- "You only need an inline trend with no axes \u2014 use TSparkline.",
3171
+ "You only need an inline trend with no axes \u2014 use TSparkline (`fluid` fills the card width).",
2991
3172
  "The data is a part-of-whole breakdown \u2014 use TDonutChart."
2992
3173
  ],
2993
3174
  alternatives: [
@@ -3159,6 +3340,17 @@ var treeui_catalog_default = {
3159
3340
  storyTitle: "Components/Data Display/CodeBlock",
3160
3341
  manifestFile: "docs/ai/COMPONENTS/code-block.yaml",
3161
3342
  props: [
3343
+ {
3344
+ name: "size",
3345
+ type: "TSize",
3346
+ default: "md",
3347
+ values: [
3348
+ "sm",
3349
+ "md",
3350
+ "lg"
3351
+ ],
3352
+ description: "Density. Scales the type size and the padding of the `<pre>` by tokens, like every other sized component. `md` is what the block has always shipped; `sm` is for a block inside a dense surface \u2014 a table cell, a list row \u2014 where the fixed type size dominated the row."
3353
+ },
3162
3354
  {
3163
3355
  name: "code",
3164
3356
  type: "string",
@@ -3207,7 +3399,9 @@ var treeui_catalog_default = {
3207
3399
  'scroll_region: The `<pre>` is `role="region"` + `tabindex="0"` + `aria-label` (from `label`) so keyboard users can scroll it \u2014 the library does this for you.',
3208
3400
  "copy_button_state: The copy button's aria-label reflects the copied state briefly."
3209
3401
  ],
3210
- behavior: [],
3402
+ behavior: [
3403
+ 'wrap_reduces_the_min_content: `.t-code-block.is-wrap .t-code-block__pre` uses `overflow-wrap: anywhere`, not `break-word`. `break-word` breaks only once a width is already settled, so wherever the block\'s width came from its content \u2014 a grid `auto` track, a table cell, a flex item without `min-width: 0` \u2014 the longest run without a break opportunity became the minimum width and pushed the container instead of wrapping. That is precisely the case `wrap` exists for: a URL, a token, a credential. Same semantics as `TText wrap="anywhere"`.'
3404
+ ],
3211
3405
  selection: {
3212
3406
  keywords: [
3213
3407
  "code",
@@ -3245,6 +3439,7 @@ var treeui_catalog_default = {
3245
3439
  recipes: [],
3246
3440
  practices: [
3247
3441
  "accessible-by-default",
3442
+ "content-alignment",
3248
3443
  "token-driven"
3249
3444
  ]
3250
3445
  },
@@ -3766,6 +3961,7 @@ var treeui_catalog_default = {
3766
3961
  "icon_slot_marked_aria_hidden: true"
3767
3962
  ],
3768
3963
  behavior: [
3964
+ "surface_never_inflated_by_a_descendant: `.t-confirm-dialog` and its body declare `grid-template-columns: minmax(0, 1fr)`, and the icon variant uses `auto minmax(0, 1fr)`. It inherits TModal's title and description wrapping, which is what keeps confirm and cancel on the surface when the dialog names a long resource \u2014 it passes `title`/`description` as strings and exposes no `#header` slot, so there was no way around it from the API.",
3769
3965
  "built_on_modal_contract: true",
3770
3966
  "default_confirm_button_variant: danger",
3771
3967
  "default_cancel_button_variant: ghost",
@@ -3811,7 +4007,8 @@ var treeui_catalog_default = {
3811
4007
  "confirm-destructive-action"
3812
4008
  ],
3813
4009
  practices: [
3814
- "accessible-by-default"
4010
+ "accessible-by-default",
4011
+ "content-alignment"
3815
4012
  ]
3816
4013
  },
3817
4014
  {
@@ -4191,6 +4388,8 @@ var treeui_catalog_default = {
4191
4388
  "focus_is_not_trapped_and_tab_leaves_the_open_calendar: true"
4192
4389
  ],
4193
4390
  behavior: [
4391
+ 'panel_is_teleported_to_the_body: The calendar panel renders through `<Teleport to="body">` and is placed with `position: fixed` from the trigger\'s viewport rect by `useAnchoredLayer`. It used to be absolutely positioned inside the root, so inside a `TModal` it was trapped in the surface and clipped. Query it from `document.body` in tests.',
4392
+ 'month_title_capitalises_only_its_first_letter: `text-transform: capitalize` uppercased every word, which in most locales hits a particle in the middle of the title \u2014 pt-BR\'s "setembro de 2026" rendered as "Setembro De 2026". The rule is now `none` plus a `::first-letter` uppercase.',
4194
4393
  "value_format: YYYY-MM-DD",
4195
4394
  "controlled_and_uncontrolled_open: true",
4196
4395
  "open_state_emits_are_deduped: true",
@@ -4239,7 +4438,9 @@ var treeui_catalog_default = {
4239
4438
  ]
4240
4439
  },
4241
4440
  recipes: [],
4242
- practices: []
4441
+ practices: [
4442
+ "accessible-by-default"
4443
+ ]
4243
4444
  },
4244
4445
  {
4245
4446
  name: "TDateTimePicker",
@@ -5253,6 +5454,24 @@ var treeui_catalog_default = {
5253
5454
  storyTitle: "Components/Data Entry/FileUpload",
5254
5455
  manifestFile: "docs/ai/COMPONENTS/file-upload.yaml",
5255
5456
  props: [
5457
+ {
5458
+ name: "clearLabel",
5459
+ type: "string",
5460
+ default: "Clear all",
5461
+ description: "Label for the button that drops every selected file. It was hard-coded English with no way out."
5462
+ },
5463
+ {
5464
+ name: "removeLabel",
5465
+ type: "string",
5466
+ default: "Remove",
5467
+ description: "Label for a row's remove button."
5468
+ },
5469
+ {
5470
+ name: "removeAriaLabel",
5471
+ type: "(file: File) => string",
5472
+ default: "(f) => `Remove ${f.name}`",
5473
+ description: "Accessible name for a row's remove button. A function, not a string, because the file name sits INSIDE the sentence and its position differs by language \u2014 a prefix and a suffix cannot express that."
5474
+ },
5256
5475
  {
5257
5476
  name: "modelValue",
5258
5477
  type: "File[]",
@@ -5512,7 +5731,9 @@ var treeui_catalog_default = {
5512
5731
  recipes: [
5513
5732
  "page-drop-target"
5514
5733
  ],
5515
- practices: []
5734
+ practices: [
5735
+ "accessible-by-default"
5736
+ ]
5516
5737
  },
5517
5738
  {
5518
5739
  name: "TFlag",
@@ -5825,6 +6046,12 @@ var treeui_catalog_default = {
5825
6046
  name: "dense",
5826
6047
  type: "boolean",
5827
6048
  default: "false"
6049
+ },
6050
+ {
6051
+ name: "balance",
6052
+ type: "boolean",
6053
+ default: "false",
6054
+ note: 'Let the last row divide itself among the items it has instead of leaving empty tracks to its right \u2014 five cards over four tracks read as "one card failed to load". `auto-fit` cannot do it: it collapses a track only when that track is empty on EVERY row, so the remainder row keeps the widths of the rows above it. Balanced mode lays out with flex, where each line sizes itself: full rows are identical to the grid, only the remainder is shared out. Ignored when `columns` is set, since a declared track count already answers the same question.\n'
5828
6055
  }
5829
6056
  ],
5830
6057
  events: [],
@@ -5838,6 +6065,7 @@ var treeui_catalog_default = {
5838
6065
  ],
5839
6066
  behavior: [
5840
6067
  "semantic_element_controlled_by_as: true",
6068
+ "balance_shares_the_last_row_instead_of_leaving_holes: true",
5841
6069
  "fixed_columns_supported: true",
5842
6070
  "auto_fit_columns_supported: true",
5843
6071
  "dense_mode_uses_grid_auto_flow_dense: true"
@@ -6130,6 +6358,7 @@ var treeui_catalog_default = {
6130
6358
  "calendar-plus",
6131
6359
  "calendar-range",
6132
6360
  "calendar-x",
6361
+ "campaign",
6133
6362
  "carousel",
6134
6363
  "catalog",
6135
6364
  "chart-column",
@@ -6166,7 +6395,6 @@ var treeui_catalog_default = {
6166
6395
  "companion",
6167
6396
  "compass",
6168
6397
  "connections",
6169
- "contentpilot",
6170
6398
  "copy",
6171
6399
  "cpu",
6172
6400
  "cpu-chip",
@@ -6412,8 +6640,6 @@ var treeui_catalog_default = {
6412
6640
  "tickets",
6413
6641
  "timeline",
6414
6642
  "timer",
6415
- "toggle-left",
6416
- "toggle-right",
6417
6643
  "token-input",
6418
6644
  "token-output",
6419
6645
  "trail",
@@ -6451,10 +6677,18 @@ var treeui_catalog_default = {
6451
6677
  },
6452
6678
  {
6453
6679
  name: "size",
6454
- type: "number | string",
6680
+ type: "number | TIconSize",
6455
6681
  default: "20",
6456
- description: "Pixel size for both width and height of the rendered svg.",
6457
- 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'
6682
+ values: [
6683
+ "sm",
6684
+ "md",
6685
+ "lg",
6686
+ "xl",
6687
+ "2xl",
6688
+ "<number of pixels>"
6689
+ ],
6690
+ description: "A token name from the icon scale, or a pixel number.",
6691
+ note: '`size` used to be `number | string`, which meant `<TIcon size="sm" />`\ntype-checked, wrote width="sm" onto the svg, and left the icon unsized \u2014\nit then stretched to fill its container, measured at 300px in the report\nthat produced this change. It now takes either a NUMBER of pixels or one\nof the icon-scale token names, which map to the same values as\n--tree-size-icon-sm | -md | -lg | -xl | -2xl (16 / 20 / 24 / 32 / 48 px).\nAn unrecognised string is a compile error in TypeScript and, for\nJavaScript consumers, falls back to the default size with a console\nwarning in development rather than rendering at an arbitrary size.\nA free-form CSS length is no longer accepted: set width/height in CSS\nfrom the icon scale instead, which is what TLanguageSelect\'s switcher\nvariant does.\n'
6458
6692
  },
6459
6693
  {
6460
6694
  name: "strokeWidth",
@@ -6484,7 +6718,7 @@ var treeui_catalog_default = {
6484
6718
  behavior: [
6485
6719
  "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.",
6486
6720
  '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).',
6487
- "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.",
6721
+ "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 370 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.",
6488
6722
  "resolved_per_render: TIcon resolves its name in a computed, not once at setup, so an icon registered after the component mounted still appears.",
6489
6723
  "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.",
6490
6724
  "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."
@@ -6534,7 +6768,9 @@ var treeui_catalog_default = {
6534
6768
  recipes: [
6535
6769
  "nav-menu-icons"
6536
6770
  ],
6537
- practices: []
6771
+ practices: [
6772
+ "branchline-icons"
6773
+ ]
6538
6774
  },
6539
6775
  {
6540
6776
  name: "TImage",
@@ -6657,7 +6893,7 @@ var treeui_catalog_default = {
6657
6893
  name: "modelValue",
6658
6894
  type: "T",
6659
6895
  default: "undefined",
6660
- note: "Generic over `T extends string | number`, so a `ref<number>` binds without a cast and `update:modelValue` pays back a number. `<script setup>` was widening every model to `string | number`, which under a consumer's `strictTemplates` made a numeric field a type error at the call site with no correct way to write it (TREEUX-011, group 3). When `T` is `number` the component parses the raw input value and only falls back to the raw string when it does not parse.\n"
6896
+ note: "Generic over `T extends string | number`, so a `ref<number>` binds without a cast and `update:modelValue` pays back a number. `<script setup>` was widening every model to `string | number`, and widening makes a numeric field a type error under `strictTemplates`, with no correct way to write the binding. When `T` is `number` the component parses the raw input value and only falls back to the raw string when it does not parse.\n"
6661
6897
  },
6662
6898
  {
6663
6899
  name: "size",
@@ -7369,7 +7605,9 @@ var treeui_catalog_default = {
7369
7605
  "aria_current: `page` when `current`.",
7370
7606
  "focus_visible: Focus ring on the tile."
7371
7607
  ],
7372
- behavior: [],
7608
+ behavior: [
7609
+ "default_slot_does_not_stretch_its_children: `.t-link-tile__body` is `align-items: flex-start`, not the `stretch` default. The default slot is where a consumer drops a TTag or a TBadge, and stretch made a four-character tag as wide as the description. Title and description are TText and still wrap to the available width."
7610
+ ],
7373
7611
  selection: {
7374
7612
  keywords: [
7375
7613
  "tile",
@@ -7405,6 +7643,7 @@ var treeui_catalog_default = {
7405
7643
  practices: [
7406
7644
  "interaction-feedback",
7407
7645
  "accessible-by-default",
7646
+ "content-alignment",
7408
7647
  "token-driven"
7409
7648
  ]
7410
7649
  },
@@ -7451,7 +7690,8 @@ var treeui_catalog_default = {
7451
7690
  "not_selectable: For a single-select list of options use TSelectableList instead."
7452
7691
  ],
7453
7692
  behavior: [
7454
- "responsive: On a container narrower than 30rem the row wraps: meta drops below the content while actions stay visible inline. Actions are NEVER hidden or auto-collapsed into an overflow menu \u2014 compose a TMenu inside the actions slot deliberately if an overflow is wanted (uses a CSS container query; the list sets container-type).",
7693
+ "actions_take_their_own_line_in_a_narrow_container: Inside the existing `@container (max-width: 30rem)` query, `.t-list-item__actions` becomes `flex-basis: 100%; order: 2; flex-wrap: wrap; justify-content: flex-end`. Rigid actions used to squeeze the content column down to 40\u2013110px rather than moving below it \u2014 the meta already dropped to its own line, and the actions now follow the same rule. Actions are still never hidden or auto-collapsed into an overflow menu; that stays a deliberate consumer choice.",
7694
+ "responsive: On a container narrower than 30rem the row wraps: meta drops below the content while actions stay visible inline, and the leading slot stays on the first line of the content \u2014 the wrap is for the meta only. Actions are NEVER hidden or auto-collapsed into an overflow menu \u2014 compose a TMenu inside the actions slot deliberately if an overflow is wanted (uses a CSS container query; the list sets container-type).",
7455
7695
  "no_overflow_ownership: TList does not create, own, or collapse an actions overflow."
7456
7696
  ],
7457
7697
  selection: {
@@ -7614,7 +7854,7 @@ var treeui_catalog_default = {
7614
7854
  kind: "overlay",
7615
7855
  category: "Overlay",
7616
7856
  status: "available",
7617
- purpose: "Rich action menu in a popover \u2014 slot-driven compound with groups, icons, descriptions, meta, destructive items, link items, and a radio (workspace-switch) item, with roving focus and keyboard support. Built on TPopover, so anchoring and focus restore come from there (TREEUX-015).",
7857
+ purpose: "Rich action menu in a popover \u2014 slot-driven compound with groups, icons, descriptions, meta, destructive items, link items, and a radio (workspace-switch) item, with roving focus and keyboard support. Built on TPopover, so anchoring and focus restore come from there.",
7618
7858
  sourceFile: "packages/vue/src/components/TMenu.vue",
7619
7859
  storyFile: "apps/docs/src/stories/Menu.stories.ts",
7620
7860
  storyTitle: "Components/Overlay/Menu",
@@ -7859,6 +8099,10 @@ var treeui_catalog_default = {
7859
8099
  "escape_closes_when_enabled: true"
7860
8100
  ],
7861
8101
  behavior: [
8102
+ "surface_never_inflated_by_a_descendant: The surface and its body declare `grid-template-columns: minmax(0, 1fr)`. An implicit `auto` track takes its minimum from the min-content of its items, so one unbreakable descendant \u2014 a table, a code block, a machine string \u2014 behind any wrapper widened the whole surface and laid every sibling out past the border: `TText truncate` never engaged, the TTable wrapper's `overflow-x` never scrolled, and anything aligned to the end was painted outside the surface or over the neighbouring card.",
8103
+ "only_the_body_scrolls: `.t-modal__surface` is a flex column with `overflow: hidden`, and `.t-modal__body` is the single scroller (`flex: 1 1 auto; min-block-size: 0; overflow: auto`). The whole surface used to scroll, so on a short viewport the footer's actions sat below the fold and the title scrolled away with the content. A flex column also removes the implicit `auto` track, which is the other half of the inflation above.",
8104
+ "title_and_description_wrap: `.t-modal__title` and `.t-modal__description` carry `overflow-wrap: anywhere` \u2014 `anywhere`, not `break-word`, because only `anywhere` reduces the min-content. A confirm dialog exists to name the thing being deleted, and a resource name without a break opportunity used to push confirm and cancel off the surface at any width, desktop included.",
8105
+ "a_child_overlay_must_be_teleported: Because the surface now clips, a panel rendered inside it would be cut off. TSelect's listbox and TDatePicker's panel teleport to the body for exactly this reason; a consumer composing its own overlay inside a modal should do the same with `useAnchoredLayer`.",
7862
8106
  "uses_teleport_to_body: true",
7863
8107
  "locks_body_scroll_while_open: true",
7864
8108
  "overlay_click_closes_when_enabled: true",
@@ -7903,7 +8147,8 @@ var treeui_catalog_default = {
7903
8147
  ],
7904
8148
  practices: [
7905
8149
  "accessible-by-default",
7906
- "predictable-api"
8150
+ "predictable-api",
8151
+ "content-alignment"
7907
8152
  ]
7908
8153
  },
7909
8154
  {
@@ -8249,6 +8494,7 @@ var treeui_catalog_default = {
8249
8494
  "aria_disabled: on link items when disabled"
8250
8495
  ],
8251
8496
  behavior: [
8497
+ "labels_wrap_rather_than_scroll_the_sidebar: `.t-nav-menu__list` and `.t-nav-menu__copy` declare `grid-template-columns: minmax(0, 1fr)`, and the label and description carry `overflow-wrap: anywhere`. A sidebar is the one place a horizontal scrollbar is never the right answer, and an item label without a break opportunity used to give it one.",
8252
8498
  "can_be_controlled_or_uncontrolled: true",
8253
8499
  "can_inherit_collapsed_state_from_sidebar: true",
8254
8500
  "supports_rich_item_rendering_via_slot: true"
@@ -8296,7 +8542,8 @@ var treeui_catalog_default = {
8296
8542
  "responsive-navigation"
8297
8543
  ],
8298
8544
  practices: [
8299
- "interaction-feedback"
8545
+ "interaction-feedback",
8546
+ "content-alignment"
8300
8547
  ]
8301
8548
  },
8302
8549
  {
@@ -8315,7 +8562,7 @@ var treeui_catalog_default = {
8315
8562
  {
8316
8563
  name: "modelValue",
8317
8564
  type: "number | null",
8318
- note: "`null` is REAL, not an error state: clearing the field is empty, and the component emits `null` for it. So `v-model` needs a `ref<number | null>`, and a `ref<number>` is a genuine type error under a consumer's `strictTemplates` rather than a gap in the library. This is the one place in the round where the checker was right and the call site was wrong \u2014 the others (TInput, TTabs, TToggleGroup) were the library's fault.\n"
8565
+ note: "`null` is REAL, not an error state: clearing the field is empty, and the component emits `null` for it. So `v-model` needs a `ref<number | null>`, and a `ref<number>` is a genuine type error under `strictTemplates` rather than a gap in the library \u2014 here the binding is what has to widen, not the model. The opposite of TInput/TTabs/TToggleGroup, where the library's own model type was too wide and no narrow ref could bind it.\n"
8319
8566
  },
8320
8567
  {
8321
8568
  name: "min",
@@ -8563,6 +8810,7 @@ var treeui_catalog_default = {
8563
8810
  "Actions area holds standard focusable controls (e.g. TButton) \u2014 no custom roles added."
8564
8811
  ],
8565
8812
  behavior: [
8813
+ "slot_presence_is_read_during_render: The template tests `$slots.title` / `$slots.subtitle` directly instead of a `computed` over `useSlots()`. The computed cached its first answer, so a `v-if`'d title slot that appeared later never rendered, and one that disappeared left an empty `<h1>` behind. This is the arrangement TCard already used for `$slots.header`.",
8566
8814
  "title_and_subtitle_optional: true",
8567
8815
  "heading_level_controlled_by_level: true",
8568
8816
  "actions_area_right_aligned_and_wraps: true",
@@ -9583,14 +9831,14 @@ var treeui_catalog_default = {
9583
9831
  props: [
9584
9832
  {
9585
9833
  name: "modelValue",
9586
- type: "string | number",
9587
- default: ""
9834
+ type: "T",
9835
+ default: "undefined"
9588
9836
  },
9589
9837
  {
9590
9838
  name: "options",
9591
- type: "TSelectOption[]",
9839
+ type: "TSelectOption<T>[]",
9592
9840
  default: "[]",
9593
- note: "Array of { label: string; value: string | number; disabled?: boolean }"
9841
+ note: "Array of { label: string; value: T; disabled?: boolean }"
9594
9842
  },
9595
9843
  {
9596
9844
  name: "open",
@@ -9686,7 +9934,9 @@ var treeui_catalog_default = {
9686
9934
  "outside_click_closes_dropdown: true",
9687
9935
  "focus_restores_on_close: true",
9688
9936
  "numeric_values_supported_without_string_coercion: true",
9689
- "listbox_flips_above_trigger_when_space_below_is_insufficient: true"
9937
+ "listbox_flips_above_trigger_when_space_below_is_insufficient: true",
9938
+ "option_label_wraps_instead_of_being_clipped: `.t-select__option` carries `overflow-wrap: anywhere`, so a label without a break opportunity wraps inside the listbox rather than overflowing it and being cut off.",
9939
+ "listbox_is_teleported_to_the_body: The listbox renders through `<Teleport to=\"body\">` and is placed with `position: fixed` from the trigger's viewport rect by the `useAnchoredLayer` composable, matching the trigger's width. It used to be positioned inside the root, which meant ANY ancestor with `overflow` clipped it \u2014 the TTable wrapper cut it off and a modal trapped it. Consequences for tests: the listbox is not a descendant of the component's root element, so query it from `document.body`."
9690
9940
  ],
9691
9941
  selection: {
9692
9942
  keywords: [
@@ -9724,6 +9974,7 @@ var treeui_catalog_default = {
9724
9974
  ],
9725
9975
  practices: [
9726
9976
  "interaction-feedback",
9977
+ "accessible-by-default",
9727
9978
  "predictable-api",
9728
9979
  "token-driven"
9729
9980
  ]
@@ -10197,7 +10448,9 @@ var treeui_catalog_default = {
10197
10448
  "Hit area is `--tree-size-control-lg` (48px) tall, above the 44px target floor.",
10198
10449
  "The label must say where it goes; the library does not supply one."
10199
10450
  ],
10200
- behavior: [],
10451
+ behavior: [
10452
+ "hidden_link_paints_no_shadow: `.t-skip-link:not(:focus-visible)` sets `box-shadow: none`. The box is translated off-screen while hidden, but a 14px offset with a 34px blur is not: it painted a grey smudge in the top-left of every header, at every width, all the time. The shadow belongs to the focused state, which is when the link is actually on screen."
10453
+ ],
10201
10454
  selection: {
10202
10455
  keywords: [
10203
10456
  "skip link",
@@ -10422,6 +10675,12 @@ var treeui_catalog_default = {
10422
10675
  default: "false",
10423
10676
  note: "Marker on the final point (line/area)."
10424
10677
  },
10678
+ {
10679
+ name: "fluid",
10680
+ type: "boolean",
10681
+ default: "false",
10682
+ note: "Fill the parent's width; `width` stays the viewBox. The height is unchanged on purpose \u2014 a sparkline is a band, and growing in both directions turns it into a chart that lies about its precision. Strokes use `non-scaling-stroke`, so the pen keeps its declared width.\n"
10683
+ },
10425
10684
  {
10426
10685
  name: "ariaLabel",
10427
10686
  type: "string",
@@ -10437,7 +10696,8 @@ var treeui_catalog_default = {
10437
10696
  behavior: [
10438
10697
  "no_axes_or_legend: true",
10439
10698
  "flat_series_renders_centered: true",
10440
- "scales_to_intrinsic_width_and_height: true"
10699
+ "scales_to_intrinsic_width_and_height: true",
10700
+ "fluid_fills_parent_width: true"
10441
10701
  ],
10442
10702
  selection: {
10443
10703
  keywords: [
@@ -10477,7 +10737,9 @@ var treeui_catalog_default = {
10477
10737
  recipes: [
10478
10738
  "metric-dashboard"
10479
10739
  ],
10480
- practices: []
10740
+ practices: [
10741
+ "content-alignment"
10742
+ ]
10481
10743
  },
10482
10744
  {
10483
10745
  name: "TSpinner",
@@ -10882,6 +11144,16 @@ var treeui_catalog_default = {
10882
11144
  name: "loading",
10883
11145
  type: "boolean",
10884
11146
  default: "false"
11147
+ },
11148
+ {
11149
+ name: "emphasis",
11150
+ type: "TStatEmphasis",
11151
+ default: "label",
11152
+ values: [
11153
+ "label",
11154
+ "value"
11155
+ ],
11156
+ note: 'Which half leads. `label` is the dashboard reading \u2014 the eye is scanning for what is measured. `value` puts the figure first, for a marketing band where the number IS the argument; it also keeps a row of figures on one baseline, because the labels above them no longer have to be the same height. Visual order only: the DOM keeps label before value, so the announcement stays "Requests served, 4.2M".\n'
10885
11157
  }
10886
11158
  ],
10887
11159
  events: [],
@@ -10908,6 +11180,7 @@ var treeui_catalog_default = {
10908
11180
  ],
10909
11181
  behavior: [
10910
11182
  "value_and_trend_are_optional: true",
11183
+ "emphasis_reorders_visually_not_in_the_dom: true",
10911
11184
  "icon_slot_adds_visual_emphasis: true",
10912
11185
  "trend_indicator_changes_with_direction: true",
10913
11186
  "loading_renders_internal_skeleton_placeholders: true"
@@ -10945,6 +11218,7 @@ var treeui_catalog_default = {
10945
11218
  "metric-dashboard"
10946
11219
  ],
10947
11220
  practices: [
11221
+ "content-alignment",
10948
11222
  "token-driven"
10949
11223
  ]
10950
11224
  },
@@ -10957,7 +11231,7 @@ var treeui_catalog_default = {
10957
11231
  kind: "navigation",
10958
11232
  category: "Navigation",
10959
11233
  status: "available",
10960
- purpose: "Stepper component for visualizing workflow progress, with optional interactive selection.",
11234
+ purpose: "Ordered sequence \u2014 a wizard to operate, or a described flow to read.",
10961
11235
  sourceFile: "packages/vue/src/components/TSteps.vue",
10962
11236
  storyFile: "apps/docs/src/stories/Steps.stories.ts",
10963
11237
  storyTitle: "Components/Navigation/Steps",
@@ -11001,7 +11275,20 @@ var treeui_catalog_default = {
11001
11275
  {
11002
11276
  name: "interactive",
11003
11277
  type: "boolean",
11004
- default: "false"
11278
+ default: "false",
11279
+ note: "Whether a step can be picked. False \u2014 the default \u2014 renders inert boxes: no button in the accessibility tree, no disabled wash, and no step elected current unless `modelValue`/`defaultValue` or an item `status` says so. A described sequence used to render one dead control per step, at 60% opacity, with the first step ringed as if the reader were standing on it.\n"
11280
+ },
11281
+ {
11282
+ name: "columns",
11283
+ type: "number",
11284
+ default: "undefined",
11285
+ note: "Fixed steps per row, horizontal only. Use for a sequence with a shape (3 + 3)."
11286
+ },
11287
+ {
11288
+ name: "minItemWidth",
11289
+ type: "string",
11290
+ default: "14rem",
11291
+ note: "Width at which a step stops shrinking and the strip wraps. Same axis as TGrid."
11005
11292
  }
11006
11293
  ],
11007
11294
  events: [
@@ -11017,10 +11304,13 @@ var treeui_catalog_default = {
11017
11304
  a11y: [
11018
11305
  "semantic_root: ol",
11019
11306
  "current_step_uses_aria_current_step: true",
11020
- "interactive_variant_uses_buttons: true"
11307
+ "interactive_variant_uses_buttons: true",
11308
+ "static_variant_emits_no_control: true"
11021
11309
  ],
11022
11310
  behavior: [
11023
11311
  "can_be_controlled_or_uncontrolled: true",
11312
+ "static_variant_elects_no_current_step: true",
11313
+ "shared_box_class_is_t_steps_box: true",
11024
11314
  "status_can_be_explicit_or_computed: true",
11025
11315
  "alias_export_available: true"
11026
11316
  ],
@@ -11051,7 +11341,10 @@ var treeui_catalog_default = {
11051
11341
  ]
11052
11342
  },
11053
11343
  recipes: [],
11054
- practices: []
11344
+ practices: [
11345
+ "accessible-by-default",
11346
+ "content-alignment"
11347
+ ]
11055
11348
  },
11056
11349
  {
11057
11350
  name: "TSwitch",
@@ -11162,7 +11455,7 @@ var treeui_catalog_default = {
11162
11455
  name: "columns",
11163
11456
  type: "TTableColumn[]",
11164
11457
  required: true,
11165
- description: "Array of column definitions with key, label, sortable, align, and width."
11458
+ description: "Array of column definitions with key, label, sortable, align, width, and minWidth."
11166
11459
  },
11167
11460
  {
11168
11461
  name: "rows",
@@ -11290,7 +11583,7 @@ var treeui_catalog_default = {
11290
11583
  name: "modelValue",
11291
11584
  type: "T",
11292
11585
  default: "undefined",
11293
- note: "The value of the currently active tab; use with v-model. Generic over `T extends string`, so a `ref<'overview' | 'logs'>` keeps its literal union instead of being widened to `string` \u2014 under a consumer's `strictTemplates` that widening made the binding an error with no correct way to write it (TREEUX-011, group 3).\n"
11586
+ note: "The value of the currently active tab; use with v-model. Generic over `T extends string`, so a `ref<'overview' | 'logs'>` keeps its literal union instead of being widened to `string` \u2014 widening makes the binding an error under `strictTemplates`, with no correct way to write it.\n"
11294
11587
  },
11295
11588
  {
11296
11589
  name: "defaultValue",
@@ -11340,6 +11633,7 @@ var treeui_catalog_default = {
11340
11633
  "aria_controls_aria_labelledby_pairing: true"
11341
11634
  ],
11342
11635
  behavior: [
11636
+ "overflowing_tabs_scroll_within_their_own_strip: `.t-tabs__list` is `overflow-x: auto` with `overscroll-behavior-x: contain`. Tabs that did not fit pushed the PAGE sideways, which moves every other element on screen to solve a problem belonging to one component. TTabList scrolls the active tab into view whenever the active value changes, so a tab reached by keyboard or restored from a model value is never left off-strip.",
11343
11637
  "arrow_left_right_moves_focus: true",
11344
11638
  "home_focuses_first_tab: true",
11345
11639
  "end_focuses_last_tab: true",
@@ -11379,7 +11673,9 @@ var treeui_catalog_default = {
11379
11673
  "router-backed-tabs"
11380
11674
  ],
11381
11675
  practices: [
11382
- "interaction-feedback"
11676
+ "interaction-feedback",
11677
+ "accessible-by-default",
11678
+ "content-alignment"
11383
11679
  ]
11384
11680
  },
11385
11681
  {
@@ -11717,6 +12013,17 @@ var treeui_catalog_default = {
11717
12013
  ],
11718
12014
  note: "Break axis for a string with no break opportunity \u2014 an id, ARN, API key or hash is one long word, so it overflows its box. `truncate` is the wrong answer when the string IS what the reader came to copy: an ellipsis makes an id useless. `anywhere` breaks at any character (and sets `min-inline-size: 0`, without which a flex or grid child still refuses to shrink below its longest word and never breaks); `break-word` only breaks a word that would otherwise overflow. Ignored when `truncate` is set.\n"
11719
12015
  },
12016
+ {
12017
+ name: "align",
12018
+ type: "TTextAlign",
12019
+ default: "undefined",
12020
+ values: [
12021
+ "start",
12022
+ "center",
12023
+ "end"
12024
+ ],
12025
+ note: "How the LINES sit inside the box, which is the other half of `TStack align` \u2014 that one centres the box, and a centred box only looks centred while it is narrow: at full width the paragraph inside reads left-aligned. Renders block, because `text-align` does nothing on an inline box that shrink-wraps its content. Logical values, so `start`/`end` follow the writing direction. Combined with `measure`, `center` also centres the capped block itself.\n"
12026
+ },
11720
12027
  {
11721
12028
  name: "balance",
11722
12029
  type: "boolean",
@@ -11757,6 +12064,7 @@ var treeui_catalog_default = {
11757
12064
  "Choose `as` to convey the correct semantics (e.g. headings via h1\u2013h6); TText adds only visual styling."
11758
12065
  ],
11759
12066
  behavior: [
12067
+ 'the_wrap_axis_outranks_preserve_whitespace: `.t-text.t-text--wrap-anywhere` is qualified with `.t-text` so it matches the (0,2,0) specificity of `.t-text.is-pre-wrap`, and wins by order. Without it `preserveWhitespace` silently downgraded `wrap="anywhere"` to `break-word`, which is the one thing `anywhere` exists to do differently: only `anywhere` reduces the min-content.',
11760
12068
  "semantic_element_controlled_by_as: true",
11761
12069
  "token_driven_size_tone_weight: true",
11762
12070
  "truncate_takes_precedence_over_preserve_whitespace: true"
@@ -11778,6 +12086,7 @@ var treeui_catalog_default = {
11778
12086
  practices: [
11779
12087
  "accessible-by-default",
11780
12088
  "predictable-api",
12089
+ "content-alignment",
11781
12090
  "token-driven"
11782
12091
  ]
11783
12092
  },
@@ -11794,6 +12103,12 @@ var treeui_catalog_default = {
11794
12103
  storyTitle: "Components/Data Entry/Textarea",
11795
12104
  manifestFile: "docs/ai/COMPONENTS/textarea.yaml",
11796
12105
  props: [
12106
+ {
12107
+ name: "spellcheck",
12108
+ type: "boolean",
12109
+ default: "undefined",
12110
+ description: 'A real `<textarea>` attribute that the declared surface was missing. It matters most with `family="mono"`: a JSON or config editor wants the spell-checker to stop underlining keys, ARNs and identifiers.'
12111
+ },
11797
12112
  {
11798
12113
  name: "modelValue",
11799
12114
  type: "string",
@@ -11867,7 +12182,7 @@ var treeui_catalog_default = {
11867
12182
  "sans",
11868
12183
  "mono"
11869
12184
  ],
11870
- note: "Font family of the editable content, same vocabulary as TText. `mono` is for machine text \u2014 JSON, a policy document, a payload \u2014 which otherwise leaves a `.mono` class behind in the consumer's stylesheet. Applied to the `<textarea>`, not the label wrapper, which also holds the loading spinner.\n"
12185
+ note: "Font family of the editable content, same vocabulary as TText. `mono` is for machine text \u2014 JSON, a policy document, a payload \u2014 which otherwise needs a one-off `.mono` font-family rule in product CSS. Applied to the `<textarea>`, not the label wrapper, which also holds the loading spinner.\n"
11871
12186
  }
11872
12187
  ],
11873
12188
  events: [
@@ -11967,6 +12282,7 @@ var treeui_catalog_default = {
11967
12282
  "timestamp_uses_time_element_when_provided: true"
11968
12283
  ],
11969
12284
  behavior: [
12285
+ "content_stays_inside_the_container: `.t-timeline` and `.t-timeline__content` declare `grid-template-columns: minmax(0, 1fr)`, and the title and description carry `overflow-wrap: anywhere`. Together they stop an unbreakable string from setting the column's min-content and carrying the whole entry across the container.",
11970
12286
  "items_render_in_order_given: true",
11971
12287
  "line_hidden_on_last_item: true",
11972
12288
  "marker_tone_defaults_to_neutral: true"
@@ -11982,7 +12298,9 @@ var treeui_catalog_default = {
11982
12298
  notes: []
11983
12299
  },
11984
12300
  recipes: [],
11985
- practices: []
12301
+ practices: [
12302
+ "content-alignment"
12303
+ ]
11986
12304
  },
11987
12305
  {
11988
12306
  name: "TToast",
@@ -11997,6 +12315,12 @@ var treeui_catalog_default = {
11997
12315
  storyTitle: "Components/Feedback/Toast",
11998
12316
  manifestFile: "docs/ai/COMPONENTS/toast.yaml",
11999
12317
  props: [
12318
+ {
12319
+ name: "closeLabel",
12320
+ type: "string",
12321
+ default: "Dismiss notification",
12322
+ description: "Accessible name for the dismiss button, on `TToastProvider` as the instance default and on a single toast's options to override it. It was hard-coded English, which left the toast's only control unreadable to a screen reader in any other language."
12323
+ },
12000
12324
  {
12001
12325
  name: "toast",
12002
12326
  type: "ToastItem",
@@ -12056,6 +12380,7 @@ var treeui_catalog_default = {
12056
12380
  "confirm-destructive-action"
12057
12381
  ],
12058
12382
  practices: [
12383
+ "accessible-by-default",
12059
12384
  "token-driven"
12060
12385
  ]
12061
12386
  },
@@ -12076,7 +12401,7 @@ var treeui_catalog_default = {
12076
12401
  name: "modelValue",
12077
12402
  type: "TToggleGroupModel<T, M> \u2014 `T` in single mode, `T[]` in multiple",
12078
12403
  default: "undefined",
12079
- note: "Generic over the option type AND the selection mode, so the model is the type the call site actually has: `<TToggleGroup v-model=\"view\">` with a `ref<'grid' | 'list'>` binds, and `selectionMode=\"multiple\"` binds a `('grid' | 'list')[]`. It was `string | string[]` in and `string | string[] | undefined` out, which no literal-union ref could bind under a consumer's `strictTemplates` \u2014 the same defect as TTabs/TInput (TREEUX-011, group 3), found by the gate once it ran on the same `vue-tsc` major consumers use. `undefined` was never actually emitted.\n"
12404
+ note: "Generic over the option type AND the selection mode, so the model is the type the binding actually has: `<TToggleGroup v-model=\"view\">` with a `ref<'grid' | 'list'>` binds, and `selectionMode=\"multiple\"` binds a `('grid' | 'list')[]`. It was `string | string[]` in and `string | string[] | undefined` out, which no literal-union ref could bind under `strictTemplates` \u2014 the same defect as TTabs/TInput, and invisible to any build that does not typecheck templates against the published types. `undefined` was never actually emitted.\n"
12080
12405
  },
12081
12406
  {
12082
12407
  name: "options",
@@ -12137,6 +12462,7 @@ var treeui_catalog_default = {
12137
12462
  "activation_keys_select_option: true"
12138
12463
  ],
12139
12464
  behavior: [
12465
+ 'selected_item_repaints_its_descendants_secondary_text: `.t-toggle-group__item.is-selected` rebinds `--tree-color-text-muted` to `--tree-color-brand-contrast`. Only the inherited colour used to change, so a `TText tone="muted"` in the `#option` slot kept reading the muted token and measured 1.18:1 (light) and 1.09:1 (dark) over the brand fill, where `xs` text needs 4.5:1. Rebinding the token is what keeps a slot the library does not control legible; `brand-contrast` is the only value that clears AA in both themes (5.19:1 / 6.21:1) \u2014 a `color-mix` at 85% still measured 4.18:1.',
12140
12466
  "single_and_multiple_modes: true",
12141
12467
  "variant_changes_visual_style_only: true",
12142
12468
  "visible_option_set_expected: true"
@@ -12177,7 +12503,9 @@ var treeui_catalog_default = {
12177
12503
  ]
12178
12504
  },
12179
12505
  recipes: [],
12180
- practices: []
12506
+ practices: [
12507
+ "accessible-by-default"
12508
+ ]
12181
12509
  },
12182
12510
  {
12183
12511
  name: "TTooltip",
@@ -13326,25 +13654,25 @@ var treeui_catalog_default = {
13326
13654
  {
13327
13655
  cssVar: "--tree-color-status-success",
13328
13656
  path: "color.status.success",
13329
- value: "#1a7f37",
13657
+ value: "#197d36",
13330
13658
  category: "color",
13331
13659
  derived: false,
13332
13660
  description: "Themed semantic color, resolved per [data-tree-theme].",
13333
13661
  themeValues: {
13334
- light: "#1a7f37",
13335
- dark: "#59ac5c"
13662
+ light: "#197d36",
13663
+ dark: "#5bae5e"
13336
13664
  }
13337
13665
  },
13338
13666
  {
13339
13667
  cssVar: "--tree-color-status-warning",
13340
13668
  path: "color.status.warning",
13341
- value: "#956400",
13669
+ value: "#946300",
13342
13670
  category: "color",
13343
13671
  derived: false,
13344
13672
  description: "Themed semantic color, resolved per [data-tree-theme].",
13345
13673
  themeValues: {
13346
- light: "#956400",
13347
- dark: "#c69026"
13674
+ light: "#946300",
13675
+ dark: "#c99227"
13348
13676
  }
13349
13677
  },
13350
13678
  {
@@ -13650,25 +13978,25 @@ var treeui_catalog_default = {
13650
13978
  {
13651
13979
  cssVar: "--tree-color-status-success-hover",
13652
13980
  path: "color.status.success-hover",
13653
- value: "#15682d",
13981
+ value: "#15672c",
13654
13982
  category: "color",
13655
13983
  derived: true,
13656
13984
  description: "Themed semantic color, resolved per [data-tree-theme]. Derived by the library from the semantic layer \u2014 read it, do not override it.",
13657
13985
  themeValues: {
13658
- light: "#15682d",
13659
- dark: "#77bb79"
13986
+ light: "#15672c",
13987
+ dark: "#79bd7b"
13660
13988
  }
13661
13989
  },
13662
13990
  {
13663
13991
  cssVar: "--tree-color-status-success-press",
13664
13992
  path: "color.status.success-press",
13665
- value: "#125625",
13993
+ value: "#115525",
13666
13994
  category: "color",
13667
13995
  derived: true,
13668
13996
  description: "Themed semantic color, resolved per [data-tree-theme]. Derived by the library from the semantic layer \u2014 read it, do not override it.",
13669
13997
  themeValues: {
13670
- light: "#125625",
13671
- dark: "#8ec790"
13998
+ light: "#115525",
13999
+ dark: "#8fc892"
13672
14000
  }
13673
14001
  },
13674
14002
  {
@@ -13680,31 +14008,31 @@ var treeui_catalog_default = {
13680
14008
  description: "Themed semantic color, resolved per [data-tree-theme]. Derived by the library from the semantic layer \u2014 read it, do not override it.",
13681
14009
  themeValues: {
13682
14010
  light: "#dfede3",
13683
- dark: "#2a3a34"
14011
+ dark: "#2a3a35"
13684
14012
  }
13685
14013
  },
13686
14014
  {
13687
14015
  cssVar: "--tree-color-status-success-soft-hover",
13688
14016
  path: "color.status.success-soft-hover",
13689
- value: "#c3decb",
14017
+ value: "#c3ddcb",
13690
14018
  category: "color",
13691
14019
  derived: true,
13692
14020
  description: "Themed semantic color, resolved per [data-tree-theme]. Derived by the library from the semantic layer \u2014 read it, do not override it.",
13693
14021
  themeValues: {
13694
- light: "#c3decb",
13695
- dark: "#314a3a"
14022
+ light: "#c3ddcb",
14023
+ dark: "#314a3b"
13696
14024
  }
13697
14025
  },
13698
14026
  {
13699
14027
  cssVar: "--tree-color-status-success-border",
13700
14028
  path: "color.status.success-border",
13701
- value: "#419559",
14029
+ value: "#419359",
13702
14030
  category: "color",
13703
14031
  derived: true,
13704
14032
  description: "Themed semantic color, resolved per [data-tree-theme]. Derived by the library from the semantic layer \u2014 read it, do not override it.",
13705
14033
  themeValues: {
13706
- light: "#419559",
13707
- dark: "#4d9052"
14034
+ light: "#419359",
14035
+ dark: "#4f9154"
13708
14036
  }
13709
14037
  },
13710
14038
  {
@@ -13722,49 +14050,49 @@ var treeui_catalog_default = {
13722
14050
  {
13723
14051
  cssVar: "--tree-color-status-success-on-soft",
13724
14052
  path: "color.status.success-on-soft",
13725
- value: "#197934",
14053
+ value: "#187733",
13726
14054
  category: "color",
13727
14055
  derived: true,
13728
14056
  description: "Themed semantic color, resolved per [data-tree-theme]. Derived by the library from the semantic layer \u2014 read it, do not override it.",
13729
14057
  themeValues: {
13730
- light: "#197934",
13731
- dark: "#61b064"
14058
+ light: "#187733",
14059
+ dark: "#63b266"
13732
14060
  }
13733
14061
  },
13734
14062
  {
13735
14063
  cssVar: "--tree-color-status-success-on-soft-hover",
13736
14064
  path: "color.status.success-on-soft-hover",
13737
- value: "#15672d",
14065
+ value: "#156b2e",
13738
14066
  category: "color",
13739
14067
  derived: true,
13740
14068
  description: "Themed semantic color, resolved per [data-tree-theme]. Derived by the library from the semantic layer \u2014 read it, do not override it.",
13741
14069
  themeValues: {
13742
- light: "#15672d",
13743
- dark: "#85c287"
14070
+ light: "#156b2e",
14071
+ dark: "#80c082"
13744
14072
  }
13745
14073
  },
13746
14074
  {
13747
14075
  cssVar: "--tree-color-status-warning-hover",
13748
14076
  path: "color.status.warning-hover",
13749
- value: "#7a5200",
14077
+ value: "#795100",
13750
14078
  category: "color",
13751
14079
  derived: true,
13752
14080
  description: "Themed semantic color, resolved per [data-tree-theme]. Derived by the library from the semantic layer \u2014 read it, do not override it.",
13753
14081
  themeValues: {
13754
- light: "#7a5200",
13755
- dark: "#d0a44d"
14082
+ light: "#795100",
14083
+ dark: "#d3a64e"
13756
14084
  }
13757
14085
  },
13758
14086
  {
13759
14087
  cssVar: "--tree-color-status-warning-press",
13760
14088
  path: "color.status.warning-press",
13761
- value: "#654400",
14089
+ value: "#654300",
13762
14090
  category: "color",
13763
14091
  derived: true,
13764
14092
  description: "Themed semantic color, resolved per [data-tree-theme]. Derived by the library from the semantic layer \u2014 read it, do not override it.",
13765
14093
  themeValues: {
13766
- light: "#654400",
13767
- dark: "#d8b46b"
14094
+ light: "#654300",
14095
+ dark: "#dab56c"
13768
14096
  }
13769
14097
  },
13770
14098
  {
@@ -13794,13 +14122,13 @@ var treeui_catalog_default = {
13794
14122
  {
13795
14123
  cssVar: "--tree-color-status-warning-border",
13796
14124
  path: "color.status.warning-border",
13797
- value: "#a77f2c",
14125
+ value: "#a67e2c",
13798
14126
  category: "color",
13799
14127
  derived: true,
13800
14128
  description: "Themed semantic color, resolved per [data-tree-theme]. Derived by the library from the semantic layer \u2014 read it, do not override it.",
13801
14129
  themeValues: {
13802
- light: "#a77f2c",
13803
- dark: "#a37a28"
14130
+ light: "#a67e2c",
14131
+ dark: "#a57b29"
13804
14132
  }
13805
14133
  },
13806
14134
  {
@@ -13818,25 +14146,25 @@ var treeui_catalog_default = {
13818
14146
  {
13819
14147
  cssVar: "--tree-color-status-warning-on-soft",
13820
14148
  path: "color.status.warning-on-soft",
13821
- value: "#8e5f00",
14149
+ value: "#8d5e00",
13822
14150
  category: "color",
13823
14151
  derived: true,
13824
14152
  description: "Themed semantic color, resolved per [data-tree-theme]. Derived by the library from the semantic layer \u2014 read it, do not override it.",
13825
14153
  themeValues: {
13826
- light: "#8e5f00",
13827
- dark: "#c99631"
14154
+ light: "#8d5e00",
14155
+ dark: "#cc9732"
13828
14156
  }
13829
14157
  },
13830
14158
  {
13831
14159
  cssVar: "--tree-color-status-warning-on-soft-hover",
13832
14160
  path: "color.status.warning-on-soft-hover",
13833
- value: "#805600",
14161
+ value: "#7f5500",
13834
14162
  category: "color",
13835
14163
  derived: true,
13836
14164
  description: "Themed semantic color, resolved per [data-tree-theme]. Derived by the library from the semantic layer \u2014 read it, do not override it.",
13837
14165
  themeValues: {
13838
- light: "#805600",
13839
- dark: "#d5ad5f"
14166
+ light: "#7f5500",
14167
+ dark: "#d5ab58"
13840
14168
  }
13841
14169
  },
13842
14170
  {
@@ -14547,16 +14875,23 @@ var treePrimitives = {
14547
14875
  600: "#633fa6",
14548
14876
  800: "#332e4a"
14549
14877
  },
14878
+ /**
14879
+ * The status hues carry the narrowest margin in the palette, because the band
14880
+ * they have to clear is `bg.subtle` — the secondary surface a status line
14881
+ * usually lands on (inside a card, under a field), not the primary one they
14882
+ * are easy to calibrate against. Each of these three was a step away from the
14883
+ * floor and is now a step above it; `status.test.ts` holds the headroom, and
14884
+ * the contract validator holds the floor.
14885
+ */
14550
14886
  green: {
14551
- 400: "#59ac5c",
14552
- 500: "#1a7f37"
14887
+ 400: "#5bae5e",
14888
+ 500: "#197d36"
14553
14889
  },
14554
14890
  amber: {
14555
- 400: "#c69026",
14556
- 500: "#956400"
14891
+ 400: "#c99227",
14892
+ 500: "#946300"
14557
14893
  },
14558
14894
  red: {
14559
- /** Landed on 4.50:1 against the dark subtle band; nudged for headroom. */
14560
14895
  400: "#f5766e",
14561
14896
  500: "#d1242f"
14562
14897
  },