# Quadrant — Dental Website Template Next.js

> For an independent dental practice: a dental website template nextjs where a patient points to the tooth and the page prices it before they phone.

- Price: $29, one-time
- License: Standard
- Version: 1.0.0
- Category: Local business
- Editions: React, HTML
- Dark mode: Yes
- Stack: Next.js >=15 <17, React >=19 <20, Tailwind CSS >=4 <5
- Dependencies: `lucide-react`

## What's inside

- 15 pages
- 47 components
- 83 design tokens plus 83 dark overrides

## Pages

| Path | Sections |
| --- | --- |
| `/` | `site-header`, `hero`, `chart-index`, `tooth-readout`, `visit-fees`, `visit-strip`, `site-footer` |
| `/treatments` | `site-header`, `treatments-index`, `treatments-end`, `site-footer` |
| `/treatments/fissure-sealant` | `site-header`, `treatment-chart`, `treatment-quote`, `treatment-notes`, `treatments-end`, `site-footer` |
| `/treatments/white-filling-front` | `site-header`, `treatment-chart`, `treatment-quote`, `treatment-notes`, `treatments-end`, `site-footer` |
| `/treatments/white-filling-back` | `site-header`, `treatment-chart`, `treatment-quote`, `treatment-notes`, `treatments-end`, `site-footer` |
| `/treatments/ceramic-crown` | `site-header`, `treatment-chart`, `treatment-quote`, `treatment-notes`, `treatments-end`, `site-footer` |
| `/treatments/root-canal` | `site-header`, `treatment-chart`, `treatment-quote`, `treatment-notes`, `treatments-end`, `site-footer` |
| `/treatments/removal` | `site-header`, `treatment-chart`, `treatment-quote`, `treatment-notes`, `treatments-end`, `site-footer` |
| `/treatments/wisdom-tooth-removal` | `site-header`, `treatment-chart`, `treatment-quote`, `treatment-notes`, `treatments-end`, `site-footer` |
| `/treatments/whitening` | `site-header`, `treatment-chart`, `treatment-quote`, `treatment-notes`, `treatments-end`, `site-footer` |
| `/children` | `site-header`, `children-opener`, `children-chart`, `children-readout`, `children-visits`, `site-footer` |
| `/team` | `site-header`, `team-chairs`, `team-days`, `team-desk`, `site-footer` |
| `/book` | `site-header`, `book-request`, `book-halfday`, `book-direct`, `book-asked`, `book-next`, `site-footer` |
| `/emergency` | `site-header`, `emergency-opener`, `emergency-before`, `site-footer` |
| `/components` | `site-header`, `site-footer` |

## Components

| Name | What it renders |
| --- | --- |
| `site-header` | The wordmark, four routes with aria-current, the phone, the mode toggle and a quiet "Ask for a time"; below lg the routes take a second row under one hairline, and at 375 the phone keeps the top row so a patient can ring in one tap. |
| `hero` | The H1 "Point to the tooth.", the first look's fee in one sentence, "Book a first look" and the call link, beside the Chair 2 plate cropped at its fixture focal point; unphotographed, the H1 row runs the full measure and the chart rises into the first screen. |
| `chart-index` | The record card holding the 32-tooth chart at 8px a millimetre, the Zsigmondy cross, the by-name select for anyone unsure which tooth, and the live readback under it. |
| `tooth-readout` | What the picked tooth would need: its chip and name, the first look itemised to $116, every tooth-specific fee that applies with who does it, and the three dentists who do a first look, with or without their portraits. |
| `visit-fees` | The two whole-mouth visits a patient asks about by name, a check-up and a new-patient visit, each itemised from the schedule to its sum and its chair time. |
| `visit-strip` | Today's held pain slots, today's hours, the address, funds claimed at the desk, and the route's one repeat of the filled action. |
| `site-footer` | The week as a real table with today named in words, the address and phone, every route and the styleguide link, and the one line that says fees are in Australian dollars. |
| `treatments-index` | All fifteen fees as one record card: the eight tooth-specific rows each with its 160px chart strip and where-words, the root canal's range and three canal steps with its pricing rule in a hint, the first look's sum, and the five whole-mouth rows with their visit sums. |
| `treatments-end` | The step every fee leads to: the first look itemised, funds claimed at the desk, what is referred out, the filled action and the call, full width on the card ground. |
| `treatment-chart` | A treatment page's masthead over its own chart: the strip and "Done on N teeth" in the card header, the by-name select, the 32 radios, and a readback that re-prices on every tooth, a root canal by its canal count. |
| `treatment-quote` | The re-priced fee for the picked tooth at display size, the lines it is made of, each visit and the interval between them, and who would see you; on a tooth it is not done on, where it is done and every fee that is. |
| `treatment-notes` | A treatment's clinical words as native details rows, the first open, beside the other fees that are done on one tooth; never a fee behind a disclosure. |
| `children-opener` | The kids'-corner plate full bleed, "Point to the wobbly one." with who sees children and what a first visit costs, the filled action and the call, beside the baby chart; unphotographed, the words and the chart open the page. |
| `children-chart` | The 20-tooth baby chart on tenth-millimetre columns at the adult chart's 8px a millimetre, in its own 552px record card, with the by-name select and a readback that says when the tooth usually comes out. |
| `children-readout` | A baby tooth's arrival, the adult tooth that follows it and the one that arrives behind it, then the first look and every fee that reaches that tooth with who does it. |
| `children-visits` | Five things that happen at a child's first visit, both kids' visits itemised to $137 and $114 with their chairs and people, funds at the desk, and the end repeat of the action. |
| `emergency-opener` | A type-only head whose H1 is the held same-day slots as a sentence that moves with the clock, the desk's open state and the address beside it, who sees you, the filled call and the 000 line. |
| `emergency-before` | Five steps written as the desk would say them, what a first look costs itemised to $116 and its minutes, the promise that anything more is priced first, and the end repeat of the call. |
| `team-chairs` | Four columns in chair order on a graphite rule, each a 3:4 portrait, name, role, week strip and the person's own fee rows on one subgrid; unphotographed, four ruled rows with the chair numeral in the portrait's place. |
| `team-days` | A person's week as six cells on a shared hairline, the days they are in reversed out in bold ink, with the sentence it stands for as the accessible text. |
| `team-desk` | The front desk across the full width: the person a request reaches, her days and duties, the two-hour call-back promise, "Ask for a time" and the call, with or without the reception plate. |
| `book-request` | The request form whose first field is the compact chart, optional and pre-picked from ?tooth=, then what is wrong, name, phone, the half-day and new or existing patient, validating with a focused summary and posting with no script. |
| `book-halfday` | The week as a timetable of morning and afternoon cells with their hours, one radio group and one tab stop, "First free time, any day" across the foot, and a readback naming the dentists in that half-day. |
| `book-direct` | The direct hand-off for a practice whose own system takes bookings: one record card with "Book online" to the system's URL and the phone with today's desk status. |
| `book-asked` | The tooth asked about on the home page, carried into the direct state as the picked-tooth chip and one line saying to mention it when booking. |
| `book-next` | Beside the form, what happens after sending in three timed steps, the same-day pain slots with the call, and where the practice is, with the shopfront plate when photographed. |
| `ui/tooth-chart` | The signature's picker on ui/variant-selector: 32 adult or 20 baby cells at their real widths on a half-millimetre grid, the cross ruled between the arches, the picked tooth filled in the orchid; arches from md, or quadrants pinned at any width. |
| `ui/chart-strip` | The chart's own geometry at 160px, read and not operated: the teeth a fee applies to filled in the orchid, the rest on the card, the cross between the arches. |
| `ui/tooth-state` | The one picked tooth a route's sections share, seeded from ?tooth= on the server and after hydration, so the action's href, the chart and the readout always agree. |
| `ui/tooth-chip` | The picked tooth's FDI number in the mono at lead size on the accent wash, a full-round label that never reads as a button; the only ground the accent paints. |
| `ui/fee-line` | One schedule row as a list item: the house code in the mono, the treatment's name and one line of what it involves, and the fee right-aligned in tabular figures over a hairline. |
| `ui/button` | The one action shape in two weights, filled orchid with data-cta primary or a quiet graphite outline, 44px tall, hover and press moving lightness, pressed sinking .98, and an aria-current underline when it is the page it is on. |
| `ui/book-link` | "Book a first look", the filled action whose label never changes and whose href carries the picked tooth to /book. |
| `ui/text-link` | An underlined link in the deeper link ink, 2px on hover; the call beside every filled action is one, never a ghost button. |
| `ui/photo` | A generated plate cropped in code at its fixture focal point, square-cornered over the muted ground, tagged data-plate; decorative portraits sit beside the name they show. |
| `ui/mode-toggle` | One 40px icon button flipping enamel and graphite, named for what pressing it does, aria-pressed for the dark state, the choice kept in storage. |
| `ui/wordmark` | The practice's name set in Besley at the display weight, linking home, with data-brand-name for the rebrand preview; no drawn mark. |
| `ui/type` | The type roles as class strings: caption to d4 on the 1.333 ratio, the tracked label, the Besley heading, the Atkinson mono and tabular figures; the only file that names a --text-* token. |
| `ui/variant-selector` | A labelled set of native radios as bordered rows with the dot left visible; the chosen row steps to the neutral selection ground and a graphite edge, and the readback line under it is announced. The tooth chart composes the same part under its own recipe. |
| `ui/field` | A label, an optional (optional) mark and a one-clause note over a bare native input, select or textarea drawn on the white field with its 3.75:1 edge; an error keeps a critical edge, a circle-alert glyph and its sentence while the blue focus ring is drawn outside it. |
| `ui/form` | The booking request's form and fieldset, with no paint of its own while pending; on success, focus lands on a receipt set on the positive soft ground in the foreground ink. |
| `ui/form-error-summary` | The panel a rejected request inserts and focuses: critical's soft ground and edge, the count of answers to fix as a sentence, and a bulleted list of underlined links that each go to the field. |
| `ui/accordion-disclosure` | A native details row for aftercare and clinical explanation on a treatment page: label at body weight 600 above a hairline, a chevron that turns instantly on open, and the prose region at reading measure. Never wraps a fee. |
| `ui/card-panel` | The record card: a hairline edge and a lightness step off the page, the 0.5rem outer corner, no shadow, a Besley title and an Atkinson meta line over the header's one rule, and an optional footer; the bleed extent drops the side edges and corners. |
| `ui/popover` | A small record card anchored to its trigger: the overlay ground, a hairline edge, the 0.5rem corner, a Besley header over the reasoning, no arrow and no shadow, placed rather than faded. |
| `ui/hint` | A one-clause helper line with a 24px question-mark trigger on its first line, muted at rest and in the link ink on hover; pressing it opens the fee rule's reasoning on the popover's surface. |
| `ui/dialog` | A record card over a graphite scrim, rising from the bottom edge at 375 and centred from sm, with a Besley title, a 40px close button, a scrolling body and a muted footer row; the critical tone draws the whole edge, never a stripe. |
## Design tokens

| Token | Light | Dark override |
| --- | --- | --- |
| `--background` | `#f6f4ef` | `#171615` |
| `--foreground` | `#1f1d1b` | `#ede9e2` |
| `--card` | `#fffefb` | `#1f1e1c` |
| `--card-foreground` | `#1f1d1b` | `#ede9e2` |
| `--secondary` | `#e6e2dc` | `#2d2b28` |
| `--secondary-foreground` | `#1f1d1b` | `#ede9e2` |
| `--muted` | `#efece7` | `#11100f` |
| `--muted-foreground` | `#625c55` | `#a8a198` |
| `--border` | `#dcd6cc` | `#34312d` |
| `--surface-overlay` | `#fffefb` | `#282624` |
| `--primary` | `#be04ca` | `#f13bfe` |
| `--primary-foreground` | `#ffffff` | `#1a0a1c` |
| `--primary-hover` | `#a308ad` | `#f574fe` |
| `--primary-active` | `#8a0193` | `#f69ffb` |
| `--accent` | `#f7e4f8` | `#3b2340` |
| `--accent-foreground` | `#9a12a3` | `#f2b3f6` |
| `--link` | `#9a12a3` | `#f0a6f6` |
| `--link-hover` | `#801188` | `#f9c1fd` |
| `--ring` | `#2f5aa8` | `#8fb3f0` |
| `--field` | `#ffffff` | `#141312` |
| `--field-border` | `#8a8379` | `#77716a` |
| `--control-border` | `#8a8379` | `#77716a` |
| `--selection` | `#e9e6df` | `#302d2b` |
| `--selection-foreground` | `#1f1d1b` | `#ede9e2` |
| `--selection-border` | `#1f1d1b` | `#ede9e2` |
| `--chart-rule` | `#cfc9be` | `#3d3a36` |
| `--chart-cross` | `#8a8379` | `#77716a` |
| `--positive` | `#137738` | `#68ca80` |
| `--positive-foreground` | `#ffffff` | `#171615` |
| `--positive-soft` | `#e5f5e7` | `#15291a` |
| `--positive-border` | `#a9d0b0` | `#2f5838` |
| `--positive-fill` | `#2d7b44` | `#60ac72` |
| `--warning` | `#825b00` | `#edb345` |
| `--warning-foreground` | `#ffffff` | `#171615` |
| `--warning-soft` | `#fbf1dc` | `#2d220f` |
| `--warning-border` | `#dcc49c` | `#644f2a` |
| `--warning-fill` | `#966a00` | `#ca9c48` |
| `--critical` | `#ba2d1f` | `#f87966` |
| `--critical-foreground` | `#ffffff` | `#171615` |
| `--critical-soft` | `#ffebe7` | `#351c18` |
| `--critical-border` | `#e9b6ad` | `#6e3e36` |
| `--critical-fill` | `#a74639` | `#e17363` |
| `--scrim` | `rgb(31 29 27 / 0.48)` | `rgb(0 0 0 / 0.62)` |
| `--radius` | `0.375rem` | `0.375rem` |
| `--radius-cell` | `0rem` | `0rem` |
| `--radius-card` | `0.5rem` | `0.5rem` |
| `--radius-chip` | `9999px` | `9999px` |
| `--tooth-mm` | `0.5rem` | `0.5rem` |
| `--tooth-row` | `3.75rem` | `3.75rem` |
| `--tooth-row-compact` | `3rem` | `3rem` |
| `--chart-cross-width` | `2px` | `2px` |
| `--strip-width` | `10rem` | `10rem` |
| `--chart-measure` | `calc(127 * var(--tooth-mm) + 2px)` | `calc(127 * var(--tooth-mm) + 2px)` |
| `--icon-stroke` | `1.75` | `1.75` |
| `--ease-house` | `cubic-bezier(0.16, 1, 0.3, 1)` | `cubic-bezier(0.16, 1, 0.3, 1)` |
| `--duration-micro` | `120ms` | `120ms` |
| `--duration-state` | `150ms` | `150ms` |
| `--text-caption` | `0.75rem` | `0.75rem` |
| `--leading-caption` | `1.4` | `1.4` |
| `--text-small` | `0.875rem` | `0.875rem` |
| `--leading-small` | `1.45` | `1.45` |
| `--text-body` | `1rem` | `1rem` |
| `--leading-body` | `1.55` | `1.55` |
| `--text-lead` | `1.125rem` | `1.125rem` |
| `--leading-lead` | `1.6` | `1.6` |
| `--text-d1` | `1.5rem` | `1.5rem` |
| `--leading-d1` | `1.25` | `1.25` |
| `--tracking-d1` | `-0.005em` | `0.0085em` |
| `--text-d2` | `2rem` | `2rem` |
| `--leading-d2` | `1.2` | `1.2` |
| `--tracking-d2` | `-0.01em` | `0.0035em` |
| `--text-d3` | `clamp(2rem, 1.55rem + 1.9vw, 2.666rem)` | `clamp(2rem, 1.55rem + 1.9vw, 2.666rem)` |
| `--leading-d3` | `1.15` | `1.15` |
| `--tracking-d3` | `-0.015em` | `-0.0015em` |
| `--text-d4` | `clamp(2.5rem, 1.6rem + 3vw, 3.553rem)` | `clamp(2.5rem, 1.6rem + 3vw, 3.553rem)` |
| `--leading-d4` | `1.08` | `1.08` |
| `--tracking-d4` | `-0.02em` | `-0.0065em` |
| `--tracking-label` | `0.06em` | `0.06em` |
| `--weight-display` | `600` | `500` |
| `--font-display` | `var(--font-quadrant-display), Rockwell, Georgia, serif` | `var(--font-quadrant-display), Rockwell, Georgia, serif` |
| `--font-text` | `var(--font-quadrant-text), ui-sans-serif, system-ui, sans-serif` | `var(--font-quadrant-text), ui-sans-serif, system-ui, sans-serif` |
| `--font-sans` | `var(--font-text)` | `var(--font-text)` |
| `--font-mono` | `var(--font-quadrant-mono), ui-monospace, 'Courier New', monospace` | `var(--font-quadrant-mono), ui-monospace, 'Courier New', monospace` |
## Use it

- Registry: `bunx shadcn add https://tailthemes.com/r/quadrant.json`
- MCP: [https://tailthemes.com/api/mcp](https://tailthemes.com/api/mcp)
- Download: [https://tailthemes.com/api/download/quadrant](https://tailthemes.com/api/download/quadrant)

## Links

- Product page: [https://tailthemes.com/themes/quadrant](https://tailthemes.com/themes/quadrant)
- Live preview: [https://tailthemes.com/preview/quadrant](https://tailthemes.com/preview/quadrant)
- Docs: [https://tailthemes.com/docs/quadrant](https://tailthemes.com/docs/quadrant)
- Manifest JSON: [https://tailthemes.com/api/themes/quadrant](https://tailthemes.com/api/themes/quadrant)
- Registry item: [https://tailthemes.com/r/quadrant.json](https://tailthemes.com/r/quadrant.json)
