Search

Search bills, members, committees and pages...

Sessions

Every session the jurisdiction has on file, newest first, each with its bill count; the current one is marked.

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/sessions

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

components/cards/sessions.tsx
"use client" import * as React from "react" 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 { CardFoot } from "@/components/card-foot"import { CardAnchor } from "@/components/admin/blocks/card-tools"import { CardAction, CardContent, CardHeader, CardTitle } from "@govblock/ui/components/card"import { Item, ItemContent, ItemDescription, ItemGroup, ItemTitle } from "@govblock/ui/components/item" // Sessions — the picker. Choosing one scopes every other card; the current// one is marked.type ApiSession = { session_id: number; bills: number; title: string } export function SessionsCard() {  const { data, session, state, congress } = useScoped<ApiSession[]>("sessions", null as unknown as ApiSession[], { titles: 1 })  const sessions = React.useMemo(    () =>      data        ? data.map((row) => ({            session_year: row.session_id,            label: row.title,            // The span when the title carries one ("2025-2026 Regular Session"),            // otherwise the year the session opened.            years: row.title.match(/\d{4}-\d{4}/)?.[0] ?? String(row.session_id),            bills: row.bills,          }))        : congress          ? F.sessions          : [],    [data, congress]  )  return (    <CardFrame id="sessions">      <CardHeader>        <CardAnchor>Sessions</CardAnchor>        <CardAction>          <ComponentActions rows={sessions} id="sessions" />        </CardAction>      </CardHeader>      <CardContent>        <ItemGroup>          {sessions.map((row) => {            const isCurrent = row.session_year === session            return (              <Item key={row.session_year} variant="muted" aria-current={isCurrent ? "true" : undefined} className={isCurrent ? "ring-1 ring-ring/40" : undefined} render={<button type="button" className="w-full text-left" />}>                <ItemContent>                  <ItemTitle>{row.label}</ItemTitle>                  <ItemDescription>                    {row.years} · {fmtNumber(row.bills)} bills                  </ItemDescription>                </ItemContent>              </Item>            )          })}        </ItemGroup>      </CardContent>      <CardFoot href={`/docs/datasets/${state.toLowerCase()}`} label="The sessions as files" />    </CardFrame>  )} 

Usage

import { SessionsCard } from "@/components/cards/sessions"
<SessionsCard />

Composition

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

SessionsCard├── 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

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