Skip to content

Channel — Videos screen - #1

Merged
argentinaluiz merged 7 commits into
mainfrom
channel-videos
Aug 25, 2026
Merged

Channel — Videos screen#1
argentinaluiz merged 7 commits into
mainfrom
channel-videos

Conversation

@argentinaluiz

Copy link
Copy Markdown
Contributor

Implementa a tela Channel — Videos do .pen, seguindo as regras de design/DESIGN-SYSTEM.md.

O que entra

15 componentes com fronteira 1:1 com o design (Masthead, Sidebar, Channel Header, Card / Video, Chip, Tab, os quatro botões, etc.), a rota app/[handle]/videos e as fixtures extraídas do próprio .pen.

Cada componente carrega data-component com o nome exato do frame. Isso transforma a fronteira 1:1 de convenção documentada em algo verificável por máquina — o audit já lê data-pencil-name do lado do design.

Traduções que dariam errado se fossem literais

design literal seria correto
thumbnail height: 201 h-[201px] aspect-video
$space-14 no Header Region p-14 (56px) px-[58px]
$radius-sm (8px) no Chip rounded-sm (4px) rounded-lg
$radius-xs (4px) no Badge rounded-xs (2px) rounded-sm
3 linhas de 3 cards grid-cols-3 auto-fill minmax(357px,1fr)

Verificação (§12)

Rodado a 1440 nos dois temas. Computed styles conferidos contra o design:

  • Chip 32px / 8px / 0 12px / 14px / 500
  • Sidebar Item 40px / 10px / gap 24px
  • Tab 48px / pt 13px / pb 1px / 16px
  • Card title 16px / 22px / 500 / pr 24px
  • Badge 4px / 1px 4px / 12px / rgba(0,0,0,0.6)

Tema escuro sai inteiro dos tokens — zero dark: no JSX. surface-pagergb(15,15,15), text-secondaryrgb(170,170,170), ambos batendo com o .pen.

Precisa de decisão de design

O .pen pede o glyph youtube da lucide para "YouTube Premium" e "YouTube Kids", mas ícones de marca saíram da biblioteca (não existe em lucide-react 1.34). SquarePlay entrou como substituto, marcado no código.

Fora de escopo

A variante shelf do Card / Video só é usada pela tela Home, que não entra aqui.

🤖 Generated with Claude Code

argentinaluiz and others added 3 commits August 25, 2026 17:48
Fifteen components and the page that composes them, translated from the .pen
under the rules in design/DESIGN-SYSTEM.md.

Every component carries data-component with its exact frame name from the
design, which turns the 1:1 boundary from a documented convention into
something a machine can check: the CI audit already reads data-pencil-name on
the design side, and the numeric comparator will join the two.

The translations that would have been wrong done literally:

- the thumbnail is aspect-video, not h-[201px]. That 201 is 16:9 of a 357px
  card frozen in pixels because the format has no ratio primitive, and the
  layout here is fluid
- the grid is auto-fill over minmax(357px, 1fr) with gap-x-4 and gap-y-8, which
  are the two gaps the design uses inside a row and between rows
- Header Region is px-[58px]. p-14 would be 56px
- $radius-sm is 8px, so Chip is rounded-lg; $radius-xs is 4px, so the badge is
  rounded-sm. Both names mean something else in Tailwind

Verified against the design at 1440 in both themes. Computed styles match on
every component measured — chip 32/8/0-12, sidebar item 40/10/gap-24, tab
48/13/1, card title 16/22/500 — and the dark theme comes entirely from tokens,
with no `dark:` anywhere in the JSX.

One divergence needs a design decision: the sidebar asks for lucide's `youtube`
glyph for Premium and Kids, but brand icons no longer ship with lucide-react.
SquarePlay stands in, marked in the code.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The audit hit error_max_turns on its first real run. Eighteen changed files,
four evidence files, and nine rules do not fit in twenty turns — and one of
those evidence files is 107KB, big enough to burn the context on a single Read.

Six of the nine rules are regular expressions over the diff. Paying an agent to
run them was the same mistake as handing it a browser: non-deterministic, slow,
and worse at the job than grep. scripts/drift-scan.sh runs them in a CI step
instead, and the agent starts from its output, verifies each occurrence, and
spends its turns on the three rules that actually need judgement against the
design.

The scan skips comment lines, because the components quote the rules in their
own comments — "NÃO os 56px de p-14" would otherwise report itself — and it
only flags the radii in the collision zone, since rounded-nav and rounded-full
are unambiguous. On this branch it comes back with no mechanical violations and
four radii to confirm.

The prompt now also forbids reading components.html whole and says to grep it
by data-pencil-name.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The audit ran out of turns again, at 31. The cause is scope rather than the
prompt: rule 7 asks whether a component exists in the design, and this branch
introduces fifteen of them at once, which is fifteen turns before any judgement
happens. A steady-state PR touches one or two.

Cross-checking data-component against the reusable frame names in the .pen is a
`comm` between two sorted lists, so the scan does it. On this branch: thirteen
matched, none unknown. What remains for the agent is the part that needs a
design to compare against.

The cap moves to 60 for the same reason — the first PR that lands a component
library is the worst case this audit will ever see.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Conflicts in the audit script and workflow taken from main, which carries the
newer versions.

<div className="flex items-center gap-1 text-body">
<span className="flex items-center gap-2">
<Link2 className="size-4 text-text-secondary" aria-hidden />

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regra 10 (drift de valor) — glyph do ícone diverge do design (§11)

O .pen especifica link para o Link Icon do Channel Links:

{ "fill": "$text-secondary", "height": 16, "icon": "link",
  "library": "lucide", "name": "Link Icon", "width": 16 }

O código usa Link2, que é outro glyph da lucide (corrente inclinada em vez da corrente partida). §11 é normativo e a tradução é mecânica — o kebab do .pen vira PascalCase: "link"Link. Diferente do caso youtubeSquarePlay em components/sidebar.tsx:27-33, aqui não há motivo de biblioteca: Link existe em lucide-react.

O resto do nó bate (size-4 = 16 ✓, text-text-secondary = $text-secondary ✓).

Correção — importar o glyph certo (na linha 2, import { Link2, Search }import { Link as LinkIcon, Search }; não há colisão com next/link neste arquivo):

Suggested change
<Link2 className="size-4 text-text-secondary" aria-hidden />
<LinkIcon className="size-4 text-text-secondary" aria-hidden />

Comment thread components/chip.tsx
Comment on lines +11 to +13
active
? "bg-surface-inverse text-text-inverse"
: "bg-surface-chip text-text-primary hover:bg-surface-hover",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regra 7 — variante de componente que não existe no .pen (§2.4, §9, §10)

O Chip do .pen tem um estado só:

{ "cornerRadius": "$radius-sm", "fill": "$surface-chip", "height": 32,
  "children": [{ "name": "Label", "fill": "$text-primary", ... }] }

E em screens.json os três Chip do Filter Chips são instâncias sem nenhum override — ou seja, na tela Channel — Videos desenhada as três pílulas são cinzas e iguais. O ramo active inverte superfície e texto, então <Chip label="Latest" active /> (app/[handle]/videos/page.tsx:25) renderiza uma pílula preta onde o design mostra uma cinza.

Os tokens usados existem, mas §2.4 fala de componente, não de token: "Nenhum componente que não exista no .pen. Precisou de um? Pare e peça design." E §9 autoriza sem design apenas hover:, focus-visible:, active:, disabled: e motion-reduce: — "filtro selecionado" é estado de produto, não de interação. Compare com o Tab, onde o estado selecionado é desenhado (o Indicator de 2px vem no componente com enabled: false), e por isso tab.tsx está correto.

O ramo inativo já bate com o design (bg-surface-chip / text-text-primary).

Correção: ou o .pen ganha a variante selecionada do Chip (§13: o design muda primeiro), ou o active fica só semântico — o aria-pressed da linha 7 já carrega o estado — até o design existir:

Suggested change
active
? "bg-surface-inverse text-text-inverse"
: "bg-surface-chip text-text-primary hover:bg-surface-hover",
active
? "bg-surface-chip text-text-primary"
: "bg-surface-chip text-text-primary hover:bg-surface-hover",

@argentinaluiz
argentinaluiz merged commit fce0d13 into main Aug 25, 2026
1 check 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