Skip to content

Commit 9bf2779

Browse files
robsongajuniorisaquebockherbert-julio-aziongabriel-lisboa-aziongablisboa
authored
feat: V4 sync release webkit/theme/icons (#768)
* feat: development environment * feat: azion deploy dev-webkit.azion.app * fix: order rules engine dev storybook * fix: repo cleanup, development base * fix: install updatinh the removed dependencies * chore: trigger * fix: overline import path * refactor: remote data, template and layout exports prefix * fix: export content * fix: equalizing the bucket prefix * fix: run required check to dev opened pull requests * feat: add textarea and field-textarea (#657) * feat: add input-textarea and field-textarea Introduces two new components under the inputs category: - InputTextarea — multi-line text control with optional iconLeft / iconRight slots, focus ring aligned with input-text/dropdown, and required (warning) / invalid (danger) border tones. - FieldTextarea — labeled wrapper composing Label + InputTextarea + helper text, with helper color swapping to warning on required and danger on invalid. Storybook stories follow the InputSelect pattern (code panel open by default, hand-crafted source snippets, Usage block in autodocs). * fix: access input-textarea slots via bracket notation to satisfy TS4111 Index-signature slot keys from defineSlots cannot be read via dot notation under noUncheckedIndexedAccess; switch to bracket access and drop the in-template $slots.iconRight dot access in favor of the existing hasIconRight computed. * fix: align input-textarea and field-textarea subpath exports * fix: rename Input Textarea story title to Textarea * refactor: rename InputTextarea component to Textarea * [ENG-46313] feat(webkit): add Skeleton loading placeholder (feedback) (#662) Skeleton placeholder (shape/circle) with pulse + reduced-motion fallback. Story under stories/components, direct `@aziontech/webkit/skeleton` export (review by robsongajunior), and a validate-tokens lookbehind so the sanctioned `var(--bg-surface-overlay)` token is not flagged as a PrimeFlex utility. * fix: storybook textarea group name * fix: storybook textarea group name * feat(copy-button): Copy Button with Tooltip and icon transition fixes (#631) * feat: add Copy Button and Tooltip components Introduce copy-button and tooltip with Storybook coverage, icon swap transitions on IconButton, and package exports for consumers. * fix: icon-button/tooltip imports and storybook category * feat(copy-button): integrate Tooltip and stabilize icon swap motion CopyButton uses Tooltip for hover/focus and post-copy feedback with outlined as default; IconButton and Tooltip presets avoid layout shift and align motion with theme tokens. * docs(tooltip): add LongContent story and use body-xs typography Replace the Disabled story with a long-content example on a small transparent info IconButton, and align tooltip panel text with body-xs. --------- Co-authored-by: Robson Júnior <robson.ga.junior@gmail.com> * chore(commands): add /open-pr and /create-branch PR-workflow commands (#670) * chore(commands): add /open-pr and /create-branch PR-workflow commands Two slash commands encoding our PR flow: /create-branch (branch off dev, prompts for the related issue) and /open-pr (ensure dev-based branch, commit by context, push, open PR to dev). Encodes our conventions: base dev, issue in branch name, split shared docs into their own PR, no attribution footers. * [NO-ISSUE] chore: refine pr-workflow commands (diff analysis, optional issue, versioning) Both commands now analyze the diff to pick the Conventional Commit type/scope (driving the semantic-release bump), prompt for the related issue as optional ([NO-ISSUE] fallback), keep one commit per scope, detect breaking changes, and never bypass commitlint. Sourced from CONTRIBUTING.md + commitlint.config.js. * [NO-ISSUE] chore(rules): add git-workflow rule pointing to /open-pr and /create-branch Auto-loaded rule so PR/branch requests in natural language route to the /open-pr and /create-branch flows instead of ad-hoc git steps. * [NO-ISSUE] chore(repo): enumerate perf/test/ci/revert in every .releaserc to match commitlint * [NO-ISSUE] docs(repo): add release-types consistency rule --------- Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * [ENG-46314] feat(webkit): add Badge (content) (#663) * [ENG-46314] feat(webkit): add Badge (content) Compact severity-coded count/short-value indicator (primary/secondary/success/ warning/danger/default; small/medium/large). Story under stories/components, direct `@aziontech/webkit/badge` export. The 'Show code' SFC detector regex is case-insensitive (/i) so CodeQL's bad-tag-filter alert is resolved. * [ENG-46314] fix(webkit): default Badge value prop to empty string, not undefined * [ENG-46314] refactor(webkit): simplify Badge severity validation with includes addresses review feedback — replaces the explicit severity if-chain with a validSeverities array + includes guard. --------- Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * feat: add InputSelect composition (#647) * feat: add InputSelect composition Introduce `@aziontech/webkit/inputs/input-select` and its sub-components (`input-select-trigger`, `input-select-content`, `input-select-group`, `input-select-option`), composed via a shared injection key for context sharing without prop drilling. The composition pattern follows the shadcn-vue convention: the consumer controls the structure (`<InputSelect><InputSelectTrigger /><InputSelectContent> <InputSelectGroup><InputSelectOption /></InputSelectGroup></InputSelectContent></InputSelect>`), while the parent `InputSelect` owns selection state and exposes `modelValue` + `update:modelValue` for v-model binding. * fix: popup animation * fix: input-select type errors on aria attributes and emit values * feat: expose InputSelect sub-components as static properties and wrap options in ScrollArea * fix: avoid TS4023 on InputSelect by typing sub-component augmentation explicitly * refactor: rename input-select to select and flatten exports * style: prettier format renamed select files * refactor: collapse select to single subpath export --------- Co-authored-by: Herbert Vicente Cotta Julio <herbert.julio@azion.com> Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * [NO-ISSUE] chore(specs): default optional text props to empty string, not undefined (#671) * [NO-ISSUE] chore(specs): default optional text props to empty string, not undefined Optional string props that hold renderable text now default to '' across the spec template, the spec-create / component-scaffold skills, and the scaffolder agent. Reserve undefined (unquoted) for props where absence differs from empty (open, modelValue, src); never the literal 'undefined'. Prevents the default-value issue raised in review of PR #646. * [NO-ISSUE] chore(specs): reject string-literal 'undefined' in spec Default cells Enforces the empty-string default convention documented earlier in this PR via spec-validate Step 3 plus a shared defaultCellIsStringUndefined helper and a unit test; status:implemented specs (checkbox/dropdown) are not re-validated so they stay green. --------- Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * fix: removing GIT_PKG token from storybook action (#683) * chore: update storybook README to trigger pipeline * docs(webkit): codify Show code pattern + flat-import rule (#665) * docs(webkit): codify Show code pattern + flat-import rule storybook-write skill: document the copy-paste-ready 'Show code' transform, now in the current repo format (stories under stories/components, title Components/<Category>/<Name>, direct `@aziontech/webkit/<name>` imports, /i on the SFC-detector regex). Adds .claude/rules/imports.md codifying the flat public export name (category lives in the folder + story title, not the import). * docs(webkit): translate imports rule blockquote to English --------- Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * [NO-ISSUE] docs: translate .claude/rules files to English (#673) Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * [ENG-46310] feat(webkit): add Chip (inputs) (#664) * [ENG-46310] feat(webkit): add Chip (inputs) Compact dismissible token (small/medium, optional removable button emitting `remove`). Story under stories/components, direct `@aziontech/webkit/chips` export. The 'Show code' SFC detector regex is case-insensitive (/i) so CodeQL's bad-tag-filter alert is resolved. * [ENG-46310] fix(webkit): default Chip label to empty string, not undefined * [ENG-46310] feat(webkit): animate Chip removal with Message-style fade-out --------- Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * docs(webkit): compound-api rule + TanStack table dependency exception (#666) Companion docs/rules for the composable Table (#ENG-46087): new compound-api.md rule (compound dot-notation API for composition components), the @tanstack/vue-table exception in dependencies.md, component-scaffold + _template updates. Export/import references flattened to the public flat name per .claude/rules/imports.md. Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * feat: add HelperText input primitive (#646) * feat: add HelperText input primitive Introduce `@aziontech/webkit/inputs/helper-text` — a small text element that renders auxiliary copy below a form field. The `kind` prop drives the visual tone: - `helper` (default): muted token, neutral copy. - `required`: warning-tone copy paired with the Required tag treatment. - `invalid`: danger-tone copy for validation errors; usually wired to `aria-describedby` on the input. - `disabled`: muted with a leading lock icon. The component is the helper line only — wrapping form-field components own the wiring of `aria-describedby` and the conditional rendering. * fix: adjust show code * fix: align helper-text subpath export * fix: default fallback value prop to empty string * fix: default tag icon prop to empty string * revert: scope value default change to label and helper-text only * fix: move HelperText story to Components/Inputs * chore: move HelperText story to components/inputs path --------- Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * feat: InputText v2 + FieldText composition (#648) * feat: add Label input primitive Introduce `@aziontech/webkit/inputs/label` — a thin `<label>` wrapper that renders the field text, supports a default slot, and appends a `Required` tag when the field is required. Wires `for` to the underlying input id so clicking the label focuses the control. The component is the label only — helper text, error messages, and the input itself live in sibling primitives composed by the form-field layer. * feat: add HelperText input primitive Introduce `@aziontech/webkit/inputs/helper-text` — a small text element that renders auxiliary copy below a form field. The `kind` prop drives the visual tone: - `helper` (default): muted token, neutral copy. - `required`: warning-tone copy paired with the Required tag treatment. - `invalid`: danger-tone copy for validation errors; usually wired to `aria-describedby` on the input. - `disabled`: muted with a leading lock icon. The component is the helper line only — wrapping form-field components own the wiring of `aria-describedby` and the conditional rendering. * feat: InputText v2 + FieldText composition Redesign the `InputText` field around the new `--ring-color` token, raise the spec to v2, and introduce a sibling `FieldText` wrapper that composes `Label` + `InputText` + `HelperText` into a single vertical stack with consistent spacing. InputText changes: - Restrict `type` to plain-text variants (`'text' | 'email'`). - Add `maxLength`, `required`, `invalid` props. - Add `iconLeft` / `iconRight` slots. - Drive visual states (hover, focus, filled) via native CSS pseudo-classes instead of props; `data-size`, `data-disabled`, `data-invalid`, `data-required` mirror the props for `data-[attr]:` Tailwind variants. FieldText: - `useId()`-backed `inputId` wired through Label `for` + input `id` + `aria-describedby` -> HelperText. - `helperKind` switches between `helper`, `required`, `invalid`, `disabled` based on prop state; falls back to a default `'This field is locked.'` copy when `disabled` is true and `helperText` is empty. - Forwards `iconLeft` / `iconRight` slots to the underlying InputText. * fix: align InputText/FieldText showcode with Message pattern * fix: align input-text family subpath exports * fix: allow type=number on InputText to unblock data-table position input * Revert "fix: allow type=number on InputText to unblock data-table position input" This reverts commit 708d5a698817374c431cfe6aee74d02dc82bdad8. * Revert "Revert "fix: allow type=number on InputText to unblock data-table position input"" This reverts commit 8860d49e1fc791ad2224bcc4622b83aaf16ba6d7. * fix: storybook path * fix: address PR review on input-text, helper-text and story titles * fix: remove undefined defaults and align story namespace * fix: keep maxLength default as undefined to satisfy vue-tsc * fix: default field-text inputId and name to empty string --------- Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * feat: InputPassword + FieldPassword composition (#649) * feat: add Label input primitive Introduce `@aziontech/webkit/inputs/label` — a thin `<label>` wrapper that renders the field text, supports a default slot, and appends a `Required` tag when the field is required. Wires `for` to the underlying input id so clicking the label focuses the control. The component is the label only — helper text, error messages, and the input itself live in sibling primitives composed by the form-field layer. * feat: add HelperText input primitive Introduce `@aziontech/webkit/inputs/helper-text` — a small text element that renders auxiliary copy below a form field. The `kind` prop drives the visual tone: - `helper` (default): muted token, neutral copy. - `required`: warning-tone copy paired with the Required tag treatment. - `invalid`: danger-tone copy for validation errors; usually wired to `aria-describedby` on the input. - `disabled`: muted with a leading lock icon. The component is the helper line only — wrapping form-field components own the wiring of `aria-describedby` and the conditional rendering. * feat: InputText v2 + FieldText composition Redesign the `InputText` field around the new `--ring-color` token, raise the spec to v2, and introduce a sibling `FieldText` wrapper that composes `Label` + `InputText` + `HelperText` into a single vertical stack with consistent spacing. InputText changes: - Restrict `type` to plain-text variants (`'text' | 'email'`). - Add `maxLength`, `required`, `invalid` props. - Add `iconLeft` / `iconRight` slots. - Drive visual states (hover, focus, filled) via native CSS pseudo-classes instead of props; `data-size`, `data-disabled`, `data-invalid`, `data-required` mirror the props for `data-[attr]:` Tailwind variants. FieldText: - `useId()`-backed `inputId` wired through Label `for` + input `id` + `aria-describedby` -> HelperText. - `helperKind` switches between `helper`, `required`, `invalid`, `disabled` based on prop state; falls back to a default `'This field is locked.'` copy when `disabled` is true and `helperText` is empty. - Forwards `iconLeft` / `iconRight` slots to the underlying InputText. * feat: InputPassword + FieldPassword composition Introduce `@aziontech/webkit/inputs/input-password` — a single-line password input that shares InputText's visual language and adds a built-in visibility toggle button on the trailing edge (driven by the existing `IconButton`). Type flips between `password` and `text` via local state; the toggle button announces its state via `aria-pressed`. `InputPassword` props: `modelValue`, `placeholder`, `maxLength`, `disabled`, `readonly`, `required`, `invalid`, `toggleable`, `autocomplete` (`'current-password' | 'new-password' | 'off'`). Slots: `iconLeft` (always available), `iconRight` (only when `toggleable=false` — the visibility toggle occupies that position otherwise). Single fixed height (40px / `large`). `FieldPassword` mirrors `FieldText`: composes `Label` + `InputPassword` + `HelperText` with the same `useId()` wiring for `for` / `id` / `aria-describedby`. Forwards `iconLeft` / `iconRight` slots and adds password-specific props (`maxLength`, `toggleable`, `autocomplete`). Storybook templates use the v-model pattern documented in the `storybook-write` skill — local `ref` + `watch` + `onUpdate` so the toggle has a value to reveal and the Actions panel still receives `update:modelValue` events. Ships the `input-password.figma.ts` Code Connect mapping. * fix: align InputPassword/FieldPassword showcode with Message pattern * fix: align input-password and field-password subpath imports * fix: allow type=number on InputText to unblock data-table position input * fix: remove undefined defaults and align story namespace * fix: keep maxLength default as undefined to satisfy vue-tsc * refactor: type inputId and name as string with empty default on FieldPassword * docs: spell out maxLength type as number | undefined in input/field specs * feat(webkit): sync Global Header structure and chrome with updated Figma (#661) * fix(webkit): align Global Header chrome with updated Figma Match the Webkit GlobalHeader design (node 4310:19617): symmetric horizontal padding (--spacing-md both sides), --spacing-md shell gap, and the canonical --border-default bottom border. Adjust start/end region gaps (--spacing-xs / --spacing-sm) to the Figma values. Update the spec's Figma reference, Purpose, and Tokens table accordingly. * feat(webkit): add Global Header Container region and Nav alias Mirror the Figma GlobalHeader structure (node 4310:19617) without breaking changes. Add GlobalHeader.Container, a shrink-0 flex wrapper that groups the menu trigger and brand as the Figma "Container" region, and expose the center region under its Figma name via GlobalHeader.Nav as an alias of the existing Middle (Middle is retained). Both additions are purely additive: no export path, prop, event, or slot changes, and existing compositions render identically. --------- Co-authored-by: Herbert Vicente Cotta Julio <herbert.julio@azion.com> Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * [NO-ISSUE] feat(webkit): add EmptyState component (#674) Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * [NO-ISSUE] chore(webkit): drop per-component package.json + dev dts s… (#684) * [NO-ISSUE] chore(webkit): drop per-component package.json + dev dts scripts, hoist sideEffects The exports map in packages/webkit/package.json points every public path directly at a source file (.vue/.ts/.js), so the per-component package.json files were never consulted for resolution: their main/module/types/browser fields are dead under the exports map, and nothing reads them. - Hoist sideEffects to the root as ["**/*.vue", "**/*.css"] (covers the lone styles/country-flags.css; .ts/.js stay tree-shakeable as before). - Delete all 70 per-component package.json under src. - Remove the dev/CI build:dts + clean:dts scripts and the webkit:build:dts alias; drop the build:dts steps from the storybook and governance workflows. Type declarations are unaffected for consumers: .releaserc's prepareCmd (vue-tsc --declaration --emitDeclarationOnly) still generates and ships .d.ts at publish time. type-check (vue-tsc --noEmit, declaration: true) keeps declaration-emit validation in CI. * [NO-ISSUE] docs(webkit): align rules/skills/docs with the package.json + build:dts removal Follow-up to the package.json/build:dts cleanup — bring the component-authoring rules, skills, agent prompts, and docs in line with the new reality. - compound-api.md, component-scaffold (skill) + scaffolder (agent), COMPONENT_REQUIREMENTS (×2): components and sub-components no longer ship a per-folder package.json; the root `#exports` map plus the root `sideEffects` are the single source of wiring. The composition `index.ts` stays. - Drop the removed `webkit:build:dts` / `build:dts` / `clean:dts` references from AGENTS.md (×2), README, CONTRIBUTING, validate-component, component-create, settings.json, the governance doc, and the Storybook Get Started page. Declarations are noted as publish-time (`.releaserc` prepareCmd); CI declaration validation stays via `type-check` (vue-tsc --noEmit). * feat: refine input-switch and field-switch with documented stories (#656) * feat: refine input-switch and field-switch with documented stories Tighten the InputSwitch / FieldSwitch / FieldSwitchBlock visuals against the Figma spec, and align the Storybook stories with the InputSelect pattern (Show code panel open by default, hand-crafted source snippets, `## Usage` block in autodocs). * refactor: rename InputSwitch component to Switch * fix: align FieldSwitch story CORE_IMPORT to flat subpath * fix: default modelValue to false in field-switch components * chore: Delete packages/webkit/src/components/inputs/switch/package.json --------- Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * feat: add input-number component (#654) * feat: add input-number component Spec-driven monolithic input for numeric values (counts, quantities, ports, thresholds) with small/medium/large sizes, configurable min/max/step, optional spinner column, prefix/suffix slots, and a lock indicator in the disabled state. Visual states (hover/focus-within/invalid/required/disabled) match the input-text v2 pattern: border-color hover gated by :not(:focus-within), focus-within ring with offset, --danger-border for invalid, --warning-border for required. modelValue is always numeric — clearing the native input falls back to min ?? 0. Adds Event/HTMLInputElement to the shared eslint globals so future components using native DOM types lint clean. * fix: align input-number subpath export and imports * fix: remove undefined defaults and align story namespace * fix: keep min/max defaults as undefined to satisfy vue-tsc * choreDelete packages/webkit/src/components/inputs/input-number/package.json * docs: type min/max as number | undefined in input-number spec --------- Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * [ENG-46315] feat(webkit): add Toast (feedback) (#668) * [ENG-46315] feat(webkit): add Toast (feedback) Composable Toast (Toaster + toast store + toast-item/title/description/action/close sub-components). Story under stories/components/feedback/toast with Components/Feedback/Toast title; flat exports (@aziontech/webkit/toast, /toast-item, ...). 'Show code' SFC-detector regex is case-insensitive (/i). * [ENG-46315] fix(webkit): reconcile Toast spec and stories with implementation - spec: max default undefined→3 and accurate overflow wording (toasts queue behind, not dropped) - spec/state: data-expand→data-expanded to match the rendered attribute name - title typography token .text-body-xs→.text-label-sm (drops the raw font-medium weight utility) - stories: now Default/Types/WithDescription/WithAction/Positions per the spec (removed Stacking) * chore: Delete packages/webkit/src/components/feedback/toast/toast-action/package.json * chore: Delete packages/webkit/src/components/feedback/toast/toast-close/package.json * chore: Delete packages/webkit/src/components/feedback/toast/package.json * chore: Delete packages/webkit/src/components/feedback/toast/toast-title/package.json * chore: Delete packages/webkit/src/components/feedback/toast/toast-item/package.json * chore: Delete packages/webkit/src/components/feedback/toast/toast-description/package.json * [ENG-46315] refactor(webkit): drive Toast motion from foundation animation tokens --------- Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * [NO-ISSUE] chore: add audit-fix skill for pnpm audit remediation (#689) * [NO-ISSUE] chore: bump pnpm to 10.34.4 to clear high-severity audit advisories (#690) * [NO-ISSUE] chore: bump pnpm to 10.34.4 to clear high-severity audit advisories * fix: pnpm 11.9.0 * Fix/checkbox glitch (#669) * fix(webkit): stop checkbox jumping vertically on toggle The inputs/checkbox root is `inline-flex` with the default `vertical-align: baseline`. While unchecked it has no in-flow children (the native input is `absolute`), so its baseline resolves to the box's bottom edge; on check, the `v-if` SVG becomes an in-flow flex child and the baseline jumps to the icon, shifting the whole control down ~3px on the line. Adding `align-middle` makes vertical placement independent of content, so the box stays put across checked/unchecked. No effect in flex layouts (e.g. the Disabled story), where vertical-align is ignored. * refactor(webkit): bring checkbox into spec conformance, keep jump fix Re-authored .specs/checkbox.md from the real component (props/events/ slots/tokens/a11y now match what ships) and re-approved it (spec_version 3, fresh checksum) — the previous spec had drifted and its checksum no longer validated. Rewrote inputs/checkbox/checkbox.vue to the canonical styling pattern the spec's Constraints require: all utilities inline on the root with data-* driven variants, dropping the JS class presets (sharedClasses / checkedClasses / disabledClasses / iconClasses / rootClasses computed) and the interactive-states preset import. Behavior, tokens, and the align-middle fix for the on-toggle vertical jump are preserved; verified in Storybook (box top identical checked vs unchecked) and lint/spec compliance pass. * docs(storybook): rebuild checkbox story per storybook-write spec Rewrite Webkit/Inputs/Checkbox to the canonical story shape: inject the spec's Purpose + ## Usage block into docs.description.component, declare argTypes for every spec prop/event (grouped by table.category), and add a reactive v-model Template (local ref synced from args.modelValue, forwards update:modelValue so the field toggles and the Actions panel logs). Stories limited to the spec's list — Default + a Disabled composite showing the checked and unchecked states. No Figma refs, no argTypesRegex, no legacy .args form. * fix(checkbox): align usage import with dev export consolidation Merging dev removed the ./inputs/checkbox export and repointed ./checkbox at the webkit checkbox component (the old PrimeVue checkbox was deleted in dev's cleanup). The 3-way merge already corrected the story's actual import and title to dev's conventions; this fixes the two remaining string references — the embedded Usage snippet in the story's docs and the spec's Usage block — to @aziontech/webkit/checkbox, and refreshes the spec checksum. * style(storybook): sort checkbox story imports, fix title indent * docs(checkbox): address review — type tabindex as number | undefined Per Robson's review on .specs/checkbox.md: make the optional tabindex type explicit as `number | undefined` (escaped pipe so the markdown table cell renders correctly), and mirror it in the story argType summary. The other points he raised (value typed as any, quoted 'undefined' string defaults) were already resolved by the spec_version 3 rewrite — value/modelValue are `unknown` with unquoted `undefined` defaults. Refreshes the spec checksum. --------- Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * [ENG-46312] feat(webkit): add Divider (layout) (#678) * [ENG-46312] feat(webkit): add Divider (layout) * [ENG-46312] fix(webkit): align Divider with dev and make Show code runnable - drop per-component package.json (matches #684; exports point at the .vue) - access default slot via slots['default'] to fix TS4111 under current tooling - escape the Props-table union pipe and recompute the spec checksum - migrate the story to the runnable Show code pattern (PascalCase tag, single <script setup> + <template>, prose lead, source.transform + sourceState) * [ENG-46312] fix(webkit): Divider Show code via explicit source.code (no dynamic) * [ENG-46312] fix(webkit): reactive Divider stories + labelled examples --------- Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * [NO-ISSUE] docs: add standalone root export rule for composition components (#691) * [NO-ISSUE] feat(webkit): add tree-shakeable root and select sub-component exports (#692) * feat: add indeterminate state to Checkbox and align with Figma (#675) * feat: add indeterminate state to Checkbox and align with Figma 2027:7311 - new `indeterminate` prop renders a horizontal-bar visual and sets `aria-checked="mixed"` plus the native `input.indeterminate` DOM property - `data-state` exposes `unchecked | checked | indeterminate` on the root - swap `--shape-button` for `--shape-elements` (same value, vocabulary aligned with Select/MultiSelect and the Figma frame) - adopt the Figma `0.8px` border via `border-[0.8px]` until `--border-width-default` lands in DESIGN.md - new Storybook story `Indeterminate`; all stories now bind `args` so the controls panel actually drives the component - spec bumped to v3 with the new prop, state, and theme gap entry * chore: default checkbox inputId and name to empty string * chore: align checkbox spec defaults with implementation * chore: default checkbox tabindex to 0 * chore(storybook): enforce runnable "Show code" SFC via shared helper (#688) * chore(storybook): enforce runnable "Show code" SFC via shared helper The Docs "Show code" panel emitted snippets that could not be pasted and run: Storybook's dynamic Vue source lowercases the tag (`<skeleton>` instead of `<Skeleton>`) and a naive transform wrapped it in a nested `<template>`. The snippet must express 100% of the canvas and run as-is in a consumer app. - add apps/storybook/src/stories/_shared/story-source.js (toSfc, sfcTransform, runnableDocs): one sanctioned way to emit a single runnable PascalCase SFC; the transform unwraps the stray <template> and restores PascalCase tags - add .claude/rules/storybook-source.md: the well-defined rule - add .claude/hooks/validate-story-source.mjs (registered PreToolUse): blocks hand-rolled transforms, lowercase/kebab tags, nested <template>, and new stories that bypass the helper; only newly introduced violations block - update storybook-write skill + COMPONENT_REQUIREMENTS to mandate the helper - migrate Skeleton, Badge, Chip stories to runnableDocs / toSfc - cover the hook with tests in .claude/hooks/__tests__/run.mjs * fix(storybook): make "Show code" explicit source.code, drop dynamic source Root cause of the broken/inconsistent "Show code": Storybook's dynamic Vue source emits the tag from the .vue file name (skeleton.vue -> <skeleton>, chips.vue -> <chips>, not the PascalCase import), double-wraps <template>, and when `parameters.docs` is a function call it prints the raw CSF story object instead of the snippet. - story-source.js: reduce to a single `toSfc(imports, body)` SFC builder; drop the dynamic `sfcTransform` / `runnableDocs` path entirely - every story now declares an explicit `parameters.docs.source.code = toSfc(...)` with PascalCase tags; `parameters.docs` stays a plain object literal - Skeleton, Badge, Chip migrated to the explicit pattern (Chip <chips> fixed) - rule, skill, COMPONENT_REQUIREMENTS rewritten to the explicit pattern - hook now blocks: docs-as-function-call, any source.transform, lowercase/kebab tag, nested <template>, and (new files) missing toSfc / sourceState - hook tests updated * fix(webkit): rename Chips -> Chip (singular) and guard naming consistency The component shipped plural on every surface (chips.vue, ./chips, name 'Chips', testid input-chips) but the story imported it singular (`import Chip from '@aziontech/webkit/chips'`). A component must have ONE name across all surfaces. - rename to singular `chip`: folder/file, export ./chip, defineOptions name 'Chip', data-testid 'input-chip', spec chip.md (name + checksum), story import - new guardrail in validate-story-source.mjs: a story import binding must equal PascalCase(export subpath) — blocks `import Chip from '.../chips'` - .claude/rules/naming.md: the single-source-of-truth invariant (one kebab name -> spec, file, export, defineOptions, testid, story binding) and what enforces each surface (validate-spec-compliance for internals, validate-story-source for the story binding) - hook test for the binding mismatch --------- Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * feat: add MultiSelect composition (#677) * feat: add MultiSelect composition New `inputs/multi-select` composition aligned with Figma `3899:29362`: - root `MultiSelect` plus four sub-components — `MultiSelectTrigger`, `MultiSelectContent`, `MultiSelectGroup`, `MultiSelectOption` - multi-only API: no `multiple` prop, `modelValue: unknown[]` defaulting to `[]`, `displayValue: (value: unknown[]) => string` - option indicator is the existing `Checkbox` component (decorative, `aria-hidden`, `tabindex=-1`); semantics live on `role=option` + `aria-selected` - panel is `role=listbox` with `aria-multiselectable=true`; Enter / Space toggles without closing, Escape and Tab close - popover rendered via native primitives only — `<Teleport>` to body plus `getBoundingClientRect` + fixed positioning + `popup-scale-in/out` semantic animations (no `floating-ui` runtime) - `#search` and `#footer` slots on `<MultiSelectContent>` are optional and ungated by props - styling sits inline on each root `class` with `data-*` variants, in line with `.claude/rules/styling.md` - Storybook: Default, Sizes, WithGroups, WithSearchAndFooter, WithOptionExtras, LongList, Filled, Invalid, Disabled — every story binds `args` so controls drive the component - five new webkit exports: `./multi-select`, `./multi-select-trigger`, `./multi-select-content`, `./multi-select-group`, `./multi-select-option` * chore: Delete packages/webkit/src/components/inputs/multi-select/multi-select-content/package.json * chore: Delete packages/webkit/src/components/inputs/multi-select/multi-select-group/package.json * chore: Delete packages/webkit/src/components/inputs/multi-select/multi-select-option/package.json * chore: Delete packages/webkit/src/components/inputs/multi-select/multi-select-trigger/package.json * chore: Delete packages/webkit/src/components/inputs/multi-select/package.json * chore: add multi-select-root export --------- Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> Co-authored-by: Robson Júnior <robson.ga.junior@gmail.com> * [ENG-46087] feat(webkit): replace data-table with composable Table + Paginator (#667) * [ENG-46087] feat(webkit): replace data-table with composable Table + Paginator Headless, composable Table (TanStack-backed data-driven mode) + Paginator with their sub-components, replacing the monolithic data-table. Stories under stories/components/data with Components/Data/* titles; flat exports (@aziontech/webkit/table, /paginator, ...). Shared rule/doc updates (compound-api, dependencies exception, _template, component-scaffold) ship in a companion docs PR. * [ENG-46087] fix(webkit): move story-only row-action/cell-click out of Table autodocs events these are slot-driven story interactions, not component emits; recategorized so the autodocs Events tab lists only the real emits (update:* and row-click). * [ENG-46087] chore(webkit): drop per-component package.json for table/paginator Align table + paginator with the compound-api rule and the dev convention (per-component package.json removed repo-wide): the root packages/webkit/package.json#exports already points each public path at its source file, so the per-folder package.json files were never consulted. Update .specs/table.md and .specs/paginator.md anatomy to match (no per-component package.json; .d.ts generated at publish), fix the export paths to the flat form, and recompute the approved-spec checksums. * [ENG-46087] docs(webkit): drop toolbar band from Table story The toolbar/filters demo imported a removable chip component that is not yet available on this branch; remove the toolbar machinery (FullExample story, FULL_TOOLBAR/SOURCE_TOOLBAR, the toolbar params, and the now-unused Chip + Table.Search imports) so the Table stories render. The component still exposes the title/toolbar/filters slots — only the story demo is deferred until chips lands. * chore: add table-root export --------- Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> Co-authored-by: Robson Júnior <robson.ga.junior@gmail.com> * [ENG-46317] feat(webkit): add Calendar component (#672) * [ENG-46317] feat(webkit): add Calendar component * chore: Delete packages/webkit/src/components/inputs/calendar/package.json * [ENG-46317] docs(webkit): type calendar min and max props as Date | undefined --------- Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * feat: align radio layout and add unchecked hover state (#676) - RadioButton: on hover (when not checked) the border switches to `var(--primary)` to mirror the checked affordance, and the ghost-overlay is hidden so the color isn't muddied - RadioButton: keep the inner dot via `data-[checked]:after`; drop the pseudo `before` override that hid it - FieldRadio + FieldRadioBlock: render the control before the label/description block so the indicator stays on the leading edge, matching Checkbox-driven fields and the Figma layout Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * [NO-ISSUE] feat: adding theme premium linear shimmer for Skeleton (#686) * [NO-ISSUE] feat(theme): add shimmer animation preset + keyframes * [NO-ISSUE] feat(webkit): premium linear shimmer for Skeleton --------- Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * [ENG-46485] feat(webkit): add ProgressBar (feedback) (#687) * fix: run required check to dev opened pull requests * [ENG-46485] feat(theme): add progress-indeterminate animation utilities * [ENG-46485] feat(webkit): add ProgressBar (feedback) * chore: Delete packages/webkit/src/components/feedback/progress-bar/package.json --------- Co-authored-by: Robson Júnior <robson.ga.junior@gmail.com> Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * [NO-ISSUE] style(theme): alias typography tokens and set 6xl to 56px (#694) * [NO-ISSUE] style(theme): alias typography tokens and set 6xl to 56px * [NO-ISSUE] style(theme): set tag text weight to normal * [NO-ISSUE] style(theme): restore tag text weight to semibold * [NO-ISSUE] feat!: replace input dropdown and overlay dropdown-menu with navigation dropdown (#685) * [NO-ISSUE] feat!: replace input dropdown and overlay dropdown-menu with navigation dropdown The monolithic `inputs/dropdown` field and the `overlay/dropdown-menu` composition are removed. A new compound `Dropdown` lives in `navigation/dropdown/` and is the single component published under `@aziontech/webkit/dropdown`. Anatomy: `<Dropdown>` (root, owns open/closed + positioning + keyboard nav) > `<Dropdown.Trigger>` (abstract slot) + `<Dropdown.Group>` (auto-divider between groups) + `<Dropdown.Option>` (value/label/command/disabled/selected). Spec at `.specs/dropdown.md` (spec_version 2, structure composition). Production consumers updated in the same PR: `data-table-filter.vue` swapped to `@aziontech/webkit/select`; `data-table-row-actions.vue` and `breadcrumb.vue` migrated to the new compound API. Storybook: `Sidebar.stories` and `DataTable.stories` rewritten; legacy `inputs/Dropdown.stories.js` and `overlay/DropdownMenu.stories.js` deleted. BREAKING CHANGE: `@aziontech/webkit/dropdown` no longer exports the legacy input field — migrate to `@aziontech/webkit/select`. All `@aziontech/webkit/dropdown-menu*` exports are removed — migrate to the new compound `Dropdown` (`<Dropdown.Trigger>`, `<Dropdown.Group>`, `<Dropdown.Option>`). `.specs/dropdown-menu.md` is removed. * fix: dropdown trigger now opens the panel; group teleports into open panel The root template rendered the default slot twice — once inline and once inside the teleported panel — which mounted DropdownTrigger and DropdownGroup twice and clobbered triggerRef. The trigger appeared to ignore clicks because the second instance kept overwriting state. Render the slot once inline (so the trigger is always visible and clickable). Add panelBodyRef to the context; DropdownGroup now self-teleports its content into the panel body when ctx.isOpen flips true, and renders nothing when closed. * fix: register dropdown sub-components explicitly in stories Vue's runtime template compiler (used by Storybook string templates) does not resolve dot-notation sub-components like `<Dropdown.Trigger>` reliably — the parent lookup only finds the root `Dropdown` and the trigger never mounted. Register `DropdownTrigger`, `DropdownGroup`, `DropdownOption` as standalone components in each story and use the kebab-element form (matches the Select stories pattern). * docs: add Placements, OptionAffordances, WithTopAndBottomSlots, CustomTriggers, Playground stories Expands Dropdown's autodocs coverage from 4 stories (Default, Groups, States, Disabled) to 9. Each new story exercises a public API surface that the existing set didn't cover — placement axis, option affordances (command + leading + trailing slots), root top/bottom slots, abstract trigger variations, and a controls-driven playground. Spec Stories section updated with inline justifications per the Constraints rule. * [NO-ISSUE] fix: dropdown applies positioning and focus on initial open * feat: dropdown gains auto placement, functional command shortcuts and left/right option slots - Rename DropdownOption slots from leading/trailing to left/right. - Make the command hint functional via a window-level keydown listener registered while the panel is open. - Add placement='auto' that picks the best-fitting corner via the shared use-placement composable. - Extract use-placement and adopt it in tooltip; expose it as @aziontech/webkit/use-placement. - Storybook: replace Open menu Button with an IconButton plus trigger, drop the Disabled story, add AutoPlacement. - Sync .specs/dropdown.md (slots, command behavior, placement type, data-placement split, AutoPlacement story) and refresh checksum. * fix: migrate Table row-action menu to navigation/dropdown The Table.stories row-action menu still imported the removed overlay dropdown-menu, breaking the Storybook build. Rewrite the cell-actions slot (and its source snippet) to use the new navigation Dropdown compound, with two groups providing the divider before Delete. * chore: Delete packages/webkit/src/components/navigation/dropdown/package.json * chore: Delete packages/webkit/src/components/navigation/dropdown/dropdown-trigger/package.json * chore: Delete packages/webkit/src/components/navigation/dropdown/dropdown-group/package.json * chore: Delete packages/webkit/src/components/navigation/dropdown/dropdown-option/package.json --------- Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * [ENG-46315] refactor(webkit): align Toast UI with Figma using design tokens (#698) Refine the Toast component to match the Figma design, using design tokens only for typography and spacing: - severity icons (pi-check / pi-exclamation-circle) sized via text-label-md - loading spinner 16px and centered; typed icons self-start to align with the title - border-width-default, shadow-sm, shape-elements, label-md / body-xs typography - closable prop, onClose option, and functional duration - stories: two-line Types, Closable, and action logging Co-authored-by: Isaque Böck <isaquebockdos@gmail.com> * feat: log view component with spect updating with "code" category (#699) * feat: log view component with spect updating with "code" category * fix: item type-check and items export * fix: .specs/deploy-success.md list defult value * fix: clean aschild merge * [NO-ISSUE] style(webkit): reduce breadcrumb-item height and label size (#700) Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * [ENG-46316] feat(webkit): add PickList (data) (#680) * [ENG-46316] feat(webkit): add PickList (data) * [ENG-46316] refactor(webkit): replace PickList control icons with inline SVG arrows * [ENG-46316] chore(webkit): drop per-component package.json for pick-list Apply the compound-api rule / dev convention (per-component package.json removed repo-wide): the root packages/webkit/package.json#exports already points ./pick-list at the source .vue, so the per-folder package.json was never consulted. * [ENG-46316] feat(webkit): add loading state to PickList Add a `loading` prop (boolean | 'source' | 'target') that swaps a list's items for a centered Spinner and locks the move/reorder controls while data loads: `true` loads both lists, 'source'/'target' only that side. A loading list sets aria-busy; the Spinner is aria-hidden and inherits --text-muted. The two lists stack on narrow viewports (controls become a horizontal row). Also brings the story to the runnable "Show code" standard (explicit docs.source.code per story + canvas.sourceState: 'shown'; drop the embedded ## Usage block) and refreshes the approved-spec checksum. * refactor(webkit): reshape PickList into compound composition API Re-architect PickList from a monolithic component into the composition (compound) pattern, matching Table/Select/Flow: - root <PickList> owns the bound [source, target] pair and the shared selection/move/reorder state, provided via provide/inject - new sub-components composed by the consumer: <PickList.Source>, <PickList.Target>, and the context-aware <PickList.Controls> (no props) - per-list header/loading/reorderable move onto Source/Target - index.ts Object.assign compound; exports add ./pick-list (index.ts), ./pick-list-root, ./pick-list-source, ./pick-list-target, ./pick-list-controls - spec re-authored to structure=composition (spec_version 2), story rewritten to the dot-notation API with toSfc Show code * fix(webkit): refine PickList per review (reorder, double-click, mobile arrows, motion) - remove the reorder feature (prop, event, controls, story) — it rendered a broken control row and was not requested - add double-click-to-move: `item-double-click` event + single-item move to the opposite list, cancellable via the `moveOnDoubleClick` prop (default true) - fix the move-button arrow directions on mobile: rotate to up/down when the lists stack vertically (left/right when side by side) — addresses PR review - lock both the move controls and double-click while any list is loading - animate item transfer with a TransitionGroup opacity fade, driven by an inline transition from the `duration`/`curve` primitives in @aziontech/theme/animations (presets/transitions.ts, mirroring message/toast) - spec updated to match; checksum recomputed * feat(webkit): expose PickList move actions for custom controls Let consumers replace <PickList.Controls> with their own buttons, two ways: - default-slot scope { move, moveAll, hasSelection, count, disabled, loading } for controls rendered inside the root (<PickList v-slot="{ move }">) - defineExpose({ move, moveAll, hasSelection, count }) so controls rendered outside the root drive it through a template ref (<PickList ref="pl" />) Both reuse the same move actions + internal selection — no context import. Adds a CustomControls story (external buttons via ref); spec documents the slot scope + exposed methods; checksum recomputed. * docs(webkit): document PickList custom-controls capability without story/example Per review: keep the slot-scope + defineExpose API (so consumers can replace <PickList.Controls>), but drop the CustomControls story and the code example in the spec — the possibility is documented via the Slots scope + the exposed-method note only. Checksum recomputed. --------- Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * [ENG-46312] style(webkit): align Divider label to Figma overline typography and spacing (#695) Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * [ENG-46487] feat(webkit): add Flow (data) (#682) * feat(flow): add Flow component (ENG-46487) * [ENG-46487] feat(webkit): reshape Flow to compound API with custom nodes and anchors Reshape the (unreleased) Flow component to a compound, slot-driven API: - Public API is dot-notation now: import Flow and use Flow.Node / Flow.Parallel / Flow.Anchor. index.ts attaches them and is the single ./flow export (mirrors the select pattern). - Nodes are direct children of Flow; remove the FlowList wrapper. - flow-node gains an unstyled prop so the slot content defines the node (start dot, taller node, multi-row card); the default box is gated behind data-styled. - flow-anchor wraps real content and marks where connectors attach (type end = incoming endpoint, type start = outgoing origin). - Connector geometry is centralized in the root: one SVG draws every connector, so a leading/trailing flow-parallel fans in/out with no dangling stubs. - Stories and spec updated to the new API; subcomponent autodocs tables populated via explicit docgen info. --------- Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * [NO-ISSUE] feat(webkit): add CodeBlock component (#702) * feat(webkit): add CodeEditor component with syntax theme tokens Introduces a read-only tabbed code viewer with syntax highlighting, Storybook stories, component spec, and semantic label-code typography plus code-sintax theme variables for light and dark modes. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(code-editor): add line decoration and file icon utilities Extract diff/highlight line state helpers and language-to-icon resolution for the v2 CodeEditor layouts. * docs(code-editor): update spec to v4 with layouts and devx usage Document filename bar, diff, highlighted line, ScrollArea scrolling, animateLines, and tabs[].code passing patterns. * feat(code-editor): implement v2 layouts, scroll, motion, and responsive lines Add filename bar, diff/highlight decorations, ScrollArea with pinned copy, line hover, animateLines stagger, and nowrap horizontal scroll on small viewports. * docs(code-editor): expand Storybook stories and passing-code docs Add diff, highlight, and animated line stories plus DevX documentation for tabs[].code usage patterns. * [NO-ISSUE] refactor(webkit): rename CodeEditor to CodeBlock Rename component, spec, export path, and Storybook stories under Components/Code. * [NO-ISSUE] docs: document CodeBlock tokens in DESIGN.md Add code typography, syntax colors, surface-raised, and feedback border tokens. * [NO-ISSUE] docs(webkit): align CodeBlock stories with storybook-source rule Give every story an explicit source.code via toSfc, add canvas.sourceState, and replace the duplicated Usage block with a short Purpose lead. Remove the stray per-component package.json (exports resolve to the .vue). --------- Co-authored-by: gablisboa <gablisboa1@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Herbert Vicente Cotta Julio <herbert.julio@azion.com> * feat: adding CopyButton component, storybook storie (#708) * [NO-ISSUE] chore: add /include-icons command (#697) Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> Co-authored-by: Herbert Vicente Cotta Julio <herbert.julio@azion.com> * [NO-ISSUE] refactor(webkit): use CopyButton in CodeBlock (#713) - data/code-block: replace the hand-rolled copy IconButton (+ copyFeedback/copyActiveCode clipboard logic) with the shared CopyButton, keeping it pinned top-right on the content shell; public API (copy event, copyAriaLabel) unchanged. - Storybook foundation CodeBlock: add a CopyButton (top-right) that copies the content prop or slotted code text. - Update .specs/code-block.md prose (IconButton -> CopyButton, 28x28px note) with recomputed checksum. * [NO-ISSUE] feat(webkit): add loading variant to LogView (#712) - Add `loading` + `loadingLabel` props; LogViewContent shows a centered Spinner + label (role=status) in place of the log body. - Relocate the copy control to a floating CopyButton pinned top-right over the content (was an IconButton in the header); context exposes copyText/emitCopy. - Simplify header search to InputText size=small with the search icon in the iconLeft slot (removes wrapper + hardcoded classes). - Update .specs/log-view.md (checksum) and add a Loading story. Co-authored-by: Herbert Vicente Cotta Julio <herbert.julio@azion.com> * [NO-ISSUE] feat(webkit): add Popover (overlay) (#711) Co-authored-by: Herbert Vicente Cotta Julio <herbert.julio@azion.com> * [NO-ISSUE] refactor(webkit)!: remove empty-results-block in favor of empty-state (#714) Removes the legacy EmptyResultsBlock component, its `@aziontech/webkit/empty-results-block` export, and its Storybook story. The EmptyState component (`@aziontech/webkit/empty-state`) is the replacement and already ships its own story. Adds EmptyState to the Storybook README Feedback list. BREAKING CHANGE: the `@aziontech/webkit/empty-results-block` export was removed. Migrate to `@aziontech/webkit/empty-state` (the EmptyState component). Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * [NO-ISSUE] fix(webkit): apply loading as a disabled visual state with distinct cursors (#715) * [NO-ISSUE] fix(webkit): apply loading as a disabled visual state with distinct cursors * [NO-ISSUE] fix(webkit): use cursor-wait for the button loading state --------- Co-authored-by: Herbert Vicente Cotta Julio <herbert.julio@azion.com> * [NO-ISSUE] feat(icons): add colored brand icons (ai-*-cor) via CSS classes + inline-SVG catalog (#696) * [NO-ISSUE] feat(icons): add colored brand icons (ai-*-cor) via CSS classes + inline-SVG catalog * [NO-ISSUE] feat(icons-gallery): render colored brand icons inline * [NO-ISSUE] feat(storybook): show colored icons in Foundations/Icons gallery * [NO-ISSUE] feat(webkit): use colored Google logo in sign-up-card social button * [NO-ISSUE] chore: migrate jsconfig off deprecated TS 6.0 options * chore: build.mjs ajudsts colored pr review * chore: icons doc updating colored icons * fix: class .ai-cor.ai-[icon-name] generation * fix: ai ai-google-cor to ai-cor ai-google --------- Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> Co-authored-by: Robson Júnior <robson.ga.junior@gmail.com> * [ENG-46318] feat(webkit): add SplitButton (actions) (#681) * feat(webkit): add split-button composing navigation dropdown Rebuild the actions/split-button component from scratch on top of dev: a primary command button joined to a chevron toggle that opens the navigation Dropdown overlay with the model-driven action rows. Replaces the prior implementation that depended on the removed overlay/dropdown-menu. 3 kinds (primary/secondary/outlined) x 3 sizes per Figma node 477:957. * fix(webkit): keep dropdown content mounted during close animation * feat(webkit): add updateLabelOnSelect option to split-button * feat(webkit): emit the active item in split-button click payload * [ENG-46318] refactor(webkit): compose Button and IconButton in SplitButton --------- Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> Co-authored-by: Isaque Böck <isaquebockdos@gmail.com> * [ENG-46310] feat(webkit): add clickable prop and click event to Chip (#705) * [ENG-46310] feat(webkit): add clickable prop and click event to Chip * [ENG-46310] fix(webkit): align chip active state and sizing with Figma --------- Co-authored-by: Isaque Böck <isaquebockdos@gmail.com> * [NO-ISSUE] refactor: replace Label Required tag with inline * (Required) indicator (#710) * [NO-ISSUE] refactor: replace Label Required tag with inline *Required indicator The Required tag (severity=warning size=small) is replaced by inline text 'asterisk + Required', where the asterisk uses var(--primary) (orange F3652B) and the word Required uses var(--text-muted). The asterisk is decorative (aria-hidden=true) so screen readers announce only 'Required' alongside the label text. Applies uniformly across every consumer of Label with required=true: field-text, field-password, field-input-group, field-checkbox, field-radio, field-switch, field-textarea. Tag component is no longer imported by label.vue. Spec body updated (Purpose, Props JSDoc, Tokens, Accessibility); checksum refreshed to e261b72f (also fixes a pre-existing checksum drift on label.md that the enforce-spec-exists hook flagged when this change tried to write). * [NO-ISSUE] fix: format Label required indicator as * (Required) with parentheses Wrap the required word in parentheses and add a space between the asterisk and the parenthesized text, producing '* (Required)' instead of the previous '*Required'. The asterisk stays orange (var(--primary)) and (Required) stays muted (var(--text-muted)); the * remains aria-hidden so screen readers still announce only '(Required)'. Spec Purpose, Props JSDoc, Tokens, and Accessibility sections updated to match; checksum refreshed. * feat: unify Label across choice fields and add required prop - field-checkbox, field-radio, field-switch now render their label via the shared Label component; outer <label> wrapper switched to <div> to avoid nested <label> HTML - field-checkbox and field-switch gain a `required` prop matching field-text/password/textarea: the Label shows the *(Required) indicator and native/aria-required propagates to the control - Storybook: add Required stories to FieldCheckbox and FieldSwitch and expose the `required` control in argTypes --------- Co-authored-by: Herbert Vicente Cotta Julio <herbert.julio@azion.com> * refactor: rework textarea layout to inline-flex and refresh field-textarea stories (#701) * refactor: rework textarea layout to inline-flex and refresh field-textarea stories Replace absolute-positioned icon slots with an inline-flex row in textarea.vue so left/right icons share spacing tokens with the textarea control and disabled/required/invalid state styles read off data-* on the root wrapper. Filter class and data-testid out of the textarea passthrough attrs to avoid duplicating them on the inner element. Update FieldTextarea stories to use args-driven Template, add Default and Disabled stories, replace the synthetic Required story with a submit-driven async demo, and rewrite the docs description block. * feat: add resizable prop to Textarea and drop icon slots Textarea now accepts `resizable: 'vertical' | 'horizontal' | 'both' | 'none'` (default `vertical`) and no longer exposes `iconLeft` / `iconRight` slots or the hardcoded disabled lock icon. FieldTextarea forwards the new prop to the underlying Textarea for parity. Storybook stories migrated to the mandatory toSfc source pattern. --------- Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * [ENG-46087] feat(webkit): data table (toolbar, filters, animation) + paginator (#706) * [ENG-46087] fix(webkit): table select-all tri-state (page-aware) and header-cell sorting Select-all header checkbox now reflects the current page's selection as a tri-state: checked when all page rows are selected, indeterminate when some are, unchecked when none. Switches to TanStack's page-scoped getIsAllPageRowsSelected / getIsSomePageRowsSelected / toggleAllPageRowsSelected (falls back to the full filtered model when the table is not paginated, so the non-paginated behavior is unchanged). Sorting now triggers from the whole sortable header cell — a pointer click anywhere on it, or Enter/Space while focused — in addition to the sort button. The sort button stops its own click/keydown from bubbling so activating it never double-toggles. Sortable headers are focusable with a focus-visible ring, matching the spec's accessibility intent. * feat(webkit): data table toolbar, filters and load animation Align the data-table toolbar with Figma using existing components: outlined 32px controls, a growing search with a leading icon, the ai-column glyph, p-sm toolbar/filters bands, and medium applied-filter chips. The filter popover now closes on apply and removing a chip no longer reopens the filter; the applied-filters band renders only when there are active filters. Scope the body enter animation to the load then data cycle (fade-only when columns are pinned so sticky columns do not jump under a transform), fade the empty state in, size skeleton rows to the visible page, and drop vertical-scroll overflow when no maxHeight is set. * fix(webkit): make applied-filter chips clickable for edit * [ENG-46087] fix(webkit): paginator icon-only controls and story reactivity - Table footer now renders the Paginator in its data-driven default (icon prev/next, numbers with an overflow ellipsis, info line, page-size selector) instead of hand-composed text buttons. - Paginator prev/next are icon-only (chevron) squared to 40px; the button slot renders only for numbered pages. - Full Example (Table) binds its control args so the Controls panel drives the canvas; register the Paginator dot-notation sub-components so the composition stories render their buttons; rename the Paginator "Data Driven" story to "Full Example". --------- Co-authored-by: Isaque Böck <isaquebockdos@gmail.com> * [ENG-46317] feat(webkit): evolve Calendar into a date-range picker (#707) * [ENG-46317] feat(webkit): evolve Calendar into a date-range picker Replace the inline month grid with a full date-range picker (composition, spec_version 3): a trigger that opens a CSS-positioned popover with a multi-month grid, Start/End date + time fields, a timezone selector, an Apply action, a presets rail, a clearable/split trigger, size variants, a horizontal layout, and a Select Period relative-time mode (parses 45m, last month, 1/1 - 1/2). Native Date + Intl only; no positioning or date libraries. * [ENG-46317] feat(webkit): single-month Calendar with two-part preset + period trigger * [ENG-46317] fix(webkit): stable calendar trigger size + time-aware range label - Fixed-width trigger (container tokens) so selecting or clearing the value never resizes the control; two-part preset trigger gets its own width and the label truncates - Range label shows an endpoint's time when it differs from the default (00:00 start / 23:59 end), e.g. Jun 29, 1:00 - Jul 30, 22:59 - A range spanning exactly one whole calendar month with default times collapses to the month label (July 2026) - Start/End time fields display and hint 24h times (00:00 / 23:59) * style(webkit): apply prettier formatting to calendar format.ts --------- Co-authored-by: Isaque Böck <isaquebockdos@gmail.com> * [NO-ISSUE] fix: resolve all pnpm audit advisories and strengthen the audit gate (#722) * fix: pnpm audit resolutions * chore: package.json adjust security:audit * fix: remove true condition of pnpm audit * fix: update azion@1.20.22 * chore: pnpm audit withou pipe | before run * fix: remove azion lib v3 from package.json (#725) * [NO-ISSUE] fix: resolve prettier format and vue-tsc type-check CI failures (#726) * [ENG-46318] fix(webkit): disable SplitButton menu toggle while loading (#720) Co-authored-by: ROBSON.JUNIOR <robsongajunior@users.noreply.github.com> * [NO-ISSUE] feat: rework InputGroup to composition (PrimeVue-style) with <InputGroup.Addon> (#709) * [NO-ISSUE] feat: add InputGroup composition component with Addon sub-component Implements Figma node 3714-10802. Composition pattern with compound API: InputGroup root + InputGroup.Addon sub-component. States driven by data-invalid / data-required attributes (danger border when invalid alone, warning border when invalid + required). Provides InputGroupContextKey via inject/provide so future input primitives can render borderless inside the group in a follow-up PR. * [NO-ISSUE] refactor: align InputGroup border/focus chrome with input-text pattern Independent invalid/required semantics (invalid -> danger, required -> warning), focus-within ring on the group root, hover border-strong, and transition-colors with motion-reduce fallback. Spec States/Motion/Tokens/ Accessibility sections updated to match; checksum refreshed. * [NO-ISSUE] fix: apply text-label-sm to InputGroup middle input to match addons The stock <input> in the middle slot was rendering at browser default (~16px) while the addons use text-label-sm (12px), producing a size mismatch. Add text-label-sm + placeholder:text-[var(--text-muted)] so the middle input matches both the addons and input-text's inner input font. Spec and stories updated together; checksum refreshed. * [NO-ISSUE] fix: match middle input surface and text color to InputGroup addons The <input> in the middle slot inherited the group's --bg-surface and used --text-default, making it read visually distinct from the addons (which use --bg-canvas and --text-muted). Align both so left addon, middle input, and right addon share the same dark fill and muted text — one continuous surfa…
1 parent fd67354 commit 9bf2779

3,372 files changed

Lines changed: 109791 additions & 65562 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/AGENTS.md

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ pnpm storybook:dev
4242
pnpm storybook:build
4343
pnpm storybook:preview
4444
pnpm icons:build
45-
pnpm webkit:build:dts
4645
```
4746

4847
## 4) Where to change what
@@ -96,10 +95,7 @@ Run the minimum relevant validations for the scope of your change.
9695
- `pnpm webkit:lint`
9796
- `pnpm webkit:type-check`
9897
- `pnpm webkit:type-coverage`
99-
- `pnpm webkit:build:dts`
10098
- `pnpm storybook:build`
101-
- Other webkit typings/API surface change:
102-
- `pnpm webkit:build:dts`
10399

104100
If a full validation is too expensive, run targeted checks and document what was/was not validated.
105101

@@ -153,7 +149,7 @@ The legacy monolithic skill `skills/component-create.md` has been **removed**. N
153149
| Focused skills (one per phase) | [`.claude/skills/`](.claude/skills/)`spec-create`, `spec-validate`, `figma-discover`, `token-map`, `reuse-audit`, `structure-decide`, `component-scaffold`, `storybook-write`, `code-connect-write`, `validate-component`, `echo-report` |
154150
| Isolated sub-agent prompts | [`.claude/agents/`](.claude/agents/) — one per skill, no chat history, no cross-talk |
155151
| Immutable rules (injected verbatim) | [`.claude/rules/`](.claude/rules/)`no-invention`, `migration`, `dependencies` |
156-
| Centralized design docs (sources of truth) | [`.claude/docs/`](.claude/docs/)`DESIGN.md` (tokens + animations + forbidden list), `COMPONENT_REQUIREMENTS.md` (component pattern + Storybook discipline), `PRIMEVUE_ABSTRACTION.md` |
152+
| Centralized design docs (sources of truth) | [`.claude/docs/`](.claude/docs/)`DESIGN.md` (tokens + animations + forbidden list), `COMPONENT_REQUIREMENTS.md` (component pattern + Storybook discipline) |
157153
| Run logs (audit trail) | [`.claude/logs/<run-id>.jsonl`](.claude/logs/) |
158154

159155
**How `/component-create` runs:**
@@ -166,7 +162,7 @@ The legacy monolithic skill `skills/component-create.md` has been **removed**. N
166162
6. **storybook-writer** — minimal stories only (Default + per kind + per size + Disabled).
167163
7. **code-connect-writer** — skips if `@figma/code-connect` missing.
168164
8. **echo-reporter** (cross-check) — independent parser; disagreement with the hook marks the run degraded.
169-
9. **validate-component**`pnpm webkit:lint && type-check && type-coverage && build:dts && storybook:build`.
165+
9. **validate-component**`pnpm webkit:lint && type-check && type-coverage && storybook:build`.
170166
10. **Finalize**`status: approved → implemented`, refresh checksum, close log.
171167

172168
**Why this is mandatory:** the previous workflow gave a single 749-line skill creative latitude — it sometimes added props, variants, or imports the user did not request. The new pipeline removes that latitude structurally: sub-agents see only the spec + their narrow rules; two hooks (`enforce-spec-exists`, `validate-spec-compliance`) verify the `.vue` matches the spec 1-to-1.
@@ -195,7 +191,7 @@ The trigger logic now lives in the orchestrator command [`.claude/commands/compo
195191
- New components use `<script setup lang="ts">` with `defineProps<...>()`, `defineEmits<...>()`, `defineSlots<...>()` and `defineModel<...>()` where applicable. JSDoc on every public prop. Zero `any`. Zero `// @ts-ignore`.
196192
- Variants are always exposed as `kind`. Sizes as `size` (`'small' | 'medium' | 'large'`). Boolean state props have no `is`/`has` prefix.
197193
- Typography is **always** applied via the generated class from DESIGN.md (`text-heading-md`, `text-body-sm`, etc.). Never `text-[length:var(--text-*)]`, `leading-*`, `tracking-*`, or `font-family` directly.
198-
- Colors, spacing, max-width, and shape come from semantic `var(--*)` tokens. No hex, no Tailwind palette names (`bg-gray-*`), no PrimeVue color utilities (`text-color`, `surface-*`).
194+
- Colors, spacing, max-width, and shape come from semantic `var(--*)` tokens. No hex, no Tailwind palette names (`bg-gray-*`), no external/legacy color utilities (`text-color`, `surface-*`).
199195
- `defineOptions({ name, inheritAttrs: false })` + `useAttrs()` + `rootClasses` that merges `attrs.class`. Never declare `class` in `defineProps`.
200196
- `data-testid` hierarchical, BEM-style: root with fallback `'<category>-<name>'`, children with `${testId}__<part>` (two underscores).
201197
- Composition Pattern only when the consumer needs to swap the order or omit parts (Dialog, Card composto, Tabs, Accordion, DropdownMenu, Sheet/Drawer, Form). When in doubt, stay monolithic. When applying it, ship the complete shadcn-vue anatomy (e.g. Dialog = Root + Trigger + Portal + Overlay + Content + Title + Description + Close).
@@ -216,7 +212,6 @@ Uses Storybook features fully: `argTypes` (with `control`, `description`, `table
216212
pnpm webkit:lint
217213
pnpm webkit:type-check
218214
pnpm webkit:type-coverage
219-
pnpm webkit:build:dts
220215
pnpm storybook:build
221216
```
222217

@@ -226,7 +221,7 @@ pnpm storybook:build
226221
- Adding hex colors, raw typography classes, or Tailwind palette names "until the theme catches up". Register a theme gap with `TODO: tokenizar` instead.
227222
- Applying Composition Pattern reflexively. Use the decision rule: "does the consumer need to swap order or omit parts?"
228223
- Removing `focus-visible`, `aria-*`, `data-testid`, `disabled` HTML, or `<a>`/`<button>` polymorphism to simplify code.
229-
- Editing `.claude/docs/DESIGN.md`, `COMPONENT_REQUIREMENTS.md`, or `PRIMEVUE_ABSTRACTION.md` without explicit human approval (these are sources of truth).
224+
- Editing `.claude/docs/DESIGN.md` or `COMPONENT_REQUIREMENTS.md` without explicit human approval (these are sources of truth).
230225

231226
For deeper, package-specific instructions, agents should also read [`packages/webkit/AGENTS.md`](packages/webkit/AGENTS.md) when working inside `packages/webkit/`.
232227

.claude/README.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# `.claude/` — governance system: folder map & index
2+
3+
Everything that makes the design system's standards apply by construction and block off-
4+
standard code. This is the entry-point map; each area links to its own index.
5+
6+
## Folder layout
7+
8+
```
9+
.claude/
10+
├── rules/ # the 23 construction standards (one .md each) — see rules/README.md
11+
│ └── README.md # ↳ index (foundational/construction · general/webkit · enforcer)
12+
├── hooks/ # write-time gates — exit 2 blocks (PreToolUse, except where noted)
13+
│ ├── validate-authoring.mjs # blocks off-standard component authoring
14+
│ ├── validate-spec-compliance.mjs # .vue must match its spec 1:1 (PostToolUse)
15+
│ ├── validate-tokens.mjs # tokens only; no hex/palette/raw typography
16+
│ ├── validate-references.mjs # no phantom imports / forbidden deps
17+
│ ├── validate-story-source.mjs # runnable "Show code"
18+
│ ├── enforce-spec-exists.mjs # no .vue without an approved spec
19+
│ ├── enforce-component-create.mjs # authoring only via the pipeline
20+
│ └── _lib/ # shared, single-source engines
21+
│ ├── standards.mjs # the registry: rule ↔ enforcement + scope (general/webkit)
22+
│ ├── authoring-checks.mjs # construction checks (one of FOUR shared engines: authoring, token, spec, story)
23+
│ ├── prop-vocabulary.mjs # canonical prop dictionary
24+
│ ├── spec.mjs # SFC/spec parsing
25+
│ └── legacy-components.json # grandfather list
26+
├── skills/ # executable playbooks (spec-create, component-scaffold, …)
27+
├── agents/ # isolated sub-agents that run the skills — see agents/_README.md
28+
├── commands/ # orchestrators (/component-create, /open-pr, …)
29+
├── docs/ # internal sources of truth: DESIGN.md, COMPONENT_REQUIREMENTS.md
30+
└── settings.json # hook registration + permissions
31+
32+
packages/webkit/ # the parts of the system that live in the package
33+
├── scripts/check-authoring.mjs # CI ratchet — runs the four shared engines repo-wide
34+
├── scripts/authoring-baseline.json # frozen debt; a new violation fails the PR
35+
├── test/standards/invariant.test.mjs# the meta-check: rule ↔ enforcement can't drift
36+
├── src/eslint-plugin/ # consumer lints (11 rules, all error)
37+
├── src/mcp/ # MCP server (guides the AI to the right usage)
38+
├── docs/GUIDELINES.md # consumer-facing styleguide (build & use)
39+
└── catalog.json # generated manifest read by the lints + MCP
40+
```
41+
42+
## Where each concern lives (index)
43+
44+
| Concern | Path |
45+
|---|---|
46+
| The standards (human) | [`rules/`](./rules/)[`rules/README.md`](./rules/README.md) |
47+
| Standard ↔ enforcement (machine) | [`hooks/_lib/standards.mjs`](./hooks/_lib/standards.mjs) |
48+
| The check engine (hook + ratchet) | [`hooks/_lib/authoring-checks.mjs`](./hooks/_lib/authoring-checks.mjs) |
49+
| Write-time gates | [`hooks/`](./hooks/) |
50+
| CI ratchet + baseline | `packages/webkit/scripts/check-authoring.mjs` · `authoring-baseline.json` |
51+
| The invariant (anti-drift) | `packages/webkit/test/standards/invariant.test.mjs` |
52+
| Consumer lints | `packages/webkit/src/eslint-plugin/rules/*.js` |
53+
| Creation pipeline | [`skills/`](./skills/) · [`agents/`](./agents/) · [`commands/`](./commands/) |
54+
| Tokens (source of truth) | [`docs/DESIGN.md`](./docs/DESIGN.md) |
55+
| Consumer styleguide | `packages/webkit/docs/GUIDELINES.md` |
56+
57+
## The standards flow (single source, no drift)
58+
59+
```
60+
rules/<id>.md ──registered in──► hooks/_lib/standards.mjs ──scope: general|webkit
61+
│ │
62+
│ mechanizable check │ invariant test asserts the pairing
63+
▼ ▼
64+
hooks/_lib/authoring-checks.mjs ──used by──► validate-authoring.mjs (write-time)
65+
└─used by──► scripts/check-authoring.mjs (CI ratchet)
66+
```
67+
68+
One rule, one enforcement, two surfaces — the write-time hook and the CI ratchet run the
69+
**same** engine, and `invariant.test.mjs` fails CI if a rule loses its gate (or vice-versa).
70+
Nothing is advisory: every standard blocks the merge, automatically or by mandatory review.

.claude/agents/_README.md

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,35 +29,48 @@ If anything is ambiguous, emit a `BLOCKED: <reason>` line and write no files.
2929

3030
## Catalog
3131

32-
| Sub-agent | Skill it executes | Reads (rules) | Writes |
33-
|---|---|---|---|
34-
| `spec-author.md` | `spec-create` | tokens, naming, dependencies, migration, storybook | `.specs/<name>.md` (draft) |
35-
| `spec-validator.md` | `spec-validate` | tokens, naming | spec frontmatter only (status, checksum, last_updated) |
36-
| `figma-extractor.md` | `figma-discover` | migration | stdout JSON only |
37-
| `token-mapper.md` | `token-map` | tokens | stdout Markdown only |
38-
| `reuse-auditor.md` | `reuse-audit` | dependencies | stdout JSON only |
39-
| `structure-decider.md` | `structure-decide` | naming | stdout 2 lines only |
40-
| `scaffolder.md` | `component-scaffold` | **no-invention, naming, bem-testid, tokens, accessibility, dependencies, migration** | `<name>.vue`, sub-components, `injection-key.ts`, local `package.json`, root `package.json#exports` |
41-
| `storybook-writer.md` | `storybook-write` | naming, tokens, **storybook**, no-invention | `apps/storybook/src/stories/webkit/<category>/<Name>.stories.js` |
42-
| `code-connect-writer.md` | `code-connect-write` | naming, migration | `<name>.figma.ts` |
43-
| `echo-reporter.md` | `echo-report` | naming, tokens, storybook | stdout report only |
32+
| Sub-agent | Skill it executes | Reads (rules) | Writes |
33+
| ------------------------ | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
34+
| `spec-author.md` | `spec-create` | tokens, naming, dependencies, migration, storybook | `.specs/<name>.md` (draft) |
35+
| `spec-validator.md` | `spec-validate` | tokens, naming | spec frontmatter only (status, checksum, last_updated) |
36+
| `figma-extractor.md` | `figma-discover` | migration | stdout JSON only |
37+
| `token-mapper.md` | `token-map` | tokens | stdout Markdown only |
38+
| `reuse-auditor.md` | `reuse-audit` | dependencies | stdout JSON only |
39+
| `structure-decider.md` | `structure-decide` | naming | stdout 2 lines only |
40+
| `scaffolder.md` | `component-scaffold` | **no-invention, naming, component-structure, props, prop-vocabulary, v-model, emits, event-payloads, slots, composables, root-element, component-states, styling, tokens, accessibility, testid, dependencies, migration** | `<name>.vue`, sub-components, `injection-key.ts`, root `package.json#exports` |
41+
| `storybook-writer.md` | `storybook-write` | naming, tokens, **storybook**, no-invention | `apps/storybook/src/stories/components/<category>/<PascalName>.stories.js` |
42+
| `code-connect-writer.md` | `code-connect-write` | naming, migration | `<name>.figma.ts` |
43+
| `echo-reporter.md` | `echo-report` | naming, tokens, storybook | stdout report only |
4444

4545
## Rules catalog ([.claude/rules/](../rules/))
4646

47-
| File | Purpose |
48-
|---|---|
49-
| `no-invention.md` | The hard prohibitions; the spec is the contract |
50-
| `dependencies.md` | **No external positioning/animation libs.** CSS + Vue primitives only |
51-
| `migration.md` | **Never inherit artifacts as-is.** Rewrite to our conventions |
52-
| `styling.md` | **Classes inline on the root.** No JS class presets, no `<style>` block, variants via `data-*` |
47+
| File | Purpose |
48+
| ------------------------ | -------------------------------------------------------------------------------------------------- |
49+
| `no-invention.md` | The hard prohibitions; the spec is the contract |
50+
| `dependencies.md` | **No external positioning/animation libs.** CSS + Vue primitives only |
51+
| `migration.md` | **Never inherit artifacts as-is.** Rewrite to our conventions |
52+
| `styling.md` | **Classes inline on the root.** No JS class presets, no `<style>` block, variants via `data-*` |
53+
| `component-structure.md` | Fixed folder layout + `<script setup>` section order |
54+
| `props.md` | Typed `interface Props` + `withDefaults` + JSDoc; exported variant unions |
55+
| `prop-vocabulary.md` | One canonical name/type/default per concept (`kind`, `size`, `disabled`…) |
56+
| `v-model.md` | Two-way values via `defineModel` — controlled + uncontrolled, one macro |
57+
| `emits.md` | Typed `defineEmits`, kebab names, model vs. activation |
58+
| `event-payloads.md` | Activation events emit `(event, item)` — DOM event first |
59+
| `slots.md` | Typed `defineSlots`, kebab names, fallback inside the slot |
60+
| `composables.md` | `readonly` outward, `toValue` args, `onScopeDispose` cleanup; context composable |
61+
| `root-element.md` | Own the root: polymorphism via `href`, `$attrs` forwarding, minimal `defineExpose` |
62+
| `component-states.md` | Declared, rendered state surface (loading/empty/error via DS components) |
63+
| `accessibility.md` | Role, keyboard, focus, `motion-reduce` — owned by the component |
64+
| `testid.md` | `data-testid` derived `<category>-<name>` / `input-<name>`, overridable |
65+
| `deprecation.md` | Mark `@deprecated` → one major → remove |
66+
| `bundle-budget.md` | Per-entry budget recorded in `.size-limit.json`; automated CI gate pending — review holds the line |
5367

5468
## Source-of-truth docs ([.claude/docs/](../docs/))
5569

56-
| File | Purpose |
57-
|---|---|
58-
| `DESIGN.md` | Tokens (typography, spacing, container, shape, shadow, colors), animation catalog, forbidden list |
70+
| File | Purpose |
71+
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
72+
| `DESIGN.md` | Tokens (typography, spacing, container, shape, shadow, colors), animation catalog, forbidden list |
5973
| `COMPONENT_REQUIREMENTS.md` | Component pattern: TypeScript, naming, slots, BEM data-testid, ARIA, Composition Pattern, Storybook discipline, Styling discipline |
60-
| `PRIMEVUE_ABSTRACTION.md` | PrimeVue wrapping under `core/primevue/*` |
6174

6275
## Rules every agent file inherits
6376

.claude/agents/code-connect-writer.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
name: code-connect-writer
33
description: Isolated sub-agent that writes the <name>.figma.ts Code Connect mapping next to the .vue. Skips itself when @figma/code-connect is not installed.
44
status: active
5+
scope: webkit
56
---
67

78
# Agent: code-connect-writer

.claude/agents/echo-reporter.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
name: echo-reporter
33
description: Isolated sub-agent that re-reads every file written this run, parses props/events/slots/animations independently, and diffs against the spec. Cross-checks against validate-spec-compliance.mjs.
44
status: active
5+
scope: webkit
56
---
67

78
# Agent: echo-reporter

0 commit comments

Comments
 (0)