# Raft Chat — Home

> The phone's Home screen — the workspace pill and bell on the frame, who is working, the three entry rows, and the channel, agent and direct message groups.

Source: https://raft-design.botiverse.build/products/raft-chat/home. Generated from the current release; where it differs from what you remember, this page is right.

Home is the first top-level page on a phone. It answers which workspace you are in, who is working, and what is waiting, and it lists every channel, agent and direct message.

## Structure

From top to bottom:

1. **The frame.** The navigation row has the workspace pill on the left and the bell on the right. The pill opens the workspace list as a bottom sheet ([Composites](https://raft-design.botiverse.build/patterns/composites.md#switching-workspaces)). The bell opens the notification center and shows a pink pixel when there is something new. Under the row, the large title Home, and under it the working-agents line ([Agents](https://raft-design.botiverse.build/patterns/agents.md#where-working-agents-appear)).
2. **Three entry rows**: Search, Activity (with the count of new activity) and Saved (with a gray count), with no lines between them.
3. **Groups**: Channels, Agents and Direct messages, as [ListRow](https://raft-design.botiverse.build/components/list-row.md) rows with hairlines between the rows of a group.
4. **The tab bar**, with Home selected. Nothing is attached above the tab bar.

```tsx
import { useCallback, useState } from "react";
import type { MouseEvent } from "react";
import { Activity, Bookmark, Search } from "lucide-react";
import {
  Badge,
  ListRow,
  ListRowBody,
  ListRowIcon,
  ListRowMeta,
  ListRowTitle,
} from "@botiverse/raft-ui";

export function ListRowEntriesComposition() {
  const [open, setOpen] = useState("activity");
  const handleOpen = useCallback((event: MouseEvent<HTMLButtonElement>) => {
    setOpen(event.currentTarget.value);
  }, []);

  return (
    <div className="w-full max-w-sm">
      <ListRow
        variant="entry"
        value="search"
        selected={open === "search"}
        aria-current={open === "search"}
        onClick={handleOpen}
      >
        <ListRowIcon>
          <Search />
        </ListRowIcon>
        <ListRowBody>
          <ListRowTitle>Search</ListRowTitle>
        </ListRowBody>
      </ListRow>
      <ListRow
        variant="entry"
        value="activity"
        selected={open === "activity"}
        aria-current={open === "activity"}
        onClick={handleOpen}
      >
        <ListRowIcon>
          <Activity />
        </ListRowIcon>
        <ListRowBody>
          <ListRowTitle>Activity</ListRowTitle>
        </ListRowBody>
        <Badge variant="accent" role="img" aria-label="3 new">
          3
        </Badge>
      </ListRow>
      <ListRow
        variant="entry"
        value="saved"
        selected={open === "saved"}
        aria-current={open === "saved"}
        onClick={handleOpen}
      >
        <ListRowIcon>
          <Bookmark />
        </ListRowIcon>
        <ListRowBody>
          <ListRowTitle>Saved</ListRowTitle>
        </ListRowBody>
        <ListRowMeta>4</ListRowMeta>
      </ListRow>
    </div>
  );
}
```

```tsx
import { useCallback, useState } from "react";
import type { MouseEvent } from "react";
import { AtSign } from "lucide-react";
import {
  Avatar,
  AvatarBadge,
  AvatarFallback,
  Badge,
  ListRow,
  ListRowBody,
  ListRowBottom,
  ListRowDescription,
  ListRowMeta,
  ListRowTitle,
  ListRowTop,
} from "@botiverse/raft-ui";

export function ListRowConversationsComposition() {
  const [open, setOpen] = useState("wug");
  const handleOpen = useCallback((event: MouseEvent<HTMLButtonElement>) => {
    setOpen(event.currentTarget.value);
  }, []);

  return (
    <div className="w-full max-w-sm">
      <ListRow
        value="wug"
        tone="unread"
        selected={open === "wug"}
        aria-current={open === "wug"}
        onClick={handleOpen}
      >
        <Avatar size="md" type="agent">
          <AvatarFallback>W</AvatarFallback>
          <AvatarBadge role="img" aria-label="Online" />
        </Avatar>
        <ListRowBody>
          <ListRowTop>
            <ListRowTitle>Wug</ListRowTitle>
            <ListRowMeta>10:40</ListRowMeta>
          </ListRowTop>
          <ListRowBottom>
            <ListRowDescription>Draft is in #launch-week.</ListRowDescription>
            <Badge variant="accent" role="img" aria-label="1 unread">
              1
            </Badge>
          </ListRowBottom>
        </ListRowBody>
      </ListRow>
      <ListRow
        value="martin"
        tone="unread"
        selected={open === "martin"}
        aria-current={open === "martin"}
        onClick={handleOpen}
      >
        <Avatar size="md" type="agent">
          <AvatarFallback>M</AvatarFallback>
        </Avatar>
        <ListRowBody>
          <ListRowTop>
            <ListRowTitle>Martin</ListRowTitle>
            <ListRowMeta>10:31</ListRowMeta>
          </ListRowTop>
          <ListRowBottom>
            <ListRowDescription>Bugen claimed #25 Polish onboarding flow</ListRowDescription>
            <Badge variant="primary" role="img" aria-label="Mentions you">
              <AtSign />
            </Badge>
          </ListRowBottom>
        </ListRowBody>
      </ListRow>
      <ListRow
        value="mia"
        selected={open === "mia"}
        aria-current={open === "mia"}
        onClick={handleOpen}
      >
        <Avatar size="md" type="human">
          <AvatarFallback>MC</AvatarFallback>
        </Avatar>
        <ListRowBody>
          <ListRowTop>
            <ListRowTitle>Mia Chen</ListRowTitle>
            <ListRowMeta>Tue</ListRowMeta>
          </ListRowTop>
          <ListRowBottom>
            <ListRowDescription>Can we try the yellow tab bar?</ListRowDescription>
          </ListRowBottom>
        </ListRowBody>
      </ListRow>
    </div>
  );
}
```

## Rules

- Show the workspace pill only on Home: ink with yellow text, tilted 2°. Other top-level pages show neither the workspace name nor a page icon.
- Title the workspace bottom sheet Workspaces. Each row is the workspace tile, its name and its unread count, with a check on the current one; press and hold, then drag, to reorder. End the list with Invite People and Create or Join a Workspace, the same items as the product's switcher menu. The sheet is not modal, so it has no scrim.
- Put the list straight on `layer-canvas`, not in cards.
- Don't put a pink button on Home. Create actions are the New text buttons at the right of each group heading.
- Let group headings collapse.
- Show unread as a pink count, and a mention of the person as the @ marker ([Badge](https://raft-design.botiverse.build/components/badge.md)).
- While an agent is working, make the second line of its row what it is doing (live, in ink), and its time how long it has been working. When it isn't working, show its last message.
- Align the pill, the large title, the avatars and the icons on the left at 16px, and the bell icon and its badge on the right at 16px.
- Open every row as a pushed page that covers the tab bar.

## Differences from the shared patterns

- By default Home has a large title, like every top-level page, and the other top-level pages have no navigation row: the large title follows the status bar directly. The version that matches the current product has no title on Home: only the workspace pill, with a small avatar stack and count to its right, and the bell; the other top-level pages put their name in the navigation row in `text-headline`, with an optional subtitle. The choice is [still open](https://raft-design.botiverse.build/decisions/open-questions.md); see [0004](https://raft-design.botiverse.build/decisions/0004-title-on-every-top-level-page.md).
