Skip to content

fix(web): restore PM wizard styling regression from specs 010-012#1152

Merged
zbigniewsobiecki merged 5 commits intodevfrom
fix/pm-wizard-styling-regression
Apr 18, 2026
Merged

fix(web): restore PM wizard styling regression from specs 010-012#1152
zbigniewsobiecki merged 5 commits intodevfrom
fix/pm-wizard-styling-regression

Conversation

@zbigniewsobiecki
Copy link
Copy Markdown
Member

Summary

Specs 010/3, 011, and 012 migrated the PM wizards (Trello/JIRA/Linear) off legacy per-provider step components onto shared step components + per-provider adapters. The migration preserved structure and SSR test coverage but stripped every visual style — the new components rendered raw <input>, <button>, <select>, <label> with BEM-style class names (pm-wizard-*) that are never defined in any CSS file anywhere.

User-visible symptom: the Linear API-key input was invisible (raw <input type="password">, no border, no padding, browser-default transparent background on the dark theme). Status/label/custom-field selects were borderless. Create/delete webhook buttons were unstyled. Linear info banner was a plain div.

This PR restores shadcn primitives + Tailwind throughout the PM wizard to match the legacy baseline, and adds a regression guard so this class of bug cannot silently recur.

  • Swap raw → shadcn across the seven shared StandardStepKind components (steps/*.tsx) and the four provider adapters ({trello,jira,linear}/webhook-step.tsx + jira/issue-type-step.tsx).
  • New NativeSelect primitive (ui/native-select.tsx) — SSR-safe <select> wrapper matching shadcn SelectTrigger's utility classes. Can't use shadcn Select (radix portal breaks renderToStaticMarkup).
  • New DataProps helper (lib/data-props.ts) — restores the [key: \data-${string}`]: unknownindex signature that@types/react19.1 dropped fromHTMLAttributes, needed so createElement(Button, { 'data-action': 'x' })` typechecks under strict mode.
  • Extract CopyButton to ui/copy-button.tsx (was awkwardly cross-file-imported from integration-scm-tab.tsx).
  • Regression guard (tests/unit/web/pm-wizard-styling-guard.test.ts) greps every .tsx under pm-providers/** for raw HTML interactive elements and fails CI if any slip back in.

5 atomic commits — reviewable each in isolation.

Test plan

  • npm test — 8202 / 8202 unit tests pass
  • npm run lint — clean
  • npm run typecheck — clean
  • cd web && npm run build — builds (the check that was hidden-failing before PR fix: web build + dev deploy failing on tsc strict checks #1151)
  • npx vitest run --project unit-core tests/unit/web/pm-wizard-styling-guard.test.ts — 15 / 15 pass
  • Post-merge browser smoke: Linear wizard API-key input visible; Trello wizard Create Webhook + delete + curl styled; JIRA wizard project/issue-type selects styled.

🤖 Generated with Claude Code

zbigniewsobiecki and others added 5 commits April 18, 2026 19:21
SSR-safe `<select>` wrapper matching shadcn SelectTrigger's utility
classes — shadcn's radix-based Select breaks renderToStaticMarkup,
so the PM wizards need a plain styled select they can use in
createElement paths.

DataProps is a tiny index-signature widener restoring the
`[key: \`data-\${string}\`]: unknown` shape that @types/react 19.1
dropped from HTMLAttributes — it's needed so createElement(Button,
{ 'data-action': 'x' }) typechecks under strict mode.

Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
Moved the previously cross-file-imported CopyButton from
integration-scm-tab.tsx into its own primitive under ui/copy-button.tsx.
The alerting tab and PM webhook adapters now import from the canonical
location instead of reaching into a sibling tab module.

Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
Swap raw <input>, <button>, <select>, <label> elements — all of which
shipped with pm-wizard-* BEM class names that have zero CSS definitions
anywhere — to shadcn Input/Button/NativeSelect/Label + Tailwind utility
classes across the seven shared StandardStepKind components.

The Linear API-key password field was invisible on the dark theme
because the raw <input> had no border, no padding, and browser-default
transparent background. Status/label/custom-field selects were
borderless. Credentials verify button and Create-label button were
unstyled. This commit brings them back to the legacy pre-spec-010/3
visual baseline without touching SSR-level behavior.

SSR tests in tests/unit/web/steps/ were loosened to match shadcn's
attribute-order-agnostic output and to walk by prop id rather than
raw element tag.

Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
Swap raw <button>, <select>, <label>, <input> elements to shadcn
primitives + Tailwind utility classes across the Trello, JIRA, and
Linear webhook-step adapters plus the JIRA issue-type step.

Visible fix: active-webhooks list now has bordered rows, delete button
is a real ghost-icon Button with a Trash2 icon, Create Webhook is a
primary Button with a spinner during creation, the curl fallback sits
inside a styled <details>/<summary> block, and the Linear info banner
uses the themed blue surface from the legacy component instead of raw
divs.

Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
New regression test walks every .tsx under pm-providers/** and fails
CI if any file contains createElement('input'|'button'|'select'|'label')
or <input/<button/<select/<label in JSX. Comments are stripped before
matching to avoid false positives on JSDoc prose.

This is the structural guard that was missing when specs 010/3, 011,
and 012 silently stripped the PM wizard styling — root tsc and SSR
tests passed because neither asserts visual output.

Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
@zbigniewsobiecki zbigniewsobiecki merged commit 0245daf into dev Apr 18, 2026
7 checks passed
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 18, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

zbigniewsobiecki added a commit that referenced this pull request Apr 18, 2026
Eight new tests, one per (provider × scenario) combo. Fresh setup →
false; edit with stored creds + empty API-key → true; edit with
re-typed API-key → false; edit without stored creds → false. Locks in
the #1152-follow-up contract that stored-creds-aware mutations route
through projectId instead of throwing "Missing credentials".

Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
zbigniewsobiecki added a commit that referenced this pull request Apr 18, 2026
* fix(pm-wizard): route edit-mode mutations through projectId

buildEditState intentionally leaves raw API credentials blank when
re-opening an existing integration (security), but the verify,
create-label, and create-custom-field hooks required form-state
credentials and threw "Missing credentials or team selection"
client-side before reaching the backend. The discovery hooks already
had the projectId fallback — now the mutation hooks do too.

Introduces shouldUseStoredCredentials(state) in pm-wizard-state.ts
as the single source of truth for "send projectId vs send credentials".
Each hook (useVerification, useTrello/LinearLabelCreation,
useTrello/JiraCustomFieldCreation) now picks the correct path.

Team / board / project-key checks stay — those come from config
state, not credentials, so their error messages are split out.

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

* fix(pm-wizard): always render Verify Connection button

The gate `(!state.isEditing || !state.hasStoredCredentials || credsReady)`
hid the button precisely when it was most useful — editing an existing
integration with stored credentials but an empty API-key field. User
had no way to test that the stored key still works.

Drop the gate. Enable the button whenever credentials are ready OR the
user is editing with stored credentials (backend resolves them via
projectId path). Add a muted "Using stored credentials" hint when
taking the stored-creds path so it's obvious what's happening.

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

* test(pm-wizard): cover shouldUseStoredCredentials edit-mode paths

Eight new tests, one per (provider × scenario) combo. Fresh setup →
false; edit with stored creds + empty API-key → true; edit with
re-typed API-key → false; edit without stored creds → false. Locks in
the #1152-follow-up contract that stored-creds-aware mutations route
through projectId instead of throwing "Missing credentials".

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

---------

Co-authored-by: Claude Opus 4 (1M context) <noreply@anthropic.com>
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