Meowland docs
Workbench

Component reference

ListGroup

Rows that read as one set: a single rounded outline with hairlines between the rows.

Preview

ListGroup has no story of its own; this one draws it as part of PageHeader.

Page header, cards and grouped rows

Shows each public component's props and slots separately; does not assemble an application page.

packages/meowtail/stories/page-structure.stories.tsxline 24tsx
render: () => (
  <Stack>
    <PageHeader
      title="Example page header"
      description="Component description slot"
      leading={<Icon name="folder" />}
      actions={<Button size="small">Action</Button>}
    />
    <ResourceCard
      title="Example resource"
      subtitle="Resource category"
      description="The caller provides the description."
      icon={<Icon name="folder" />}
    />
    <ResourceCard
      title="Disabled resource"
      tone="muted"
      description="Component example in the disabled state."
    />
    <ListRow
      tone="accent"
      title="Summary row"
      tags={<Tag tone="accent">Selected</Tag>}
      description="Standalone item"
    />
    <ListGroup>
      <ListRow title="First item" description="The caller provides the content" />
      <ListRow title="Expanded item" expanded>
        <p>Expanded content slot</p>
      </ListRow>
    </ListGroup>
  </Stack>
)

Installation

bun add meowtail

Usage

Taken from the examples on this page.

usage.tsxtsx
import { ListGroup } from "meowtail";

<ListGroup>
  <ListRow title="First item" description="The caller provides the content" />
  <ListRow title="Expanded item" expanded>
    <p>Expanded content slot</p>
  </ListRow>
</ListGroup>

Examples

Other stories that draw ListGroup.

Text, indicator, and page slots

packages/meowtail/stories/status.stories.tsxline 29tsx
render: () => (
  <SchemePair>
    {(scheme) => (
      <Stack gap="relaxed">
        <Inline gap="normal">
          <Status state="processing" label="In progress" />
          <Status state="returned" label="Run returned" />
          <Status state="warning" label="Waiting for answer" />
          <Status state="danger" label="Connection failed" />
          <Status state="unknown" label="Status unconfirmed" />
        </Inline>
        <ListGroup>
          <ListRow
            title="Model source"
            description="Choose an executable model connection"
            status={<Status state="success" label="In use" />}
            actions={
              <Button size="small" variant="quiet">
                Configure
              </Button>
            }
          />
          <ListRow
            title="Local service"
            status={<Status state="unknown" label="No version yet" />}
          />
        </ListGroup>
        <ResourceCard
          title="Message extensions"
          subtitle="Channel"
          status={<Status state="success" label="Enabled" />}
          actions={<Button size="small">View settings</Button>}
        />
        <Status
          state="danger"
          label="Connection failed for development-workspace-with-a-long-identifier; retry after checking its configuration."
        />
        <Field label="Connection name" htmlFor={`status-connection-${scheme}`}>
          <Input id={`status-connection-${scheme}`} value="Development workspace" />
        </Field>
      </Stack>
    )}
  </SchemePair>
)

Documentation page with sections

One content page inside a host region: identity, page tools, a status row and the section rhythm. The outer Container stands in for the host shell's page area; Page itself owns no viewport and no scrolling.

packages/meowtail/stories/page.stories.tsxline 36tsx
render: () => (
  <Container width="page">
    <Page
      eyebrow="Guide · Composition"
      title="Build a page from regions"
      description="Page arranges the page identity, optional tools and the content rhythm; Section names one part of that content and keeps its heading level."
      actions={[
        <Button variant="outline">Copy page link</Button>,
        <Button variant="quiet">Edit this page</Button>,
      ]}
      toolbar={
        <Toolbar label="Page tools">
          <Button variant="quiet" size="small">
            <Icon name="list-checks" />
            Filters
          </Button>
          <Button variant="quiet" size="small">
            <Icon name="list" />
            Outline
          </Button>
        </Toolbar>
      }
      notice={
        <Alert
          layout="bar"
          tone="info"
          actions={
            <Button variant="quiet" size="small">
              View source
            </Button>
          }
        >
          This guide is generated from the authoring templates; only the local controls run here.
        </Alert>
      }
    >
      <Section title="Overview" description="What the two compositions own.">
        <p>
          The page owns the identity block and the spacing between its sections; each section owns
          one titled region. Both arrangements compose primitives that already exist, so the page
          keeps one visual language instead of starting another one.
        </p>
      </Section>

      <Section
        title="Compose the identity"
        description="Eyebrow, title, description and actions form one block."
        actions={
          <Button variant="quiet" size="small">
            Open example
          </Button>
        }
      >
        <p>
          PageHeader renders the h1 and its supporting copy. The eyebrow names the area the page
          belongs to, and the actions act on the page rather than on one section.
        </p>
        <ListGroup>
          <ListRow
            title="Eyebrow"
            description="A small label for the area the page belongs to."
            status="Optional"
          />
          <ListRow
            title="Actions"
            description="Controls that act on the whole page, aligned with the title."
          />
          <ListRow
            title="Notice"
            description="A status row between the identity and the content."
            status={[<Badge tone="accent">Current</Badge>]}
          />
        </ListGroup>
      </Section>

      <Section
        title="Keep one section rhythm"
        description="Sections stack at the page's spacing step."
        actions={
          <Button variant="quiet" size="small">
            Reset
          </Button>
        }
        footer="A nested section steps down one heading level."
        variant="card"
      >
        <p>
          The card variant wraps the same section in the existing Card surface, so a card section
          and a plain section stay one visual language.
        </p>
        <Section title="Nested section">
          <p>
            A section inside a page renders h2; a section nested in another section renders h3.
            The heading level comes from the surrounding region rather than from the caller.
          </p>
        </Section>
      </Section>

      <Section title="Escapes stay available" description="Custom chrome replaces identity only.">
        <p>
          A host that already renders its own header passes the header slot: the toolbar, notice
          and content stay, and the identity block is replaced rather than duplicated. Genuinely
          custom regions can still drop to PageFrame, Card or a layout primitive.
        </p>
      </Section>
    </Page>
  </Container>
)

API reference

Props

Also takes className, children and the attributes and events of its root element.

DOM parts

root

Registry

The component is registered as list-group in the meowtail component registry.