Layout
The anatomy, dimensions, and page patterns of a Forge application, for designers building screens by hand.
Almost every Forge application is built on forge-app-layout, a shell that provides the app bar, navigation, and content regions and handles responsive behavior. Developers don’t build that structure themselves. They drop content into its slots.
So the most useful thing a designer can do is design inside the shell. Start every screen from the regions below, keep their dimensions fixed, and spend your design effort on what goes in the body. This page breaks down that shell and the page patterns that repeat across Forge’s blocks.
Structure of a Tyler Cloud App
lorem ipsum dolor sit amet, consectetur adipiscing elit.
Headings
The app title in the app bar is the page’s h1. Content headings start at h2:
- Page title in the body header:
forge-typography--heading4, one step larger than container titles. - Card, dialog, and drawer titles:
forge-typography--heading3, in the container’s header toolbar. Never larger, sinceforge-typography--heading4and up are reserved for page titles. - Section headings inside a card or form:
forge-typography--heading2. - Body text:
forge-typography--body2is the page default.forge-typography--body1is for dense or secondary content. - Group labels (above a checkbox list or filter facet):
forge-typography--label1orforge-typography--label2, often in--forge-theme-text-medium.
Forge’s heading scale runs from small to large, so forge-typography--heading4 is larger than forge-typography--heading3, which is larger than forge-typography--heading2. Visual size and semantic level are independent: a page title is an h2 styled with forge-typography--heading4. Sizes and weights for each style are on the typography tokens page.
Responsive behavior
The shell has one breakpoint, 960px by default. Teams can adjust it to fit their app with the app layout’s breakpoint property, so confirm the value with your developers before designing around it.
- 960px and wider: navigation is a persistent drawer beside the body.
- Below 960px: navigation collapses behind a menu button in the app bar and opens as a modal drawer over the content.
Within the body, content reflows at these widths: 640px, 768px, 1024px, and 1280px. Design at least two frames: one around 1440px and one around 390px. The shell handles everything in between, as long as body content reflows the way the patterns below describe.
Navigation styles
Choose one per app. Every block uses an icon with each nav item.
| Style | When to use | Width |
|---|---|---|
| Standard | The default. Six to ten destinations with short labels. | 320px |
| Mini | Content needs the width, like data-heavy screens or editors. Users recognize the icons. | 56px, expands to 256px on hover |
| Context switcher | The whole app is scoped to an organization, facility, or account the user can switch between. The switcher sits at the top of the drawer, above the nav list. | 320px |
Group secondary destinations like Settings and Help at the bottom of the list, separated by a divider.
Standard navigation with a page title toolbar and footer.
<forge-app-layout app-title="My Application" app-title-href="/">
<!-- App bar logo -->
<forge-icon slot="app-bar-logo" name="home">
</forge-icon>
<!-- App bar end actions -->
<div slot="app-bar-end" class="flex items-center gap-xsmall">
<forge-icon-button density="medium" aria-label="Notifications" theme="app-bar">
<forge-icon name="notifications" external>
</forge-icon>
</forge-icon-button>
<forge-user-profile
email="tyler.tech@tylertech.com"
button-label="Open the incredibly awesome profile menu"
theme-toggle
image-url
full-name="Tyler tech"
slot="app-bar-end">
<forge-profile-link slot="link">
<forge-icon slot="icon" name="settings" external>
</forge-icon>
<a href="http://www.google.com" target="_blank">
Settings
</a>
</forge-profile-link>
<forge-profile-link slot="link">
<forge-icon slot="icon" name="account" external>
</forge-icon>
<a href="http://www.google.com" target="_blank">
Profile
</a>
</forge-profile-link>
<span slot="sign-in-button-text">
Sign in
</span>
<span slot="sign-out-button-text">
Sign Out
</span>
</forge-user-profile>
</div>
<!-- Navigation drawer content -->
<forge-list slot="navigation" navlist>
<forge-list-item selected>
<forge-icon slot="start" name="dashboard">
</forge-icon>
<a href="#">
Dashboard
</a>
</forge-list-item>
<forge-list-item>
<forge-icon slot="start" name="bar_chart">
</forge-icon>
<a href="#">
Analytics
</a>
</forge-list-item>
<forge-list-item>
<forge-icon slot="start" name="people">
</forge-icon>
<a href="#">
Users
</a>
</forge-list-item>
<forge-list-item>
<forge-icon slot="start" name="folder">
</forge-icon>
<a href="#">
Projects
</a>
</forge-list-item>
<forge-divider>
</forge-divider>
<forge-list-item>
<forge-icon slot="start" name="settings">
</forge-icon>
<a href="#">
Settings
</a>
</forge-list-item>
<forge-list-item>
<forge-icon slot="start" name="help">
</forge-icon>
<a href="#">
Help
</a>
</forge-list-item>
</forge-list>
<!-- Body header toolbar -->
<div slot="body-header">
<forge-toolbar>
<h2 slot="start" class="text-heading4">
Page title
</h2>
<div slot="end" class="flex gap-xsmall">
<forge-icon-button density="medium" aria-label="Notifications">
<forge-icon name="notifications">
</forge-icon>
</forge-icon-button>
<forge-icon-button density="medium" aria-label="Settings">
<forge-icon name="settings">
</forge-icon>
</forge-icon-button>
<forge-icon-button density="medium" aria-label="More options">
<forge-icon name="more_vert">
</forge-icon>
</forge-icon-button>
</div>
</forge-toolbar>
</div>
<!-- Main content -->
<main class="p-medium grid bg-surface-dim" slot="body">
<div class="striped-box">
</div>
</main>
<!-- Footer -->
<footer slot="body-footer">
<forge-toolbar inverted>
<div slot="center" class="text-body1">
© 2026 My Application. All rights reserved.
</div>
</forge-toolbar>
</footer>
</forge-app-layout>Page patterns
Most screens are one of the patterns below. Find the closest one and design within its structure.
Dashboard or overview
A responsive grid of cards in the body.
- Cards use a
--forge-spacing-mediumgap in every direction. - Use an auto-fill grid targeting about 320px per card, or set column counts by breakpoint: 1 column on mobile, 2 at 640px, 3 at 1024px, 4 at 1280px.
- Give cards a consistent height within a row.
Data table
A table inside a card that fills the body width.
- The card header holds the table title and icon actions (filter, export, more). The primary page action, like “New order”, goes in the body header, not the card.
- Remove the card’s padding so the table runs edge to edge.
- Pagination sits in the card footer.
- Filters open in a 256px side panel on the right, with a header toolbar (“Filters”), a padded body of facets separated by dividers, and a footer with “Clear all” and “Apply”.
See the table with filters block for a paginated table with a filter side panel.
Form
A card containing a header toolbar, a padded body, and a footer toolbar with actions.
- Width: short forms max out around 672px. Long, sectioned forms max out around 768px. Never stretch a form to fill a wide screen.
- Columns: stack fields in one column, or use a 2-column (short) or 6-column (long) grid where related fields share a row: first and last name, or city, state, and ZIP.
- Footer actions are end-aligned: secondary action first, primary action last.
- See Spacing for field and section spacing.
A long form divided into sections on a 6-column grid.
<forge-card class="max-w-3xl mx-auto my-medium" no-padding>
<forge-scaffold>
<forge-toolbar slot="header">
<h2 slot="start" class="text-heading3">
New Project
</h2>
</forge-toolbar>
<div slot="body" class="p-medium">
<form id="complex-form" class="flex flex-col gap-xlarge">
<!-- Section: Project Details -->
<div>
<h2 class="text-heading2">
Project Details
</h2>
<div class="mt-medium grid grid-cols-1 gap-x-medium gap-y-large sm:grid-cols-6">
<div class="col-span-full">
<forge-text-field label-position="block-start">
<label for="project-name">
Project Name
</label>
<input type="text" id="project-name" />
</forge-text-field>
</div>
<div class="sm:col-span-3">
<forge-select label="Category" label-position="block-start">
<forge-option value="">
Select a category
</forge-option>
<forge-option value="development">
Development
</forge-option>
<forge-option value="design">
Design
</forge-option>
<forge-option value="marketing">
Marketing
</forge-option>
<forge-option value="research">
Research
</forge-option>
</forge-select>
</div>
<div class="sm:col-span-3">
<forge-select label="Priority" label-position="block-start">
<forge-option value="">
Select priority
</forge-option>
<forge-option value="low">
Low
</forge-option>
<forge-option value="medium">
Medium
</forge-option>
<forge-option value="high">
High
</forge-option>
<forge-option value="critical">
Critical
</forge-option>
</forge-select>
</div>
<div class="col-span-full">
<forge-text-field label-position="block-start">
<label for="description">
Description
</label>
<textarea id="description" rows="3">
</textarea>
<span slot="support-text">
Provide a brief overview of the project scope and objectives.
</span>
</forge-text-field>
</div>
<div class="col-span-full">
<div class="flex flex-col gap-xsmall">
<span class="text-label2 text-high">
Project Files
</span>
<forge-file-picker accept=".pdf,.doc,.docx,.xls,.xlsx" multiple>
<span slot="primary">
Drag files here or
</span>
<span slot="secondary">
PDF, Word, or Excel files up to 10MB each
</span>
<forge-button variant="outlined">
<forge-icon name="upload" slot="start">
</forge-icon>
Select Files
</forge-button>
</forge-file-picker>
</div>
</div>
</div>
</div>
<forge-divider>
</forge-divider>
<!-- Section: Timeline -->
<div>
<h2 class="text-heading2">
Timeline
</h2>
<div class="mt-medium grid grid-cols-1 gap-x-medium gap-y-large sm:grid-cols-6">
<div class="sm:col-span-2">
<forge-date-picker>
<forge-text-field label-position="block-start">
<label for="start-date">
Start Date
</label>
<input type="text" id="start-date" />
</forge-text-field>
</forge-date-picker>
</div>
<div class="sm:col-span-2">
<forge-date-picker>
<forge-text-field label-position="block-start">
<label for="end-date">
End Date
</label>
<input type="text" id="end-date" />
</forge-text-field>
</forge-date-picker>
</div>
<div class="sm:col-span-2">
<forge-text-field label-position="block-start">
<label for="budget">
Budget
</label>
<span slot="start">
$
</span>
<input type="number" id="budget" min="0" step="100" />
</forge-text-field>
</div>
</div>
</div>
<forge-divider>
</forge-divider>
<!-- Section: Team & Contact -->
<div>
<h2 class="text-heading2">
Team & Contact
</h2>
<div class="mt-medium grid grid-cols-1 gap-x-medium gap-y-large sm:grid-cols-6">
<div class="sm:col-span-3">
<forge-text-field label-position="block-start">
<label for="project-lead">
Project Lead
</label>
<forge-icon slot="start" name="person">
</forge-icon>
<input type="text" id="project-lead" />
</forge-text-field>
</div>
<div class="sm:col-span-3">
<forge-text-field label-position="block-start">
<label for="contact-email">
Contact Email
</label>
<forge-icon slot="start" name="email">
</forge-icon>
<input type="email" id="contact-email" autocomplete="email" />
</forge-text-field>
</div>
<div class="col-span-full">
<forge-text-field label-position="block-start">
<label for="phone">
Phone Number
</label>
<forge-icon slot="start" name="phone">
</forge-icon>
<input type="tel" id="phone" autocomplete="tel" />
<span slot="support-text">
Optional
</span>
</forge-text-field>
</div>
</div>
</div>
<forge-divider>
</forge-divider>
<!-- Section: Location -->
<div>
<h2 class="text-heading2">
Project Location
</h2>
<div class="mt-medium grid grid-cols-1 gap-x-medium gap-y-large sm:grid-cols-6">
<div class="col-span-full">
<forge-text-field label-position="block-start">
<label for="street-address">
Street Address
</label>
<input type="text" id="street-address" autocomplete="street-address" />
</forge-text-field>
</div>
<div class="sm:col-span-2 sm:col-start-1">
<forge-text-field label-position="block-start">
<label for="city">
City
</label>
<input type="text" id="city" autocomplete="address-level2" />
</forge-text-field>
</div>
<div class="sm:col-span-2">
<forge-select label="State" label-position="block-start">
<forge-option value="">
Select state
</forge-option>
<forge-option value="AL">
Alabama
</forge-option>
<forge-option value="AK">
Alaska
</forge-option>
<forge-option value="AZ">
Arizona
</forge-option>
<forge-option value="CA">
California
</forge-option>
<forge-option value="CO">
Colorado
</forge-option>
<forge-option value="TX">
Texas
</forge-option>
</forge-select>
</div>
<div class="sm:col-span-2">
<forge-text-field label-position="block-start">
<label for="zip">
ZIP Code
</label>
<input type="text" id="zip" autocomplete="postal-code" maxlength="10" />
</forge-text-field>
</div>
</div>
</div>
<forge-divider>
</forge-divider>
<!-- Section: Project Settings -->
<div>
<h2 class="text-heading2">
Project Settings
</h2>
<div class="mt-medium flex flex-col">
<forge-card class="tonal-card p-small [--forge-card-shape: 12px]">
<div class="flex items-center justify-between gap-medium">
<div>
<p class="text-label1">
Public Project
</p>
<p class="text-body2 text-medium">
Allow anyone in the organization to view this project
</p>
</div>
<forge-switch aria-label="Public project">
</forge-switch>
</div>
</forge-card>
<forge-card class="tonal-card p-small [--forge-card-shape: 12px]">
<div class="flex items-center justify-between gap-medium">
<div>
<p class="text-label1">
Active Project
</p>
<p class="text-body2 text-medium">
Mark this project as actively being worked on
</p>
</div>
<forge-switch checked aria-label="Active project">
</forge-switch>
</div>
</forge-card>
</div>
</div>
<forge-divider>
</forge-divider>
<!-- Section: Notifications -->
<div>
<h2 class="text-heading2">
Notifications
</h2>
<div class="mt-medium flex flex-col">
<forge-card class="tonal-card p-small [--forge-card-shape: 12px]">
<fieldset class="flex flex-col">
<legend class="text-label1">
Email Notifications
</legend>
<forge-checkbox>
Project status updates
</forge-checkbox>
<forge-checkbox>
Weekly summary reports
</forge-checkbox>
<forge-checkbox>
Budget alerts
</forge-checkbox>
</fieldset>
</forge-card>
<forge-card class="tonal-card p-small [--forge-card-shape: 12px]">
<fieldset class="flex flex-col">
<legend class="text-label1">
Update Frequency
</legend>
<forge-radio-group name="frequency">
<forge-radio value="realtime">
Real-time
</forge-radio>
<forge-radio value="daily">
Daily digest
</forge-radio>
<forge-radio value="weekly">
Weekly digest
</forge-radio>
</forge-radio-group>
</fieldset>
</forge-card>
</div>
</div>
</form>
</div>
<forge-toolbar slot="footer" inverted>
<div slot="end" class="flex items-center gap-small">
<forge-button type="button">
Cancel
</forge-button>
<forge-button variant="raised" type="submit" form="complex-form">
Save Project
</forge-button>
</div>
</forge-toolbar>
</forge-scaffold>
</forge-card>Master-detail
A primary list or table in the body, with details for the selected item in a right side panel. The body and the panel scroll independently, so design both as separate scroll areas.
See the dual scrolling containers block for a body and side panel that scroll independently.
Tabbed page
When a page has several views of the same object, put a tab bar directly below the page title, inside the body header. Remove the title toolbar’s bottom divider so the title and tabs read as one header.
See the basic application layout with tabs block for a tab bar below a borderless page title.
Containers
Forge’s cards, dialogs, and drawers share one internal structure, built from the same two components: a scaffold (forge-scaffold) nested inside the container lays out a header, body, and footer, and a toolbar (forge-toolbar) fills the header and footer. Learn it once and every container follows it.
- Header: a
forge-toolbarin the scaffold’sheaderslot, with the title (forge-typography--heading3) instartand icon actions inend. 56px tall with a bottom divider. - Body: the scaffold’s
bodyslot, with--forge-spacing-mediumpadding. - Footer: a
forge-toolbarwithinvertedin the scaffold’sfooterslot, with actions inendand the primary action last. 56px tall with a top divider. - Nest the scaffold directly inside the container:
forge-card,forge-dialog, or a drawer. On a card, setno-paddingso the toolbars reach its edges. - For a card, structured card (
forge-structured-card) provides this structure pre-built, with slots for the title, header actions, body, and footer actions instead of a scaffold and toolbars. - The header and footer stay put while the body scrolls.
- Corner radius is 4px (
--forge-shape-medium) for cards, dialogs, and toolbars. - Cards are flat with a 1px (
--forge-border-thin) border in--forge-theme-outline. Use the raised (shadow) variant only to lift a card above other content. - A container doesn’t need all three parts. A simple card can be body only.
Actions
- Actions live in toolbars, at the top of the page (body header) or the bottom of a container (footer).
- One primary action per container. It goes last (rightmost) and uses the
filledbutton. - The secondary action (Cancel) sits to its left as a
tonalbutton, spaced--forge-spacing-mediumapart. See Button grouping for the full hierarchy. - Icon-only actions in a header use 36px icon buttons (
density="medium"), spaced--forge-spacing-xsmallapart, with a tooltip.