docs(webkit): ship the webkit-lists skill — the index page and its filter system - #885
Open
gabriel-lisboa-azion wants to merge 3 commits into
Open
docs(webkit): ship the webkit-lists skill — the index page and its filter system#885gabriel-lisboa-azion wants to merge 3 commits into
gabriel-lisboa-azion wants to merge 3 commits into
Conversation
…lter system
Every list page in a product is the same page, and each one gets rebuilt by
whoever needed it: a row of Selects here, a badged funnel there, an operator
builder whose operator nobody changes. The skill fixes the page skeleton
(one band holding the controls, the filters and the rows they narrow), the
split between search and filters, and the filter model — a field catalog
plus a flat { fieldId: values[] } state where fields intersect and the
values inside a field union.
Routed from webkit-ui-craft between webkit-tables (the Table) and
webkit-navigation (the shell).
… motion skills The sample app's signed-out screens and filter bar carry motion the catalog cannot express — a card that follows its own content's height, a chip that grows a `0fr → 1fr` track to hold its value, a composition that assembles from opposite edges on first paint, and a routed step swap an order of magnitude smaller than that entrance. All of it was documented only in the call sites that discovered it, so the next screen rediscovers the same failures. webkit-motion-polish gains the two sanctioned layout exceptions in their exact shapes, the entrance and route/step recipes, and a glitch catalog of the fourteen ways this fails SILENTLY — `transition-[transform]` beside a `translate-x-*`, a single rAF, `<component :is>` under `out-in`, a fragment root, `scrollHeight` read after the pin, a ResizeObserver watching what it sizes, permanent `overflow-hidden` shaving a focus ring. Each compiles, lints and type-checks; each renders a correct final state, which is why the DoD now asks for measured frames rather than a screenshot. add-animation gains the prior question — a keyframe is a fixed journey, so a resize whose endpoints are runtime facts is a transition recipe, not a catalog entry — so the catalog stops growing entries that are wrong on every instance but the one they were authored against.
herbert-julio-azion
approved these changes
Aug 12, 2026
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.
Why
Every list page in a product is the same page, and every one of them gets rebuilt by whoever needed it. In our own sample app, six surfaces narrowed six different ways: a chip bar on one, a badged funnel of
Selects on four more, three width-tunedSelects in a row on another, and the table's own field/operator/value builder on Billing — whose operator column offeredis one ofon every row, a control with one option./webkit-tablesalready fixes what happens inside theTable. Nothing fixed the page around it.What the skill fixes
v-model:globalFilter); filters narrow:datafrom outside it. With the reason: a field is often not a column at all (an author who renders inside a Last Modified cell), and the table's applied-filter band only exists once a filter exists, so the affordance that starts filtering has nowhere to live inside the table.Custom…; free-text column → nothing, the search covers it; magnitude → nothing, because a field over it offers one option per row.{ fieldId: values[] }, flat, arrays, empty means absent. Fields intersect, values inside a field union. Count fields, not values: three authors is one filter on Author, and reading "3" suggests three columns are cut when only one is.Popoveranchor walking fields then values,Chip kind="dashed"as the trigger,filled/outlinedper field, chips in catalog order and never reordered.:datafrom outside does not trip TanStack'sautoResetPageIndex, so a narrowed list lands on an empty page offset.Scope
scope: general— it ships to consuming projects. There is deliberately no@aziontech/webkit/filter-bar: the field catalog and itsmatchfunctions are the consumer's data, so a package component would take them as props anyway and you would own the same file with more indirection. The skill teaches the composition fromPopover+Chipinstead, the way/webkit-navigationteaches the two app shells.Registration
The four registries a consumer skill touches:
CLAUDE_BUNDLEinsrc/cli/plan.js, the copy-list assertion intest/cli/plan.test.mjs, the Skills section ofCLAUDE.fragment.md, andwebkit-ui-craft(description, review chain, progression table).Verification
validate-authoring-docsexits 0 ·check-authoring-docsratchet reports 0 new violations ·plan.test.mjs+invariant.test.mjs33/33, including the two that matter here — every skill declares a non-emptyenforced_by, and every entry resolves to a rule of its own population.