From 135059ee3eed57bb1349ec1e7190711f278ee8b8 Mon Sep 17 00:00:00 2001 From: Viserion77 Date: Wed, 7 Oct 2026 02:57:54 +0000 Subject: [PATCH] chore: update documentation and README files across packages - Updated `tag.yaml` to change `component` to `name` and updated `source` to `source_file`. - Incremented `primary_exports_count` in `CONTRACTS.yaml` and added new components to the list. - Updated `DECISIONS.md` to reflect the increase in components accepting the `size` prop. - Modified `INDEX.md` to include `VALIDATION.yaml` in the loading order and updated the description of `treeui.catalog.json`. - Updated `RECIPES.yaml` to reflect the increase in built-in icon names. - Updated `SELECTION.yaml` to reflect the increase in built-in icon names. - Updated `SETUP.yaml` to change import statements for `TreeUIPlugin`. - Updated `practices.json` to include new components and their corresponding practices. - Updated `treeui.catalog.json` and `generated/treeui.catalog.json` to reflect the new version and changes in built-in names. - Updated `README.md` files for `@treeui/vue`, `@treeui/tokens`, and `@treeui/utils` to provide better clarity and information. - Added new `README.md` files for `@treeui/tokens` and `@treeui/utils` with detailed usage instructions. - Updated `mcp` README to enumerate resources and tools by name. --- .changeset/docs-pente-fino-readmes.md | 8 +++ .github/pull_request_template.md | 8 +-- AGENTS.md | 14 ++--- CONTRIBUTING.md | 18 +++++-- README.md | 3 +- RELEASING.md | 17 +++--- apps/docs/src/Roadmap.mdx | 3 ++ apps/docs/src/stories/AppShell.stories.ts | 2 + apps/docs/src/stories/ColorSwatch.stories.ts | 4 ++ apps/docs/src/stories/DatePicker.stories.ts | 4 ++ apps/docs/src/stories/FileUpload.stories.ts | 4 ++ apps/docs/src/stories/NavMenu.stories.ts | 4 ++ apps/docs/src/stories/Radio.stories.ts | 4 ++ apps/docs/src/stories/Sparkline.stories.ts | 4 ++ apps/docs/src/stories/Stat.stories.ts | 4 ++ apps/docs/src/stories/Text.stories.ts | 4 ++ apps/docs/src/stories/Textarea.stories.ts | 4 ++ apps/docs/src/stories/Timeline.stories.ts | 4 ++ apps/docs/src/stories/Toast.stories.ts | 2 +- apps/docs/src/stories/ToggleGroup.stories.ts | 4 ++ apps/docs/src/stories/practice-refs.ts | 34 +++++++++--- apps/landing/src/i18n.ts | 6 +-- docs/ai/COMPONENTS/avatar.yaml | 4 +- docs/ai/COMPONENTS/context-menu.yaml | 2 +- docs/ai/COMPONENTS/divider.yaml | 4 +- docs/ai/COMPONENTS/form-field.yaml | 4 +- docs/ai/COMPONENTS/markdown-editor.yaml | 2 +- docs/ai/COMPONENTS/pricing.yaml | 4 +- docs/ai/COMPONENTS/progress.yaml | 2 +- docs/ai/COMPONENTS/table.yaml | 46 +++++++++++++++- docs/ai/COMPONENTS/tag.yaml | 4 +- docs/ai/CONTRACTS.yaml | 7 ++- docs/ai/DECISIONS.md | 2 +- docs/ai/INDEX.md | 3 ++ docs/ai/RECIPES.yaml | 4 +- docs/ai/SELECTION.yaml | 2 +- docs/ai/SETUP.yaml | 12 ++--- docs/ai/practices.json | 13 +++++ docs/ai/treeui.catalog.json | 46 ++++++++++++++-- packages/icons/README.md | 2 +- packages/mcp/README.md | 4 +- .../mcp/src/generated/treeui.catalog.json | 46 ++++++++++++++-- packages/tokens/README.md | 52 +++++++++++++++++++ packages/utils/README.md | 47 +++++++++++++++++ packages/utils/src/index.ts | 6 +-- packages/vue/README.md | 43 +++++++-------- 46 files changed, 424 insertions(+), 96 deletions(-) create mode 100644 .changeset/docs-pente-fino-readmes.md create mode 100644 packages/tokens/README.md create mode 100644 packages/utils/README.md diff --git a/.changeset/docs-pente-fino-readmes.md b/.changeset/docs-pente-fino-readmes.md new file mode 100644 index 0000000..0248c8a --- /dev/null +++ b/.changeset/docs-pente-fino-readmes.md @@ -0,0 +1,8 @@ +--- +'@treeui/tokens': patch +'@treeui/utils': patch +'@treeui/vue': patch +'@treeui/mcp': patch +--- + +New `README.md` files for `@treeui/tokens` and `@treeui/utils`, previously blank on npm. `@treeui/vue`'s README now uses the named `TreeUIPlugin` import/install and replaces its hand-kept component list with a category overview pointing at the generated Storybook index and `docs/ai/CONTRACTS.yaml`. `@treeui/mcp`'s README now enumerates its resources and tools by name instead of by category. diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index a4f69b9..771603c 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -5,10 +5,10 @@ ## Validation -- [ ] `pnpm lint` -- [ ] `pnpm typecheck` -- [ ] `pnpm test` -- [ ] `pnpm build` +- [ ] Ran the quality gates in [CONTRIBUTING.md](../CONTRIBUTING.md#before-opening-a-pull-request) +- [ ] Added a changeset (`pnpm changeset`) if this is a user-facing package change +- [ ] Ran the Kotlin/Rust port gates if this touches `packages/compose` or `packages/egui` +- [ ] Updated the `docs/ai` contracts if a public API changed ## Notes diff --git a/AGENTS.md b/AGENTS.md index 41b2421..6a668a6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -120,7 +120,7 @@ changes, update `docs/ai/practices.json`. `packages/icons/README.md` and `docs/ai/STANDARDS.yaml` → `icons.branchline`. The rules are enforced by rendering, not by review: `branchline.test.ts` fails a build when two icons differ by less than 5% of their ink at 16px, or when any node changes less than 1% - of a glyph's ink. Never derive geometry from an icon's name. + of a glyph's ink at 32px. Never derive geometry from an icon's name. - **Sizes**: `sm | md | lg` — shared across most components. - **Action variants**: `solid | outline | ghost | soft | danger`. - **Card variants**: `outline | soft | inset` — a surface scale, not action variants. `solid` is @@ -177,11 +177,13 @@ Run before any PR — [CONTRIBUTING.md](./CONTRIBUTING.md#before-opening-a-pull- owns this list and its Docker equivalents: ```bash -pnpm lint # ESLint, zero warnings -pnpm typecheck # TypeScript strict mode across every workspace package -pnpm test # Vitest unit tests with coverage -pnpm build:site # what CI builds: packages + landing + both Storybooks + examples -pnpm test:e2e # Playwright; optional locally, required in CI +pnpm lint # ESLint, zero warnings +pnpm typecheck # TypeScript strict mode across every workspace package +pnpm test # Vitest unit tests with coverage +pnpm build:site # what CI builds: packages + landing + both Storybooks + examples +pnpm typecheck:strict-templates # typechecks consumer templates against the built package (strictTemplates) +pnpm check:theme # validates the example's accent presets against the colour contract +pnpm test:e2e # Playwright; optional locally, required in CI ``` When touching the token model, regenerate the ports' source and check it in — diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bc14c06..3cd81ba 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,17 +9,25 @@ Use the setup in [README.md](./README.md#getting-started) to install dependencie Run the quality gates — the same commands CI runs: ```bash -pnpm lint # ESLint, zero warnings -pnpm typecheck # TypeScript strict mode across every workspace package -pnpm codegen:native:check # the ports' generated token source matches the model -pnpm test # Vitest unit tests with coverage -pnpm build:site # what CI builds: packages + landing + both Storybooks + examples +pnpm lint # ESLint, zero warnings +pnpm typecheck # TypeScript strict mode across every workspace package +pnpm codegen:native:check # the ports' generated token source matches the model +pnpm test # Vitest unit tests with coverage +pnpm build:site # what CI builds: packages + landing + both Storybooks + examples +pnpm typecheck:strict-templates # typechecks consumer templates against the built package (strictTemplates) +pnpm check:theme # validates the example's accent presets against the colour contract ``` If `codegen:native:check` fails, run `pnpm codegen:native` and commit what it writes. It means the token model changed and the Kotlin and Rust ports are carrying the previous release's values. +`typecheck:strict-templates` and `check:theme` both read the **built** +package, not the source, so they run after `build:site` here — in CI they sit +between the dedicated `build:packages` step and the `build:site` step, but +this list has no standalone `build:packages` line, since `build:site` already +runs it first. + If your change touches interaction or accessibility, also run: ```bash diff --git a/README.md b/README.md index d522ff3..b965bb5 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,8 @@ packages/compose Kotlin component package for Android (Jetpack Compo packages/egui Rust component crates for the desktop (egui) packages/mcp TreeUI AI catalog and MCP server for coding agents docs/ai Machine-oriented contracts for tools and agents -tooling Docker, ESLint, and TypeScript shared config +assets Self-hosted fonts used by the Vue and React Storybooks +tooling Docker, ESLint, TypeScript config, and the strictTemplates gate scripts Site assembly, static serving, and asset scripts tests Playwright end-to-end specs ``` diff --git a/RELEASING.md b/RELEASING.md index b302038..7b71193 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -101,10 +101,15 @@ Required check for branch protection. Steps: Fix with `pnpm codegen:native` and commit the result. 5. `pnpm test` (Vitest) 6. `pnpm build:packages` -7. `pnpm build:site` (landing + Vue/React Storybooks + example dashboards) -8. `pnpm exec playwright install --with-deps chromium` -9. `pnpm test:e2e` (with `PW_SKIP_BUILD=1`, reusing the build from step 7) -10. Uploads the `site` artifact for the pages job. +7. `pnpm typecheck:strict-templates` — typechecks consumer-app templates with + `strictTemplates` against the package just built in step 6, not the source. +8. `pnpm check:theme` — validates the example dashboard's accent presets + against the colour contract; the validator is also imported from the + built package. +9. `pnpm build:site` (landing + Vue/React Storybooks + example dashboards) +10. `pnpm exec playwright install --with-deps chromium` +11. `pnpm test:e2e` (with `PW_SKIP_BUILD=1`, reusing the build from step 9) +12. Uploads the `site` artifact for the pages job. ### `kotlin` and `rust` jobs (run on every PR and on push to `main`) @@ -280,8 +285,8 @@ release-specific commands are: ```bash pnpm build:packages # build the six published packages only pnpm changeset # create a changeset entry -pnpm changeset status # list pending changesets -pnpm ai:catalog # regenerate docs/ai/treeui.catalog.json +pnpm changeset:status # list pending changesets since origin/main +pnpm ai:catalog # regenerate docs/ai/treeui.catalog.json and packages/mcp/src/generated/treeui.catalog.json pnpm codegen:native # regenerate the ports' token source pnpm codegen:native:check # fail if that source is stale (runs in CI) pnpm mcp:start # run the local TreeUI MCP server diff --git a/apps/docs/src/Roadmap.mdx b/apps/docs/src/Roadmap.mdx index 000ef36..9213368 100644 --- a/apps/docs/src/Roadmap.mdx +++ b/apps/docs/src/Roadmap.mdx @@ -18,6 +18,8 @@ Milestones 1–3 are complete and part of the public surface: - **Milestone 3 — Routing, cards & inline links**: `TNavMenu` RouterLink support, `TCard` `title` prop and `#actions` slot, `TCard variant="inset"`, `TLink`. - **Data visualization**: `TChart`, `TSparkline`, `TDonutChart`, sharing a framework-agnostic geometry engine in `@treeui/utils` and the `--tree-color-chart-*` palette. - **React package**: `@treeui/react` ships the core primitives on the same tokens and `t-*` classes. +- **Android / Compose**: `packages/compose` (`treeui-tokens`, `treeui-compose`) — token layer complete, component set starting (`TButton`, `TBadge`, `TCard`). +- **Desktop / Rust**: `packages/egui` (`treeui-tokens`, `treeui-egui`) — token layer complete, component set starting (`TButton`, `TBadge`, `TCard`). ## Planned @@ -29,6 +31,7 @@ Milestones 1–3 are complete and part of the public surface: | Motion token expansion | More duration/easing steps and a reduced-motion contract. Not started. | | Theme builder | Visual token editor on top of `@treeui/tokens`. Exploratory. | | Additional framework packages | `@treeui/svelte` and Web Components reusing the same tokens, naming, and accessibility guidance. Exploratory. | +| Storybook coverage for shipped components | `TPane`, `TDropVeil`, `TCalendar` / `TCalendarMonthGrid` / `TCalendarTimeGrid`, `TSpanLanes`, `TAudioPlayer`, `TVoiceRecorder` are implemented and exported but have no story file, so they render with no link in the generated Foundation/Components index. Not started. | ## Table direction diff --git a/apps/docs/src/stories/AppShell.stories.ts b/apps/docs/src/stories/AppShell.stories.ts index 4a2688b..47a7b8d 100644 --- a/apps/docs/src/stories/AppShell.stories.ts +++ b/apps/docs/src/stories/AppShell.stories.ts @@ -1,6 +1,7 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite'; import { ref } from 'vue'; import { TAppShell, TAvatar, TBadge, TButton, TNavMenu } from '@treeui/vue'; +import { practiceNote } from './practice-refs'; const items = [ { label: 'Overview', value: 'overview', description: 'Summary and recent work', shortLabel: 'O' }, @@ -17,6 +18,7 @@ const meta = { parameters: { // The shell fills the viewport, so give it the whole canvas. layout: 'fullscreen', + docs: { description: { component: practiceNote('TAppShell') } }, }, args: { side: 'left', diff --git a/apps/docs/src/stories/ColorSwatch.stories.ts b/apps/docs/src/stories/ColorSwatch.stories.ts index 89e3c29..dcc4d70 100644 --- a/apps/docs/src/stories/ColorSwatch.stories.ts +++ b/apps/docs/src/stories/ColorSwatch.stories.ts @@ -1,6 +1,7 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite'; import { ref } from 'vue'; import { TColorSwatch } from '@treeui/vue'; +import { practiceNote } from './practice-refs'; const presets = [ { label: 'Ocean blue', value: '#0969da' }, @@ -14,6 +15,9 @@ const meta = { title: 'Components/Data Entry/ColorSwatch', component: TColorSwatch, tags: ['autodocs'], + parameters: { + docs: { description: { component: practiceNote('TColorSwatch') } }, + }, args: { options: presets, allowCustom: true, diff --git a/apps/docs/src/stories/DatePicker.stories.ts b/apps/docs/src/stories/DatePicker.stories.ts index d34aae9..8ec7ddb 100644 --- a/apps/docs/src/stories/DatePicker.stories.ts +++ b/apps/docs/src/stories/DatePicker.stories.ts @@ -2,11 +2,15 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite'; import { ref } from 'vue'; import { TButton, TDatePicker } from '@treeui/vue'; import { InfoIcon, iconProps } from './icon-helpers'; +import { practiceNote } from './practice-refs'; const meta = { title: 'Components/Data Entry/DatePicker', component: TDatePicker, tags: ['autodocs'], + parameters: { + docs: { description: { component: practiceNote('TDatePicker') } }, + }, args: { size: 'md', disabled: false, diff --git a/apps/docs/src/stories/FileUpload.stories.ts b/apps/docs/src/stories/FileUpload.stories.ts index f386352..b47aaac 100644 --- a/apps/docs/src/stories/FileUpload.stories.ts +++ b/apps/docs/src/stories/FileUpload.stories.ts @@ -5,11 +5,15 @@ import type { TFileUploadRetryPayload, TFileUploadState, } from '@treeui/vue'; +import { practiceNote } from './practice-refs'; const meta = { title: 'Components/Data Entry/FileUpload', component: TFileUpload, tags: ['autodocs'], + parameters: { + docs: { description: { component: practiceNote('TFileUpload') } }, + }, args: { size: 'md', multiple: true, diff --git a/apps/docs/src/stories/NavMenu.stories.ts b/apps/docs/src/stories/NavMenu.stories.ts index 1bd3249..f35b318 100644 --- a/apps/docs/src/stories/NavMenu.stories.ts +++ b/apps/docs/src/stories/NavMenu.stories.ts @@ -1,6 +1,7 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite'; import { ref } from 'vue'; import { TNavMenu } from '@treeui/vue'; +import { practiceNote } from './practice-refs'; const items = [ { label: 'Overview', value: 'overview', description: 'Summary and activity', badge: '12', shortLabel: 'O' }, @@ -19,6 +20,9 @@ const meta = { title: 'Components/Layout/NavMenu', component: TNavMenu, tags: ['autodocs'], + parameters: { + docs: { description: { component: practiceNote('TNavMenu') } }, + }, args: { size: 'md', collapsed: false, diff --git a/apps/docs/src/stories/Radio.stories.ts b/apps/docs/src/stories/Radio.stories.ts index 7cd7e4b..54bc4a2 100644 --- a/apps/docs/src/stories/Radio.stories.ts +++ b/apps/docs/src/stories/Radio.stories.ts @@ -1,11 +1,15 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite'; import { ref } from 'vue'; import { TRadio, TRadioGroup } from '@treeui/vue'; +import { practiceNote } from './practice-refs'; const meta = { title: 'Components/Data Entry/Radio', component: TRadioGroup, tags: ['autodocs'], + parameters: { + docs: { description: { component: practiceNote('TRadio') } }, + }, args: { size: 'md', disabled: false, diff --git a/apps/docs/src/stories/Sparkline.stories.ts b/apps/docs/src/stories/Sparkline.stories.ts index 27c1bbf..69fabb1 100644 --- a/apps/docs/src/stories/Sparkline.stories.ts +++ b/apps/docs/src/stories/Sparkline.stories.ts @@ -1,5 +1,6 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite'; import { TSparkline, TStat } from '@treeui/vue'; +import { practiceNote } from './practice-refs'; const sample = [12, 18, 9, 22, 30, 24, 28, 26, 33, 38]; @@ -7,6 +8,9 @@ const meta = { title: 'Components/Data Display/Sparkline', component: TSparkline, tags: ['autodocs'], + parameters: { + docs: { description: { component: practiceNote('TSparkline') } }, + }, args: { data: sample, type: 'line', diff --git a/apps/docs/src/stories/Stat.stories.ts b/apps/docs/src/stories/Stat.stories.ts index 0552459..1bab0bf 100644 --- a/apps/docs/src/stories/Stat.stories.ts +++ b/apps/docs/src/stories/Stat.stories.ts @@ -1,11 +1,15 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite'; import { TCard, TStat, TStatGroup, TText } from '@treeui/vue'; import { CheckIcon, InfoIcon, iconProps } from './icon-helpers'; +import { practiceNote } from './practice-refs'; const meta = { title: 'Components/Data Display/Stat', component: TStat, tags: ['autodocs'], + parameters: { + docs: { description: { component: practiceNote('TStat', 'TStatGroup') } }, + }, args: { label: 'Monthly recurring revenue', value: '$48.2k', diff --git a/apps/docs/src/stories/Text.stories.ts b/apps/docs/src/stories/Text.stories.ts index a10d06f..8e4472d 100644 --- a/apps/docs/src/stories/Text.stories.ts +++ b/apps/docs/src/stories/Text.stories.ts @@ -1,10 +1,14 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite'; import { TText } from '@treeui/vue'; +import { practiceNote } from './practice-refs'; const meta = { title: 'Components/Data Display/Text', component: TText, tags: ['autodocs'], + parameters: { + docs: { description: { component: practiceNote('TText') } }, + }, args: { as: 'span', size: 'md', diff --git a/apps/docs/src/stories/Textarea.stories.ts b/apps/docs/src/stories/Textarea.stories.ts index ad4afa3..1d1195b 100644 --- a/apps/docs/src/stories/Textarea.stories.ts +++ b/apps/docs/src/stories/Textarea.stories.ts @@ -1,11 +1,15 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite'; import { ref } from 'vue'; import { TTextarea } from '@treeui/vue'; +import { practiceNote } from './practice-refs'; const meta = { title: 'Components/Data Entry/Textarea', component: TTextarea, tags: ['autodocs'], + parameters: { + docs: { description: { component: practiceNote('TTextarea') } }, + }, args: { size: 'md', disabled: false, diff --git a/apps/docs/src/stories/Timeline.stories.ts b/apps/docs/src/stories/Timeline.stories.ts index 78b3143..547ffe3 100644 --- a/apps/docs/src/stories/Timeline.stories.ts +++ b/apps/docs/src/stories/Timeline.stories.ts @@ -2,6 +2,7 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite'; import { TTimeline } from '@treeui/vue'; import type { TTimelineItem } from '@treeui/vue'; import { CheckIcon, InfoIcon, iconProps } from './icon-helpers'; +import { practiceNote } from './practice-refs'; const releaseEvents: TTimelineItem[] = [ { @@ -56,6 +57,9 @@ const meta = { title: 'Components/Data Display/Timeline', component: TTimeline, tags: ['autodocs'], + parameters: { + docs: { description: { component: practiceNote('TTimeline') } }, + }, args: { size: 'md', items: releaseEvents, diff --git a/apps/docs/src/stories/Toast.stories.ts b/apps/docs/src/stories/Toast.stories.ts index 83c612b..ef75e82 100644 --- a/apps/docs/src/stories/Toast.stories.ts +++ b/apps/docs/src/stories/Toast.stories.ts @@ -6,7 +6,7 @@ const meta = { title: 'Components/Feedback/Toast', component: TToastProvider, parameters: { - docs: { description: { component: practiceNote('TToastProvider') } }, + docs: { description: { component: practiceNote('TToast', 'TToastProvider') } }, }, tags: ['autodocs'], args: { diff --git a/apps/docs/src/stories/ToggleGroup.stories.ts b/apps/docs/src/stories/ToggleGroup.stories.ts index 769da5a..7597f35 100644 --- a/apps/docs/src/stories/ToggleGroup.stories.ts +++ b/apps/docs/src/stories/ToggleGroup.stories.ts @@ -2,6 +2,7 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite'; import type { ComponentProps } from 'vue-component-type-helpers'; import { ref } from 'vue'; import { TStack, TText, TToggleGroup } from '@treeui/vue'; +import { practiceNote } from './practice-refs'; // `TToggleGroup` is generic over its option type AND its selection mode, so // `typeof TToggleGroup` is a generic FUNCTION, which Storybook's @@ -21,6 +22,9 @@ const meta: Meta = { title: 'Components/Data Entry/ToggleGroup', component: TToggleGroup as never, tags: ['autodocs'], + parameters: { + docs: { description: { component: practiceNote('TToggleGroup') } }, + }, args: { size: 'md', variant: 'outline', diff --git a/apps/docs/src/stories/practice-refs.ts b/apps/docs/src/stories/practice-refs.ts index aff7b2b..d9122c6 100644 --- a/apps/docs/src/stories/practice-refs.ts +++ b/apps/docs/src/stories/practice-refs.ts @@ -8,12 +8,7 @@ const { practices, storybookDocPage } = practicesData; const practiceLink = (id: string, title: string) => `${title}`; -/** - * Docs-page note for a story meta (`parameters.docs.description.component`) - * listing the named TreeUI practices — from `docs/ai/practices.json` — that the - * component follows, each linking to its section on Foundation/Practices. - */ -export const practiceNote = (componentName: string): string => { +const practiceNoteForComponent = (componentName: string): string => { const followed = practices.filter((practice) => practice.components.includes(componentName)); if (followed.length === 0) { @@ -26,3 +21,30 @@ export const practiceNote = (componentName: string): string => { return `Follows the TreeUI practices: ${links}.`; }; + +/** + * Docs-page note for a story meta (`parameters.docs.description.component`) + * listing the named TreeUI practices — from `docs/ai/practices.json` — that the + * component follows, each linking to its section on Foundation/Practices. + * + * Pass a single component name for a story whose meta documents one + * component — the output is a single, unprefixed sentence, unchanged from the + * original single-argument form. Pass more than one name (e.g. a provider + * story that also demonstrates a paired component) and each component gets + * its own labelled block, listing only the practices IT follows — the sets + * are never merged, since that would misstate which practices the other + * component actually follows. + */ +export const practiceNote = (...names: string[]): string => { + if (names.length <= 1) { + return names.length === 0 ? '' : practiceNoteForComponent(names[0]); + } + + return names + .map((name) => { + const note = practiceNoteForComponent(name); + return note ? `**${name}** — ${note}` : ''; + }) + .filter((block) => block !== '') + .join('\n\n'); +}; diff --git a/apps/landing/src/i18n.ts b/apps/landing/src/i18n.ts index 194a3e4..969165d 100644 --- a/apps/landing/src/i18n.ts +++ b/apps/landing/src/i18n.ts @@ -108,7 +108,7 @@ const en: LandingMessages = { ariaLabel: 'Documentation', vueBadge: 'Stable', vueBody: - 'The complete library: 60+ production components, a plugin, full type exports, and the entire design-system documentation.', + 'The complete library: 100+ production components, a plugin, full type exports, and the entire design-system documentation.', vueGo: 'Open Vue docs →', reactBadge: 'Early', reactBody: @@ -192,7 +192,7 @@ const pt: LandingMessages = { ariaLabel: 'Documentação', vueBadge: 'Estável', vueBody: - 'A biblioteca completa: mais de 60 componentes de produção, um plugin, exports de tipos e toda a documentação do design system.', + 'A biblioteca completa: mais de 100 componentes de produção, um plugin, exports de tipos e toda a documentação do design system.', vueGo: 'Abrir docs Vue →', reactBadge: 'Inicial', reactBody: @@ -313,7 +313,7 @@ const es: LandingMessages = { ariaLabel: 'Documentación', vueBadge: 'Estable', vueBody: - 'La librería completa: más de 60 componentes de producción, un plugin, exports de tipos y toda la documentación del design system.', + 'La librería completa: más de 100 componentes de producción, un plugin, exports de tipos y toda la documentación del design system.', vueGo: 'Abrir docs Vue →', reactBadge: 'Inicial', reactBody: diff --git a/docs/ai/COMPONENTS/avatar.yaml b/docs/ai/COMPONENTS/avatar.yaml index 1bc18eb..7b1ef2c 100644 --- a/docs/ai/COMPONENTS/avatar.yaml +++ b/docs/ai/COMPONENTS/avatar.yaml @@ -1,7 +1,7 @@ -component: TAvatar +name: TAvatar status: available package: "@treeui/vue" -source: TAvatar.vue +source_file: packages/vue/src/components/TAvatar.vue description: User avatar that renders an image when `src` is set, otherwise initials derived from `alt`, plus an optional status indicator dot. props: diff --git a/docs/ai/COMPONENTS/context-menu.yaml b/docs/ai/COMPONENTS/context-menu.yaml index da2b18e..2ebe72a 100644 --- a/docs/ai/COMPONENTS/context-menu.yaml +++ b/docs/ai/COMPONENTS/context-menu.yaml @@ -1,7 +1,7 @@ # TContextMenu # Right-click floating menu anchored at cursor position. -component: TContextMenu +name: TContextMenu source_file: packages/vue/src/components/TContextMenu.vue since: 0.5.0 status: available diff --git a/docs/ai/COMPONENTS/divider.yaml b/docs/ai/COMPONENTS/divider.yaml index 550356a..69e3203 100644 --- a/docs/ai/COMPONENTS/divider.yaml +++ b/docs/ai/COMPONENTS/divider.yaml @@ -1,7 +1,7 @@ -component: TDivider +name: TDivider status: available package: "@treeui/vue" -source: TDivider.vue +source_file: packages/vue/src/components/TDivider.vue description: > Horizontal or vertical visual separator. Renders a single native
and nothing else — there is no default slot, so the "text in the middle of a rule" pattern (an "OR" divider) diff --git a/docs/ai/COMPONENTS/form-field.yaml b/docs/ai/COMPONENTS/form-field.yaml index 0c3c1bc..8fa4cd7 100644 --- a/docs/ai/COMPONENTS/form-field.yaml +++ b/docs/ai/COMPONENTS/form-field.yaml @@ -1,7 +1,7 @@ -component: TFormField +name: TFormField status: available package: "@treeui/vue" -source: TFormField.vue +source_file: packages/vue/src/components/TFormField.vue description: > Label + input wrapper with error and hint slots. Provides consistent layout, labelling, and validation messaging for any form control. diff --git a/docs/ai/COMPONENTS/markdown-editor.yaml b/docs/ai/COMPONENTS/markdown-editor.yaml index 989b0d8..db48339 100644 --- a/docs/ai/COMPONENTS/markdown-editor.yaml +++ b/docs/ai/COMPONENTS/markdown-editor.yaml @@ -1,4 +1,4 @@ -component: TMarkdownEditor +name: TMarkdownEditor source_file: packages/vue/src/components/TMarkdownEditor.vue status: available since: 0.x.x diff --git a/docs/ai/COMPONENTS/pricing.yaml b/docs/ai/COMPONENTS/pricing.yaml index af856d9..da2d361 100644 --- a/docs/ai/COMPONENTS/pricing.yaml +++ b/docs/ai/COMPONENTS/pricing.yaml @@ -1,7 +1,7 @@ # Pricing — Component Contract # Components: TPricingCard, TPricing -component: PricingCard +name: TPricingCard source_file: packages/vue/src/components/TPricingCard.vue status: available category: data-display @@ -119,7 +119,7 @@ a11y: --- -component: Pricing +name: TPricing source_file: packages/vue/src/components/TPricing.vue status: available category: data-display diff --git a/docs/ai/COMPONENTS/progress.yaml b/docs/ai/COMPONENTS/progress.yaml index dfe45c9..c623002 100644 --- a/docs/ai/COMPONENTS/progress.yaml +++ b/docs/ai/COMPONENTS/progress.yaml @@ -1,4 +1,4 @@ -component: TProgress +name: TProgress source_file: packages/vue/src/components/TProgress.vue package: "@treeui/vue" since: "0.2.0" diff --git a/docs/ai/COMPONENTS/table.yaml b/docs/ai/COMPONENTS/table.yaml index d0035d7..7ceed7d 100644 --- a/docs/ai/COMPONENTS/table.yaml +++ b/docs/ai/COMPONENTS/table.yaml @@ -1,7 +1,7 @@ -component: TTable +name: TTable status: available package: "@treeui/vue" -source: TTable.vue +source_file: packages/vue/src/components/TTable.vue description: Sortable, accessible data table with column definitions and row data. props: @@ -49,11 +49,50 @@ props: required: false 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." a11y_note: "Dimming is a visual aid only, never the sole signal — pair `muted` with a status cell (TBadge/TTag) or visually hidden text conveying the same meaning, per the accessible-by-default practice." + rowHref: + type: "(row: Record, index: number) => string | undefined" + default: undefined + description: >- + The row NAVIGATES: a real `href` per row, rendered as an `` 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` — dev builds warn. The affordance follows the RESOLVED + target: a row whose function returns `undefined` renders no link and + gets no pointer. + rowTo: + type: "(row: Record, index: number) => string | undefined" + default: undefined + description: "Same as `rowHref`, resolved through the app's RouterLink instead of a plain ``." + rowLabel: + type: "(row: Record, index: number) => string" + default: undefined + description: >- + Accessible name for the row's activator, per row — 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. + rowActivatable: + type: boolean + default: false + description: >- + The row ACTIVATES something that is not a route — a modal, a selection. + Renders a real `