WOODFINE CAPITAL PROJECTS BIM Design System

IfcSpatialElement

spatial tree

Universal AEC interface component. Anchored to IfcSpatialElement in the IFC 4.3 hierarchy; classified as Uniclass SL. Consumed by app-workplace-bim (Tauri 2.10 + xeokit) and app-console-bim (web-only read surface) under the mode-prop pattern.

IFCIfcSpatialElementUniclassSLmodeworkplace · consolecode overlays0 registered
Preview
recipe.html
<!-- bim-spatial-tree — universal AEC interface component.
     Default expansion: storey-level (per BB.4 Bonsai research).
     Mode prop: workplace (selectable, draggable, editable) | console (selectable, read-only).
     Purpose-built widget — NOT a repurposed scene-graph viewer.
-->

<aside class="bim-spatial-tree" data-mode="console" aria-label="Spatial hierarchy">
  <header class="bim-spatial-tree__header">
    <h3>Spatial</h3>
    <input type="search" class="bim-spatial-tree__search"
           placeholder="Search by space name…"
           aria-label="Search spaces" />
  </header>

  <ul class="bim-spatial-tree__list" role="tree">
    <li role="treeitem" aria-expanded="true" data-ifc-class="IfcSite">
      <span class="bim-spatial-tree__icon" aria-hidden="true">⌧</span>
      <span class="bim-spatial-tree__label">Site</span>
      <ul role="group">
        <li role="treeitem" aria-expanded="true" data-ifc-class="IfcBuilding">
          <span class="bim-spatial-tree__icon" aria-hidden="true">▣</span>
          <span class="bim-spatial-tree__label">Building A</span>
          <ul role="group">
            <li role="treeitem" aria-expanded="true" data-ifc-class="IfcBuildingStorey">
              <span class="bim-spatial-tree__icon" aria-hidden="true">═</span>
              <span class="bim-spatial-tree__label">Ground Floor</span>
              <ul role="group" hidden><!-- spaces deliberately collapsed by default --></ul>
            </li>
            <li role="treeitem" aria-expanded="true" data-ifc-class="IfcBuildingStorey">
              <span class="bim-spatial-tree__icon" aria-hidden="true">═</span>
              <span class="bim-spatial-tree__label">Level 02</span>
              <ul role="group" hidden></ul>
            </li>
            <li role="treeitem" aria-expanded="true" data-ifc-class="IfcBuildingStorey">
              <span class="bim-spatial-tree__icon" aria-hidden="true">═</span>
              <span class="bim-spatial-tree__label">Level 03</span>
              <ul role="group" hidden></ul>
            </li>
          </ul>
        </li>
      </ul>
    </li>
  </ul>
</aside>
recipe.css
.bim-spatial-tree {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  font-size: 0.9rem;
  color: #1a1a1a;
  border-right: 1px solid #e5e7eb;
  background: #fafbfc;
  width: 18rem;
  height: 100%;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
}

.bim-spatial-tree__header {
  padding: 0.75rem;
  border-bottom: 1px solid #e5e7eb;
  background: #fff;
  position: sticky;
  top: 0;
}

.bim-spatial-tree__header h3 {
  margin: 0 0 0.5rem;
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #6b7280;
}

.bim-spatial-tree__search {
  width: 100%;
  padding: 0.4rem 0.6rem;
  font: inherit;
  border: 1px solid #d1d5db;
  border-radius: 4px;
}

.bim-spatial-tree__list {
  list-style: none;
  margin: 0;
  padding: 0.5rem 0;
}

.bim-spatial-tree__list ul {
  list-style: none;
  margin: 0;
  padding-left: 1.25rem;
}

.bim-spatial-tree__list li[role="treeitem"] {
  padding: 0.25rem 0.5rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  border-radius: 3px;
}

.bim-spatial-tree__list li[role="treeitem"]:hover {
  background: #e5e7eb;
}

.bim-spatial-tree__list li[role="treeitem"][aria-selected="true"] {
  background: #1e3a8a;
  color: #fff;
}

.bim-spatial-tree__icon {
  display: inline-block;
  width: 1rem;
  text-align: center;
  font-size: 0.85rem;
  color: #6b7280;
}

.bim-spatial-tree[data-mode="workplace"] .bim-spatial-tree__list li[role="treeitem"] {
  /* draggable affordance for authoring mode */
  cursor: grab;
}
aria.md

bim-spatial-tree — accessibility

Role and structure

  • Container is <aside aria-label="Spatial hierarchy">.
  • Tree is <ul role="tree">.
  • Each spatial item is <li role="treeitem" aria-expanded="…">.
  • Children are <ul role="group">.
  • The aria-expanded attribute reflects the collapse/expand state. Storey-level nodes default to aria-expanded="true"; their child <ul role="group"> is hidden by default to defer per BB.4 ("expanded-to-storey, no auto-expand to spaces").

Selection

  • Selected node carries aria-selected="true".
  • Multi-select is allowed in workplace mode (Ctrl/Cmd-click, Shift-click); console mode is single-select.

Keyboard navigation

| Key | Action | |---|---| | Arrow Up / Down | Move focus between sibling tree items | | Arrow Right | Expand the focused item if it has children; otherwise focus first child | | Arrow Left | Collapse the focused item if expanded; otherwise focus parent | | Enter / Space | Activate (select) the focused item | | Home / End | Focus first / last visible tree item | | / (slash) | Move focus to the search input |

Search

  • Search input is <input type="search" aria-label="Search spaces">.
  • Search filters the tree by space name (IfcSpace.LongName, IfcSpace.Name), case-insensitive substring match.
  • Match results expand the matching path automatically; non-matching branches collapse.

Mode-prop behaviour

  • data-mode="workplace" — affordance for drag-to-reorder and multi-select; cursor: grab.
  • data-mode="console" — read-only; cursor: pointer; no drag-to-reorder; single-select only.

Don't

  • Don't auto-expand into the space level. Bonsai's storey-default expansion is the convention every AEC practitioner expects.
  • Don't reuse a generic scene-graph viewer (the Outliner-as-Tree pattern). Build the dedicated SpatialTree widget.
IFC mapping
TokenIFC anchorUniclass
bim-spatial-treeIfcSpatialElementSL

Component renders the IfcSpatialElement family. See the token taxonomy research for the full IFC × Uniclass cross-walk.

Code overlays applicable

This token's IFC anchor (IfcSpatialElement) accepts IfcConstraint relationships from any jurisdictional code overlay registered in service-codes. Composition order: municipal → provincial → federal → accessibility.

No overlays registered for IfcSpatialElement in this jurisdiction. First Woodfine BC RS-1 encoding lands at v0.0.3 (per sub-agent B's 6–8 week roadmap).

How City Code as Composable Geometry works →