@pie-players/pie-tool-tts-inline
v0.3.29
Published
Inline TTS (Text-to-Speech) tool component for PIE Players Assessment Toolkit.
Readme
@pie-players/pie-tool-tts-inline
Inline TTS (Text-to-Speech) tool component for PIE Players Assessment Toolkit.
Overview
pie-tool-tts-inline is a web component that renders an inline speaker trigger with an expanded floating control panel for reading controls. Unlike floating modal tools, this component renders at its natural position in the DOM (typically in passage/item headers).
Features
- Speaker trigger that toggles an expanded panel
- Expanded controls: Play/Pause, Stop, Fast-forward, Rewind, configurable Speed options
- Play button switches to Pause while reading
- Panel remains open while reading and closes on Stop
- Arrow-key navigation within the controls toolbar
- Registers with
ToolCoordinatorfor lifecycle management - Integrates with
TTSServicefor QTI 3.0 catalog-based TTS - Size variants:
sm,md,lg - Full accessibility support (ARIA labels,
role="toolbar", live status updates) - Coordinator-controlled visibility via CSS
displayproperty
Installation
bun add @pie-players/pie-tool-tts-inlineUsage
import '@pie-players/pie-tool-tts-inline';
import { TTSService, BrowserTTSProvider, ToolCoordinator } from '@pie-players/pie-assessment-toolkit';
// Initialize services
const ttsService = new TTSService();
await ttsService.initialize(new BrowserTTSProvider());
const toolCoordinator = new ToolCoordinator();
// Create element
const ttsButton = document.createElement('pie-tool-tts-inline');
ttsButton.setAttribute('tool-id', 'tts-passage-1');
ttsButton.setAttribute('catalog-id', 'passage-1');
ttsButton.setAttribute('size', 'md');
// Bind services as JavaScript properties (not HTML attributes)
ttsButton.ttsService = ttsService;
ttsButton.coordinator = toolCoordinator;
// Coordinator controls visibility
toolCoordinator.showTool('tts-passage-1');With Svelte
<script>
import '@pie-players/pie-tool-tts-inline';
import { ZIndexLayer } from '@pie-players/pie-assessment-toolkit';
let ttsToolElement;
$effect(() => {
if (ttsToolElement && toolCoordinator) {
ttsToolElement.ttsService = ttsService;
ttsToolElement.coordinator = toolCoordinator;
if (ttsService) {
toolCoordinator.showTool('tts-passage-1');
}
}
});
</script>
<div class="header">
<h3>Passage Title</h3>
<pie-tool-tts-inline
bind:this={ttsToolElement}
tool-id="tts-passage-1"
catalog-id="passage-1"
size="md"
></pie-tool-tts-inline>
</div>Props
HTML Attributes
tool-id- Unique identifier for tool registration (default:'tts-inline')catalog-id- QTI 3.0 accessibility catalog ID for SSML lookup (default:'')language- Language code for TTS (default:'en-US')size- Icon size:'sm'(1.5rem),'md'(2rem), or'lg'(2.5rem) (default:'md')
JavaScript Properties
ttsService- ITTSService instance (required)coordinator- IToolCoordinator instance (optional, for visibility management)speedOptions- Optional number array controlling inline speed button rendering
speedOptions Configuration
speedOptions is intended to be set as a JavaScript property (not as a
serialized HTML attribute), either directly on the element or via toolkit
provider settings.
const ttsButton = document.createElement("pie-tool-tts-inline");
ttsButton.speedOptions = [2, 1.25, 1.5]; // rendered in this orderSemantics:
- Omitted or non-array: defaults to
[0.8, 1.25]. - Explicit
[]: no speed buttons rendered. - Invalid-only values: fall back to
[0.8, 1.25]. - Values are deduplicated while preserving first-seen order.
1is excluded from rendered options.
Behavior
- Tool Registration: Registers with ToolCoordinator on mount using the provided
tool-id - Text Extraction: Finds nearest
.pie-section-player__passage-contentor.pie-section-player__item-contentcontainer - TTS Trigger: Calls
ttsService.speak(text, { catalogId, language }) - Catalog Resolution: TTSService checks for SSML in accessibility catalogs (priority order):
- Extracted catalogs (from embedded SSML) - auto-generated by section player
- Item-level catalogs (manually authored)
- Assessment-level catalogs (manually authored)
- Plain text fallback (browser TTS)
- Expanded Controls:
- Trigger button opens/closes the panel
- Play/Pause toggles based on playback state
- Stop halts playback and closes the panel
- Fast-forward/Rewind invoke sentence-jump seek on
ITTSService - Speed buttons call
ttsService.updateSettings({ rate }) - Selecting another speed switches active state to that option
- Clicking the currently active speed resets back to
1x - If
speedOptionsis[], speed controls are omitted while rewind/forward/stop still render
- Keyboard Interaction: Arrow keys move between controls; Tab enters/leaves the toolbar
- Cleanup: Unregisters from coordinator on unmount
SSML Extraction Integration
When used with the section player, this tool automatically benefits from SSML extraction:
Author embeds SSML in content:
<div>
<speak>Solve <prosody rate="slow">x squared plus two</prosody>.</speak>
<p>Solve x² + 2 = 0</p>
</div>Section player extracts SSML at runtime:
- Generates catalog with ID like
auto-prompt-q1-0 - Adds
data-catalog-id="auto-prompt-q1-0"to visual content - Registers catalog with AccessibilityCatalogResolver
Tool uses extracted catalog:
- User clicks TTS button in header
- Tool calls
ttsService.speak(text, { catalogId: 'auto-prompt-q1-0' }) - TTSService finds SSML in extracted catalogs
- Speaks with proper math pronunciation and pacing
Result: Authors get high-quality TTS without maintaining separate catalog files.
Styling
The component uses scoped styles and doesn't require external CSS. Styling uses --pie-* token variables:
- Trigger: Circular speaker button that indicates panel open state
- Panel: Floating card with vertically stacked controls
- Speed state: Active speed button receives distinct token-driven styling
- Disabled: Reduced opacity, no pointer
Architecture
This tool follows the PIE Assessment Toolkit tool pattern:
- Always rendered in DOM at natural position
- ToolCoordinator controls visibility via
showTool()/hideTool()(CSSdisplayproperty) - Registers with
ZIndexLayer.TOOLfor proper layering - Services passed as JavaScript properties (objects can't be HTML attributes)
Example
See active demos in apps/section-demos.
License
MIT
