Getting Started

Build a two-panel app shell and learn the first layout shape.

Build a two-panel app shell

Start here when you want a working Tilery layout in an application. This page builds the smallest useful workspace: two resizable panels, each with one tab.

The important idea is that Tilery does not ask you to position rectangles by hand. You describe a tree of groups and panels, then Tilery derives the panel geometry, dividers, tab bars, drag targets, and content hosts.

Install

Install the React adapter package. It depends on the framework-agnostic tilery core package automatically, so application code only needs to install @tileryjs/react.

npm install @tileryjs/react

Use tilery directly only when you are building framework adapters or tooling around the core layout types.

Add the base styles

Import the stylesheet once in your application. It provides the panel chrome, tab bars, resize handles, drag previews, and default theme variables.

import '@tileryjs/react/style.css';

Use the styling docs later when you want to change the theme. The base stylesheet should stay loaded even if you override every color.

Create the first layout

This layout is a horizontal group with two child panels. Each panel owns a list of tabs; each tab carries the data your render functions need.

import { Tilery } from '@tileryjs/react';
import '@tileryjs/react/style.css';
import type { TileryInitialLayout } from '@tileryjs/react';

type MyTab = { title: string };

const layout: TileryInitialLayout<MyTab> = {
  type: 'group',
  direction: 'horizontal',
  children: [
    {
      type: 'panel',
      id: 'left',
      size: 50,
      tabs: [{ id: 'a', data: { title: 'Panel A' } }],
    },
    {
      type: 'panel',
      id: 'right',
      size: 50,
      tabs: [{ id: 'b', data: { title: 'Panel B' } }],
    },
  ],
};

The size values are sibling weights inside the parent group. In this example, both children use 50, so the group starts as a 50/50 split.

Render Tilery

Tilery needs two render functions: one for the tab button and one for the tab panel content. Keep the container height explicit; tiling layouts need a real box to fill.

function App() {
  return (
    <div style={{ width: '100%', height: '100vh' }}>
      <Tilery
        initialLayout={layout}
        renderTabHeader={(tab) => <span>{tab.data.title}</span>}
        renderTabContent={(tab) => <div>{tab.data.title} content</div>}
      />
    </div>
  );
}

Try the finished layout

import { Tilery } from '@tileryjs/react';
import '@tileryjs/react/style.css';
import type { TileryInitialLayout } from '@tileryjs/react';

type MyTab = { title: string };

const layout: TileryInitialLayout<MyTab> = {
  type: 'group',
  direction: 'horizontal',
  children: [
    {
      type: 'panel',
      id: 'left',
      size: 50,
      tabs: [{ id: 'a', data: { title: 'Panel A' } }],
    },
    {
      type: 'panel',
      id: 'right',
      size: 50,
      tabs: [{ id: 'b', data: { title: 'Panel B' } }],
    },
  ],
};

export function App() {
  return (
    <div style={{ width: '100%', height: '100vh' }}>
      <Tilery
        initialLayout={layout}
        renderTabHeader={(tab) => <span>{tab.data.title}</span>}
        renderTabContent={(tab) => <div>{tab.data.title} content</div>}
      />
    </div>
  );
}

Where to go next

Read Concepts to understand the panel tree, snapshots, floating panels, and tab preservation model, or head to Examples to experience what Tilery has to offer — layout persistence, tab overflow, or native popout windows.