A chat composer in dictation mode: a strip of recorded waveform bars scrolls left and fades at both ends, beside a pulsing record dot, a timer, cancel and done buttons. The bars are one inline SVG.
Also known as: dictation waveform css, voice input bar animation, chatgpt dictation animation, recording waveform css.
<div class="aia-dictation-composer" role="status" aria-label="Dictating, 0:14">
<button class="aia-dictation-composer-cancel" type="button" aria-label="Cancel dictation">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M7 7l10 10M17 7L7 17"/></svg>
</button>
<div class="aia-dictation-composer-wave">
<svg class="aia-dictation-composer-bars" viewBox="0 0 240 18" preserveAspectRatio="none" aria-hidden="true"><rect x="1" y="7.5" width="1.6" height="3" rx="0.8"/><rect x="4" y="6.5" width="1.6" height="5" rx="0.8"/><rect x="7" y="7" width="1.6" height="4" rx="0.8"/><rect x="10" y="5" width="1.6" height="8" rx="0.8"/><rect x="13" y="3" width="1.6" height="12" rx="0.8"/><rect x="16" y="5.5" width="1.6" height="7" rx="0.8"/><rect x="19" y="7" width="1.6" height="4" rx="0.8"/><rect x="22" y="7.5" width="1.6" height="3" rx="0.8"/><rect x="25" y="6" width="1.6" height="6" rx="0.8"/><rect x="28" y="4" width="1.6" height="10" rx="0.8"/><rect x="31" y="1.5" width="1.6" height="15" rx="0.8"/><rect x="34" y="3.5" width="1.6" height="11" rx="0.8"/><rect x="37" y="5.5" width="1.6" height="7" rx="0.8"/><rect x="40" y="6.5" width="1.6" height="5" rx="0.8"/><rect x="43" y="4.5" width="1.6" height="9" rx="0.8"/><rect x="46" y="2.5" width="1.6" height="13" rx="0.8"/><rect x="49" y="5" width="1.6" height="8" rx="0.8"/><rect x="52" y="7" width="1.6" height="4" rx="0.8"/><rect x="55" y="7.5" width="1.6" height="3" rx="0.8"/><rect x="58" y="6.5" width="1.6" height="5" rx="0.8"/><rect x="61" y="5.5" width="1.6" height="7" rx="0.8"/><rect x="64" y="3" width="1.6" height="12" rx="0.8"/><rect x="67" y="1" width="1.6" height="16" rx="0.8"/><rect x="70" y="4" width="1.6" height="10" rx="0.8"/><rect x="73" y="6" width="1.6" height="6" rx="0.8"/><rect x="76" y="7" width="1.6" height="4" rx="0.8"/><rect x="79" y="5" width="1.6" height="8" rx="0.8"/><rect x="82" y="3.5" width="1.6" height="11" rx="0.8"/><rect x="85" y="6" width="1.6" height="6" rx="0.8"/><rect x="88" y="7.5" width="1.6" height="3" rx="0.8"/><rect x="91" y="7" width="1.6" height="4" rx="0.8"/><rect x="94" y="4.5" width="1.6" height="9" rx="0.8"/><rect x="97" y="2" width="1.6" height="14" rx="0.8"/><rect x="100" y="4.5" width="1.6" height="9" rx="0.8"/><rect x="103" y="6.5" width="1.6" height="5" rx="0.8"/><rect x="106" y="5.5" width="1.6" height="7" rx="0.8"/><rect x="109" y="4" width="1.6" height="10" rx="0.8"/><rect x="112" y="6" width="1.6" height="6" rx="0.8"/><rect x="115" y="7" width="1.6" height="4" rx="0.8"/><rect x="118" y="7.5" width="1.6" height="3" rx="0.8"/><rect x="121" y="7.5" width="1.6" height="3" rx="0.8"/><rect x="124" y="6.5" width="1.6" height="5" rx="0.8"/><rect x="127" y="7" width="1.6" height="4" rx="0.8"/><rect x="130" y="5" width="1.6" height="8" rx="0.8"/><rect x="133" y="3" width="1.6" height="12" rx="0.8"/><rect x="136" y="5.5" width="1.6" height="7" rx="0.8"/><rect x="139" y="7" width="1.6" height="4" rx="0.8"/><rect x="142" y="7.5" width="1.6" height="3" rx="0.8"/><rect x="145" y="6" width="1.6" height="6" rx="0.8"/><rect x="148" y="4" width="1.6" height="10" rx="0.8"/><rect x="151" y="1.5" width="1.6" height="15" rx="0.8"/><rect x="154" y="3.5" width="1.6" height="11" rx="0.8"/><rect x="157" y="5.5" width="1.6" height="7" rx="0.8"/><rect x="160" y="6.5" width="1.6" height="5" rx="0.8"/><rect x="163" y="4.5" width="1.6" height="9" rx="0.8"/><rect x="166" y="2.5" width="1.6" height="13" rx="0.8"/><rect x="169" y="5" width="1.6" height="8" rx="0.8"/><rect x="172" y="7" width="1.6" height="4" rx="0.8"/><rect x="175" y="7.5" width="1.6" height="3" rx="0.8"/><rect x="178" y="6.5" width="1.6" height="5" rx="0.8"/><rect x="181" y="5.5" width="1.6" height="7" rx="0.8"/><rect x="184" y="3" width="1.6" height="12" rx="0.8"/><rect x="187" y="1" width="1.6" height="16" rx="0.8"/><rect x="190" y="4" width="1.6" height="10" rx="0.8"/><rect x="193" y="6" width="1.6" height="6" rx="0.8"/><rect x="196" y="7" width="1.6" height="4" rx="0.8"/><rect x="199" y="5" width="1.6" height="8" rx="0.8"/><rect x="202" y="3.5" width="1.6" height="11" rx="0.8"/><rect x="205" y="6" width="1.6" height="6" rx="0.8"/><rect x="208" y="7.5" width="1.6" height="3" rx="0.8"/><rect x="211" y="7" width="1.6" height="4" rx="0.8"/><rect x="214" y="4.5" width="1.6" height="9" rx="0.8"/><rect x="217" y="2" width="1.6" height="14" rx="0.8"/><rect x="220" y="4.5" width="1.6" height="9" rx="0.8"/><rect x="223" y="6.5" width="1.6" height="5" rx="0.8"/><rect x="226" y="5.5" width="1.6" height="7" rx="0.8"/><rect x="229" y="4" width="1.6" height="10" rx="0.8"/><rect x="232" y="6" width="1.6" height="6" rx="0.8"/><rect x="235" y="7" width="1.6" height="4" rx="0.8"/><rect x="238" y="7.5" width="1.6" height="3" rx="0.8"/></svg>
</div>
<span class="aia-dictation-composer-time"><i class="aia-dictation-composer-dot"></i>0:14</span>
<button class="aia-dictation-composer-done" type="button" aria-label="Finish dictation">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5.5 12.5l4 4 9-9.5"/></svg>
</button>
</div>.aia-dictation-composer {
--c: var(--aia-color, #7c5cff);
font-size: var(--aia-size, 16px);
font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
line-height: 1.4;
display: flex;
align-items: center;
gap: 0.7em;
width: 24em;
padding: 0.45em;
box-sizing: border-box;
border-radius: 99em;
background: color-mix(in srgb, currentColor 5%, transparent);
box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 13%, transparent);
}
.aia-dictation-composer-cancel,
.aia-dictation-composer-done {
flex: none;
display: grid;
place-items: center;
width: 2.3em;
height: 2.3em;
padding: 0;
border: 0;
border-radius: 50%;
font: inherit;
color: inherit;
background: color-mix(in srgb, currentColor 9%, transparent);
cursor: pointer;
}
.aia-dictation-composer-done {
color: #fff;
background: var(--c);
box-shadow: 0 0.3em 0.8em -0.3em color-mix(in srgb, var(--c) 80%, transparent);
}
.aia-dictation-composer-cancel svg,
.aia-dictation-composer-done svg {
width: 1.1em;
fill: none;
stroke: currentColor;
stroke-width: 2.2;
stroke-linecap: round;
stroke-linejoin: round;
}
.aia-dictation-composer-cancel:focus-visible,
.aia-dictation-composer-done:focus-visible { outline: 2px solid var(--c); outline-offset: 0.15em; }
.aia-dictation-composer-wave {
flex: 1;
height: 1.7em;
overflow: hidden;
color: color-mix(in srgb, currentColor 70%, transparent);
-webkit-mask: linear-gradient(90deg, transparent, #000 18%, #000 82%, transparent);
mask: linear-gradient(90deg, transparent, #000 18%, #000 82%, transparent);
}
.aia-dictation-composer-bars {
display: block;
width: 200%;
height: 100%;
fill: currentColor;
animation: aia-dictation-composer-scroll 5s linear infinite;
}
.aia-dictation-composer-time {
display: flex;
align-items: center;
gap: 0.4em;
font-size: 0.9em;
font-variant-numeric: tabular-nums;
color: color-mix(in srgb, currentColor 75%, transparent);
}
.aia-dictation-composer-dot {
width: 0.45em;
height: 0.45em;
border-radius: 50%;
background: var(--c);
animation: aia-dictation-composer-blink 1.2s ease-in-out infinite;
}
@keyframes aia-dictation-composer-scroll {
to { transform: translateX(-50%); }
}
@keyframes aia-dictation-composer-blink {
50% { opacity: 0.25; }
}
@media (prefers-reduced-motion: reduce) {
.aia-dictation-composer-bars,
.aia-dictation-composer-dot { animation: none; }
}
@media (prefers-reduced-motion: reduce) {
.aia-dictation-composer, .aia-dictation-composer *, .aia-dictation-composer::before, .aia-dictation-composer::after, .aia-dictation-composer *::before, .aia-dictation-composer *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}--aia-color on the element or a parent.
Currently previewing #3b82f6.--aia-size. Every other dimension is in
em, so the whole thing scales together. Currently previewing 16px.transition or animation
shorthand. Staggered delays are relative, so they keep their rhythm.