Skip to content

Components / Sections

Floor Plan

A home's floors drawn from its rooms: each room a rectangle on a grid of metres with its walls round it and its name and area over it, and beside the plan the same rooms as a list with the total. Pointing at a room in the list, or focusing it, lights the room on the plan, and pointing at a room on the plan lights its line (:has(), one rule a room up to twelve). Two or three floors take tabs. The plan is a picture of the list and is hidden from a screen reader, which reads the rooms and their areas. Zero JavaScript.

Live demo

Room by room

Point at a room in the list to find it on the plan.

Rooms · Ground floor

  • Living room22.5 m²
  • Kitchen18 m²
  • Hall7.5 m²
  • Dining room19.5 m²

Total67.5 m²

Rooms · First floor

  • Bedroom 118 m²
  • Bedroom 218 m²
  • Bathroom10.5 m²
  • Bedroom 312.3 m²
  • Landing8.8 m²

Total67.5 m²

Live, from the library itself, at full size: scroll, hover, navigate away and back. The demo is never gated.

Variants · each row writes the attribute the prop writes; the section's own CSS answers

tone
density

Measured

JavaScript of its own

0 B

Uses Reveal and the shared runtime (1.9 kB raw, once per site). With those included: 3.0 kB raw.

CSS 16.0 kB raw including the base tokens. Measured from a production build, and again in CI for every change that can move it.

Browser support

Baseline · newly available

Chrome 105 · Firefox 121 · Safari 15.4; needs has. Elsewhere: without :has() the plan and the list do not light each other, and only the first floor shows.

Install Pro

The demo above is never gated; the source is. With a key in components.json (see account), the registry serves it like any other item:

terminal
npx shadcn@latest add @moonarc-pro/floor-plan
src/pages/index.astro
---
import FloorPlan from '@/components/moonarc/pro/FloorPlan.astro';
---
<FloorPlan
  headline="Floor plan"
  floors={[
    { label: 'Ground floor', rooms: [
      { name: 'Living room', x: 0, y: 0, w: 6, h: 4.5 },
      { name: 'Kitchen', x: 6, y: 0, w: 4, h: 4.5 },
      { name: 'Hall', x: 0, y: 4.5, w: 3, h: 2.5 },
      { name: 'Dining', x: 3, y: 4.5, w: 7, h: 2.5 },
    ] },
  ]}
/>

Without a key the registry answers 401 with an upgrade message. Everything this section composes is free: reveal.

Props

PropTypeDefaultDescription
floors{ label; rooms: { name; x; y; w; h; block? }[] }[]noneOne to three floors, each one to twelve rooms placed in metres from the top left corner; block tints a room.
unitstring'{n} m²'How an area is written: {n} is the number of square metres.
words{ rooms?; total?; floors? }EnglishThe words over the list, before the total and the tabs' name.
headlinestringnoneThe heading.
eyebrowstringnoneA short line above the heading.
copystringnoneA line under the heading.
level2 | 32Heading level of the heading.
tone'surface' | 'muted' | 'ink' | 'brand'unset (paints nothing)The section's ground.
density'compact' | 'cozy' | 'roomy''cozy'Block padding ×0.8 / ×1 / ×1.25 through --ma-density.

Theming and overrides

The section reads the theme contract (shadcn's variable names with the base tokens as fallback), so a pasted theme or one --ma-brand recolours it. Its class names are the override surface and stay stable; a named slot replaces the matching prop with your own markup.

Classes

.ma-plan.ma-plan__copy.ma-plan__drawing.ma-plan__eyebrow.ma-plan__floor.ma-plan__head.ma-plan__headline.ma-plan__inner.ma-plan__item.ma-plan__label.ma-plan__list.ma-plan__radio.ma-plan__room.ma-plan__subhead.ma-plan__svg.ma-plan__tab.ma-plan__tabs.ma-plan__total

Slots

slot="headline"

Reduced motion

A room lights at once, with no fade.

With ClientRouter

CSS only.

Why it is built this way

Replaces: Floor plan images exported from a drawing tool. See the migration table.

Home Art

Backgrounds

A building drawn flat, for a listing that has no photograph yet: a house, a terrace, an apartment block, a villa, a cabin, a tower, an office or a shop, in the colour of the block or tone it sits on, with a shade, a light and the windows mixed from it.

every browserpointer

The Boathouse

Southbank, on the river path

$1,150,000 Guide price (a sample)

Bedrooms
4
Bathrooms
3
Floor area
204 m²
Built
2019

Book a viewing

The top of a home's own page: its pictures on one side, each a building drawn by HomeArt under a Lens that magnifies it at the pointer, with a row of thumbnails that picks one (radios and :has(), so the arrow keys move along them); on the other side the price, the title, the address, the facts and two actions.

newly · Chrome 105 · Firefox 121 · Safari 15.4clickpointer

What it would cost a month

Each month
$3,796
Loan
$676,000
Interest over the term
$462,770
Monthly payment by deposit and term
Deposit15 years20 years25 years30 years
10%$5,857$4,852$4,270$3,899
20%$5,206$4,313$3,796$3,465
30%$4,555$3,774$3,321$3,032

An estimate to plan with. A lender works out the real figure.

What a home costs a month.

every browserclick

Also: view transitions · how costs are measured · browser support · accessibility policy · five-minute setup · MCP for agents · this page as Markdown