Logo VitNode
Documentation

Frame

A titled settings card that wraps a list of rows in a soft outer frame, with icon tiles, badges and controls on each row.

Frame groups related settings or facts under one title. The title sits on a soft outer layer, and the rows sit on a raised inner panel. It is the card the Settings → Overview page is built from.

Usage

import {
  Frame,
  FrameAction,
  FrameDescription,
  FrameFooter,
  FrameHeader,
  FramePanel,
  FrameTitle,
} from '@vitnode/core/components/ui/frame'
<Frame>
  <FrameHeader>
    <FrameTitle render={<h2 />}>AI features</FrameTitle>
  </FrameHeader>
  <FramePanel>
    <Item>
      <ItemMedia aria-hidden variant="tile">
        <BotIcon />
      </ItemMedia>
      <ItemContent>
        <ItemTitle>
          Semantic search <Badge variant="outline">Smart</Badge>
        </ItemTitle>
        <ItemDescription>Find content by meaning, not exact wording.</ItemDescription>
      </ItemContent>
      <ItemActions>
        <Switch aria-label="Semantic search" />
      </ItemActions>
    </Item>
  </FramePanel>
</Frame>
  • FrameHeader holds the title, an optional description and an optional action.
  • FramePanel is the inner card. It draws a divider between its children, so you never add separators yourself.
  • Rows are regular Item components. Inside a panel they lose their own border and radius, so they line up edge to edge.
  • ItemMedia variant="tile" gives the icon its small rounded square.

Header description and action

Add FrameDescription under the title and put a button in FrameAction. The action stays on the end side and centers against the title block.

<FrameHeader>
  <FrameTitle render={<h2 />}>Publishing</FrameTitle>
  <FrameDescription>Where visitors find your site.</FrameDescription>
  <FrameAction>
    <Button size="sm" variant="ghost">
      Learn more
    </Button>
  </FrameAction>
</FrameHeader>

Put a short note under the panel with FrameFooter. It sits on the outer layer, so it reads as a remark about the whole group, not as another row.

<Frame>
  <FrameHeader>...</FrameHeader>
  <FramePanel>...</FramePanel>
  <FrameFooter>A signed-out device has to sign in again.</FrameFooter>
</Frame>

Side by side

Frames stretch to fill their grid cell, so two frames in a md:grid-cols-2 grid keep the same height even with different row counts.

<div className="grid gap-4 md:grid-cols-2">
  <Frame>...</Frame>
  <Frame>...</Frame>
</div>

Accessibility

  • FrameTitle renders a div. Pass render={<h2 />} (or the level that fits the page) so screen readers can jump between frames.
  • For a list of rows, render the panel as a list and each row as an item: <FramePanel render={<ul />}> with <Item render={<li />}>.
  • Icon tiles are decorative. Give ItemMedia aria-hidden.
  • A switch or icon-only button in a row needs an aria-label that names the setting.

Props

Frame, FrameHeader, FrameDescription, FrameAction and FrameFooter take regular element props.

FrameTitle and FramePanel

Prop

Type

API Reference

Base UI - useRender