Add the text shimmer component for "Thinking…" labels (#3152)

This commit is contained in:
Paweł Kuna authored and GitHub committed 2026-10-05 23:26:59 +02:00
1 parent 6c46d55336
commit 744f9fecf5
13 files changed
+409 -1

No files matched your search

+1 -1
View File
@@ -330,7 +330,7 @@ async function main() {
if (system) {
await encode(system, sampled, ['-c:v', 'libx264', '-preset', 'slow', '-crf', '18', '-pix_fmt', 'yuv420p', '-movflags', '+faststart'], path.join(outDir, `${name}.mp4`))
await encode(system, sampled, ['-vf', `fps=15,scale=iw/2:-1:flags=lanczos,split[s0][s1];[s0]palettegen=max_colors=128[p];[s1][p]paletteuse=dither=sierra2_4a`, '-loop', '0'], path.join(outDir, `${name}.gif`))
await encode(system, sampled, ['-vf', `fps=${FPS},scale=iw/2:-1:flags=lanczos,split[s0][s1];[s0]palettegen=max_colors=128[p];[s1][p]paletteuse=dither=sierra2_4a`, '-loop', '0'], path.join(outDir, `${name}.gif`))
console.log(` ✓ ${name}.mp4, ${name}.gif`)
}
}
@@ -0,0 +1,15 @@
---
// Text shimmer for the video recorder (`pnpm run record text-shimmer-animation`):
// one "Thinking…" label with its loader, nothing else, zoomed in so the
// fade-in, the spinner and the sweeping highlight fill the frame.
// steps/text-shimmer-animation.json only waits, long enough for the fade-in
// and two full sweeps. Without ?motion the layout freezes the animation.
import ScreenshotLayout from '../layouts/ScreenshotLayout.astro'
import TextShimmer from '@ui/TextShimmer.astro'
---
<ScreenshotLayout title="Text shimmer animation" zoom={2} showLogo={false}>
<div class="text-center">
<TextShimmer loader live>Thinking…</TextShimmer>
</div>
</ScreenshotLayout>
+35
View File
@@ -0,0 +1,35 @@
---
// Text shimmer in the place it is made for: an assistant that has not
// answered yet. The layout turns animations off, so each label is drawn at a
// fixed point of the sweep with an inline mask-position — the band sits early
// in the first line, in the middle of the second and late in the third, which
// reads as motion on a still picture. The last label carries the loader, and
// the layout zoom keeps the text at its real size while the picture stays
// legible.
import ScreenshotLayout from '../layouts/ScreenshotLayout.astro'
import Card from '@ui/Card.astro'
import CardBody from '@ui/CardBody.astro'
import TextShimmer from '@ui/TextShimmer.astro'
const steps = [
{ label: 'Searching the web…', position: '80%' },
{ label: 'Reading 3 files…', position: '50%' },
]
---
<ScreenshotLayout title="Text shimmer" columns={2} zoom={2}>
<Card>
<CardBody class="p-4">
<div class="d-flex flex-column gap-3">
{
steps.map((step) => (
<TextShimmer class="text-secondary" style={`--tblr-text-shimmer-width: 40%; mask-position: ${step.position} 0`}>
{step.label}
</TextShimmer>
))
}
<TextShimmer loader style="--tblr-text-shimmer-width: 40%; --tblr-text-shimmer-opacity: 0.3; mask-position: 50% 0">Thinking…</TextShimmer>
</div>
</CardBody>
</Card>
</ScreenshotLayout>
@@ -0,0 +1 @@
[{ "wait": 4800 }]