Repository navigation
Conversation
…N-4270) Adds frontend/src/v1/ as an isolated tree for the v1 frontend (P0-T01): - Folder taxonomy from the spec, a public entry (src/v1/index.ts, imported by v0 as `@v1`) and a cloud overlay placeholder. - src/v1/tsconfig.json: strict, no JS, unused locals/params are errors, `@v1` alias only. v0's tsconfig/jsconfig exclude src/v1. - Biome overrides for the two-way import boundary and v1 bans (no `../`, `@/`, prop-types, antd, component CSS; noExplicitAny). - scripts/check-v1.mjs for what Biome cannot express: TypeScript-only files, the folder taxonomy and import contract, PropTypes, `ant-`. - typecheck:v1, lint:v1 and test:v1 scripts; v0 scripts are unchanged. - test-fixtures/v1-boundary/ proves each rule fails and passes as specified, run with node --test so the v0 vitest suite never sees it. - .gitignore re-includes src/v1/lib/ (the Python `lib/` rule matched it). v0 build output, test counts, typecheck and Biome results are unchanged.
…270) check-v1.mjs: - Scan comments with a string/template-aware tokenizer; a `/*` or `//` inside a string or line comment no longer hides the imports after it. - Read template-literal specifiers, import.meta.glob and `import(..., opts)`. - Flag specifiers that leave src/v1 (`/`, `..`, `@/`, `src/`) itself, not only via Biome, which skips template literals. - Check `@import`/`url()` and `ant-` in styles/ CSS; report symlinks; catch built `ant-` names; treat .test/.spec .mts/.cts as test files; ignore .DS_Store; drop the unused --root option. biome.json: also ban `..`, `./../**`, `/**`, `antd/**`, `prop-types/**`. tsconfig: skipLibCheck off so v1's own .d.ts files are checked. .gitignore: re-include lib/ at any depth under src/v1. Fixtures: a generated matrix over every folder-contract pair, every import form, every outside spelling, a symlink case, and cases for each new rule; tsc cases assert error codes; output matching excludes the command text and spawn errors fail loudly. Comment and README corrections.
… (UN-4270) - ci-frontend-lint: the typecheck job also runs `typecheck:v1` and `lint:v1`, so the strict v1 tsconfig and the scripts/check-v1.mjs checks (folder contract, TypeScript-only files, PropTypes, `ant-`) gate PRs now rather than from P0-T10. - Pages may no longer import app/, test/ or the v1 entry, only the shared folders (components, shell, services, stores, hooks, lib, styles, plugins). Test files in a page may still import test/. Contract table, README and the fixture matrix updated together.
…(UN-4270) check-v1.mjs: split the comment scanner into small helpers (cognitive complexity 40 -> under 15), drop the nested ternary and nested template literal, use String.raw for the import regexes, keep CLI flags in a Set. Fixture runner: - Cases and the expected folder contract are parsed text tables instead of repeated object literals (the 10% duplication). - Sorts use an explicit localeCompare comparator. - The contract matrix is built by a helper. - Spawns /bin/sh by absolute path and no longer needs `git init` (Biome only needs the ignore file). The git check-ignore call keeps a PATH lookup, with the reason and a NOSONAR marker. Fixture cases: re-exports rewritten as small functions and read-only props, without changing what each case exercises.
…nnot see (UN-4270) Addresses Greptile review on #2380: - import.meta.glob([...]): every pattern in the array is checked, not only the first, so an allowed first pattern no longer hides a forbidden one. - check-v1 --code also scans v0 (src/ outside v1, including the cloud src/plugins overlay) for template-literal imports, globs, require(), @/v1, src/v1, relative paths and CSS @import that reach into v1 other than through `@v1`. Biome still covers plain imports. Fixtures: Greptile's example as a case, a glob array with a forbidden later pattern, and a generated test of every v0 -> v1 form (denied and allowed). The v0 scan reports nothing on the current tree.
…i 5.2 both declare containSubset Co-Authored-By: Claude Opus 5.5 <[email protected]>
… per-browser preference Co-Authored-By: Claude Opus 5.5 <[email protected]>
…tore Co-Authored-By: Claude Opus 5.5 <[email protected]>
…in three modes Co-Authored-By: Claude Opus 5.5 <[email protected]>
… match the v1 Tailwind root Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
…t it Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ercase letters only Co-Authored-By: Claude Opus 5.5 <[email protected]>
…heme mapping and the focus utility Co-Authored-By: Claude Opus 5.5 <[email protected]>
…so biome ci passes src/v1/styles/tokens.css is written by scripts/build-v1-tokens.mjs and checked byte-for-byte by styles/tokens.test.ts; the formatter would rewrap it and break the check. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
…sts and on missing variants Co-Authored-By: Claude Opus 5.5 <[email protected]>
…and portal sync Co-Authored-By: Claude Opus 5.5 <[email protected]>
…tEffect Co-Authored-By: Claude Opus 5.5 <[email protected]>
…line styles, CSS imports and !important fail lint Co-Authored-By: Claude Opus 5.5 <[email protected]>
… arbitrary values Co-Authored-By: Claude Opus 5.5 <[email protected]>
… and the fixtures v0's root auto-detected sources across the whole frontend, so the v1 tree, scripts/check-v1-styles.mjs and test-fixtures/ added 12 unprefixed utilities and 8 theme variables to v0's stylesheet. With these three @source not lines the v0 build is byte-identical to the base again (239/239 files). Co-Authored-By: Claude Opus 5.5 <[email protected]>
…longer cancel each other Co-Authored-By: Claude Opus 5.5 <[email protected]>
…our arbitrary values and !important after a variant Co-Authored-By: Claude Opus 5.5 <[email protected]>
…cope variants, shadows and the root fill to v1 Co-Authored-By: Claude Opus 5.5 <[email protected]>
…the theme test exercises the mode effect Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ge, the pixel escape and the current unprefixed-class rationale Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Runtime geometry (a page's aspect ratio, a highlight's position) cannot be a token or a class. Rule S1 now accepts a style attribute whose value is an object literal with only "--name" keys, so the numbers travel through custom properties that ui: classes read (ui:aspect-(--page-aspect)); a string, a variable, a spread or a plain key still fails. Three fixtures pin it. Co-Authored-By: Claude Fable 5.1 <[email protected]>
pre-commit's check-shebang-scripts-are-executable fails on branches stacked on this one; check-v1.mjs already carries the bit. Co-Authored-By: Claude Fable 5.1 <[email protected]>
React's CSSProperties has no index signature for "--*" keys, so the object literal rule S1 allows fails TS2353 under strict mode. Augment it under lib/, and typecheck the passing fixture so the augmentation is exercised. Raised by Ali on the viewer stack. Co-Authored-By: Claude Fable 5.1 <[email protected]>
A component that needs its own node and also forwards the caller's ref feeds both through one callback ref. Co-Authored-By: Claude Opus 5.5 <[email protected]>
FieldFrame gives every text control the same border, radius, padding and focus ring, with hover, invalid, disabled and read-only states as data attributes. On it: Input (32 tall, leading/trailing icons and prefix/suffix text), Textarea, PromptTextarea (104 minimum, grows to a maximum then scrolls; Enter submits, Shift+Enter breaks the line, an IME composition never submits), SearchField (Escape clears a value and stops; on an empty field it bubbles) and SecretField (masked, Reveal with aria-pressed, Copy writes the real value and reports the outcome to the caller for the toast). Field wires Label, HelperText and ErrorText to the control: the label names it, aria-describedby lists the rendered texts, and an error sets aria-invalid and renders as role=alert. Co-Authored-By: Claude Opus 5.5 <[email protected]>
A caller that passes id now gets stable describedby ids, and the markup snapshot no longer depends on useId render order. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…up frames Fill is the background token (216:8126), inputs pad 10 with a 6 gap (676:9487), the prompt pads 10 vertically (676:9547), and a label sits 6 above its control (639:5296). Co-Authored-By: Claude Opus 5.5 <[email protected]>
The composed callback now returns a cleanup, so React calls it instead of the callback with null: a ref that returned its own cleanup gets it run, and every other ref is set to null. Co-Authored-By: Claude Opus 5.5 <[email protected]>
SearchField: a Radix dialog that skips dismissal for data-escape-clears calls preventDefault in the capture phase, so the clear now ignores a preventDefault made before it; only the caller's own onKeyDown cancels it. The lock reads disabled and read-only from props and Field alike, and a controlled field with no onValueChange lets Escape through. PromptTextarea: Enter does not submit when read-only. Where field-sizing is missing, it re-fits after its form resets and keeps the height automatic while scrollHeight is 0. SecretField: onCopyResult is required and is called once, after the clipboard write, so a throwing handler is not reported as a failed copy. An empty value is not written and reports status empty. Reveal and Copy follow a disabled Field and stay usable when read-only. new-password, the password-manager ignore hints and spellcheck off are set after the props spread. Tests cover each fix, a real Radix Dialog, and the wiring of all five controls to Field. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Object and callback refs reach the control, and are released on unmount, for the three controls that compose refs. FieldAction inside a form clicks without submitting it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
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.



What
frontend/src/v1/components/ui/form/, all drawn by oneFieldFrame(border, radius, padding, focus ring and the hover, invalid, disabled and read-only states):Input: height 32, with leading and trailing icons and prefix and suffix text.Textarea, andPromptTextarea: at least 104 tall, grows with its text to a maximum, then scrolls. Enter submits, Shift+Enter breaks the line, and an IME composition never submits.SearchField: Escape clears it when it has a value; on an empty field Escape reaches the dialog or popover around it. A Clear button does the same for the mouse.SecretField: masked by default; Reveal (aria-pressed) and Copy, which copies the real value and reports the result throughonCopyResult.Field,Label,HelperText,ErrorText:Fieldwires the label,aria-describedbyandaria-invalidfor whichever control it holds;ErrorTextis announced (role="alert").lib/compose-refs.ts, which merges a component's own ref with the caller's, including React 19 ref cleanups.Why
How
ui:classes only, no raw colours or lengths. Styling follows the kit's Input Group frames (216:8125) and the search and prompt spec frames (676:9483, 676:9513, 676:9543).SearchFieldinside a Radix dialog: Radix callspreventDefaulton Escape in the capture phase when the dialog chooses not to close. The field ignores that, so a dialog that skips dismissal for targets carryingdata-escape-clearsgets "Escape clears the field, then closes the dialog", which a test with a real Radix Dialog checks. Only apreventDefaultfrom the caller's ownonKeyDowncancels the clear.SecretFieldsetsautoComplete="new-password",data-1p-ignore,data-lpignoreand turns off spellcheck, autocapitalise and autocorrect, so password managers and browser spellcheck services leave the value alone; callers cannot override these. Copy on an empty field writes nothing and reports{status: "empty"}.onCopyResultis required: no toast component exists yet (P1-T13 builds it), so the caller raises the toast. This is the seam to swap when it lands.field-sizing: contentis unsupported (Firefox),PromptTextareasizes itself fromscrollHeightthrough the--prompt-heightcustom property, and re-fits after a form reset.Can this PR break any existing features. If yes, please list possible items. If no, please explain why. (PS: Admins do not merge the PR without this section filled)
frontend/src/v1/, which no v0 route renders. No v0 file, dependency or build file changes.Database Migrations
Env Config
Relevant Docs
83e4fff.Related Issues or PRs
mainand rebase onto it from UN-4299 [FEAT] v1 design tokens, themes and style isolation (P0-T04) #2399's last tip.test:v1).Dependencies Versions
Notes on Testing
lint:v1,typecheck:v1andbiome check src/v1clean.test:v1: 118 vitest tests (83 on the base) and 59 boundary fixtures. The same checks pass on a merge with the newest scaffold commits (65 fixtures).keyCode 229, Escape clear and bubbling, the Radix dialog case, read-only and disabled locks from props and fromField, copy result handling, empty copy, privacy attributes, ref cleanups, the fallback re-fit): removing each one fails a test.Design questions (no frame answers them)
dark:input/30, which no token carries. This PR uses--backgroundin every theme.--destructiveat 50% (one focus treatment) or the kit's raw red at 20%? Disabled fill#e5e5e540has no token.Screenshots
Checklist
I have read and understood the Contribution Guidelines.
🤖 Generated with Claude Code