Skip to content

feat(F0Dialog): a footer action can be a route - #5258

Draft
sauldom102 wants to merge 1 commit into
mainfrom
feat/dialog-action-href
Draft

feat(F0Dialog): a footer action can be a route#5258
sauldom102 wants to merge 1 commit into
mainfrom
feat/dialog-action-href

Conversation

@sauldom102

Copy link
Copy Markdown
Collaborator

Description

A footer action was always a handler: primaryAction / secondaryAction required onClick and took no href.

But some footer actions leave the dialog — "Go to post", "Open in Contracts" — and a place you cannot cmd-click is a place the reader has to come back from: no new tab, no copied link, no middle click. DialogControls already takes a url for its resource affordance and says why in its own comment ("routed through the app's LinkProvider, so it is cmd/middle-clickable"); footer actions had no equivalent.

Came up wiring the Home's Communities carousel: a post opens in F0CarouselDialog, and the way out to the post's own page belongs in the footer as a link.

Public API

F0DialogPrimaryAction and F0DialogSecondaryAction now take a route or a handler:

type F0DialogActionTarget =
  | { href: string; onClick?: () => void }
  | { href?: never; onClick: () => void }

A union rather than two optional fields, so a link cannot be declared without somewhere to go and a handler cannot be declared without something to do. Both together is a link that also reports the press (analytics, closing what's behind it). The footer spreads whichever it was given into F0Button, which has supported href all along — so nothing new renders, an existing button just becomes an anchor when it's given a route.

Unchanged: every existing call site (they all pass onClick), and the multi-action dropdown form — ButtonDropdownItem has no href, so a footer of several actions still carries handlers only. Worth a follow-up if a dropdown ever needs a link in it.

Tests

F0Dialog.footer-actions.test.tsx — a primary action with a route renders as a link with that href, a secondary one too, a handler action stays a button and fires, and a link that also has onClick reports the press. 10 pass across src/patterns/F0Dialog/; build:types and oxlint clean.

Pairs with #5256, which exports F0CarouselDialog so an app can use it at all.

🤖 Generated with Claude Code

A footer action was always a handler. But some of them LEAVE the dialog —
"Go to post", "Open in Contracts" — and a place you cannot cmd-click is
a place the reader has to come back from: no new tab, no copied link, no
middle click. `DialogControls` already takes a `url` for its resource
affordance, and says why in its own comment; footer actions could not.

`primaryAction` and `secondaryAction` now take a route OR a handler, as a
union, so a link cannot be declared without somewhere to go and a handler
cannot be declared without something to do. Both together is a link that
also reports the press. The footer spreads whichever it was given into
`F0Button`, which has supported `href` all along.

The multi-action (dropdown) form is unchanged: `ButtonDropdownItem` has
no href, so a footer of several actions still carries handlers only.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions github-actions Bot added feat react Changes affect packages/react labels Aug 26, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Review policy: Feature

The PR title starts with feat, so this is a feature: it needs one approval from f0-devs AND one from f0-designers (rule 3).

Required approvals

Team Why Status
@factorialco/f0-devs Features need a dev approval ⏳ pending
@factorialco/f0-designers Features need a design approval ⏳ pending
How this was decided
  • PRs touching only sds/ modules require their owners and nothing else.
  • Otherwise, docs-only changes (*.md, *.mdx, *.stories.tsx, anything in __stories__/) → one f0-general approval.
  • Otherwise, feat: titles → one f0-devs and one f0-designers approval. Not a feature? Fix the title prefix.
  • Anything else → one f0-devs approval.
  • Add the needs-design-review label to also request a design approval on any PR.
  • Creating a new sds/ module (new package.yml) additionally requires an f0-general approval.

Policy source: ownership/review-policy.ts · Team members: ownership/teams.yml

@github-actions

Copy link
Copy Markdown
Contributor

✅ No New Circular Dependencies

No new circular dependencies detected. Current count: 0

@github-actions

Copy link
Copy Markdown
Contributor

📦 Alpha Package Version Published

Use pnpm i github:factorialco/f0#npm/alpha-pr-5258 to install the package

Use pnpm i github:factorialco/f0#4aaa46d376e258f46bab9205c6ec9b3d4146b6ff to install this specific commit

@github-actions

Copy link
Copy Markdown
Contributor

🔍 Visual review for your branch is published 🔍

Here are the links to:

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Breaking public API changes (3)

These public exports were renamed/removed, or had a property/parameter removed, retyped, or newly required compared to main — that breaks consumers. Adding new exports or new optional props is always safe and is not flagged. If a breaking change is intentional, note it in the PR description and use a feat!:/BREAKING CHANGE commit so the release is a major bump.

Comparing f0, experimental and ai against main. Adding components, types, or optional props is safe. This check is non-blocking.

f0

  • ✏️ F0DialogActionsPropsbreaking change

    • required primaryAction.href was added
    • required secondaryAction.href was added
    before → after
    // before
    F0DialogActionsProps
    // after
    F0DialogActionsProps
  • ✏️ F0DialogPrimaryActionbreaking change

    • type changed shape (object → union)
    before → after
    // before
    F0DialogPrimaryAction
    // after
    F0DialogPrimaryAction
  • ✏️ F0DialogSecondaryActionbreaking change

    • type changed shape (object → union)
    before → after
    // before
    F0DialogSecondaryAction
    // after
    F0DialogSecondaryAction

⚠️ Could not analyze component-status (no-base) — a build may have failed; results may be incomplete.

@github-actions

Copy link
Copy Markdown
Contributor

♿ Accessibility (axe) — components changed in this PR

✅ No a11y issues in the stories this PR changed.

Scope: only stories in the files/component folders this PR changed. It can't yet flag downstream ripple from shared-code/token changes, or diff against main (planned: base-vs-head delta).

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for packages/react

Status Category Percentage Covered / Total
🔵 Lines 68.86% 28991 / 42099
🔵 Statements 67.82% 30669 / 45218
🔵 Functions 61.66% 6914 / 11212
🔵 Branches 61.48% 21697 / 35286
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/react/src/patterns/F0Dialog/types.ts 0% 100% 100% 0% 4-12
packages/react/src/patterns/F0Dialog/components/F0DialogFooter.tsx 66.66% 90% 45.45% 69.23% 39-48, 75-84
Generated in workflow #17509 for commit ed9cb54 by the Vitest Coverage Report Action

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking changes feat react Changes affect packages/react

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant