Search

Search bills, members, committees and pages...

Chambers

The chambers of the jurisdiction, each with its seal, seats and bill count.

On the site it lives at /home. Open it on the canvas, where it can be sized, coloured and rearranged with the rest.

Installation

pnpm dlx shadcn@latest add @44gov/chambers

Or copy the source into your project and update the import paths to match it.

components/cards/chambers.tsx
"use client" import * as React from "react" import Link from "next/link" import * as F from "@/lib/fixtures"import { useScoped } from "@/lib/policy/use-scoped"import { fmtNumber } from "@/lib/format"import { CardFrame, ComponentActions } from "@/components/card-frame"import { ChamberSeal } from "@/components/policy/imagery"import { CardAnchor } from "@/components/admin/blocks/card-tools"import { CardAction, CardContent, CardHeader, CardTitle } from "@govblock/ui/components/card"import { Item, ItemContent, ItemGroup, ItemMedia, ItemTitle } from "@govblock/ui/components/item" // Chambers — each chamber and who sits in it (Brendan, 2026-09-01: the row is// seal · name · members; the bill count moved out). The row filters the grid.type Option = { value: string; count: number } // `compact` is the docs-rail size, as on the calendar card.export function ChambersCard({ compact = false }: { compact?: boolean }) {  const { data: options, state, congress } = useScoped<{ chambers: Option[] }>("options", null as unknown as { chambers: Option[] })  const { data: seats } = useScoped<{ chamber: string; seats: number }[]>("seats", null as unknown as { chamber: string; seats: number }[])  const chambers = React.useMemo(() => {    if (!options) return congress ? F.chambers : []    const members = new Map<string, number>()    for (const row of seats ?? []) members.set(row.chamber, (members.get(row.chamber) ?? 0) + row.seats)    return options.chambers.map((c) => ({ label: c.value, bills: c.count, members: members.get(c.value) ?? 0 }))  }, [options, seats, congress])  return (    <CardFrame id="chambers" size={compact ? "sm" : "default"}>      <CardHeader>        <CardAnchor>Chambers</CardAnchor>        <CardAction>          <ComponentActions rows={chambers} id="chambers" />        </CardAction>      </CardHeader>      <CardContent>        <ItemGroup>          {chambers.map((row) => (            <Item              key={row.label}              variant="muted"              size={compact ? "sm" : "default"}              render={<Link href={`/bills?state=${state}&chamber=${encodeURIComponent(row.label)}`} className="no-underline" />}            >              <ItemMedia>                <ChamberSeal state={state} chamber={row.label} size={compact ? 28 : 36} />              </ItemMedia>              <ItemContent>                <ItemTitle>{row.label}</ItemTitle>              </ItemContent>              <span className="shrink-0 text-sm font-semibold tabular-nums">{fmtNumber(row.members)}</span>            </Item>          ))}        </ItemGroup>      </CardContent>    </CardFrame>  )} 

Usage

import { ChambersCard } from "@/components/cards/chambers"
<ChambersCard />

Composition

The parts the block is built from, in the order they appear.

ChambersCard├── CardHeader├── CardAction├── CardContent└── ItemGroup

Data

The routes the block reads, each under the jurisdiction and year in scope. Every one is documented in the API.

API Reference

ChambersCard takes no props. It reads the jurisdiction and year from the page.