import type { Meta, StoryObj } from 'storybook-solidjs-vite'; import { Context, ContextTrigger, ContextContent, ContextContentHeader, ContextContentBody, ContextContentFooter, ContextInputUsage, ContextOutputUsage, ContextReasoningUsage, ContextCacheUsage, ModelSwitcher, Button, Separator, } from '../index'; import type { ModelOption } from '../types'; import { createSignal } from 'solid-js'; const meta: Meta = { title: 'Examples/Context & Token Usage', parameters: { layout: 'padded', docs: { description: { component: [ 'Show how much of the model\'s context window is consumed. `` (or its SolidJS `Context` primitive) takes token counts and renders a circular meter trigger + hover-card breakdown.', '', '**Color thresholds** are configurable via `warnThreshold` (default `0.7`) and `dangerThreshold` (default `0.9`) props on both `` and ``:', '- Green (`bg-primary`): `usedTokens / maxTokens` ≤ `warnThreshold`', '- Yellow (`bg-yellow-400`): above `warnThreshold`', '- Red (`bg-red-400`): above `dangerThreshold`', '', 'When the computed severity level changes, `` fires a **`kc-threshold-change`** CustomEvent with `detail.level` set to `\'ok\'`, `\'warn\'`, or `\'danger\'`.', '', '**Where token counts come from:** read them from the API response `usage` object (`input_tokens`, `output_tokens`, `cache_read_input_tokens`, etc.) after each turn and pass them as props. The element fires no data-fetching events.', '', '**Live-update pattern:** for SolidJS, drive the `Context` props from reactive signals that you update after each streaming response completes. The element re-renders automatically when props change.', '', '**`` web-component route:** pass a single `context` object as a **property** (not an attribute — attributes only accept strings). Set `warnThreshold` / `dangerThreshold` as numeric properties to override defaults. The WC renders the full trigger + popover for you with no composition needed.', ].join('\n'), }, }, }, }; export default meta; type Story = StoryObj; export const LowUsage: Story = { name: 'Low Usage (Green)', parameters: { docs: { description: { story: 'Early in a conversation. `usedTokens / maxTokens` ≤ `warnThreshold` (default 70%) → green meter. Only input + output rows shown; omit `reasoningTokens` / `cacheTokens` to hide those rows.', }, }, }, render: () => (

Early in a conversation -- minimal token usage.

), }; export const MediumUsage: Story = { name: 'Medium Usage (Yellow)', parameters: { docs: { description: { story: '`usedTokens / maxTokens` > `warnThreshold` (default 70%) → yellow meter. Add `reasoningTokens` to surface a reasoning row in the breakdown. Pass `warnThreshold` to `` / `` to override the 70% default.', }, }, }, render: () => (

Extended conversation with reasoning -- approaching 75% usage.

), }; export const HighUsage: Story = { name: 'High Usage (Red)', parameters: { docs: { description: { story: '`usedTokens / maxTokens` > `dangerThreshold` (default 90%) → red meter. Pass `dangerThreshold` to `` / `` to override the 90% default. Signal to the user to start a new conversation.', }, }, }, render: () => (

Near the context limit -- user should consider starting a new conversation.

), }; export const WithCacheBreakdown: Story = { name: 'Full Breakdown with Cache', parameters: { docs: { description: { story: 'Add `cacheTokens` to expose the cache row. From the API: cache-hit tokens come from `usage.cache_read_input_tokens` in the response; cache-write tokens from `usage.cache_creation_input_tokens`. Both count toward `usedTokens`.', }, }, }, render: () => (

Detailed usage including cache hit tokens.

), }; export const InHeaderBar: Story = { name: 'In a Header Bar', parameters: { docs: { description: { story: '`Context` (or ``) is a plain inline element — place it anywhere in your header. Here it sits next to a `ModelSwitcher`. Drive both from reactive signals that you update after each API response.', }, }, }, render: () => { const [modelId, setModelId] = createSignal('claude-4'); const models: ModelOption[] = [ { id: 'claude-4', name: 'Claude 4 Opus', provider: 'Anthropic' }, { id: 'claude-4-sonnet', name: 'Claude 4 Sonnet', provider: 'Anthropic' }, ]; return (

Context usage as it appears in the app header, alongside model switcher.

Database indexing strategies

24 messages
Chat content area
); }, };