Clawscale

Status bar

A StatusBar is a thin bar along the bottom of an app. It shows connection state, counts and quick settings.

Usage#

import { StatusBar, StatusBarItem, StatusBarSpacer } from "@clawscale/react";
<StatusBar>
  <StatusBarItem icon="tick-circle" intent="success">
    Connected
  </StatusBarItem>
</StatusBar>

Examples#

Connection state#

icon and intent show state at a glance. Use a different icon for each state and always add text, so color is never the only signal.

Connected to eu-central-1analytics-prod
Reconnecting, attempt 2 of 5analytics-prod
Offline since 14:05 UTCanalytics-prod
import { StatusBar, StatusBarItem } from "@clawscale/react";

const states = [
  { icon: "tick-circle", intent: "success", text: "Connected to eu-central-1" },
  { icon: "warning-sign", intent: "warning", text: "Reconnecting, attempt 2 of 5" },
  { icon: "error", intent: "danger", text: "Offline since 14:05 UTC" },
] as const;

export default function StatusBarConnection() {
  return (
    <div style={{ display: "grid", gap: 16 }}>
      {states.map((state) => (
        <StatusBar key={state.text}>
          <StatusBarItem icon={state.icon} intent={state.intent} role="status">
            {state.text}
          </StatusBarItem>
          <StatusBarItem icon="database">analytics-prod</StatusBarItem>
        </StatusBar>
      ))}
    </div>
  );
}

Spacer#

StatusBarSpacer pushes the items after it to the right edge.

Connectedmain12,480 rowsUTF-8UTC
import { StatusBar, StatusBarItem, StatusBarSpacer } from "@clawscale/react";

export default function StatusBarWithSpacer() {
  return (
    <StatusBar>
      <StatusBarItem icon="tick-circle" intent="success">
        Connected
      </StatusBarItem>
      <StatusBarItem icon="git-branch">main</StatusBarItem>
      <StatusBarSpacer />
      <StatusBarItem>12,480 rows</StatusBarItem>
      <StatusBarItem>UTF-8</StatusBarItem>
      <StatusBarItem>UTC</StatusBarItem>
    </StatusBar>
  );
}

Clickable items#

An item with onClick renders a button with a hover state. Use it for quick settings and trays. Click the time zone or the notification count.

Connected
import { StatusBar, StatusBarItem, StatusBarSpacer } from "@clawscale/react";
import { useState } from "react";

export default function StatusBarClickable() {
  const [utc, setUtc] = useState(true);
  const [unread, setUnread] = useState(3);
  return (
    <StatusBar>
      <StatusBarItem icon="tick-circle" intent="success">
        Connected
      </StatusBarItem>
      <StatusBarSpacer />
      <StatusBarItem icon="time" onClick={() => setUtc(!utc)}>
        {utc ? "UTC" : "Local time"}
      </StatusBarItem>
      <StatusBarItem icon="notifications" aria-label={`${unread} notifications`} onClick={() => setUnread(0)}>
        {unread}
      </StatusBarItem>
    </StatusBar>
  );
}

App frame#

Make the bar the last child of a full-height flex column, and give the content flex: 1 and overflow: auto. The bar stays at the bottom and long content scrolls above it.

Pipeline runs
orders-syncSucceeded4m 12s
billing-exportRunning11m 03s
search-reindexFailed26m 30s
ledger-closeSucceeded8m 55s
Connectedanalytics-prod4 runsUTC
import {
  HTMLTable,
  Navbar,
  NavbarGroup,
  NavbarHeading,
  StatusBar,
  StatusBarItem,
  StatusBarSpacer,
} from "@clawscale/react";

const runs = [
  { pipeline: "orders-sync", status: "Succeeded", duration: "4m 12s" },
  { pipeline: "billing-export", status: "Running", duration: "11m 03s" },
  { pipeline: "search-reindex", status: "Failed", duration: "26m 30s" },
  { pipeline: "ledger-close", status: "Succeeded", duration: "8m 55s" },
];

export default function StatusBarAppFrame() {
  return (
    <div style={{ border: "1px solid var(--cs-color-border)", display: "flex", flexDirection: "column", height: 240 }}>
      <Navbar>
        <NavbarGroup>
          <NavbarHeading>Pipeline runs</NavbarHeading>
        </NavbarGroup>
      </Navbar>
      <div style={{ flex: 1, overflow: "auto" }}>
        <HTMLTable compact style={{ width: "100%" }}>
          <tbody>
            {runs.map((run) => (
              <tr key={run.pipeline}>
                <td>{run.pipeline}</td>
                <td>{run.status}</td>
                <td style={{ textAlign: "right" }}>{run.duration}</td>
              </tr>
            ))}
          </tbody>
        </HTMLTable>
      </div>
      <StatusBar>
        <StatusBarItem icon="tick-circle" intent="success" role="status">
          Connected
        </StatusBarItem>
        <StatusBarItem icon="database">analytics-prod</StatusBarItem>
        <StatusBarSpacer />
        <StatusBarItem>4 runs</StatusBarItem>
        <StatusBarItem>UTC</StatusBarItem>
      </StatusBar>
    </div>
  );
}

Accessibility#

The bar is a plain div. Give items that change on their own, such as the connection state, role="status" so screen readers announce the change. Items with only an icon or a number need an aria-label.

Props interface#

StatusBar accepts the HTML attributes of a div. StatusBarItem renders a span, or a button when it has onClick, and accepts their HTML attributes.

interface StatusBarProps extends HTMLAttributes<HTMLDivElement>@clawscale/react
PropsDescription
children
ReactNode
interface StatusBarItemProps extends Omit<ButtonHTMLAttributes<HTMLElement>, "type">@clawscale/react
PropsDescription
children
ReactNode
icon
IconName | MaybeElement
Icon name or element shown before the text.
intent
Intent
Colors the icon to show state.
onClick
ButtonHTMLAttributes<HTMLElement>["onClick"]
Renders a button when set.