A chat composer that starts as a single pill and opens into a full prompt surface on focus. The open and close curve is not a hand-picked cubic-bezier: it is the unit step response of a real second-order system sampled into a CSS linear() easing, so Bounce is a damping ratio the author can move continuously: at 0 the curve provably never crosses its target, and the overshoot grows smoothly from there to about 40% without ever needing a retune when the duration changes. Browsers without linear() still animate, on a cubic-bezier fallback declared first and overridden inside a @supports block. The field grows with what is typed and is never written and read back in the same frame: a detached mirror carrying the same typography and content box does the measuring, so no keystroke forces a synchronous layout, and a trailing newline keeps its line instead of collapsing the field under the caret. Past the ceiling the field scrolls and the fade mask follows the scroll position rather than a static overflow flag, so the first line is never dimmed while it is still at the top. The model and effort pills carry exactly the width of what they currently say (every label is measured off-DOM on a canvas, so the set costs no layout) and morph between them. Attachments slide out of a tray tucked behind the card, and an image thumbnail opens into a viewer through a genuine FLIP: both rectangles are read, the destination is inverted onto the thumbnail for one frame, then released, so the picture travels instead of cross-fading. Object URLs are revoked on removal, on submit and on teardown. The action button morphs between send, record and stop, and while recording it widens over a five-bar level meter with real ballistics: a fast attack and a slow release per bar, frame-rate independent, which is how a hardware meter behaves and why the bars read as a voice rather than as noise. The meter runs off the microphone only when the author chooses that mode; the default is a synthesised envelope that sums two sines at an irrational rate ratio, so it never visibly loops, uses no random numbers and never triggers a permission prompt in an exported file. The glyph colour is derived from the accent luminance, so a light accent does not ship an invisible arrow, and the whole component stands down under prefers-reduced-motion. Edit the colours, geometry, placeholder, model and effort lists, spring duration and bounce, meter mode and ballistics, then export one self-contained HTML file with no dependencies.
UI/UX · HTML / CSS / JS · All tools