Components
Each page has a live preview, the markup in three languages, and the reasoning behind anything in it that looks unusual.
The preview runs inside a frame against /v2/wayne-ui.css, which is the file packages/css/dist produced on the build that published this page. It has its own light and dark switch, because most of the color defects found while building this system were visible in only one theme.
The three code samples are checked rather than trusted. When this site builds, every wsu- class name in every sample is looked up in contract/markup-contract.json and in the shipped stylesheet, and a name that appears in neither fails the build. Documentation showing markup that nothing renders is worse than no documentation.
Chrome
The frame around an application. Layout, navigation, identity.
- App shellThe page frame: ribbon, bar, body, footer. A four-row grid where the body takes the remaining height, so a short page still puts its footer at the bottom of the viewport.
- App barOne bar carrying the shield, the application name, the application navigation, search, the theme switch and the signed-in user.
- App searchSearch inside the application, not wayne.edu. A real form role="search" rather than a bare input, so it lands in the search landmark and submits on Enter with no script.
- SidebarSection navigation. Docked at desktop widths, a drawer below them.
- Sidebar navThe links inside a Sidebar: one heading's worth, or several, with one level of nesting.
- BreadcrumbsWhere this page sits. The last crumb is the current page and is not a link.
- Page headerThe page h1, an optional subtitle, and the actions that belong to the page as a whole.
- Skip linkWCAG 2.4.1. First thing in the tab order, invisible until focused.
- Environment ribbonA strip saying which non-production environment this is.
- FooterThe compact footer used by the internal template.
- MastheadWayneUI's own university masthead: a wordmark, a couple of utility links and an optional wayne.edu search box, styled on the design system's own tokens rather than the official chrome.
- Official headerThe real wayne.edu masthead, rendered from @waynestate/wsuheader rather than copied into the project.
- Official footerThe real wayne.edu footer, rendered from @waynestate/wsufooter, the required pair for OfficialHeader.
- University footerWayneUI's own full university footer: a wordmark, an address, grouped links and the legal links a public site is expected to carry, styled on the design system's own tokens.
- IconA symbol from the Lucide sprite, inheriting currentColor.
Content
What goes inside main.
- ButtonFive variants, three sizes, and an icon-only form that insists on a name.
- BadgeA small status pill. The text is not optional.
- KbdA literal keyboard key or shortcut, styled as a key cap.
- Status dotA colored dot with a text label beside it. Five variants, matching Badge.
- CardA bounded region of content, with an optional real heading and a footer.
- StatA single figure with its label.
- TableA data table inside a scrollable, focusable region with a caption for its name.
- PaginationPage links, with the current page marked and the ends always reachable.
- TabsA tablist with roving tabindex, arrow-key movement and a focusable panel.
- CarouselA set of slides, moved between with Previous, Next or a row of dots. Never advances on its own.
- AccordionA stack of disclosures, each a native <details> and <summary>, so a reader opens only the ones they need.
- AvatarA person, as a photo or as initials. Always named, because an avatar identifies someone.
- ChatA conversation, read in the order it happened.
- Code blockA block of code with a button that copies it.
- BrowserA browser window around whatever the slot holds: a page, a screenshot, a live embed.
- WindowA generic window frame around whatever the slot holds.
- PhoneA phone body around whatever the slot holds.
- TerminalA recorded terminal session: what running something looked like, not code to take away.
- CountdownA count to a fixed moment, such as a registration deadline or an application closing.
- DividerA rule between blocks of content, with an optional label.
- Text rotateA short list of facts, shown one at a time. An announcement strip, not a marketing carousel.
- TimelineA sequence of dated events, read as one history.
Forms
Every control carries its own label, hint and error wiring.
- InputA labeled text field with its hint above and its error below, both wired with aria-describedby.
- TextareaMulti-line text, wired with the same label, hint and error contract as Input.
- SelectA native select with the same label, hint and error wiring as every other field.
- Checkbox and radioNative controls, with the label wrapping the input so the whole thing is a target.
- Radio groupA set of radios in one fieldset, with one legend and one error for the whole group.
- Error summaryOne list at the top of a failed form, each entry linking to the field that failed.
Feedback
Telling someone what happened, or that nothing is there.
- DialogA native dialog element, opened modally.
- Empty stateThere is nothing here yet, and here is what would change that.
- AlertA status message with an icon, a title and a role that matches its urgency.
- ToastA transient message in a live region, paused while it has focus or the pointer.
- SkeletonA loading placeholder that is announced once and drawn as decoration.
- LoadingAn in-progress marker with a text label beside it.
- ProgressA determinate progress bar, or an indeterminate one for a wait whose length nobody knows yet.
What the contract is
apps/examples/static-html/index.html and public-app.html are the source of truth for what WayneUI markup looks like. The Vue components, the Blade components and the framework-free PHP helpers all emit the same class names, the same ARIA and the same data attributes, which is the only reason the four consumer paths render identically rather than merely similarly.
That is not held together by anyone remembering. The templates are extracted:
node scripts/extract-contract.mjs # regenerate
node scripts/extract-contract.mjs --check # fail if staleEvery package tests against the result. If a template changes on purpose, every other path needs the same change, which is exactly what the failing check is telling you.