# FloorPlan

> A salon plan on a logical-unit canvas, read-only unless `editable`.

Source: https://ui.jcsoftdev.com/docs/components/floor-plan

A salon plan on a logical-unit canvas, read-only unless `editable`. The canvas fills its container and keeps the
`width` x `height` aspect ratio, and every item is placed in percentages of it, so hit areas
always match what is drawn. Items are buttons in array order with roving arrow-key focus. A
state shows as an icon plus text (never colour alone), `late` and `selected` as one ring around
the whole item, and the label moves under the shape when the table is too small to hold it.

## Import

```ts
import { FloorPlan } from "@jcsoftdev/ui/containers";
```

Single-component entry points tree-shake to just this component: `@jcsoftdev/ui/containers/floor-plan`.

## Usage

```tsx
<FloorPlan
  width={36}
  height={26}
  items={plan.items}
  landmarks={plan.landmarks}
/>
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `width` * | `number` |  | Canvas size in grid units. The canvas fills its container and keeps this aspect ratio. |
| `height` * | `number` |  |  |
| `items` * | `readonly FloorPlanItem[]` |  |  |
| `landmarks` | `readonly FloorPlanLandmark[]` | `[]` |  |
| `selectedId` | `string \| null` |  | Controlled selection; the item gets the selected ring and `aria-pressed`. |
| `onSelect` | `((id: string) => void)` |  | Called with the id of the item or landmark that was picked, by click, keyboard or the start of a drag. |
| `editable` | `boolean` | `false` | Lets people rearrange the plan: drag an item or landmark to move it, drag a corner handle of the selected one to resize, press the rotate button or `r` to turn it a quarter, Alt with an arrow to nudge and Alt and Shift with an arrow to resize. Edits snap to `… |
| `onChange` | `((items: FloorPlanItem[], landmarks: FloorPlanLandmark[]) => void)` |  | Receives the full lists with the edited box applied; called once per drop and once per key press. |
| `snap` | `number` | `1` | Grid step in units that positions and sizes snap to while editing. Defaults to 1. |
| `minSize` | `number` | `1` | Smallest width or height in units while editing. Defaults to 1. |
| `aria-label` | `string` |  | Accessible name of the plan. Defaults to the localized "Floor plan". |
| `className` | `string` |  |  |
| `classNames` | `Partial<Record<FloorPlanPart, string>>` |  | Per-part classes merged with `cn`; consumer classes win. `className` still targets the root and is merged last. |

`*` marks a required prop.

## Storybook stories

- [Default](/storybook/?path=/story/containers-floorplan--default)
- [Merged Tables](/storybook/?path=/story/containers-floorplan--merged-tables)
- [Selectable](/storybook/?path=/story/containers-floorplan--selectable)
- [Roving Focus](/storybook/?path=/story/containers-floorplan--roving-focus)
- [Every State](/storybook/?path=/story/containers-floorplan--every-state)
- [Selected Ring](/storybook/?path=/story/containers-floorplan--selected-ring)
- [Dark](/storybook/?path=/story/containers-floorplan--dark)
- [Dark Every State](/storybook/?path=/story/containers-floorplan--dark-every-state)
- [Spanish](/storybook/?path=/story/containers-floorplan--spanish)
- [Editable](/storybook/?path=/story/containers-floorplan--editable)
- [Editable Dark](/storybook/?path=/story/containers-floorplan--editable-dark)

## Source

`packages/ui/src/containers/floor-plan/floor-plan.tsx`
