• Blog
  • Docs
  • Pricing
  • We’re hiring!
Log inSign up
drewmcdonald

drewmcdonald

promptCompare

Public
Like
promptCompare
Home
Code
7
.claude
3
backend
2
docs
1
frontend
4
shared
.mcp.json
deno.json
Environment variables
2
Branches
1
Pull requests
Remixes
History
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Sign up now
Code
/
.claude
/
skills
/
ai-elements
/
references
/
transcription.md
Code
/
.claude
/
skills
/
ai-elements
/
references
/
transcription.md
Search
…
Viewing readonly version of main branch: v116
View latest version
transcription.md

Transcription

A composable component for displaying interactive, synchronized transcripts from AI SDK transcribe() results with click-to-seek functionality.

The Transcription component provides a flexible render props interface for displaying audio transcripts with synchronized playback. It automatically highlights the current segment based on playback time and supports click-to-seek functionality for interactive navigation.

See scripts/transcription.tsx for this example.

Installation

npx ai-elements@latest add transcription

Features

  • Render props pattern for maximum flexibility
  • Automatic segment highlighting based on current time
  • Click-to-seek functionality for interactive navigation
  • Controlled and uncontrolled component patterns
  • Automatic filtering of empty segments
  • Visual state indicators (active, past, future)
  • Built on Radix UI's useControllableState for flexible state management
  • Full TypeScript support with AI SDK transcription types

Props

<Transcription />

Root component that provides context and manages transcript state. Uses render props pattern for rendering segments.

PropTypeDefaultDescription
segmentsTranscriptionSegment[]-Array of transcription segments from AI SDK transcribe() function.
currentTimenumber0Current playback time in seconds (controlled).
onSeek(time: number) => void-Callback fired when a segment is clicked or when currentTime changes.
children(segment: TranscriptionSegment, index: number) => ReactNode-Render function that receives each segment and its index.
...propsOmit<React.ComponentProps<-Any other props are spread to the root div element.

<TranscriptionSegment />

Individual segment button with automatic state styling and click-to-seek functionality.

PropTypeDefaultDescription
segmentTranscriptionSegment-The transcription segment data.
indexnumber-The segment index.
...propsReact.ComponentProps<-Any other props are spread to the button element.

Behavior

Render Props Pattern

The component uses a render props pattern where the children prop is a function that receives each segment and its index. This provides maximum flexibility for custom rendering while still benefiting from automatic state management and context.

Segment Highlighting

Segments are automatically styled based on their relationship to the current playback time:

  • Active (isActive): When currentTime is within the segment's time range. Styled with primary color.
  • Past (isPast): When currentTime is after the segment's end time. Styled with muted foreground.
  • Future: When currentTime is before the segment's start time. Styled with dimmed muted foreground.

Click-to-Seek

When onSeek is provided, segments become interactive buttons. Clicking a segment calls onSeek with the segment's start time, allowing your audio/video player to seek to that position.

Empty Segment Filtering

The component automatically filters out segments with empty or whitespace-only text to avoid rendering unnecessary elements.

State Management

Uses Radix UI's useControllableState hook to support both controlled and uncontrolled patterns. When currentTime is provided, the component operates in controlled mode. Otherwise, it maintains its own internal state.

Data Format

The component expects segments from the AI SDK transcribe() function:

Create val
type TranscriptionSegment = { text: string; startSecond: number; endSecond: number; };

Styling

The component uses data attributes for custom styling:

  • data-slot="transcription": Root container
  • data-slot="transcription-segment": Individual segment button
  • data-active: Present on the currently playing segment
  • data-index: The segment's index in the array

Default segment appearance:

  • Active segment: text-primary (primary brand color)
  • Past segments: text-muted-foreground
  • Future segments: text-muted-foreground/60 (dimmed)
  • Interactive segments: cursor-pointer hover:text-foreground
  • Non-interactive segments: cursor-default

Accessibility

  • Uses semantic <button> elements for interactive segments
  • Full keyboard navigation support
  • Proper button semantics for screen readers
  • data-active attribute for assistive technology
  • Hover and focus states for keyboard users

Notes

  • Empty or whitespace-only segments are automatically filtered out
  • The component uses flex-wrap for responsive text flow
  • Segments maintain inline layout with gap-1 spacing
  • text-sm and leading-relaxed provide comfortable reading
  • Click events on segments still fire the onClick handler if provided
  • The onSeek callback is called both when segments are clicked and when controlled currentTime changes
FeaturesVersion controlCode intelligenceCLIMCP
Use cases
TeamsAI agentsSlackGTM
DocsShowcaseTemplatesNewestTrendingAPI examplesNPM packages
PricingNewsletterBlogAboutCareers
We’re hiring!
Brandhi@val.townStatus
X (Twitter)
Discord community
GitHub discussions
YouTube channel
Bluesky
Open Source Pledge
Terms of usePrivacy policyAbuse contact
© 2026 Val Town, Inc.