@treeui/mcp 0.8.1 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/{chunk-DGIMKZPZ.js → chunk-VPOHUNDH.js} +280 -6
- package/dist/cli.cjs +280 -6
- package/dist/cli.js +1 -1
- package/dist/index.cjs +280 -6
- package/dist/index.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -11,8 +11,8 @@ TreeUI ships a local Model Context Protocol server so coding agents can:
|
|
|
11
11
|
## What it serves
|
|
12
12
|
|
|
13
13
|
- a generated catalog built from `docs/ai/*.yaml` and `@treeui/tokens`
|
|
14
|
-
- MCP resources
|
|
15
|
-
- MCP tools
|
|
14
|
+
- 7 MCP resources: `treeui://catalog`, `treeui://selection`, `treeui://setup`, `treeui://recipes`, `treeui://practices`, `treeui://tokens`, and `treeui://components/<name>` (one per component)
|
|
15
|
+
- 6 MCP tools: `search_components`, `recommend_components`, `get_component`, `get_setup_guide`, `search_recipes`, `search_tokens`
|
|
16
16
|
|
|
17
17
|
## Token search
|
|
18
18
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// src/generated/treeui.catalog.json
|
|
2
2
|
var treeui_catalog_default = {
|
|
3
|
-
generatedAt: "0.
|
|
3
|
+
generatedAt: "0.34.1",
|
|
4
4
|
packageName: "@treeui/vue",
|
|
5
|
-
packageVersion: "0.
|
|
5
|
+
packageVersion: "0.34.1",
|
|
6
6
|
decisionGuides: [
|
|
7
7
|
{
|
|
8
8
|
id: "single-choice",
|
|
@@ -462,7 +462,7 @@ var treeui_catalog_default = {
|
|
|
462
462
|
"`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.",
|
|
463
463
|
"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.",
|
|
464
464
|
"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.",
|
|
465
|
-
"Check the name is not already taken before registering it \u2014 `hasTreeIcon(name)` answers that. Registering one of the
|
|
465
|
+
"Check the name is not already taken before registering it \u2014 `hasTreeIcon(name)` answers that. Registering one of the 370 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.",
|
|
466
466
|
"Keep the icon vocabulary consistent: built-ins use TreeUI's descriptive kebab-case names, so register custom ones with the same convention.",
|
|
467
467
|
"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.",
|
|
468
468
|
"Set `to` for the route target on each item \u2014 `TNavMenuItem` has no `href` and no `id`; identity is `value`.",
|
|
@@ -787,6 +787,7 @@ var treeui_catalog_default = {
|
|
|
787
787
|
"TDropdown",
|
|
788
788
|
"TFileUpload",
|
|
789
789
|
"TFormField",
|
|
790
|
+
"TIconTile",
|
|
790
791
|
"TImage",
|
|
791
792
|
"TLinkTile",
|
|
792
793
|
"TMenu",
|
|
@@ -794,7 +795,9 @@ var treeui_catalog_default = {
|
|
|
794
795
|
"TPopover",
|
|
795
796
|
"TSelect",
|
|
796
797
|
"TSkipLink",
|
|
798
|
+
"TStatGroup",
|
|
797
799
|
"TSteps",
|
|
800
|
+
"TTable",
|
|
798
801
|
"TTabs",
|
|
799
802
|
"TText",
|
|
800
803
|
"TToast",
|
|
@@ -879,6 +882,7 @@ var treeui_catalog_default = {
|
|
|
879
882
|
"TGrid",
|
|
880
883
|
"THero",
|
|
881
884
|
"THide",
|
|
885
|
+
"TIconTile",
|
|
882
886
|
"TLinkTile",
|
|
883
887
|
"TList",
|
|
884
888
|
"TModal",
|
|
@@ -893,7 +897,9 @@ var treeui_catalog_default = {
|
|
|
893
897
|
"TSplit",
|
|
894
898
|
"TStack",
|
|
895
899
|
"TStat",
|
|
900
|
+
"TStatGroup",
|
|
896
901
|
"TSteps",
|
|
902
|
+
"TTable",
|
|
897
903
|
"TTabs",
|
|
898
904
|
"TText",
|
|
899
905
|
"TTimeline"
|
|
@@ -923,6 +929,7 @@ var treeui_catalog_default = {
|
|
|
923
929
|
"TColorSwatch",
|
|
924
930
|
"TDescriptionList",
|
|
925
931
|
"THero",
|
|
932
|
+
"TIconTile",
|
|
926
933
|
"TImage",
|
|
927
934
|
"TInput",
|
|
928
935
|
"TKeyValueEditor",
|
|
@@ -936,6 +943,7 @@ var treeui_catalog_default = {
|
|
|
936
943
|
"TSection",
|
|
937
944
|
"TSelect",
|
|
938
945
|
"TStat",
|
|
946
|
+
"TStatGroup",
|
|
939
947
|
"TSwitch",
|
|
940
948
|
"TTag",
|
|
941
949
|
"TTagInput",
|
|
@@ -975,7 +983,7 @@ var treeui_catalog_default = {
|
|
|
975
983
|
},
|
|
976
984
|
vueSetup: {
|
|
977
985
|
pluginInstall: {
|
|
978
|
-
import: "import TreeUIPlugin from '@treeui/vue'",
|
|
986
|
+
import: "import { TreeUIPlugin } from '@treeui/vue'",
|
|
979
987
|
usage: "app.use(TreeUIPlugin)"
|
|
980
988
|
},
|
|
981
989
|
individualImports: {
|
|
@@ -2942,6 +2950,12 @@ var treeui_catalog_default = {
|
|
|
2942
2950
|
storyTitle: "Components/Data Display/Chart",
|
|
2943
2951
|
manifestFile: "docs/ai/COMPONENTS/chart.yaml",
|
|
2944
2952
|
props: [
|
|
2953
|
+
{
|
|
2954
|
+
name: "axisValueFormat",
|
|
2955
|
+
type: "(value: number) => string",
|
|
2956
|
+
default: "undefined",
|
|
2957
|
+
description: "Formatter for the AXIS ticks only, falling back to `valueFormat`. The two have different jobs and the axis is the one with no room: a tooltip can spell `R$ 1.500.000.000,00` in full, while the same string on a y-axis at 320px eats the plot \u2014 and the space reserved for it is capped at 40% of the chart, so past that it clips. One formatter could not serve both."
|
|
2958
|
+
},
|
|
2945
2959
|
{
|
|
2946
2960
|
name: "yAxisWidth",
|
|
2947
2961
|
type: "number",
|
|
@@ -3092,6 +3106,7 @@ var treeui_catalog_default = {
|
|
|
3092
3106
|
"point-click has no keyboard equivalent \u2014 do not make it the only way to reach a behavior."
|
|
3093
3107
|
],
|
|
3094
3108
|
behavior: [
|
|
3109
|
+
"edge_x_labels_anchor_with_a_class_not_an_attribute: The first and last x labels carry `is-anchor-start` / `is-anchor-end`, not a `text-anchor` ATTRIBUTE. CSS always beats a presentation attribute, so `.t-chart__axis-label--x { text-anchor: middle }` silently won and the anchoring never applied \u2014 the last label kept rendering centred and hanging off the SVG.",
|
|
3095
3110
|
"colors_auto_assign_from_chart_palette: --tree-color-chart-1..8, cycling by series index; per-series color overrides",
|
|
3096
3111
|
"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.",
|
|
3097
3112
|
"y_domain_uses_nice_ticks: every type runs through niceScale, which rounds the min down and the max up to round numbers",
|
|
@@ -3350,6 +3365,7 @@ var treeui_catalog_default = {
|
|
|
3350
3365
|
"copy_button_state: The copy button's aria-label reflects the copied state briefly."
|
|
3351
3366
|
],
|
|
3352
3367
|
behavior: [
|
|
3368
|
+
"copyable_reserves_the_toolbar_width: With the copy button rendered, `.t-code-block.is-copyable .t-code-block__pre` reserves its width as `padding-inline-end`. The toolbar floats over the code, so a wrapped line used to run underneath it and the characters behind the button were unreadable. This only became visible once `wrap` started breaking for real: before, the long token overflowed sideways and never reached the button.",
|
|
3353
3369
|
'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"`.'
|
|
3354
3370
|
],
|
|
3355
3371
|
selection: {
|
|
@@ -4831,6 +4847,7 @@ var treeui_catalog_default = {
|
|
|
4831
4847
|
"Provide a meaningful ariaLabel describing what the chart shows."
|
|
4832
4848
|
],
|
|
4833
4849
|
behavior: [
|
|
4850
|
+
"legend_label_is_the_flexible_column: `.t-donut-chart__legend-label` is `flex: 1 1 0` with `min-width: 0` and an ellipsis, and `.t-donut-chart__legend-value` is `flex: 0 0 auto`. A 60-character label used to push the value out of the card. The full text is carried in `title`, since truncation hides data the chart is meant to show.",
|
|
4834
4851
|
"colors_auto_assign_from_chart_palette: --tree-color-chart-1..8, cycling by visible-segment index; per-segment color overrides",
|
|
4835
4852
|
"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",
|
|
4836
4853
|
"hovering_a_legend_row_drives_the_same_highlight: legend items carry the same pointerenter/pointerleave handlers as the segments",
|
|
@@ -5404,6 +5421,30 @@ var treeui_catalog_default = {
|
|
|
5404
5421
|
storyTitle: "Components/Data Entry/FileUpload",
|
|
5405
5422
|
manifestFile: "docs/ai/COMPONENTS/file-upload.yaml",
|
|
5406
5423
|
props: [
|
|
5424
|
+
{
|
|
5425
|
+
name: "uploadingLabel",
|
|
5426
|
+
type: "string",
|
|
5427
|
+
default: "Uploading files",
|
|
5428
|
+
description: "Accessible name for the spinner shown while `loading`."
|
|
5429
|
+
},
|
|
5430
|
+
{
|
|
5431
|
+
name: "uploadedAnnouncement",
|
|
5432
|
+
type: "(name: string) => string",
|
|
5433
|
+
default: "(n) => `${n} uploaded.`",
|
|
5434
|
+
description: "What the live region announces when a file succeeds. A function, because the file name sits inside the sentence and its position differs by language."
|
|
5435
|
+
},
|
|
5436
|
+
{
|
|
5437
|
+
name: "failedAnnouncement",
|
|
5438
|
+
type: "(name: string) => string",
|
|
5439
|
+
default: "(n) => `${n} failed.`",
|
|
5440
|
+
description: "The same, for a failure. The error text is appended after it."
|
|
5441
|
+
},
|
|
5442
|
+
{
|
|
5443
|
+
name: "showRejections",
|
|
5444
|
+
type: "boolean",
|
|
5445
|
+
default: "true",
|
|
5446
|
+
description: "Render the built-in rejection messages. Turn it off when the product already surfaces `files-rejected` in its own alert \u2014 otherwise the user reads the same refusal twice, and the embedded copy is the one that cannot be placed where the product wants it. The event fires either way."
|
|
5447
|
+
},
|
|
5407
5448
|
{
|
|
5408
5449
|
name: "clearLabel",
|
|
5409
5450
|
type: "string",
|
|
@@ -5630,6 +5671,7 @@ var treeui_catalog_default = {
|
|
|
5630
5671
|
"remove_and_retry_meet_the_44px_target: true"
|
|
5631
5672
|
],
|
|
5632
5673
|
behavior: [
|
|
5674
|
+
"a_rejection_follows_the_active_language: A rejection is held as DATA (the file and the reason) and formatted during render. It used to be stored as its rendered string, frozen at refusal time, so switching language afterwards left the old sentence on screen \u2014 the one piece of copy in this component that could not be retranslated.",
|
|
5633
5675
|
"accepts_files_from_input_drop_and_paste: true",
|
|
5634
5676
|
"multiple_false_replaces_existing_selection: true",
|
|
5635
5677
|
"accept_maxFiles_and_maxFileSize_apply_to_all_entry_points: true",
|
|
@@ -6722,6 +6764,86 @@ var treeui_catalog_default = {
|
|
|
6722
6764
|
"branchline-icons"
|
|
6723
6765
|
]
|
|
6724
6766
|
},
|
|
6767
|
+
{
|
|
6768
|
+
name: "TIconTile",
|
|
6769
|
+
aliases: [],
|
|
6770
|
+
package: "@treeui/vue",
|
|
6771
|
+
kind: "display",
|
|
6772
|
+
category: "Data Display",
|
|
6773
|
+
status: "available",
|
|
6774
|
+
purpose: "A registered icon on a toned ground, sized and coloured so the glyph reads at phone size.",
|
|
6775
|
+
sourceFile: "packages/vue/src/components/TIconTile.vue",
|
|
6776
|
+
storyFile: "apps/docs/src/stories/IconTile.stories.ts",
|
|
6777
|
+
storyTitle: "Components/Data Display/IconTile",
|
|
6778
|
+
manifestFile: "docs/ai/COMPONENTS/icon-tile.yaml",
|
|
6779
|
+
props: [
|
|
6780
|
+
{
|
|
6781
|
+
name: "name",
|
|
6782
|
+
type: "TIconName",
|
|
6783
|
+
default: "undefined",
|
|
6784
|
+
description: "Registry name. Use the default slot for a glyph that is not registered."
|
|
6785
|
+
},
|
|
6786
|
+
{
|
|
6787
|
+
name: "tone",
|
|
6788
|
+
type: "TIconTileTone",
|
|
6789
|
+
default: "brand",
|
|
6790
|
+
values: [
|
|
6791
|
+
"brand",
|
|
6792
|
+
"neutral",
|
|
6793
|
+
"success",
|
|
6794
|
+
"warning",
|
|
6795
|
+
"danger",
|
|
6796
|
+
"info"
|
|
6797
|
+
],
|
|
6798
|
+
description: "Selects the `--tree-icon-tile-accent` / `--tree-icon-tile-soft` pair. The ink is the tone's full-strength colour on its own `*-soft` tint, which is the pairing that tint is derived for."
|
|
6799
|
+
},
|
|
6800
|
+
{
|
|
6801
|
+
name: "size",
|
|
6802
|
+
type: "TSize",
|
|
6803
|
+
default: "md",
|
|
6804
|
+
values: [
|
|
6805
|
+
"sm",
|
|
6806
|
+
"md",
|
|
6807
|
+
"lg"
|
|
6808
|
+
],
|
|
6809
|
+
description: "2rem / 2.75rem / 3.5rem. The glyph steps with the tile (16 / 20 / 24px) so the ink keeps its proportion of the pill."
|
|
6810
|
+
},
|
|
6811
|
+
{
|
|
6812
|
+
name: "label",
|
|
6813
|
+
type: "string",
|
|
6814
|
+
default: "undefined",
|
|
6815
|
+
description: "Accessible name. Omit it when the tile sits beside a heading that already says the same thing \u2014 the glyph is then decoration, and a screen reader reading it twice is noise."
|
|
6816
|
+
}
|
|
6817
|
+
],
|
|
6818
|
+
events: [],
|
|
6819
|
+
slots: [
|
|
6820
|
+
{
|
|
6821
|
+
name: "default"
|
|
6822
|
+
}
|
|
6823
|
+
],
|
|
6824
|
+
a11y: [
|
|
6825
|
+
"semantic_element: span",
|
|
6826
|
+
'role_img_only_when_named: With `label` the tile is `role="img"` with that name; without it, `aria-hidden`. There is no third state where a glyph is announced as nothing.',
|
|
6827
|
+
"contrast_floor: 3:1, measured. An icon is a non-text UI component under WCAG 1.4.11, so the floor is 3:1 and not the 4.5:1 a badge has to clear \u2014 a badge carries a word. `packages/tokens/src/icon-tile-contrast.test.ts` measures every tone in both themes and fails the build below the floor, the same way the badge's own floor is held."
|
|
6828
|
+
],
|
|
6829
|
+
behavior: [],
|
|
6830
|
+
selection: {
|
|
6831
|
+
keywords: [],
|
|
6832
|
+
useWhen: [],
|
|
6833
|
+
avoidWhen: [],
|
|
6834
|
+
alternatives: []
|
|
6835
|
+
},
|
|
6836
|
+
setup: {
|
|
6837
|
+
required: [],
|
|
6838
|
+
notes: []
|
|
6839
|
+
},
|
|
6840
|
+
recipes: [],
|
|
6841
|
+
practices: [
|
|
6842
|
+
"accessible-by-default",
|
|
6843
|
+
"content-alignment",
|
|
6844
|
+
"token-driven"
|
|
6845
|
+
]
|
|
6846
|
+
},
|
|
6725
6847
|
{
|
|
6726
6848
|
name: "TImage",
|
|
6727
6849
|
aliases: [],
|
|
@@ -11048,6 +11170,33 @@ var treeui_catalog_default = {
|
|
|
11048
11170
|
storyTitle: "Components/Data Display/Stat",
|
|
11049
11171
|
manifestFile: "docs/ai/COMPONENTS/stat.yaml",
|
|
11050
11172
|
props: [
|
|
11173
|
+
{
|
|
11174
|
+
name: "variant",
|
|
11175
|
+
type: "TStatVariant",
|
|
11176
|
+
default: "card (plain inside a TStatGroup)",
|
|
11177
|
+
values: [
|
|
11178
|
+
"card",
|
|
11179
|
+
"plain"
|
|
11180
|
+
],
|
|
11181
|
+
description: "Whether the tile draws its own card. `plain` keeps the padding, the type and the tones and drops the border, radius, shadow and background. Inside a `TStatGroup` the default flips to `plain`, because the group owns the surface; an explicit value always wins. A stat drawing its own card inside a TCard is a card within a card \u2014 doubled frame, summed padding, and eight of them read as eight objects rather than one row of figures."
|
|
11182
|
+
},
|
|
11183
|
+
{
|
|
11184
|
+
name: "metaPlacement",
|
|
11185
|
+
type: "'top' | 'bottom'",
|
|
11186
|
+
default: "top",
|
|
11187
|
+
description: 'Where the `meta` note sits. `top` shares the label\'s line; `bottom` puts it under the value, for the reading order of an indicator with a footnote. It is also a height fix: on the shared line a long label and a long note do not fit, the note wraps onto a line of its own ABOVE the value, and that one tile grows \u2014 the grid then stretches the whole row and every sibling shows an empty band. With `bottom` the DOM follows the visual order, so the announced order is label, value, note. Different from `emphasis="value"`, which promotes the FIGURE and takes the label down with it.'
|
|
11188
|
+
},
|
|
11189
|
+
{
|
|
11190
|
+
name: "size",
|
|
11191
|
+
type: "TSize",
|
|
11192
|
+
default: "md",
|
|
11193
|
+
values: [
|
|
11194
|
+
"sm",
|
|
11195
|
+
"md",
|
|
11196
|
+
"lg"
|
|
11197
|
+
],
|
|
11198
|
+
description: "Density. `sm` lowers the value's floor from 1.5rem to 1.125rem and tightens the padding, which is what lets two stats share a row on a phone \u2014 at the default floor a formatted negative currency does not fit, so a grid of six indicators collapsed into one tall column. The value still scales to its card through the container query, not to the viewport."
|
|
11199
|
+
},
|
|
11051
11200
|
{
|
|
11052
11201
|
name: "label",
|
|
11053
11202
|
type: "string",
|
|
@@ -11172,6 +11321,75 @@ var treeui_catalog_default = {
|
|
|
11172
11321
|
"token-driven"
|
|
11173
11322
|
]
|
|
11174
11323
|
},
|
|
11324
|
+
{
|
|
11325
|
+
name: "TStatGroup",
|
|
11326
|
+
aliases: [],
|
|
11327
|
+
package: "@treeui/vue",
|
|
11328
|
+
kind: "layout",
|
|
11329
|
+
status: "available",
|
|
11330
|
+
purpose: "A row of indicators sharing one surface, with a hairline between cells.",
|
|
11331
|
+
sourceFile: "packages/vue/src/components/TStatGroup.vue",
|
|
11332
|
+
manifestFile: "docs/ai/COMPONENTS/stat-group.yaml",
|
|
11333
|
+
props: [
|
|
11334
|
+
{
|
|
11335
|
+
name: "label",
|
|
11336
|
+
type: "string",
|
|
11337
|
+
default: "undefined",
|
|
11338
|
+
description: 'Accessible name for the band. Sets `aria-label` on a `role="group"`, so the row is announced as one unit rather than as a run of unrelated figures.'
|
|
11339
|
+
},
|
|
11340
|
+
{
|
|
11341
|
+
name: "columns",
|
|
11342
|
+
type: "number",
|
|
11343
|
+
default: "undefined",
|
|
11344
|
+
description: "Fixed track count. Leave unset to let `minItemWidth` decide."
|
|
11345
|
+
},
|
|
11346
|
+
{
|
|
11347
|
+
name: "minItemWidth",
|
|
11348
|
+
type: "string",
|
|
11349
|
+
default: "12rem",
|
|
11350
|
+
description: "Smallest a cell may get before a track is dropped. Same meaning as on TGrid."
|
|
11351
|
+
},
|
|
11352
|
+
{
|
|
11353
|
+
name: "balance",
|
|
11354
|
+
type: "boolean",
|
|
11355
|
+
default: "false",
|
|
11356
|
+
description: "Let the last row share itself out. Off by default here, unlike TGrid, and deliberately: a stat's value scales to its own cell (`container-type: inline-size`), so a lone cell stretched across the last row prints a number visibly larger than its siblings', and size on a dashboard reads as importance. An orphan beside empty space is the lesser mistake. The real fix for a band is a track count that divides the figures \u2014 set `columns`, or a `minItemWidth` that lands on one."
|
|
11357
|
+
}
|
|
11358
|
+
],
|
|
11359
|
+
events: [],
|
|
11360
|
+
slots: [
|
|
11361
|
+
{
|
|
11362
|
+
name: "default"
|
|
11363
|
+
}
|
|
11364
|
+
],
|
|
11365
|
+
a11y: [
|
|
11366
|
+
"semantic_element: div",
|
|
11367
|
+
"role: group",
|
|
11368
|
+
"naming: `label` is what makes the band a named unit. Without it the group has no accessible name and is announced as an unlabelled grouping."
|
|
11369
|
+
],
|
|
11370
|
+
behavior: [
|
|
11371
|
+
'children_render_plain_without_being_told: The group provides a context that TStat reads, so every child defaults to `variant="plain"` inside it. The alternative is the consumer repeating `variant="plain"` on all eight, which is the alignment busywork this library exists to absorb \u2014 and which goes wrong on the ninth one added later. An explicit `variant` on a child still wins.',
|
|
11372
|
+
"the_track_is_a_TGrid: Composed, not re-implemented, so `columns`, `minItemWidth` and `balance` behave exactly as they do everywhere else. `gap` is 0: the cells have to meet for the hairline to be a shared edge, and the breathing room comes from each cell's own padding.",
|
|
11373
|
+
"hairlines_survive_reflow: Every cell carries a start and a top line as pseudo-elements, and the track is pulled back one pixel so the outermost pair falls outside the clipped box. A cell that reflows onto a new row keeps its top line and becomes the first of its row, where its start line is the one being clipped \u2014 nothing hanging on the outer edge, nothing doubled between neighbours. `:nth-child` cannot express this, because which cell starts a row depends on a track count only the browser knows.",
|
|
11374
|
+
"pseudo_elements_not_borders: A border would land on the child's own `border-width`. The contract is that a cell in a band measures as frameless from the outside \u2014 `border-width` is actually 0 \u2014 so the lines are drawn beside the cell rather than on it."
|
|
11375
|
+
],
|
|
11376
|
+
selection: {
|
|
11377
|
+
keywords: [],
|
|
11378
|
+
useWhen: [],
|
|
11379
|
+
avoidWhen: [],
|
|
11380
|
+
alternatives: []
|
|
11381
|
+
},
|
|
11382
|
+
setup: {
|
|
11383
|
+
required: [],
|
|
11384
|
+
notes: []
|
|
11385
|
+
},
|
|
11386
|
+
recipes: [],
|
|
11387
|
+
practices: [
|
|
11388
|
+
"accessible-by-default",
|
|
11389
|
+
"content-alignment",
|
|
11390
|
+
"token-driven"
|
|
11391
|
+
]
|
|
11392
|
+
},
|
|
11175
11393
|
{
|
|
11176
11394
|
name: "TSteps",
|
|
11177
11395
|
aliases: [
|
|
@@ -11401,6 +11619,18 @@ var treeui_catalog_default = {
|
|
|
11401
11619
|
storyTitle: "Components/Data Display/Table",
|
|
11402
11620
|
manifestFile: "docs/ai/COMPONENTS/table.yaml",
|
|
11403
11621
|
props: [
|
|
11622
|
+
{
|
|
11623
|
+
name: "stackBelow",
|
|
11624
|
+
type: "TBreakpoint",
|
|
11625
|
+
default: "undefined",
|
|
11626
|
+
values: [
|
|
11627
|
+
"sm",
|
|
11628
|
+
"md",
|
|
11629
|
+
"lg",
|
|
11630
|
+
"xl"
|
|
11631
|
+
],
|
|
11632
|
+
description: "Below this CONTAINER width the grid becomes one block per row: the column marked `stack=\"title\"` is the block's heading, the rest sit under it, and each value carries its column's label because the header row is gone. Above it the table is unchanged, horizontal scroll included. Measured on the wrapper and not the viewport \u2014 a table can sit in a narrow panel on a wide screen, which is the case a media query cannot see. A breakpoint name and not a free length: a container query cannot read a custom property in its condition, so an arbitrary value would need a ResizeObserver per table."
|
|
11633
|
+
},
|
|
11404
11634
|
{
|
|
11405
11635
|
name: "columns",
|
|
11406
11636
|
type: "TTableColumn[]",
|
|
@@ -11447,6 +11677,35 @@ var treeui_catalog_default = {
|
|
|
11447
11677
|
type: "(row, index) => 'default' | 'muted'",
|
|
11448
11678
|
required: false,
|
|
11449
11679
|
description: "Semantic per-row state applied by data, not position, so it survives sorting. `muted` recesses a row (e.g. a resource that no longer exists) via `t-table__row--muted`, written at compound specificity so it wins over the zebra/hover rules."
|
|
11680
|
+
},
|
|
11681
|
+
{
|
|
11682
|
+
name: "rowHref",
|
|
11683
|
+
type: "(row: Record<string, unknown>, index: number) => string | undefined",
|
|
11684
|
+
default: "undefined",
|
|
11685
|
+
description: 'The row NAVIGATES: a real `href` per row, rendered as an `<a>` in the first cell and stretched over the whole row via `::after`, so ctrl/middle-click, "open in new tab", and the status-bar URL all work and the accessible role is `link`. Mutually exclusive with `rowTo` and `rowActivatable` \u2014 dev builds warn. The affordance follows the RESOLVED target: a row whose function returns `undefined` renders no link and gets no pointer.'
|
|
11686
|
+
},
|
|
11687
|
+
{
|
|
11688
|
+
name: "rowTo",
|
|
11689
|
+
type: "(row: Record<string, unknown>, index: number) => string | undefined",
|
|
11690
|
+
default: "undefined",
|
|
11691
|
+
description: "Same as `rowHref`, resolved through the app's RouterLink instead of a plain `<a>`."
|
|
11692
|
+
},
|
|
11693
|
+
{
|
|
11694
|
+
name: "rowLabel",
|
|
11695
|
+
type: "(row: Record<string, unknown>, index: number) => string",
|
|
11696
|
+
default: "undefined",
|
|
11697
|
+
description: "Accessible name for the row's activator, per row \u2014 used by BOTH `rowHref`/`rowTo` and `rowActivatable`. Required with the former and strongly advised with the latter: without it the name is every cell concatenated, repeated for every row."
|
|
11698
|
+
},
|
|
11699
|
+
{
|
|
11700
|
+
name: "rowActivatable",
|
|
11701
|
+
type: "boolean",
|
|
11702
|
+
default: "false",
|
|
11703
|
+
description: 'The row ACTIVATES something that is not a route \u2014 a modal, a selection. Renders a real `<button>` in the first cell, stretched over the row the same way `rowHref` does, rather than `role="button"` on the `<tr>`, which would make every cell presentational and destroy the table\'s grid semantics. Mutually exclusive with `rowHref`/`rowTo` \u2014 dev builds warn.'
|
|
11704
|
+
},
|
|
11705
|
+
{
|
|
11706
|
+
name: "expandedRow",
|
|
11707
|
+
type: "string | number | null",
|
|
11708
|
+
description: "Key of the row whose detail panel is open, matched against the identity `rowKey` resolves."
|
|
11450
11709
|
}
|
|
11451
11710
|
],
|
|
11452
11711
|
events: [
|
|
@@ -11454,6 +11713,11 @@ var treeui_catalog_default = {
|
|
|
11454
11713
|
name: "sort",
|
|
11455
11714
|
description: "Emitted when a sortable column header is clicked.",
|
|
11456
11715
|
payload: "TTableSortState"
|
|
11716
|
+
},
|
|
11717
|
+
{
|
|
11718
|
+
name: "row-activate",
|
|
11719
|
+
description: "Emitted when an activatable row is activated without navigating \u2014 see `rowActivatable`.",
|
|
11720
|
+
payload: "[row: Record<string, unknown>, index: number]"
|
|
11457
11721
|
}
|
|
11458
11722
|
],
|
|
11459
11723
|
slots: [
|
|
@@ -11468,6 +11732,10 @@ var treeui_catalog_default = {
|
|
|
11468
11732
|
{
|
|
11469
11733
|
name: "empty",
|
|
11470
11734
|
description: "Content shown when rows array is empty."
|
|
11735
|
+
},
|
|
11736
|
+
{
|
|
11737
|
+
name: "detail",
|
|
11738
|
+
description: "Detail panel for the expanded row, rendered as a `<tr>` adjacent to its own row. Receives `{ row, index }`."
|
|
11471
11739
|
}
|
|
11472
11740
|
],
|
|
11473
11741
|
a11y: [
|
|
@@ -11478,7 +11746,11 @@ var treeui_catalog_default = {
|
|
|
11478
11746
|
"keyboard: Sortable headers are focusable and activated with Enter or Space.",
|
|
11479
11747
|
"scope: col on all th elements."
|
|
11480
11748
|
],
|
|
11481
|
-
behavior: [
|
|
11749
|
+
behavior: [
|
|
11750
|
+
'roles_are_declared_rather_than_implied: `role` is on the table, both rowgroups, every row, every column header and every cell. Each is the element\'s own implicit role, so nothing changes while `display: table` holds \u2014 they exist to survive stacked mode, where `display: block` drops the implicit table semantics in several screen readers and the block would be announced as a run of unrelated text. Measured in the accessibility tree: a stacked cell reads as "Saldo real R$ 1.284,30", carrying its column.',
|
|
11751
|
+
"containment_is_scoped_to_tables_that_use_it: `container-type: inline-size` applies `contain: layout inline-size style`, so it is set only on a wrapper carrying a `stack-below` modifier rather than on every table in the library.",
|
|
11752
|
+
"a_row_link_covers_the_whole_block: Outside stacked mode every cell after the first is raised above the stretched-link overlay, because those are neighbouring columns and one may hold a button. Stacked, those same cells are plain text under the title, and raising them punched a hole in the link. Inside the container query only cells that actually contain something focusable are raised \u2014 and never the first, which holds the overlay: positioning it makes it the overlay's containing block, and `inset: 0` then covers that cell alone."
|
|
11753
|
+
],
|
|
11482
11754
|
selection: {
|
|
11483
11755
|
keywords: [
|
|
11484
11756
|
"table",
|
|
@@ -11513,7 +11785,9 @@ var treeui_catalog_default = {
|
|
|
11513
11785
|
],
|
|
11514
11786
|
practices: [
|
|
11515
11787
|
"interaction-feedback",
|
|
11516
|
-
"
|
|
11788
|
+
"accessible-by-default",
|
|
11789
|
+
"state-clarity",
|
|
11790
|
+
"content-alignment"
|
|
11517
11791
|
]
|
|
11518
11792
|
},
|
|
11519
11793
|
{
|