feat(site): tighten base infra step grid and card typography - #27797
Conversation
|
/coder-agents-review |
|
Chat: Review posted | View chat Review historydeep-review v0.9.0 | Round 3 | Last posted: Round 3, 35 findings (6 P2, 16 P3, 2 P4, 8 Nit, 3 Note), COMMENT. Review Finding inventoryFinding inventory: PR 27797Findings
Drop gate, CRF-38: keep-argument is that if no snapshot service existed, the PR description's "visual scale is covered" would be false outright and CRF-5's closure would be void, which would be a P2. Dropped because the premise is disproved: Severity adjustments made during cross-check, each with the keep-argument written first:
Kite's Contested and acknowledgedCRF-5 (P3, BaseInfraSelectStep.tsx:45) - No story for either changed step
Round logRound 1Netero-only first pass. 2 P2, 3 P3, 1 Nit, 4 Notes raised; 2 Notes dropped. Panel gated pending P2 resolution. Reviewed against 0e1a9a9..41ea0f3. Round 2BLOCKED by churn guard. CRF-1 to CRF-4 and CRF-6 have targeted fixes in 6930107. CRF-5 deferred with no ticket, which blocks. CRF-7 and CRF-8 are Notes that requested no change. No reviewers spawned, no panel. Reviewed against 41ea0f3..6930107. Round 3Churn guard PROCEED (CRF-5 addressed in 8c6c85f). Netero found a P2, but rounds 1 and 2 both ended without panel review, which exceeds the skill's cap of two consecutive no-panel rounds, so the Netero gate was not applied a third time and the P2 travelled with the panel. Panel of 17: Bisky, Chopper, Ging-React, Ging-TS, Gon, Hisoka, Kite, Komugi, Leorio, Mafu-san, Mafuuu, Meruem, Nami, Pariston, Robin, Zoro, plus Razor as wildcard. Ging-TS and Ging-React reported no findings. New: 4 P2, 15 P3, 2 P4, 7 Nit, 1 Note; 1 P3 dropped. Reviewed against 6930107..8c6c85f (full diff 0e1a9a9..8c6c85f). Orchestrator error recorded: in round 2 I accepted CRF-3 as fixed after verifying Law analysisNot run. Effective additions 182, below the 1000 threshold. About deep-reviewCRF = Coder Review Finding (P0-P4, Nit, Note)
|
There was a problem hiding this comment.
First-pass review only. These are mechanical findings from a single reviewer; the full review panel has not looked at this PR yet and will review once the P2s are resolved.
The changes are small and self-consistent within the three touched files, tsc --noEmit and biome check are clean, and the Tailwind classes were verified against a probe build rather than assumed (notably that text-xs/text-sm bake in fontWeight: 500, so the explicit font-bold/font-normal do win by source order). The two P2s are both about reach: one change is narrower than it looks, the other is wider than the PR applied it.
2 P2, 3 P3, 1 Nit, 2 Notes.
On the PR description question, swapping to named text-sm-bold/text-xs-body utilities is a separate decision from these findings; the mapping to text-sm font-bold / text-xs font-normal is correct for the current config.
From the reviewer, on the class this PR removed: "So the old h3 had no font-size class at all and rendered at the inherited size; this PR is the first time that heading gets an explicit size."
🤖 This review was automatically generated with Coder Agents.
| </div> | ||
|
|
||
| <div> | ||
| <h3 id={nameId} className="text-md font-semibold text-content-primary"> |
There was a problem hiding this comment.
Note [CRF-7] The removed text-md was never a real utility. (Netero)
The probe build emitted
.text-sm,.text-xs,.font-bold,.font-normal, and both arbitrary variants, but no.text-md.tailwind.config.js:26-31extendsfontSizewith2xs,xs,sm,base,3xlonly, and Tailwind's default scale has nomdkey. Nine other files still use the dead class, includingModuleCard.tsx:65,DynamicParameter.tsx:400, and fourDeploymentSettingsPagecharts.
No action needed in this PR. Worth knowing because it changes what this line does: the title was previously unsized and inherited, so text-sm is a new explicit size, not a step down from 16px. The nine remaining uses are a separate cleanup.
🤖
| "[&_p]:mb-3 [&_p]:text-content-secondary", | ||
| "[&_li]:text-content-secondary [&_li]:marker:text-content-secondary", | ||
| "[&_a]:font-normal", | ||
| "[&_code]:text-[length:inherit]", |
There was a problem hiding this comment.
Note [CRF-8] [&_code]:text-[length:inherit] also matches fenced-code code elements, with no visual effect today. (Netero)
The probe build confirms it compiles to
.[&_code]:text-[length:inherit] code { font-size: inherit }, one specificity step above the inline-codetext-smatsite/src/components/Markdown/Markdown.tsx:89, so the inline-code override works as intended. Prism blocks (Markdown.tsx:77-86) rendercodewithout a font-size class, so forcinginheritthere changes nothing today, but the selector is broader than the stated intent.
No action needed. Flagged so that if a font size is ever added to Prism code blocks, this selector is where it gets overridden.
🤖
- ConfigurationField: use text-xs for field descriptions consistently (fixes source of body-copy size mismatch instead of scoped override) - ModuleCard: apply same typography updates as TemplateCard - TemplateCard: shrink View details link to text-xs to match description - BaseInfraSelectStep: gate 4-up grid at xl instead of lg - BaseTemplateParametersStep: drop scoped wrapper and redundant marker: variant
|
/coder-agents-review |
There was a problem hiding this comment.
Further review is blocked on one unaddressed finding.
Five of the six actionable findings have targeted fixes in 6930107d3, and each one was fixed at the source rather than papered over: the wrapper selector is gone and the four ConfigurationField descriptions are now text-xs (CRF-1), ModuleCard picked up the same title, description, and link scale as TemplateCard (CRF-2, CRF-4), 4-up moved from lg to xl (CRF-3), and the redundant marker: variant is gone (CRF-6). I verified each class string in the diff.
Unaddressed:
- CRF-5 (P3, no Storybook story for either changed step). The reply says it is out of scope and "tracking as a follow-up," but no ticket is linked.
DEVEX-724is this PR's own Linear linkback, not a follow-up for story coverage. This needs a human decision: link a ticket that covers story coverage forBaseInfraSelectStepandBaseTemplateParametersStep, or state explicitly that the gap is accepted. An acknowledgement without either leaves nothing behind once this PR merges, and a visual-only change is exactly the class of change a story is the only thing that catches.
CRF-7 and CRF-8 are Notes that asked for no change; no response needed.
One thing to fix while you are here: the PR description still says "Field description size scoped to this step via child selector; shared ConfigurationField is unchanged." 6930107d3 does the opposite, and correctly so, but that also means the change now reaches every ConfigurationField consumer, including the module settings step. Worth saying in the description, since it widens what a reviewer should look at.
The review panel has still not looked at this PR. Once CRF-5 has a ticket or an explicit human decision, the next round runs the full panel against the current head.
🤖 This review was automatically generated with Coder Agents.
|
/coder-agents-review |
There was a problem hiding this comment.
First panel round. Seventeen reviewers on the current head; two (Ging-TS, Ging-React) found nothing in their domains and said so.
The typography half of this PR holds up under measurement. Reviewers probed the running components rather than reading class names, and the intended scale is what renders: card title 14px/700, description 12px/400, View details 12px/400, list items 12px with markers matching by inheritance, inline code following body size. CRF-1's fix went to the source instead of a descendant selector, CRF-2's sibling was brought along, and CRF-5 was closed by writing the stories rather than by promising a ticket. Pariston went looking for a case against the typography work and reported he could not build one.
The findings cluster in two places. The grid fix removed a tier nobody asked it to remove, and the stories added to cover this change do not render most of what changed.
My own error, since ten reviewers found it and I did not: in round 2 I verified CRF-3's fix by checking that lg:grid-cols-4 became xl:grid-cols-4 and called it fixed. I never checked what the base SHA had on that line. It had lg:grid-cols-3, so the fix deleted the 3-up tier and 1024-1279px now renders 2-up, looser than before this PR started. That is CRF-11, and it is the one finding I would fix before anything else.
One premise needs correcting for anyone reading the review threads: four reviewers assumed the pixel snapshots capture these stories at the configured 1900px desktop viewport. They do not. @coder/pixel-storybook/build/crawler/storybook.js:137-155 applies the viewport axis only to stories with parameters.layout: "fullscreen", and neither new story sets it, so both are shot autofit at the browser context default. The xl:grid-cols-4 tier makes it into the baseline only because that default sits on the xl boundary, which is coincidence rather than coverage. A separate claim that this repo has no snapshot service at all is wrong and was dropped; pixel.jsonc plus ci.yaml:1080,1088 run it.
4 P2, 15 P3, 2 P4, 7 Nit, 1 Note.
Two process notes. The commit 6930107d3 fix(site): address review feedback carries five distinct behavior changes and names none of them; whoever bisects a typography regression in this directory lands on it and has to read the diff. And the PR description has drifted from the diff in three places (CRF-11, CRF-26, and the "visual scale is covered" claim in CRF-25), which matters because it is the text that survives the squash.
CRF-7 is unchanged: the dead text-md class is still on nine files, though none of them are in TemplateBuilder any more. CRF-8's conclusion was independently re-verified by measurement and holds.
From Bisky, on the Loading story: "a story that cannot express its own name should not exist."
site/src/pages/TemplateBuilder/ConfigurationField.tsx:129
P3 [CRF-15] The required asterisk is text-sm in these four slots and text-xs in FormField, so one form shows two asterisk sizes. (Robin P3, Nami Nit)
FormField.tsx:40renders the asterisk astext-xs font-bold text-content-destructive.ConfigurationField.tsx:129,:179,:264, and:304render it astext-sm font-bold text-content-destructive. ATextFieldgoes throughFormField(:100-107); aSelectField,RadioField,SwitchField, orSwitchGroupFielddoes not. A required text field and a required dropdown sitting in the sameConfigurationFieldContainergrid (:340) therefore show two asterisk sizes.
Not introduced here, but this PR walked all four of these blocks to unify description size and left the marker beside them behind, so after the change descriptions agree and the asterisks do not. Four lines, same edit as the descriptions.
🤖
site/src/pages/TemplateBuilder/ModuleConfiguration.tsx:70
P3 [CRF-19] Secondary copy sitting beside the descriptions this PR shrank is still text-sm, so one panel now shows two sizes of secondary text. (Hisoka P3, Pariston Nit)
ModuleConfiguration.tsx:70renders "No configuration required." attext-sm text-content-secondary, in the same<section>, four pixels of margin away from descriptions that are nowtext-xs. Same root cause, one more instance:ModuleSettingsStep.tsx:165renders the sensitive-variable notice attext-sm text-content-secondarydirectly under aModuleConfiguration.
The PR deliberately reaches into the module settings step through the shared component, so these two are the remaining instances of the class it is fixing. Hisoka also notes the coverage asymmetry: ModuleConfiguration.stories.tsx exists so its mismatch lands in a snapshot, while ModuleSettingsStep has no story and its instance will not.
🤖
site/src/pages/TemplateBuilder/ConfigurationField.tsx:104
P3 [CRF-26] The PR description lists five names under "all four ConfigurationField description slots" and credits this PR with a TextField change it does not make. (Mafu-san P2, Leorio P3, and eight more at Nit or Note)
Ten of seventeen reviewers stopped on this sentence, which is itself the cost.
A reviewer reading that sentence believes the text-input description path was audited and changed here. It was not touched, so the sentence has to be checked against the diff before it can be trusted, which is the cost this finding is about.
Leorio's replacement:
All four description slots that hardcoded
text-sm(SelectField,RadioField,SwitchField,SwitchGroupField) now usetext-xs. TheTextFieldpath already renderedtext-xsthroughFormFieldand is unchanged.
While you are in that paragraph, the claim that the change "reaches every ConfigurationField consumer" also overstates what a user sees. Four reviewers grepped for it: no production code constructs select, radio or switch-group fields, so in shipped UI the change resolves to switch descriptions in the base-parameters and module-settings steps. Editing all four for internal consistency is right; the description just reads wider than the diff is.
🤖
site/src/pages/TemplateBuilder/BaseInfraSelectStep.tsx:36
P4 [CRF-27] Neither of this step's non-happy paths has handling, and the sibling step discards error and isLoading entirely. (Mafuuu P4, Nami P4, Mafu-san Note)
const bases = data?.bases ?? []feeds the grid directly, so a successful response with zero bases produces an emptyrole="radiogroup"and aContinuebutton that stays disabled forever with nothing on screen explaining why.
const { data } = useQuery(...)discardserrorandisLoading. On failurebaseis undefined, so line 127 falls back to the string "Base Template", line 128 to an empty description,variablesto[], andprerequisitesto"". The user reaches step 2 of a wizard, sees an empty card with a placeholder name, and is told nothing.
site/AGENTS.md FE5 requires loading, error and empty handling. Both predate this PR and neither is in its diff. Recorded rather than assumed as a follow-up, because this PR is the one that adds story files next to both gaps and covers neither.
🤖
site/src/pages/TemplateBuilder/BaseInfraSelectStep.tsx:18
P4 [CRF-28] detailsUrl is defined four times in this directory, as two verbatim pairs. (Robin P4)
BaseInfraSelectStep.tsx:19 `https://registry.coder.com/templates/${baseId}` BaseTemplateParametersStep.tsx:28 `https://registry.coder.com/templates/${baseId}` (verbatim duplicate) ModuleSelectStep.tsx:46 `https://registry.coder.com/modules/${moduleId}` ModuleSettingsStep.tsx:75 `https://registry.coder.com/modules/${moduleId}` (verbatim duplicate)
Untouched by this PR and outside its scope; recorded because both files in the first pair are in the diff. One helper taking a "templates" | "modules" kind retires all four.
🤖
🤖 This review was automatically generated with Coder Agents.
| </TemplateBuilderSubtitle> | ||
|
|
||
| <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4"> | ||
| <div className="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-4"> |
There was a problem hiding this comment.
P2 [CRF-11] CRF-3's fix replaced the lg tier instead of supplementing it, so 1024-1279px drops from 3-up to 2-up and the step now disagrees with the next step in the same wizard. (Netero P2, Mafu-san P2, Kite P2, Meruem P2, Nami P2, Pariston P2, Hisoka P3, Zoro P3, Razor P3, Leorio P3)
Base was grid-cols-1 sm:grid-cols-2 lg:grid-cols-3. Head is grid-cols-1 sm:grid-cols-2 xl:grid-cols-4. Nothing matches between sm (640px) and xl (1280px).
One pixel of viewport swings a card from 440px to 212px. 1024-1279 covers the common laptop widths, and the PR's stated goal is to tighten this grid, so the range it loosens most is the one users see most.
Viewport Columns Card width 1024 (pre-PR) 3 203px 1024 (HEAD) 2 312px 1279 (HEAD) 2 440px 1280 (HEAD) 4 212px
Pariston counted what the step actually renders: coderd/templatebuilder/bases.go:240 enumerates nine base directories and all nine resolve to examples, so ceil(9/3) and ceil(9/4) are both 3. The new 4-up tier removes zero rows at any width, while the lg band goes from 3 rows to 5.
ModuleSelectStep.tsx:247still uses the exact string this line abandoned,grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4, and both grids render into the same container in the same wizard. Between 1024px and 1279px the base step shows 2 columns and the module step shows 3.
That is CRF-2's divergence class applied to layout one round after CRF-2 was fixed for typography. Kite states the tradeoff honestly: restoring the tier puts 203px cards back at 1024px, which is 9px below the 212px this PR already accepts at xl, so it is the status quo rather than a new regression. Fix is one token, sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4, and decide whether ModuleSelectStep gets the matching xl tier. Meruem's structural version, one exported CARD_GRID_CLASSES consumed by both grids, is what stops the two from drifting again.
This is on me as much as on the fix: I verified CRF-3's closure against the previous round's head instead of the base SHA and missed it.
🤖
| }, | ||
| }; | ||
|
|
||
| export const Loading: Story = { |
There was a problem hiding this comment.
P2 [CRF-12] The story named Loading settles into an error alert, and what it captures depends on the surrounding server and on response latency. (Komugi P2, Bisky P2, Mafuuu P3, Chopper P3, Nami P3, Meruem P3, Razor P3, Netero P3)
Six reviewers verified this with throwaway probe stories rather than inferring it. Komugi sampled the canvas twice:
t0:<div role="status" data-testid="loader">(theLoader).t1:<div role="alert">withRequest failed with status code 502.
parameters: { queries: [] }only removes the seed thatmetainstalls. It does not stop the query. [...] The probe also proves the override direction:metaseeded{ bases: [] }(which renders an empty grid, not a loader), and the story still fetched.
The value is unpinned in three directions: 502 under pnpm test:storybook from the storybook-test-setup middleware, 404 under the static build pixel serves, and whatever CODER_HOST returns under pnpm storybook. Bisky adds that the captured pixels contain an unmasked Axios stack trace and status code, so the baseline differs between harnesses and any change produces a diff nobody can attribute.
The repo already has the fix, and Komugi found it: EditOAuth2AppPageView.stories.tsx:70-77 pins the pending state with beforeEach and a never-resolving mock.
export const Loading: Story = {
parameters: { queries: [] },
beforeEach: () => {
spyOn(API, "getTemplateBuilderBases").mockReturnValue(new Promise(() => {}));
},
};ModuleSelectStep.stories.tsx:80 has the identical defect and is where this was copied from. Fixing only the new file leaves the pattern in place for the next person to copy.
🤖
| icon: "", | ||
| os: "linux", | ||
| prerequisites, | ||
| variables: [ |
There was a problem hiding this comment.
P2 [CRF-13] The story added to cover this step renders none of the four ConfigurationField description slots the PR changed. (Bisky P2, Mafu-san P2, Nami P2, Chopper P3, Kite P3, Meruem P3, Razor P3)
The base fixture has exactly one variable,
type: "string".variableToField(BaseTemplateParametersStep.tsx:56) maps everything non-booltotype: "text", andTextField(ConfigurationField.tsx:92) delegates its description toFormField.FormField.tsx:47renderstext-xs, andgit show 0e1a9a9f0:site/src/components/FormField/FormField.tsxshowstext-xsthere before this PR too. So the one description this story renders was already the target size and is untouched by the diff.
Seven reviewers independently grepped every story that builds a ConfigurationFieldDefinition. TemplateConfiguration.stories.tsx and ModuleConfiguration.stories.tsx between them render select, radio, switch and switch-group, and not one passes a field-level description, so all four changed slots render nowhere in the repo.
The switch path is live, not theoretical. Meruem traced it to shipped data:
coderd/templatebuilder/bases/kubernetes/base.jsondefinesuse_kubeconfigwith"type": "bool"and a description, so selecting the Kubernetes base renders line 279.
Two cheap edits close it: add a bool variable with a non-empty description to this fixture, and add description to one radio, one switch-group and one select field in ModuleConfiguration.stories.tsx, whose Default story already renders all three in one snapshot.
🤖
| </Label> | ||
| {description && ( | ||
| <div id={descriptionId} className="text-sm text-content-secondary"> | ||
| <div id={descriptionId} className="text-xs text-content-secondary"> |
There was a problem hiding this comment.
P2 [CRF-14] The description slot this PR resizes in four places already exists as one component, FormField, which was already text-xs. (Robin P2, Zoro P3)
FormField.tsx:46-50renders exactly this block [...] It already wiresdescriptionIdintoaria-describedby(FormField.tsx:25-30,:59), and it was already attext-xsbefore this PR. That is whyTextFieldneeded no edit [...] So the change converged the copies on the valueFormFieldalready held, not onFormFielditself. The copies remain, and they are not decorative: they have already drifted.
Re-raise against CRF-1 with new evidence: the fix moved the resize to the right layer and landed it as four duplicates of a block the codebase owns in one place. ConfigurationField.tsx:138, :188 and :313 are now byte-identical to each other and to FormField's; :279 is the same block plus ml-[44px] font-normal. The measurable cost of the duplication is CRF-15 and CRF-16, both of which are drift between these five copies.
SwitchRow at ConfigurationField.tsx:224-242 is this file's own precedent for extracting a shared sub-component. A FieldDescription sibling, importable by FormField too, collapses five slots to one. I am not asking for a refactor as a condition of this PR, but the next scale or color change to field descriptions is a five-site edit with the same odds of missing one, and this PR is the second lockstep edit in three rounds.
🤖
| <div | ||
| id={descriptionId} | ||
| className="ml-[44px] text-sm font-normal text-content-secondary" | ||
| className="ml-[44px] text-xs font-normal text-content-secondary" |
There was a problem hiding this comment.
P3 [CRF-16] Only SwitchField keeps font-normal, so the now-uniform 12px descriptions render at two weights. (Gon P3, Mafuuu P3, Hisoka Nit)
tailwind.config.js:28bakesfontWeight: "500"intotext-xs, sotext-xs text-content-secondaryat lines 138, 188, and 313 renders at weight 500, whileSwitchFieldat line 279 renders at 400 because it keepsfont-normal.
Mafuuu names why this PR is where it becomes visible:
Before the PR the switch description differed in both size and weight, so the weight gap was invisible. Now that sizes match, weight is the only remaining difference and it shows up side by side: in the base-parameters step a string variable renders a
FormFielddescription at 500 and a bool variable renders this one at 400 in the same column.
Gon adds that the card descriptions this PR also resized use font-normal (TemplateCard.tsx:74, ModuleCard.tsx:74), so the weight question is already answered elsewhere in the same diff. Pick one weight for description text and apply it to all four slots. This is a different claim from CRF-9, which was about one pairing being correct by source order, not about the four slots disagreeing with each other.
🤖
| }, | ||
| }; | ||
|
|
||
| // Verifies that every base is rendered as a radio option with the expected |
There was a problem hiding this comment.
Nit [CRF-32] The comment restates the three assertions directly below it. (Gon P2, Mafu-san Nit)
findAllByRole("radio"),toHaveLength(bases.length), and thegetByTextloop already say "every base renders as a radio with its title and description." The comment adds no invariant, no reason, no trap. Delete it.
site/AGENTS.md FE4 forbids comments that restate assertions. Gon rated this a finding; I am posting it as a Nit because the standalone consequence is reader noise, and the part that has real cost, the comment promising description coverage that does not exist, is CRF-24. Worth contrasting with the precedent this file copied: ModuleSelectStep.stories.tsx:86 explains the fixture arithmetic instead of narrating its own calls.
🤖
|
|
||
| export const Default: Story = {}; | ||
|
|
||
| // Verifies that the field description and README body copy are rendered so |
There was a problem hiding this comment.
Nit [CRF-33] Half this comment restates the assertions; the trailing clause is the part worth keeping. (Gon P2)
"the field description and README body copy are rendered" is what
findByText(/Container image for workspaces/)and the twofindByRole("heading")calls show. The part worth keeping is why presence assertions cover a typography change.
Gon's rewrite: // The step's typography rules only render when body copy and headings exist. Leorio independently called this comment's framing the honest one of the two, so it is the sentence to keep, just shorter.
🤖
|
|
||
| export const Default: Story = {}; | ||
|
|
||
| export const Selected: Story = { |
There was a problem hiding this comment.
Nit [CRF-34] Selected sets state and asserts nothing, and no story anywhere exercises selection or the keyboard handler. (Kite)
SelectedsetsselectedBaseId: "docker"and stops. Nothing assertsaria-checked="true"on the docker card, so the story would pass unchanged ifTemplateCard'sselectedprop stopped being wired through.onSelectBaseisfn()inargsand no story clicks a card, andTemplateCard's Enter/Space handler (TemplateCard.tsx:41-46) is never invoked.
Class rather than instance: TemplateCard.stories.tsx has six stories and zero play functions, so that keyboard handler has no coverage in the repo at all. A play that tabs to a card, presses Enter, and asserts onSelectBase was called with the right base closes both, and AGENTS.md asks for exactly that.
🤖
| <div | ||
| id={descriptionId} | ||
| className="ml-[44px] text-sm font-normal text-content-secondary" | ||
| className="ml-[44px] text-xs font-normal text-content-secondary" |
There was a problem hiding this comment.
Nit [CRF-35] ml-[44px] is a derived offset with nothing recording the derivation, on a line this PR modifies. (Gon)
44px is
Switch's default width (w-9, 36px,Switch.tsx:21) plus theSwitchRowgap (gap-2, 8px, line 232), which aligns the description with the switch label. Nothing states that, so a change to either value silently breaks the alignment.
One line of comment above the div naming the two values it is derived from.
🤖
| <MemoizedMarkdown | ||
| className={cn( | ||
| "text-sm font-normal", | ||
| "text-xs font-normal", |
There was a problem hiding this comment.
Note [CRF-37] text-xs also drops paragraph leading from 24px to 16px, a 1.33 ratio on 12px prose. (Hisoka)
The utility changes two things at once, and the README is the one place in this PR with real multi-line prose. 1.33 is tight for body copy; the rest of the class list is explicit about spacing (
[&_p]:mb-3,[&_h3]:mt-2 [&_h3]:mb-1), so if the leading is deliberate it would be worth writing it down asleading-normalor similar rather than inheriting whatever the size utility happens to bake.
No change requested. Flagged because it is the same shape as CRF-17 and CRF-18: a size utility here sets three properties, and only one of them was the intent. The pixel baseline will show whether it reads well.
🤖
…odule screens - Restore the lg:grid-cols-3 tier on base infra and module select grids so 1024-1279px keeps its previous density; xl:grid-cols-4 is now additive. - Match module screens to the base parameter typography scale: ModuleConfiguration 'No configuration required' notice, ModuleSettingsStep sensitive-variable notice, and ModuleSelectStep empty-state copy all move to text-xs. - Bring BaseTemplateCard heading in TemplateCustomizationsStep in line with TemplateCard/ModuleCard (text-sm font-bold). - Remove the two new step stories; step-level story coverage will be handled as a separate follow-up.
|
Scope reset after discussion with the review app. This PR is a small design pass; anything beyond that is being tracked separately with the engineering team. Applied:
Reverted:
Deferred as follow-ups (out of scope for this design pass):
On behalf of @tracyjohnsonux; the deferred items are being coordinated with the engineering team. |
jeremyruppel
left a comment
There was a problem hiding this comment.
tried this out in my workspace and it looks great. imo no additional stories needed as this is mostly styling
Updates the base infrastructure step, base parameters step, and module screens in the template builder for typography consistency.
Base infra step
xl:grid-cols-4tier while keepinglg:grid-cols-3, so no width band gets looser than before.text-sm font-bold.View detailslink:text-xs font-normal.Base parameters step
text-xs.::markerinherittext-content-secondaryso bullets match paragraph color.<code>inherits body size instead of hardcodedtext-sm.ConfigurationFielddescription slots (SelectField,RadioField,SwitchField,SwitchGroupField) now usetext-xs. TheTextFieldpath already renderedtext-xsviaFormFieldand is unchanged.Module screens (for consistency)
ModuleSelectStep: same additivexl:grid-cols-4tier; empty-state copy moves totext-xs.ModuleCard: matchesTemplateCard(titletext-sm font-bold, description and linktext-xs font-normal).ModuleConfiguration: 'No configuration required' notice moves totext-xs.ModuleSettingsStep: sensitive-variable notice moves totext-xs.TemplateCustomizationsStepBaseTemplateCardheading matches card title style (text-sm font-bold).This PR was generated on behalf of @tracyjohnsonux by the Coder agent.