feat(core): Tabs component for json-render, with real per-component prop types - #492
Open
dvcolomban wants to merge 2 commits into
Open
feat(core): Tabs component for json-render, with real per-component prop types#492dvcolomban wants to merge 2 commits into
dvcolomban wants to merge 2 commits into
Conversation
2 tasks
@vitejs/devtools
@vitejs/devtools-kit
@vitejs/devtools-oxc
@vitejs/devtools-rolldown
@vitejs/devtools-vite
@vitejs/devtools-vitest
commit: |
dvcolomban
force-pushed
the
feat/json-render-tabs-typed-elements
branch
from
July 28, 2026 17:02
a0c6a77 to
9e07035
Compare
…rop types Adds `Tabs` to the json-render base catalog — horizontal (underlined bar) or vertical (left rail) — since building a tabbed panel today means either a Card per section or client-side `visible` wiring the spec author has to build themselves. `children[i]` renders when `tabs[i]` is active, so there's no `visible` plumbing needed in the spec; two-way bindable via `$bindState` on `value`, otherwise switches local uncontrolled state. Includes roving -tabindex keyboard navigation (arrow keys, Home/End) per the WAI-ARIA tabs pattern. Also types `Tabs`' own props (`TabsProps`, `TabDescriptor`) co-located in `Tabs.ts` itself, and adds `registryProps<Type, Props>()` — a typed alternative to the untyped `props: ['element', 'emit', ...]` array form every registry component currently uses, so `defineComponent` infers `setup`'s `ctx.element.props` as the component's own type instead of `Record<string, any>`. `RegistryComponentProps` stays generic with the same permissive default, so every other untouched component is unaffected. `TabsProps`/`TabDescriptor` are re-exported from the client webcomponents entry (`@vitejs/devtools/client/webcomponents`, already public) as opt-in strict types — most spec authors keep using kit's fully open `JsonRenderElement`. Deliberately not added to `@vitejs/devtools-kit`: kit depends on nothing in core (core depends on kit, so the reverse would cycle), and duplicating each component's props into a second, separately -maintained types package is exactly the drift risk co-location avoids.
dvcolomban
force-pushed
the
feat/json-render-tabs-typed-elements
branch
from
July 28, 2026 17:14
9e07035 to
661169d
Compare
dvcolomban
marked this pull request as ready for review
July 28, 2026 17:21
…bs-typed-elements # Conflicts: # packages/core/src/client/webcomponents/index.ts # test/__snapshots__/tsnapi/@vitejs/devtools/client/webcomponents.snapshot.d.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a
Tabsprimitive to the json-render base catalog — previously there was no way to group content into tabs, anddevtoolsRegistryhad no plugin-side registration hook, so this had to land as a first-class catalog component.components/Tabs.ts:tabs[]descriptors (value,label, optionalicon/badge/badgeVariant),children[i] ↔ tabs[i]so panels can't desync from their tab, and only the active child renders.value/$bindState, or uncontrolled viadefaultValue(falls back totabs[0]) — sameuseBoundProp+ctx.on('change')pattern asSwitch.orientation: 'horizontal' | 'vertical'(default horizontal), with matching a11y:role="tablist"/"tab",aria-selected,aria-orientation, roving tabindex, and arrow-key navigation.Propsinterfaces exported from the existing publicwebcomponents/index.tsbarrel (JsonRenderElement,TabDescriptor,TabsProps) — opt-in, the untypedJsonRenderElementfrom@vitejs/devtools-kitis untouched.Screenshots
Test plan
pnpm run lintpnpm run typecheckTabsstory: exercised both orientations, arrow-key navigation, and a composedStack+Cardtab panel