Deck
Browse the catalog

Experience / Application

Settings

  • page
  • play-fn

Settings — the nav and whichever section it has open.

The nav items carry no href. In the product these are real routes, but SettingsNav renders a route-less item as a <button>, and a button that switches the panel is the honest control for a composition with no router under it — the same call AppShell makes for the account drawer. A real app passes its own hrefs and lets the router do the work.

SettingsNav collapses to a native <select> on a phone, so this page needs no breakpoint of its own for the navigation.

Not exported from @meetcard/deck — this is a composed screen, built from the components below rather than shipped as one.

Stories

Every preview below is the real component, rendered in this page from the same story Storybook runs. The width control resizes each preview's container; CSS media queries still follow the browser window, so breakpoint behaviour is worth checking in Storybook.

How you appear on your card, and the rules behind the booking button on it. The longest section, and deliberately one screen — it is all the same object.

Profile
Source
const Profile = () => <Settings section="profile" />;

The two buttons on the card, in the order the card shows them.

Reordered with the keyboard here, which is the path that has to work: the product's own screen offers dragging and nothing else, and a grip you can only drag is a control that does not exist for anyone using a keyboard.

Reordering Calls To Action
Source
const ReorderingCallsToAction = () => <Settings section="profile" />;

The booking button's position is yours; what it says and where it points are not — those are set in Book with, and two places to edit one button is how they come to disagree. So its fields are read-only and its handle is not: where a button sits on your card is your decision even when its wording is not.

The Booking Button Is Managed Elsewhere
Source
const TheBookingButtonIsManagedElsewhere = () => <Settings section="profile" />;

Sign-in, providers, sessions, and the two doors out — export and delete.

Account
Source
const Account = () => <Settings section="account" />;

Which alerts arrive, and how. The cadence nests under what it paces.

Notifications
Source
const Notifications = () => <Settings section="notifications" />;

Every plan side by side — the screen Billing's "Compare plans" opens, and a route of its own in the product (/settings/billing/plans).

Comparing Plans
Source
const ComparingPlans = () => <Settings section="billing" />;

Prices move with the billing period rather than being listed twice — the question here is which plan, and two price columns is two questions.

Plans By The Year
Source
const PlansByTheYear = () => <Settings section="billing" />;

Plan, usage, seats, payment, invoices.

Billing
Source
const Billing = () => <Settings section="billing" />;

The company behind the business card, and where team bookings go.

Company
Source
const Company = () => <Settings section="company" />;

No save bar. Connecting a service is an OAuth round trip that has already happened by the time the row changes.

Integrations
Source
const Integrations = () => <Settings section="integrations" />;

Invitations sit in the roster, because a seat is spent when one goes out.

Team
Source
const Team = () => <Settings section="team" />;

Moving between sections. Each one remounts, so no draft leaks into the next.

Switching Sections
Source
const SwitchingSections = () => <Settings />;

The page in the shell it actually lives in.

In The Shell
Source
const InTheShell = () => (
  <AppShell currentId="/settings">
    <Settings />
  </AppShell>
);

Props

PropTypeDefaultDescription
onSectionChange(section: SettingsSectionId) => void——
section| 'profile' | 'account' | 'notifications' | 'billing' | 'company' | 'integrations' | 'team'—Which section is open. Uncontrolled unless onSectionChange is given.

Open in Storybookfor controls, the a11y panel and the interaction runner.