---
id: portfolio.ds.project-carousel-timer-button
name: "Project Carousel Timer Button"
type: subcomponent
status: active
relations: [{"type":"related_to","target":"portfolio.ds.focus-interaction-states"},{"type":"related_to","target":"portfolio.ds.header-menu-button"},{"type":"related_to","target":"portfolio.ds.project-carousel-navigation"},{"type":"related_to","target":"portfolio.ds.spacing"},{"type":"related_to","target":"portfolio.ds.typography"}]
sources: ["apps/portfolio-site/src/design-system/docs/project-carousel-timer-button.astro","apps/portfolio-site/src/lib/designSystemRegistry.ts","packages/design-system/src/components/ProjectCarouselTimerButton.astro"]
catalog: ["apps/portfolio-site/src/design-system/docs/project-carousel-timer-button.astro"]
previews: ["apps/portfolio-site/src/design-system/docs/project-carousel-timer-button.astro"]
---
# Project Carousel Timer Button

## Purpose

Project selector button with a parent-controlled progress cursor for Project Hero Carousel.

## Contract

- Belongs to `Project Carousel Navigation`, which is a direct child of `Project Hero Carousel`.
- Uses a native button and `aria-pressed` to expose the current Project selection.
- Accepts complete visible label text and a controlled progress value from `0` through `100`.
- Clamps out-of-range or invalid progress instead of changing component geometry.
- Inherits Button typography, `--radius-sm`, semantic interactive padding, and interaction-state treatment from `Header Menu Button`.
- Supports two controlled progress indicators: `cursor` moves a `2px` vertical text-color line left to right, while `underline` grows beneath the label with the menu underline's `0.125em` thickness and text-relative placement; it never sits on the button boundary.
- The underline variant renders a full-width unfilled track with component token `--project-carousel-timer-underline-track-bg` (`rgb(0 0 0 / 0.16)`); the solid current-color progress line fills above it.
- `--project-carousel-timer-underline-track-bg` is intentionally component-specific and must not redefine shared interaction backgrounds or other progress indicators.
- Has no surface fill or border: only the Project label and selected progress line render over the parent background.
- Does not fill or progressively recolor the button background in any state.
- Keeps the label in the foreground content layer while the cursor moves beneath it.
- Uses `paused` only to expose parent-owned timer state; the parent freezes the current controlled progress value.
- When `progressHidden` is true, hides animated progress without changing button dimensions. A selected underline variant immediately retains a solid full-width underline so manual selection remains visible after carousel takeover.
- Supports the canonical normal, hover, focus, focus-visible, pressed, selected, and disabled states with shared interaction tokens.
- Removes progress transition under reduced motion while preserving the selected state and exact controlled position.
- Does not own timer duration, reset boundaries, auto-advance, carousel selection state, hover pause, or manual takeover.

## Preview-Only Motion

- The cursor Preview runs an `8s` linear loop in every interaction state.
- The underline Preview fills linearly for `8000ms`, remains fully visible for `350ms`, then fades over `150ms` with `cubic-bezier(0.4, 0, 1, 1)`, for an `8500ms` total cycle.
- Progress value and progress mode are runtime integration data, not component variants, so the Prop Switcher does not expose them.
- This loop is a documentation fixture, not an autonomous timer inside `Project Carousel Timer Button`.
- Reduced motion disables the Preview loop and preserves the selected static Progress position.

## Use

- Selecting a Project from future Project Carousel Navigation.
- Showing parent-controlled auto-advance progress for the currently active Project.

## Do Not Use

- Do not use as a generic tab, progress bar, or standalone timer.
- Do not start intervals, switch Projects, or reset progress inside the component.
- Do not communicate progress by filling the button background.

## Props

| Prop | Values | Purpose |
| --- | --- | --- |
| `label` | string | Names the Project selection command. |
| `selected` | boolean | Marks the current Project and permits visible progress. |
| `progress` | number, `0–100` | Positions the controlled cursor line. |
| `indicator` | `cursor`, `underline` | Selects the vertical cursor or filling underline presentation. |
| `paused` | boolean | Exposes a parent-owned paused state at the current position. |
| `progressHidden` | boolean | Removes the cursor without changing layout. |
| `disabled` | boolean | Prevents activation and applies disabled treatment. |
| `type` | native button type | Defaults to `button`. |

## Accessibility

- Uses native button keyboard and pointer behavior.
- Exposes selection through `aria-pressed` rather than color or progress alone.
- Keeps the visible Project label readable at every progress value.
- Avoids frequent screen-reader announcements of continuously changing progress; the visual cursor is decorative.

## Verification

- Confirm both indicators clamp at both edges and never fill the background.
- Confirm the cursor passes behind the label mask without reducing text readability.
- Confirm paused and hidden modes preserve button dimensions.
- Confirm reaching `100` does not activate another Project.
- Confirm reduced motion removes progress transition.
- Run `scripts/design-system-graph --check --no-write`.
