Skip to content

🚨 fix: clear the fork's knip and lint debt that fails Fork CI - #17

Merged
DiegoJohnsonL merged 3 commits into
custom-nightlyfrom
fix/fork-ci-debt
Sep 26, 2026
Merged

DiegoJohnsonL merged 3 commits into
custom-nightlyfrom
fix/fork-ci-debt

Conversation

@DiegoJohnsonL

@DiegoJohnsonL DiegoJohnsonL commented Sep 26, 2026 •

Copy link
Copy Markdown
Collaborator

Fork CI's Check job fails on the fork's own code: vp run knip:check finds 13 unused exports in fork-only files, and vp check finds 44 shadcn lint errors (no-arbitrary-values, no-restyle, require-static-classes) in the background studio, the usage sidebar, and two fork-changed lines in upstream files. Upstream's Check passes on the same nightly.

This PR clears all of them. Every lint fix but one renders and behaves exactly as before. The exception, which the owner approved, is the hover-revealed delete button: it now animates its press and focus ring like every other Button (see Delete button).

Knip

fnKeySetupFromState, SERVE_MODE_REQUEST_DIR, keepAwakeCommand, CUSTOM_BACKGROUND_IMAGE_MAX_DIMENSION, CUSTOM_BACKGROUND_IMAGE_MAX_BYTES, readBackgroundImage, DYNAMIC_THEME_ID, IMAGE_DITHERING_FILTER, DEFAULT_CUSTOM_BACKGROUND_FILTER, MIN_/MAX_CUSTOM_BACKGROUND_ROTATION_MINUTES, VOICE_TRANSCRIPTION_MAX_BYTES and pictureLoudness are all still used inside their own file, and no test imports them. Each one only loses its export keyword.

Lint

New theme tokens go in the fork-owned custom.css, in an @theme inline block. This follows upstream's pattern of naming tokens after a feature, like --shadow-composer:

Token Value
--text-studio 0.8125rem (13px). It has no --line-height companion, so Tailwind emits only font-size, the same as text-[13px]
--radius-studio-field-inner calc(var(--radius-lg) - 1px)
--shadow-studio-field / -dark 0 1px --theme(--color-black/4%) / 0 -1px --theme(--color-white/6%)
--color-glass color-mix(in srgb, var(--glass-fill, var(--glass-surface)) var(--glass-opacity), transparent)

studio is registered with tailwind-merge in lib/utils.ts next to 2xs–5xs. Without that, cn() would read text-studio as a colour and drop it next to text-muted-foreground.

text-2xs and text-3xs set a line height, but text-[11px] and text-[10px] do not; they inherit it. So each swap also adds the leading-* that matches what that element used to inherit. Otherwise the swap alone would move text by about a pixel.

Where Old New Why it renders the same
BackgroundImagePicker field class before:rounded-[calc(var(--radius-lg)-1px)] before:rounded-studio-field-inner Same border-radius: calc(var(--radius-lg) - 1px)
BackgroundImagePicker field class …before:shadow-[0_1px_--theme(--color-black/4%)], dark:…before:shadow-[0_-1px_--theme(--color-white/6%)] …before:shadow-studio-field, dark:…before:shadow-studio-field-dark Same --tw-shadow declarations, including the @supports color-mix branch
BackgroundImagePicker field class has-focus-visible:ring-[3px], focus-visible:ring-[3px] …:ring-3 Identical --tw-ring-shadow (3px)
BackgroundImagePicker upload tiles (×2) text-[11px] text-2xs leading-(--text-xs--line-height) 11px font. The line height stays at the tile's text-xs ratio that the span used to inherit
BackgroundImagePicker order badge text-[10px] text-3xs leading-normal 10px font. Line height 1.5, inherited from html through the portaled menu
BackgroundImagePicker hint text-[11px] text-2xs leading-normal Same as above
BackgroundStudioPanel NameField <Input unstyled className={backgroundStudioFieldClass(…)}> (dynamic className on a ui component) The field look moves to a wrapping <span>. <Input unstyled className="flex min-w-0 flex-1 self-stretch"> The span has the same classes the Input's control span had. The control span fills it (flex-1, stretched), and the input still gets h-full through the same descendant selector, so the size, focus ring (:has(:focus-visible)) and bevel are unchanged. One detail differs: the input's rounded-[inherit] now inherits 0 instead of 10px. It has no background, border or outline, so the radius isn't visible
BackgroundStudioPanel section title, "Playlist", empty state text-[13px] text-studio font-size only, 13px
BackgroundStudioPanel library tile filter text-[11px] text-2xs leading-normal Inherited 1.5 inside the menu
BackgroundStudioPanel picker trigger filter text-[11px] text-2xs leading-tight Its parent sets leading-tight, so it inherited 1.25
BackgroundControls StudioField <Label className="truncate text-[13px] … @sm/studio:pt-1"> Local tag variable renamed LabelElement, text-studio This was never the ui Label. It is a local "span" | "label" whose name the rule mistook for the ui component. Same element, same classes
BackgroundStudioSidebar, UsageSidebarPanel <SidebarContent className="gap-0"> removed SidebarContent's column has no gap, and gap: normal is 0 in flex
same (fixed header) <SidebarGroup className="relative z-[1] p-[var(--sidebar-content-inset)] pt-1"> <SidebarGroup className="z-[1]"> with -mt-1 on its only child relative and the padding repeat SidebarGroup's own classes. pt-2 with a -mt-1 child puts the child at y=4 and keeps the group 4px + content + 8px tall, the same as pt-1. Nothing overflows the group. This matches upstream Sidebar's <SidebarGroup className="z-[1]"> header
same (content group) <SidebarGroup className="pt-0"> <SidebarGroup> With fixedHeader, SidebarContent already sets [&>[data-sidebar=group]:first-child]:pt-0, which is more specific
UsageSidebarPanel content group gap-4 on SidebarGroup A flex min-w-0 flex-col gap-4 div inside it The children stack the same way at the same width (the stretched item fills the group)
UsageSidebarPanel notices, window meter row text-[11px] text-2xs leading-normal The sidebar has no line height of its own, so they inherited 1.5 from html
ThreadRouteView (fork-changed line) <SidebarInset className="… bg-transparent text-foreground …"> data-thread-route-inset="", and custom.css sets background-color: transparent; color: var(--contrast-foreground) text-foreground compiles to var(--contrast-foreground). The unlayered rule beats SidebarInset's bg-background, just as the utility did once tailwind-merge dropped it. I checked that no other unlayered rule hits this element except the no-projects :has() rule, which is more specific either way. This follows custom.css's own "change upstream styling from here" convention
ChangedFilesTree header (fork-changed line) bg-[color-mix(in_srgb,var(--glass-fill,var(--glass-surface))_var(--glass-opacity),transparent)] bg-glass The same background-color, including its @supports fallback. The t3-chat light-theme override in custom.css still wins as before

I compared every old/new pair above by compiling it with the app's own index.css (Tailwind 4.3.3, the @tailwindcss/node compile API) and diffing the emitted CSS. For the layout changes (wrappers, -mt-1, the dropped gap-0/pt-0), I read through SidebarContent/SidebarGroup/Input source to show they are equivalent. I did not take before/after screenshots. The repo's AGENTS.md tells subagents not to start dev servers or browsers without permission, and nothing here is meant to change pixels.

One caveat that applies to the 11px→2xs, 10px→3xs and 13px→studio swaps alike: rem tokens equal the old px values only at the default 16px root font size. The app never changes that size, but a browser with a non-default base font size would scale these texts like the rest of the UI.

Delete button

The image picker's and the library's hover-revealed delete Button had bg-popover opacity-0 transition-opacity group-*/focus-visible/pointer-coarse:opacity-100 in its className (6 × no-restyle, 1 × require-static-classes).

Old New What changes
<Button className="absolute right-1 top-1 bg-popover opacity-0 transition-opacity group-focus-within:opacity-100 group-hover:opacity-100 focus-visible:opacity-100 pointer-coarse:opacity-100"> <span className="absolute right-1 top-1 flex opacity-0 transition-opacity group-focus-within:opacity-100 group-hover:opacity-100 has-focus-visible:opacity-100 pointer-coarse:opacity-100"> around a bare <Button>, as in upstream's KeybindingsSettings and PullRequestEditButton Same position, same fade, same reveal triggers. bg-popover already comes from the fork's outline variant. Motion change (approved by the owner): tailwind-merge used to let transition-opacity replace Button's own transition-[box-shadow,scale], so the press (scale 0.97) and the focus ring snapped instantly. Now they animate over 150ms like every other Button

Verification

  • vp run knip:check: clean
  • vp check: 0 errors, 783 warnings (unchanged). It was 44 errors before
  • vpr typecheck: passes
  • Tests for the changed files: web (BackgroundStudioPanel, ChangedFilesTree, UsageSidebarPanel.refresh, imageStore, lib/utils, themePalette) 59 passed. Server ServeMode 5 passed. contracts customBackground 14 passed. shared customBackground{Brightness,Fade,Rotation} 14 passed. desktop dictation 1 passed

Made by Claude Opus 5.5 (1M context) in Claude Code, as a subagent.

🤖 Generated with Claude Code

DiegoJohnsonL and others added 3 commits September 26, 2026 10:21
Knip's export check failed Fork CI on thirteen fork-only exports that
nothing imports. Each stays in use inside its file, so only the export
keyword goes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…w it renders

vp check failed Fork CI on arbitrary values and restyled ui components in
the background studio, the usage sidebar, the thread inset and the changed
files header. Each class now resolves to the same CSS through theme tokens
(declared in custom.css), wrapper elements or the component's own defaults.
The hover-revealed delete button is left as it was.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…Button

The delete buttons restyled Button with opacity and transition classes,
which the shadcn lint rejects. The fade now lives on a wrapping span, as
upstream does, and the Button is bare. Its press and focus ring animate
like every other Button again, since transition-opacity no longer
replaces Button's own transition.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@DiegoJohnsonL
DiegoJohnsonL merged commit 768c5a1 into custom-nightly Sep 26, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant