# App Frame
> A foundational layout component that provides the structure for an application.

## Import

```js
import { AppFrame } from '@gemini-suite/vera-react';
```

App Frame is a compound component that consists of multiple parts to help you create different kinds of layout.

- `AppFrame.Root`: The outer container for other app frame elements. It renders children inside a CSS grid layout.
- `AppFrame.AppHeader`: A wrapper for application header.
- `AppFrame.AppBar`: A wrapper for navigation across different apps or modules within the same app.
- `AppFrame.NavBar`: A wrapper for primary navigation that sits between the header and main content.
- `AppFrame.Sidebar`: A wrapper for sidebar content that appears alongside the main content, such as primary or secondary (contextual) navigation, content filters etc.
- `AppFrame.Main`: A wrapper for main content.

## Examples

<Callout variant="tip">

Examples below include `maxHeight: 50vh` CSS rule, to ensure optimal docs-browsing experience.
It should not be added in a real app environment, as **App Frame** by design will fill up full viewport.

[See Storybook for fullscreen examples](https://next--698f15fa99e7b146f9002f64.chromatic.com/?path=/story/components-layout-appframe--default)

</Callout>

### Basic

**App Frame** wraps an entire app view and helps split the viewport into key areas that houses app header, primary/secondary navigation and main content of the app.
It implements [header-based layout UX pattern](/UX-patterns/framework/app-layouts#header-based-layout-regular).

```jsx
<AppFrame.Root css={{ maxHeight: '50vh' }}>
  <AppFrame.AppHeader
    padding="spacingM"
    css={{
      borderLeft: '1px dashed $dataPurple80'
    }}
  >
    {'App header'}
  </AppFrame.AppHeader>
  <AppFrame.AppBar
    css={{
      minWidth: '3rem',
      backgroundColor: '$backgroundNeutralContrast',
      color: '$foregroundInverse',
      alignContent: 'center',
      textAlign: 'center',
      writingMode: 'sideways-lr'
    }}
  >
    {'App bar'}
  </AppFrame.AppBar>
  <AppFrame.NavBar
    padding="spacingM"
    css={{
      borderBottom: '1px dashed $dataPurple80'
    }}
  >
    {'Nav bar'}
  </AppFrame.NavBar>
  <AppFrame.Sidebar
    padding="spacingM"
    css={{
      borderRight: '1px dashed $dataPurple80',
      minWidth: '8rem'
    }}
  >
    {'Sidebar'}
  </AppFrame.Sidebar>
  <AppFrame.Main padding="spacingM">{'Main content'}</AppFrame.Main>
</AppFrame.Root>
```

### Flexible layout

**App Frame** lets you pick and choose its parts to best fit your application requirements.
If you just need to define a header and main content for your layout, you can simply leave out rendering `AppFrame.Sidebar`, `AppFrame.NavBar` or `AppFrame.AppBar`.

```jsx
<AppFrame.Root css={{ maxHeight: '50vh' }}>
  <AppFrame.AppHeader padding="spacingM">{'Header'}</AppFrame.AppHeader>
  <AppFrame.Main padding="spacingM">{'Main content'}</AppFrame.Main>
</AppFrame.Root>
```

### With overflowing content

By default `AppFrame.Main` content will become scrollable as the content overflows.
`AppFrame.AppHeader`, `AppFrame.Sidebar` or `AppFrame.NavBar` are static while scrolling down the content.

<Callout variant="tip">

It is possible to set `scroll` prop to `body` on `AppFrame.Root`. This will make `AppFrame.Main` scrollable relative to the viewport.

[See example in Storybook](https://next--698f15fa99e7b146f9002f64.chromatic.com/?path=/story/components-layout-appframe--with-body-scroll)

</Callout>

```jsx
<AppFrame.Root css={{ maxHeight: '50vh' }}>
  <AppFrame.AppHeader padding="spacingM">{'Header'}</AppFrame.AppHeader>
  <AppFrame.Sidebar
    padding="spacingM"
    css={{ borderRight: '1px dashed $dataPurple80', minWidth: '8rem' }}
  >
    {'Sidebar'}
  </AppFrame.Sidebar>
  <AppFrame.Main
    padding="spacingM"
    css={{ backgroundColor: '$backgroundNeutralSubtle' }}
  >
    <AutoGrid>
      {Array(6)
        .fill(null)
        .map((_, i) => (
          <Card.Root key={i}>
            <Card.Header as={Heading} variant="delta">
              {'Hobbitses regretted natural muster determined villager?'}
            </Card.Header>
            <Card.Body>
              <FakeText words="25" />
            </Card.Body>
          </Card.Root>
        ))}
    </AutoGrid>
  </AppFrame.Main>
</AppFrame.Root>
```

### With nav bar

`AppFrame.NavBar` should be used in tandem with [Nav Bar component](/components/nav-bar) to display primary navigation items. This navigation experience is best suited for applications with a limited number of top-level views, typically less than 7.

Elements such as logo, user profile, settings and/or user manual links should be placed within `AppFrame.AppHeader` by using the [App Header component](/components/app-header).

<Callout variant="tip">

Visit [Nav Bar docs](/components/nav-bar) and [App Header docs](/components/app-header) for more in-depth examples and additional instructions.

[See example in Storybook](https://next--698f15fa99e7b146f9002f64.chromatic.com/?path=/story/demos-applayouts-headerbased--nav-bar)

</Callout>

```jsx
<AppFrame.Root background="neutralModerate" css={{ maxHeight: '50vh' }}>
  <AppFrame.AppHeader>
    <AppHeader.Root>
      <AppHeader.Logo product="metrix" />
      <AppHeader.Title>{'Product name'}</AppHeader.Title>
      <AppHeader.ActionList aria-label="Header actions">
        <AppHeader.ActionListItem startElement={<SvgIcon iconName="book" />}>
          {'User Guide'}
        </AppHeader.ActionListItem>
        <Tooltip content="Settings" delay={300}>
          <AppHeader.ActionListItem>
            <SvgIcon iconName="settings" />
          </AppHeader.ActionListItem>
        </Tooltip>
        <Tooltip content="Notifications" delay={300}>
          <AppHeader.ActionListItem>
            <Anchor.Root>
              <SvgIcon iconName="bell" />
              <Anchor.Target
                as={Label}
                circular
                color="danger"
                inset="-40%"
                size="small"
              >
                {'2'}
              </Anchor.Target>
            </Anchor.Root>
          </AppHeader.ActionListItem>
        </Tooltip>
        <Menu.Root>
          <Menu.Trigger as={AppHeader.ActionListItem}>
            <Avatar.Root of={'Max Mustermann'}>
              <Avatar.Initials />
            </Avatar.Root>
          </Menu.Trigger>
          <Menu.Content placement={Placement.BOTTOM_RIGHT}>
            <Flex paddingY="spacingS" paddingX="spacingM">
              <Avatar.Root of={'Max Mustermann'}>
                <Avatar.Initials />
              </Avatar.Root>
              <Box>
                {'Max Mustermann'}
                <Text as="div" variant="zeta" color="foregroundNeutralSubtle">
                  {'max.mustermann@invera-tech.com'}
                </Text>
              </Box>
            </Flex>
            <Menu.Separator />
            <Menu.Item startElement={<SvgIcon iconName="mobile" />}>
              {'Activate MFA'}
            </Menu.Item>
            <Menu.Separator />
            <Menu.Item intent="danger">{'Log Out'}</Menu.Item>
          </Menu.Content>
        </Menu.Root>
      </AppHeader.ActionList>
    </AppHeader.Root>
  </AppFrame.AppHeader>
  <AppFrame.NavBar>
    <NavBar.Root defaultActiveItem="home" aria-label="Main navigation">
      <NavBar.Item id="home">{'Home'}</NavBar.Item>
      <NavBar.Item id="dashboard">{'Dashboard'}</NavBar.Item>
      <NavBar.Item id="bidding">{'Bidding'}</NavBar.Item>
      <NavBar.Item id="results">{'Results'}</NavBar.Item>
    </NavBar.Root>
  </AppFrame.NavBar>
  <AppFrame.Main
    paddingY={{ '@initial': 'spacingM', '@mqMediumAndUp': 'spacingL' }}
    paddingX="spacingM"
    css={{
      display: 'grid',
      placeItems: 'center'
    }}
  >
    <Text color="foregroundNeutralModerate">{'App view'}</Text>
  </AppFrame.Main>
</AppFrame.Root>
```

### With sidebar navigation

`AppFrame.Sidebar` integrates seamlessly with our [Sidebar Navigation component](/components/sidebar-navigation).
Example below demonstrates how these components can be used together to create a more complex primary navigation structure with numerous items, extending beyond the capabilities of the [Nav Bar](/components/nav-bar).

<Callout variant="tip">

[Visit Sidebar Navigation docs](/components/sidebar-navigation) for a more complete sidebar navigation experience examples and additional instructions.

[See example in Storybook](https://next--698f15fa99e7b146f9002f64.chromatic.com/?path=/story/demos-applayouts-headerbased--sidebar)

</Callout>

```jsx
<AppFrame.Root css={{ maxHeight: '50vh', isolation: 'isolate' }}>
  <AppFrame.AppHeader>
    <AppHeader.Root>
      <AppHeader.Logo product="va" />
      <AppHeader.Title>{'Product name'}</AppHeader.Title>
      <AppHeader.ActionList aria-label="Header actions">
        <AppHeader.ActionListItem startElement={<SvgIcon iconName="book" />}>
          {'User Guide'}
        </AppHeader.ActionListItem>
        <Menu.Root>
          <Menu.Trigger as={AppHeader.ActionListItem}>
            <Avatar.Root of={'Max Mustermann'}>
              <Avatar.Initials />
            </Avatar.Root>
          </Menu.Trigger>
          <Menu.Content placement={Placement.BOTTOM_RIGHT}>
            <Flex paddingY="spacingS" paddingX="spacingM">
              <Avatar.Root of={'Max Mustermann'}>
                <Avatar.Initials />
              </Avatar.Root>
              <Box>
                {'Max Mustermann'}
                <Text as="div" variant="zeta" color="foregroundNeutralSubtle">
                  {'max.mustermann@invera-tech.com'}
                </Text>
              </Box>
            </Flex>
            <Menu.Separator />
            <Menu.Item startElement={<SvgIcon iconName="mobile" />}>
              {'Activate MFA'}
            </Menu.Item>
            <Menu.Separator />
            <Menu.Item intent="danger">{'Log Out'}</Menu.Item>
          </Menu.Content>
        </Menu.Root>
      </AppHeader.ActionList>
    </AppHeader.Root>
  </AppFrame.AppHeader>
  <AppFrame.Sidebar>
    <SidebarNavigation.Root aria-label="Main navigation" withSeparator>
      <SidebarNavigation.Body>
        <SidebarNavigation.Items>
          <SidebarNavigation.Item iconName="home" label="Home" />
          <SidebarNavigation.Item iconName="layout" label="Dashboard" />
          <SidebarNavigation.Group iconName="move" label="Models">
            <SidebarNavigation.Item iconName="edit" label="BPMN Modeler" />
            <SidebarNavigation.Item iconName="share" label="BPMN Models" />
            <SidebarNavigation.Item iconName="timeseries" label="Data Sets" />
          </SidebarNavigation.Group>
          <SidebarNavigation.Group iconName="cases" label="Manage">
            <SidebarNavigation.Item iconName="box" label="Services" />
            <SidebarNavigation.Item iconName="distance" label="Connections" />
          </SidebarNavigation.Group>
        </SidebarNavigation.Items>
      </SidebarNavigation.Body>
      <SidebarNavigation.Footer>
        <SidebarNavigation.Items>
          <SidebarNavigation.Item iconName="settings" label="Configuration" />
        </SidebarNavigation.Items>
      </SidebarNavigation.Footer>
      <SidebarNavigation.Toggle label="Toggle panel" />
    </SidebarNavigation.Root>
  </AppFrame.Sidebar>
  <AppFrame.Main
    padding={{
      '@initial': 'spacingM',
      '@mqLargeAndUp': 'spacingL'
    }}
    css={{
      display: 'grid',
      placeItems: 'center'
    }}
  >
    <Text color="foregroundNeutralModerate">{'App view'}</Text>
  </AppFrame.Main>
</AppFrame.Root>
```

### With app bar

If you need to display a navigation bar across different apps or core modules within the same app, pair `AppFrame.AppBar` with [App Bar component](/components/app-bar).

<Callout variant="tip">

[Visit App Bar docs](/components/app-bar) for more in-depth examples and additional instructions.

[See example in Storybook](https://next--698f15fa99e7b146f9002f64.chromatic.com/?path=/story/demos-applayouts-headerbased--nav-bar-and-app-bar)

</Callout>

```jsx
<AppFrame.Root background="neutralSubtle" css={{ maxHeight: '50vh' }}>
  <AppFrame.AppHeader>
    <AppHeader.Root>
      <AppHeader.Title>{'Product name'}</AppHeader.Title>
      <AppHeader.ActionList aria-label="Header actions">
        <AppHeader.ActionListItem startElement={<SvgIcon iconName="book" />}>
          {'User Guide'}
        </AppHeader.ActionListItem>
        <Menu.Root>
          <Menu.Trigger as={AppHeader.ActionListItem}>
            <Avatar.Root of={'Max Mustermann'}>
              <Avatar.Initials />
            </Avatar.Root>
          </Menu.Trigger>
          <Menu.Content placement={Placement.BOTTOM_RIGHT}>
            <Flex paddingY="spacingS" paddingX="spacingM">
              <Avatar.Root of={'Max Mustermann'}>
                <Avatar.Initials />
              </Avatar.Root>
              <Box>
                {'Max Mustermann'}
                <Text as="div" variant="zeta" color="foregroundNeutralSubtle">
                  {'max.mustermann@invera-tech.com'}
                </Text>
              </Box>
            </Flex>
            <Menu.Separator />
            <Menu.Item startElement={<SvgIcon iconName="mobile" />}>
              {'Activate MFA'}
            </Menu.Item>
            <Menu.Separator />
            <Menu.Item intent="danger">{'Log Out'}</Menu.Item>
          </Menu.Content>
        </Menu.Root>
      </AppHeader.ActionList>
    </AppHeader.Root>
  </AppFrame.AppHeader>
  <AppFrame.AppBar>
    <AppBar.Root>
      <AppBar.Logo product="communicator" />
      <AppBar.Items>
        <AppBar.Item iconName="layout" label="Dashboard" />
        <AppBar.Item iconName="pin" label="Map" />
        <AppBar.Item iconName="timeseries" label="Time series" />
      </AppBar.Items>
    </AppBar.Root>
  </AppFrame.AppBar>
  <AppFrame.Main
    padding={{
      '@initial': 'spacingM',
      '@mqLargeAndUp': 'spacingL'
    }}
    css={{
      display: 'grid',
      placeItems: 'center'
    }}
  >
    <Text color="foregroundNeutralModerate">{'App view'}</Text>
  </AppFrame.Main>
</AppFrame.Root>
```

---

## Accessibility

By default, `AppFrame.Main` and `AppFrame.AppHeader` render semantic HTML tags to mark regions in the app and provide
[WAI-ARIA landmark roles](https://www.w3.org/TR/wai-aria-1.2/#landmark_roles).

The `AppFrame.Sidebar`, `AppFrame.NavBar`, and `AppFrame.AppBar` components do not provide a default landmark role, as their content may define its own role.

For example, when you use `SidebarNavigation` within `AppFrame.Sidebar` or `NavBar` within `AppFrame.NavBar`, the appropriate landmark role is included by the navigation component itself.

---

## API Reference

### AppFrame.Root

| Name         | Type                                                       | Default            | Description                                                                                                                                                                                                                                  | Required |
| ------------ | ---------------------------------------------------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `css`        | `StitchesCss`                                              |                    | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries or variants. |          |
| `scroll`     | `"main" \| "body"`                                         | `"main"`           | When `main` scrolling will be contained within `AppFrame.Main`, `body` keeps the default body scrolling behavior.                                                                                                                            |          |
| `background` | `"neutralMinimal" \| "neutralSubtle" \| "neutralModerate"` | `"neutralMinimal"` | The background of the app frame. Subset of background values from [color tokens](/tokens/colors) are available.                                                                                                                              |          |

### AppFrame.AppHeader

<Callout variant="tip">

In addition to the props below, you can pass [Box props](/components/layout/box#api-reference) to control the spacing.

</Callout>

| Name       | Type                                                      | Default  | Description                                                                                                                                                                                                                                                                                  | Required |
| ---------- | --------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `as`       | `keyof JSX.IntrinsicElements \| React.ComponentType<any>` | `header` | Change the component to a different HTML tag or custom component. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node.   For more details, read our [Composition](/get-started/composition#polymorphism) guide. |          |
| `css`      | `StitchesCss`                                             |          | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants.                                                |          |
| `isSticky` | `boolean`                                                 |          | When `true`, the header will stick to the top of the screen while scrolling. Use in combination with setting `scroll` to `body` on `AppFrame`.                                                                                                                                               |          |
| `size`     | `"small" \| "medium" \| "auto"`                           | `"auto"` | Size affects the minimum height of the header. When `auto`, no minimum height will be applied to the header, making it always follow the content height.                                                                                                                                     |          |

### AppFrame.AppBar

<Callout variant="tip">

In addition to the props below, you can pass [Box props](/components/layout/box#api-reference) to control the spacing.

</Callout>

| Name  | Type                                                      | Default | Description                                                                                                                                                                                                                                                                                  | Required |
| ----- | --------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `as`  | `keyof JSX.IntrinsicElements \| React.ComponentType<any>` | `div`   | Change the component to a different HTML tag or custom component. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node.   For more details, read our [Composition](/get-started/composition#polymorphism) guide. |          |
| `css` | `StitchesCss`                                             |         | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants.                                                |          |

### AppFrame.NavBar

<Callout variant="tip">

In addition to the props below, you can pass [Box props](/components/layout/box#api-reference) to control the spacing.

</Callout>

| Name  | Type                                                      | Default | Description                                                                                                                                                                                                                                                                                  | Required |
| ----- | --------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `as`  | `keyof JSX.IntrinsicElements \| React.ComponentType<any>` | `div`   | Change the component to a different HTML tag or custom component. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node.   For more details, read our [Composition](/get-started/composition#polymorphism) guide. |          |
| `css` | `StitchesCss`                                             |         | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants.                                                |          |

### AppFrame.Sidebar

<Callout variant="tip">

In addition to the props below, you can pass [Box props](/components/layout/box#api-reference) to control the spacing.

</Callout>

| Name  | Type                                                      | Default | Description                                                                                                                                                                                                                                                                                  | Required |
| ----- | --------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `as`  | `keyof JSX.IntrinsicElements \| React.ComponentType<any>` | `div`   | Change the component to a different HTML tag or custom component. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node.   For more details, read our [Composition](/get-started/composition#polymorphism) guide. |          |
| `css` | `StitchesCss`                                             |         | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants.                                                |          |

### AppFrame.Main

<Callout variant="tip">

In addition to the props below, you can pass [Box props](/components/layout/box#api-reference) to control the spacing.

</Callout>

| Name  | Type                                                      | Default | Description                                                                                                                                                                                                                                                                                  | Required |
| ----- | --------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `as`  | `keyof JSX.IntrinsicElements \| React.ComponentType<any>` | `main`  | Change the component to a different HTML tag or custom component. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node.   For more details, read our [Composition](/get-started/composition#polymorphism) guide. |          |
| `css` | `StitchesCss`                                             |         | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants.                                                |          |
