# Astryx Layout Component Architecture: How Header, Footer, Panel, and Content Slots Work

> Explore the Astryx Layout component architecture. Learn how Header, Footer, Panel, and Content slots use React contexts for seamless coordination without manual CSS.

- Repository: [Meta/astryx](https://github.com/facebook/astryx)
- Tags: architecture
- Published: 2026-08-06

---

**The Astryx Layout component orchestrates four visual slots—Header, Footer, Panel, and Content—through a root shell that uses React contexts to coordinate slot presence, padding inheritance, and divider behavior without manual CSS management.**

The Astryx Layout component provides the structural foundation for applications in the facebook/astryx design system. It manages a flexible grid system composed of **LayoutHeader**, **LayoutFooter**, **LayoutPanel** (sidebars), and **LayoutContent** areas through a combination of CSS custom properties and context providers. This architecture enables developers to build responsive, RTL-aware page shells while the framework handles complex concerns like height management, padding collapse, and nested divider inheritance.

## Core Architecture of the Layout Component

### The Root Layout Shell (Layout.tsx)

At the center of the system is the `Layout` component in [`packages/core/src/Layout/Layout.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/Layout/Layout.tsx). This root shell accepts five primary slot props: `header`, `footer`, `start`, `end`, and `content` (where `children` acts as a shorthand for `content`).

The component implements two distinct height modes controlled via the `height` prop:

- **`'fill'`** – The layout fills its container and handles internal scrolling
- **`'auto'`** – The container manages scrolling while the layout expands naturally

To achieve edge-to-edge designs, `Layout` applies negative margins through `styles.layoutOuter` to cancel container padding, while `styles.layoutInner` resets CSS custom properties for descendants. The outer padding is controlled via CSS variables `--layout-padding-outer-x` and `--layout-padding-outer-y`, which map to the `padding` prop values defined in [`packages/core/src/Layout/padding.stylex.ts`](https://github.com/facebook/astryx/blob/main/packages/core/src/Layout/padding.stylex.ts).

### Slot Detection via LayoutSlotsContext

The `LayoutSlotsContext` (defined in [`packages/core/src/Layout/LayoutSlotsContext.ts`](https://github.com/facebook/astryx/blob/main/packages/core/src/Layout/LayoutSlotsContext.ts)) propagates slot presence information throughout the tree. Created via `useMemo` in the `Layout` component, this context exposes a simple object structure:

```typescript
{
  hasHeader: boolean,
  hasFooter: boolean,
  hasStart: boolean,
  hasEnd: boolean
}

```

Descendant components consume this context to conditionally render dividers, collapse padding, or apply side-specific styling without prop drilling.

### Divider Inheritance with LayoutDividerContext

When the `Layout` component receives the `defaultHasDividers` prop, it wraps the tree with `LayoutDividerContext` from [`packages/core/src/Layout/LayoutDividerContext.ts`](https://github.com/facebook/astryx/blob/main/packages/core/src/Layout/LayoutDividerContext.ts). This boolean flag allows nested `LayoutHeader` and `LayoutFooter` components to inherit default border-bottom styles automatically, ensuring consistent visual separation across nested layout hierarchies.

### Area Identification via LayoutAreaContext

Each slot receives its positional identity through `LayoutAreaContext` ([`packages/core/src/Layout/LayoutAreaContext.ts`](https://github.com/facebook/astryx/blob/main/packages/core/src/Layout/LayoutAreaContext.ts)). The `AreaProvider` wraps individual slots with values of `'header'`, `'start'`, `'content'`, `'end'`, or `'footer'`, enabling child components to detect which layout region they occupy for context-aware styling.

## The Four Visual Slots

### LayoutHeader and LayoutFooter

**LayoutHeader** ([`packages/core/src/Layout/LayoutHeader.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/Layout/LayoutHeader.tsx)) renders the top-most slot with `flex-shrink: 0` (via `styles.header`) to maintain fixed positioning during scroll. It utilizes `themeProps('layout-header')` for theming and applies dynamic height styles. The inner wrapper (`styles.inner`) controls content width through CSS custom properties and respects the `contentWidth` constraint.

When `padding={0}` is specified, the component switches to a "full-bleed" variant that removes all container padding. The optional `hasDivider` prop renders a bottom border, which can be inherited from `LayoutDividerContext`.

**LayoutFooter** ([`packages/core/src/Layout/LayoutFooter.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/Layout/LayoutFooter.tsx)) mirrors this implementation for the bottom slot, supporting identical padding controls and divider behavior.

### LayoutPanel for Sidebars

**LayoutPanel** ([`packages/core/src/Layout/LayoutPanel.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/Layout/LayoutPanel.tsx)) represents sidebar regions positioned via the `start` (left) or `end` (right) props. It utilizes `stackItem({size: 'fit'})` to size itself to content or accept a fixed `width` prop.

The panel accepts a `role` attribute for accessibility (typically `"navigation"`) and automatically collapses its internal padding against the layout's outer padding variables, ensuring seamless edge-to-edge designs. Responsive RTL support is achieved through logical CSS properties (`margin-inline`, `padding-inline`) that automatically flip in right-to-left environments.

### LayoutContent for the Main Area

**LayoutContent** ([`packages/core/src/Layout/LayoutContent.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/Layout/LayoutContent.tsx)) serves as the central scrollable region with `role="main"` by default. Its styles include `styles.middle` (applying `flex: 1` and `min-height: 0`) to ensure the content occupies remaining vertical space while respecting flex container constraints.

When `height='fill'`, the outer wrapper calculates content height by adding the container's block padding to prevent scroll-jank during layout calculations.

## Styling and Spacing System

### CSS Custom Properties and Padding Control

The [`padding.stylex.ts`](https://github.com/facebook/astryx/blob/main/padding.stylex.ts) file ([`packages/core/src/Layout/padding.stylex.ts`](https://github.com/facebook/astryx/blob/main/packages/core/src/Layout/padding.stylex.ts)) defines CSS variable maps for spacing steps (`0`, `0.5`, `1` through `10`). These variables propagate throughout the layout system:

- `--layout-padding-outer-x` and `--layout-padding-outer-y` control container spacing
- `--layout-content-width` constrains maximum content width when the `contentWidth` prop is provided

### Height Modes and Content Width

The `contentWidth` prop on the root `Layout` component sets `--layout-content-width`, centering the inner content area when specified. Combined with `padding={0}`, this enables full-bleed layouts where background colors touch viewport edges while text content remains constrained.

## Practical Implementation Examples

### Basic Page Structure

This example demonstrates a standard application shell with header, navigation sidebar, and main content:

```tsx
import {Layout, LayoutHeader, LayoutPanel, LayoutContent} from '@astryxdesign/core';

function SimplePage() {
  return (
    <Layout
      header={<LayoutHeader hasDivider>My App</LayoutHeader>}
      start={
        <LayoutPanel width={240} role="navigation">
          {/* navigation items */}
        </LayoutPanel>
      }
      content={
        <LayoutContent>
          {/* main page content */}
        </LayoutContent>
      }
    />
  );
}

```

The `header` and `start` slots render with automatic padding management, while `LayoutContent` fills the remaining space with proper scroll behavior.

### Full-Bleed Layouts

For dashboards requiring edge-to-edge backgrounds with constrained content:

```tsx
<Layout
  padding={0}
  contentWidth={960}
  header={<LayoutHeader>Dashboard</LayoutHeader>}
  footer={<LayoutFooter>© 2026</LayoutFooter>}
  content={<LayoutContent>{/* ... */}</LayoutContent>}
/>

```

Setting `padding={0}` activates the full-bleed mode (`styles.fullBleed`), while `contentWidth={960}` centers content at a maximum width of 960 pixels.

### Nested Layouts with Inherited Dividers

Context propagation enables consistent divider behavior across nested layouts:

```tsx
<Layout defaultHasDividers>
  <LayoutHeader>Outer Header</LayoutHeader>
  <Layout
    header={<LayoutHeader>Inner Header</LayoutHeader>}
    content={<LayoutContent>Nested content</LayoutContent>}
  />
</Layout>

```

Because the outer `Layout` specifies `defaultHasDividers`, nested `LayoutHeader` and `LayoutFooter` components automatically render bottom borders unless explicitly overridden with `hasDivider={false}`.

### Using Children as Content Shorthand

The `Layout` component treats direct children as the content slot when the explicit `content` prop is omitted:

```tsx
<Layout header={<LayoutHeader>Title</LayoutHeader>}>
  <p>This renders inside LayoutContent automatically</p>
</Layout>

```

## Summary

- **The Astryx Layout component** ([`Layout.tsx`](https://github.com/facebook/astryx/blob/main/Layout.tsx)) serves as the root shell coordinating Header, Footer, Panel, and Content slots through explicit props or children.
- **Context providers** (`LayoutSlotsContext`, `LayoutAreaContext`, `LayoutDividerContext`) eliminate prop drilling by broadcasting slot presence, area identity, and divider defaults throughout the React tree.
- **CSS custom properties** defined in [`padding.stylex.ts`](https://github.com/facebook/astryx/blob/main/padding.stylex.ts) enable dynamic spacing control, supporting both constrained content widths and full-bleed edge-to-edge designs.
- **Height management** offers `'fill'` mode for internal scrolling or `'auto'` mode for container-scrolled layouts, with `LayoutContent` receiving `flex: 1` to occupy remaining space.
- **RTL support** is built into the architecture through logical CSS properties, ensuring sidebars and padding automatically adapt to right-to-left layouts without additional configuration.

## Frequently Asked Questions

### How does the Astryx Layout component handle responsive sidebar widths?

The `LayoutPanel` component accepts a `width` prop that applies a fixed pixel width to the sidebar. When no width is specified, it uses `stackItem({size: 'fit'})` to size according to content. The layout system relies on CSS Flexbox for distribution, so panels automatically adjust their dimensions within the flex container while maintaining the specified constraints.

### Can nested Layout components inherit divider styles from parent layouts?

Yes. When a parent `Layout` component receives the `defaultHasDividers` prop, it renders `LayoutDividerContext` around its children. Any nested `LayoutHeader` or `LayoutFooter` that does not explicitly define the `hasDivider` prop will automatically inherit the divider behavior from this context, ensuring consistent visual separation across complex, nested interface hierarchies.

### What is the difference between the 'fill' and 'auto' height modes?

The `height='fill'` mode causes the Layout component to expand to fill its container while managing scrolling internally within `LayoutContent`. Conversely, `height='auto'` allows the layout to expand naturally with its content, delegating scrolling responsibility to the parent container. The 'fill' mode uses `min-height: 0` constraints on flex children to prevent overflow issues, while 'auto' permits content-driven expansion.

### How does the Layout component support full-bleed designs without custom CSS?

Setting `padding={0}` on the root `Layout` component activates the full-bleed mode via `styles.fullBleed`, which removes outer container padding and allows backgrounds to touch viewport edges. Simultaneously, the `contentWidth` prop can constrain the actual content area by setting `--layout-content-width`, creating a common pattern where visual elements span the full width while text remains readable and centered.