Focus widget
StableThe focus session for a dashboard: choose a task, start or pause, see the time left in the square and today’s total.
FocusWidget is the compact view of the same session the Focus screen shows. It has the clock in a small square, the phase and cycle, the task picker, Start, Pause and Finish, and a line with the state, today’s logged time and an “Open Focus” link to wherever href says. Put it under the provider your Focus screen uses and the two follow each other; with no provider above, it brings its own. It has no card of its own.
Updated View source
On a dashboard
import { useRouter } from '@rchursin/product/lib/router'import { SampleBadge } from '@rchursin/product/shell/layout'import { FocusProvider, FocusWidget } from '@rchursin/product/timer'
/** * The widget brings no card of its own: the dashboard around it does. Choose a task, start a * session, and the square drains as the time runs. Its own session here (storagePrefix); * in an app, put it under the same FocusProvider as the full Focus screen. * href sends “Open Focus” to your own page; here, the tool’s page in this Library. */export default function FocusWidgetExample() { const { href } = useRouter() return ( <FocusProvider storagePrefix="library:focus-widget"> <div className="flex w-full max-w-sm flex-col gap-3"> <SampleBadge className="self-start" /> <div className="lux-card rounded-2xl bg-raised p-5"> <FocusWidget href={href('/library/tools/timer-app')} /> </div> </div> </FocusProvider> )}Usage
import { FocusProvider, FocusWidget } from '@rchursin/product/timer'<FocusProvider> <FocusWidget href="/focus" /></FocusProvider>Examples
One session, two views
The widget and a time log under one provider. Start, then Finish: the entry appears in the log beside it, and Undo in the toast takes it back out.
import { SampleBadge } from '@rchursin/product/shell/layout'import { FocusProvider, FocusWidget, TimeLog } from '@rchursin/product/timer'
/** * One provider, two views: start a session in the widget, press Finish, and the entry lands in the * log beside it (with Undo in the toast). Neither view keeps time of its own, so they can't disagree. */export default function FocusWidgetShared() { return ( <FocusProvider storagePrefix="library:focus-shared"> <div className="grid w-full max-w-3xl grid-cols-1 items-start gap-4 md:grid-cols-2"> <SampleBadge className="justify-self-start md:col-span-2" /> <div className="lux-card min-w-0 rounded-2xl bg-raised p-5"> <FocusWidget /> </div> <div className="lux-card min-w-0 rounded-2xl bg-raised p-5"> <TimeLog summary={false} /> </div> </div> </FocusProvider> )}API
FocusWidget props
| Prop | Type | Default | Description |
|---|---|---|---|
href | string | null | '#timer' | Where the “Open Focus” link goes: your Focus screen. The default is the product kit’s own anchor; null hides the link. |
className | string | – | Classes on the root. |
Accessibility
Keyboard
| Key | What it does |
|---|---|
| Tab | Moves to the task button, Start or Pause, Finish (once started), then the Open Focus link. |
| EnterSpace | Press the focused button. After Finish, focus moves back to Start. |
- It binds no shortcut keys, so it never competes with the page around it.
- The clock is role="timer", labelled by the phase chip, and read in words on demand; the square is decorative.
- Start, pause and the end are announced by the provider once, however many views show the session.
Guidelines
Do
- Wrap it in your dashboard’s card; it has no frame of its own.
- Share the provider with the full Focus screen, so a session started in one shows in the other.
Don’t
- Don’t expect every action here: Abandon, Skip break and the settings live in the full session.
- Don’t render the widget with its own provider on a page that already has one for the same session; nest it under that provider instead.
In use
Used on this site
Related
- TimerThe Focus screen: a focus session, a stopwatch and a countdown one switch apart, with the time log beside them.
- Focus sessionA Pomodoro session: choose a task, say what you’ll finish, then focus and break in phases, with overtime and an inline Abandon.
- Time logWhat was focused on, by day with daily totals and a seven-day chart, with time added by hand and Undo on delete.
- Tasks widgetYour open tasks for a dashboard, soonest due first: tick one to finish it, or change its status from its icon.
- Agenda widgetA mini month with event markers and the chosen day’s agenda, for a dashboard.
- Product kit overviewThe product kit’s front page: a Today screen built from every tool’s widget, a map of the kits and the shared parts.
Source
The component’s own files, exactly as they run on this site.
/** * Focus, for the Today dashboard: choose a task, start or pause a focus session, see the time left in the square, * and today's logged total. "Open Focus" goes to the full screen (`href`, the kit's #timer page by default; null * hides the link), which shows the same session. * No outer card: the Overview wraps it. */import { useId, useRef } from "react"import { cx } from "../../components/cx"import { formatDuration, formatTime } from "../lib/dates"import { Button } from "../ui/button"import { CycleSquares, LinkButton, OvertimeChip, PhaseChip } from "./bits"import { WithFocus, useFocus } from "./focus"import { TaskPicker } from "./FocusSession"import { SquareProgress } from "./SquareProgress"import { TimeDisplay, type TimeState } from "./TimeDisplay"
export interface FocusWidgetProps { /** Where “Open Focus” goes (default: the kit's #timer page). null hides the link. */ href?: string | null className?: string