Design system

Import brand dialog

Reads a design system from a company's website, shows what it found on a sample section, and applies it to the workspace.

import ImportBrandDialog from "@/pages/library/ImportBrandDialog";
import "@/pages/library/library.css";

ImportBrandDialog sets up a workspace's design system from its website, so pages and ad creatives match the brand from the first draft. It is one large dialog with three steps: where the site is, the reading of it, and what was found, shown on a sample section before anything changes. Nothing is applied until the last step is confirmed.

The reading is scripted, like the rest of the mock. No request is made to the site. Any address containing "petavue" returns Petavue's own brand; any other address is hashed to one of four sample brands, so the same address always gives the same result.

The flow

Type an address such as meridian.com and press Enter or "Read my website". The checklist ticks off one line at a time, then the review opens. "Apply to design system" writes the result to the workspace and closes the dialog. Use "Reset design system" to go back to the defaults.

{importing && (
  <ImportBrandDialog
    onClose={() => setImporting(false)}
    onApplied={(brand, host) => {
      setImporting(false);
      setTab("design");
      toast.success(`${brand}'s design system imported from ${host}.`);
    }}
  />
)}

The dialog reads and writes the design store itself (useDesignStore in src/pages/library/useDesignStore.js). The caller only opens it and reacts once it is applied.

Steps

StepBodyCancelConfirm
FormA lead sentence, Website address, Company name and a note: "Nothing changes until you have seen what was found and applied it."Cancel: closesRead my website
ReadingThe address, then five lines that tick off every 620ms: opening the homepage, colours, fonts, corners and spacing, the logo, header and footer. The review opens 450ms after the last one.Cancel: closesReading…, which does nothing
ReviewOn the left, what was found: five colours with their hex values, the heading and body fonts drawn in themselves, a sample button with its corner radius, and the Library components it was matched to. On the right, a hero and a call-to-action banner drawn in the new brand at 330px tall.Back: returns to the formApply to design system

Form

  • Website address is required. Once https://, www. and any path are removed, it must be letters, digits and hyphens in two or more parts separated by dots; Meridian.com/pricing reads as meridian.com. Otherwise the field shows "Enter an address like yourcompany.com." after the first try.
  • Company name is optional. Its placeholder, and the name used when it is left empty, is the first part of the host with a capital letter: meridian.com gives "Meridian".
  • Enter in either field starts the reading.

What Apply changes

setDesign({ brand, colors, headFont, bodyFont, radius }). The logo and the heading and body sizes are kept. The two fonts are loaded from Google Fonts when the reading starts, so the review can draw them.

States

StateWhat shows
Address not validThe address field's error, after "Read my website" or Enter. The reading does not start.
Reading, current linePrimary text with a spinning CircleNotch in --color-primary-500. With reduced motion, the spinner stops.
Reading, done lineSecondary text with a filled CheckCircle in --color-green.
Reading, waiting line--color-grey-300 text with a still CircleNotch.

Layout

PartStyle
PanelDialog at lg, 800px, with .lib-import. The body scrolls past min(64vh, 620px).
Lead14px secondary text on a 21px line.
Checklist14px lines with a 14px gap and 16px icons, at least 250px tall so the dialog keeps its height.
ReviewTwo columns: 260px for what was found, the rest for the sample, 24px apart.
Section labels12px uppercase semibold secondary text.
Colour rowsA 22px chip with 6px corners, the role in 13px and the hex in 12px monospace --color-grey-500.
FontsThe heading font at 22px semibold and the body font at 15px, each with a 12px label in --color-grey-500.
SampleScaledPreview at 330px inside a 1px --color-grey-100 frame with 10px corners.

The colours, fonts and button in the review are the imported brand's, not Petavue's. That is the point of the step.

Props

PropTypeDefaultNotes
onClose() => voidEscape, scrim click, the close icon, and Cancel in the form and reading steps.
onApplied(brand: string, host: string) => voidCalled after the design store is updated. It does not close the dialog, so close it here.

Accessibility

  • The wrapper has role="dialog", aria-modal="true" and aria-label="Import from your website".
  • The address field has autoFocus, so typing can start at once. Its error is announced with role="alert".
  • The reading checklist is a plain list with no live region. A screen reader is not told as lines tick off or when the review opens.
  • "Reading…" looks like an enabled primary button but does nothing while the site is read. The Dialog panel has no way to disable it.
  • Escape closes the dialog at any step, including the review, and the reading is lost.
  • Focus is not kept inside the dialog and is not returned to the button that opened it.

Do and don't

  • Do let people see the result on a real section before anything changes. That is why the review comes before Apply.
  • Do tell people after applying where the result went. The Library switches to the Design system tab and says which site it came from.
  • Don't apply anything during the reading step.
  • Don't use this dialog to edit single values. Colours, fonts and corners are changed one at a time on the Design system tab.

When to use it

Use it wherever a workspace has no brand yet, or wants to start again from its website. It is self-contained: render it, and handle onClose and onApplied. For other multi-step setups, build on a large Dialog from @/ui in the same way: one dialog, the confirm label naming the next step, and Back in place of Cancel after the first step.

Where it is used

FileWhat
src/pages/library/LibraryPage.jsx, LibraryPageOpened by "Import from website" in the Library header, and by the same button at the top of the Design system tab (DesignSystemTab). On apply, the Library switches to the Design system tab and shows a toast.

On this page