# Learn UI: complete text Every page of the book in reading order. Interactive figures appear as labelled placeholders; open the linked page to use them. --- # Learn UI: interfaces, explained interactively # Learn UI: An interactive guide to design engineering: how interfaces are built to feel right, from motion and typography to systems and craft. [Start reading](https://learn-ui.com/chapters/introduction) [Continue reading](https://learn-ui.com/chapters/introduction) [People](https://learn-ui.com/chapters/people)[Glossary](https://learn-ui.com/chapters/glossary)[Further reading](https://learn-ui.com/chapters/reading) ## What this book is An interactive book about design engineering, read from the people who do it: Rauno Freiberg, Emil Kowalski, Maggie Appleton, Bartosz Ciechanowski, Kathryn Gonzalez, Jim Nielsen, Paco Coursey, Steve Ruiz, Amelia Wattenberger, Andrew Swank. Gestures, motion, components, craft, taste, explanation, canvases, and the career, with every claim traced to its source. Each chapter pairs prose with figures you operate: set a spring and watch it overshoot, swipe a card and see when the action commits, stack toasts and find out why keyframes fail. Nothing shifts the page, and the glossary quotes the authors verbatim. ## Try one This one is from the Motion chapter. A spring is described by its physics, not by a duration: change the stiffness and damping, then press play and watch the same equation drive the curve and the dot. > Figure. Spring playground. A spring has no duration. Its stiffness, damping, and mass decide how it settles, and the curve and the dot are the same equation. Move a slider, watch the curve, then play.Illustrative numbers ## Contents ### [Introduction](https://learn-ui.com/chapters/introduction)[](https://learn-ui.com/chapters/introduction) - [A role between two rooms](https://learn-ui.com/chapters/introduction/a-role-between-two-rooms) - [Why the details are invisible](https://learn-ui.com/chapters/introduction/why-the-details-are-invisible) - [How to read this book](https://learn-ui.com/chapters/introduction/how-to-read-this-book) ### [Invisible details](https://learn-ui.com/chapters/invisible-details)[](https://learn-ui.com/chapters/invisible-details) - [Metaphors and learned gestures](https://learn-ui.com/chapters/invisible-details/metaphors) - [Kinetic physics and swipe gestures](https://learn-ui.com/chapters/invisible-details/kinetic-physics) - [Responsive gestures](https://learn-ui.com/chapters/invisible-details/responsive-gestures) - [Spatial consistency and fluid morphing](https://learn-ui.com/chapters/invisible-details/spatial-consistency) - [Frequency and novelty](https://learn-ui.com/chapters/invisible-details/frequency-and-novelty) - [Fitts's law](https://learn-ui.com/chapters/invisible-details/fitts-law) - [Touch, context, and fidgetability](https://learn-ui.com/chapters/invisible-details/touch-and-context) ### [Motion](https://learn-ui.com/chapters/motion)[](https://learn-ui.com/chapters/motion) - [You don't need animations](https://learn-ui.com/chapters/motion/you-dont-need-animations) - [Easing: where the speed goes](https://learn-ui.com/chapters/motion/easing) - [Springs and duration](https://learn-ui.com/chapters/motion/springs) - [Practical tips](https://learn-ui.com/chapters/motion/practical-tips) - [The magic of clip-path](https://learn-ui.com/chapters/motion/clip-path) - [Choreography and depth](https://learn-ui.com/chapters/motion/choreography-and-depth) - [Friction as a feature](https://learn-ui.com/chapters/motion/friction) ### [Components](https://learn-ui.com/chapters/components)[](https://learn-ui.com/chapters/components) - [A toast that stacks](https://learn-ui.com/chapters/components/toast) - [A drawer that follows the finger](https://learn-ui.com/chapters/components/drawer) - [A command menu with pages](https://learn-ui.com/chapters/components/command-menu) - [A modal that respects focus](https://learn-ui.com/chapters/components/modal) - [Dark mode without the flash](https://learn-ui.com/chapters/components/dark-mode) ### [Craft](https://learn-ui.com/chapters/craft)[](https://learn-ui.com/chapters/craft) - [Coding is designing](https://learn-ui.com/chapters/craft/coding-is-designing) - [HTML first](https://learn-ui.com/chapters/craft/html-first) - [Sanding the interface](https://learn-ui.com/chapters/craft/sanding-ui) - [Grids and fluid type](https://learn-ui.com/chapters/craft/grids-and-type) - [Accessibility as craft](https://learn-ui.com/chapters/craft/accessibility) - [Performance and reduced motion](https://learn-ui.com/chapters/craft/performance-and-reduced-motion) ### [Taste](https://learn-ui.com/chapters/taste)[](https://learn-ui.com/chapters/taste) - [Developing taste](https://learn-ui.com/chapters/taste/developing-taste) - [Training judgement](https://learn-ui.com/chapters/taste/training-judgement) - [Novelty and contrast](https://learn-ui.com/chapters/taste/novelty-and-contrast) - [The AI aesthetic](https://learn-ui.com/chapters/taste/the-ai-aesthetic) ### [Explaining with interaction](https://learn-ui.com/chapters/explaining)[](https://learn-ui.com/chapters/explaining) - [Explorable explanations](https://learn-ui.com/chapters/explaining/explorable-explanations) - [Data into meaning](https://learn-ui.com/chapters/explaining/data-into-meaning) - [Digital gardens and visual essays](https://learn-ui.com/chapters/explaining/digital-gardens) - [Interface patterns worth knowing](https://learn-ui.com/chapters/explaining/interface-patterns) ### [Canvases and tools for thought](https://learn-ui.com/chapters/canvases)[](https://learn-ui.com/chapters/canvases) - [Prototypes that become products](https://learn-ui.com/chapters/canvases/prototypes-to-products) - [Drawing a perfect stroke](https://learn-ui.com/chapters/canvases/perfect-stroke) - [The canvas meets the model](https://learn-ui.com/chapters/canvases/canvas-and-models) - [Tools for thought as cultural practices](https://learn-ui.com/chapters/canvases/tools-for-thought) ### [The career](https://learn-ui.com/chapters/career)[](https://learn-ui.com/chapters/career) - [The attributes of a design engineer](https://learn-ui.com/chapters/career/attributes) - [Where the role lives](https://learn-ui.com/chapters/career/where-the-role-lives) - [The case for design engineers](https://learn-ui.com/chapters/career/the-case) - [Your own site as proof](https://learn-ui.com/chapters/career/your-own-site) - [Where to go next](https://learn-ui.com/chapters/career/where-to-go-next) ### [People](https://learn-ui.com/chapters/people)[](https://learn-ui.com/chapters/people) The designers and engineers this book reads ### [Glossary](https://learn-ui.com/chapters/glossary)[](https://learn-ui.com/chapters/glossary) Every term, defined in its author's words ### [Further reading](https://learn-ui.com/chapters/reading)[](https://learn-ui.com/chapters/reading) - [Essays and talks](https://learn-ui.com/chapters/reading#essays) - [Tools and libraries](https://learn-ui.com/chapters/reading#tools) - [People and sites](https://learn-ui.com/chapters/reading#sites) - [Hubs and resources](https://learn-ui.com/chapters/reading#hubs) --- # About # About this site Learn UI is an interactive book about design engineering: the practice of designing interfaces by building them. It is for designers who write code, engineers who care how things feel, and anyone trying to understand why some software seems to respond to intent while most of it merely responds to input. Eight chapters cover interaction details, motion, components, craft, taste, explanation, canvases, and the career. Each section pairs prose with a figure you operate: you set a spring and watch it ring, swipe a card and see when the action commits, stack toasts and learn why keyframes fail, draw a stroke and change its pressure curve. No interaction shifts the page, and every figure states whether its numbers come from a cited source or are illustrative. ## Sources The book reads the published work of Rauno Freiberg, Emil Kowalski, Maggie Appleton, Bartosz Ciechanowski, Kathryn Gonzalez, Jim Nielsen, Paco Coursey, Steve Ruiz, Amelia Wattenberger, and Andrew Swank, plus the Vercel design engineering team and the hubs that collect the field. None of them are affiliated with this site, and none reviewed it. The chapter prose is original; short quotes are attributed; the glossary quotes its sources verbatim by design; every essay, library, and site cited appears in the reading list with a link. The rule while writing was simple: no claim without a source, no number a source does not state. When a figure or an explanation gets something wrong, the mistake is this site’s, not the author’s. The originals are better than any summary of them, and the best outcome of reading a section here is that you go and read the essay it draws on. ## Who built it The site does not say, but the Ask AI on any chapter will tell you if you ask. ## For developers Learn UI also publishes a keyless JSON API and an MCP server for the same chapter index. [See the developer page](https://learn-ui.com/developers). --- # Canvases and tools for thought On an infinite canvas, design and engineering are the same act: the feel of a drag is a formula, the weight of a pen line is an algorithm, and a hover area is a decision somebody made in code. This chapter reads Steve Ruiz’s posts and libraries to see how that work is done, follows the canvas into its meeting with language models, and ends with Maggie Appleton’s argument that a tool for thought is a practice people keep, not an object they ship. ## 4 sections 1. [Prototypes that become products](https://learn-ui.com/chapters/canvases/prototypes-to-products) 2. [Drawing a perfect stroke](https://learn-ui.com/chapters/canvases/perfect-stroke) 3. [The canvas meets the model](https://learn-ui.com/chapters/canvases/canvas-and-models) 4. [Tools for thought as cultural practices](https://learn-ui.com/chapters/canvases/tools-for-thought) --- # The canvas meets the model · Canvases and tools for thought ### A weekend in November 2023 The [tldraw.dev](https://tldraw.dev) hero says “Build infinite canvas apps in React with the tldraw SDK”: multiplayer with live cursors, selection and transformation with nested transforms, a geometry system for hit-testing, theming and screen reader support, a signals library and record store, alignment, reordering, camera controls. The infrastructure of a drawing tool. > Figure. TSXtldraw.dev quick start [make real, the story so far](https://tldraw.dev/blog/make-real-the-story-so-far) tells what turned it into something else. A day after an announcement, Figma engineer Sawyer Hood posted a video: draw an interface in the tldraw component, export a picture, send it to GPT-4V, get back working HTML and CSS. Two weeks later the repository passed 10,000 GitHub stars. **Make Real** (tldraw: 'Ever wanted to just sketch an interface, press a button, and get a working website? Well, now you can at makereal.tldraw.com.') is that loop as product: draw, select, click the blue button, and “in a few seconds, your website will appear on the canvas.” The first move was to put the website back on the canvas. Because the canvas “has always been made of regular HTML,” it holds iframes, so the result is a shape you move, resize to explore breakpoints, arrange beside other iterations, and draw on; click again and the annotations become the next prompt. An iframe is a black box to its page, so the model cannot see its own output; the fix hands the previous HTML back with a note to fill in the white box. “Like a chat window, the canvas is transformed into a conversation space where you and the AI can workshop an idea together.” ### A surface people and models share The launch was chaos: the rate limit broke the app for everyone, so the team added a text input for users’ own OpenAI keys. Written “roughly 72 hours” after release, the post closes: “You’ve got a canvas that can hold the whole internet and an AI that can see and think. What will you make?” By 2026 the answer is a product. [Text is not enough](https://tldraw.dev/blog/text-is-not-enough) opens with “Some ideas just don’t fit in a chat box”: an adjustment to part of a design, or a workflow, is hard through chat alone. tldraw’s MCP App puts a canvas in the conversation; the agent draws, diagrams, and wireframes, and you edit too while it sees your changes. Source Steve’s 2026 post [Stay away from my trash!](https://tldraw.dev/blog/stay-away-from-my-trash) is the other side: tldraw began auto-closing external pull requests after an influx of low-quality AI contributions. “In this system, slop is lubrication.” Amelia Wattenberger argues for the surface from the other direction. [Evolving the infinite canvas](https://wattenberger.com/thoughts/evolving-the-infinite-canvas) starts from how linear the web is (top to bottom, or if we are feeling spicy, left to right): infinite canvases “marry the easy manipulation of the digital world with the spatial strengths of the physical world,” hence their use for complex, unsorted, exploratory tasks. She proposes hardcoding the behaviours we do by hand into the canvas (preventing overlap, magnet-like grouping where “pull fast enough and they detach”) and the Gestalt-like rules we read by eye (similarity, linear order, proximity) into the exported data, and asks why an app must choose document, spreadsheet, timeline, or canvas when “each interface has its own strengths, weaknesses, and stored information.” [LLMs as a tool for thought](https://wattenberger.com/thoughts/llms-as-a-tool-for-thought) gives the reason canvas and model belong together. Most people use chatbots only to steer somewhere; a tool for thought is “like sketching while thinking,” gaining distance from thoughts to evolve them. A painter close to the canvas loses the whole; a good tool keeps thoughts outside working memory and speeds the cycle of observing, planning, painting. Chatbots are a restaurant with a 20-page menu, good enough for anyone, ideal for nothing. In [Our interfaces have lost their senses](https://wattenberger.com/thoughts/our-interfaces-have-lost-their-senses) she asks to “collaborate on tangible artifacts, not just ephemeral chat logs”; Make Real’s iframes are a literal answer. Her case against chat as default continues in [Data into meaning](https://learn-ui.com/chapters/explaining/data-into-meaning). ### Design is the bottleneck Maggie Appleton is the counterweight. Her January 2026 note on [Gas Town](https://maggieappleton.com/gastown), Steve Yegge’s entirely vibecoded agent-orchestration system, treats it as speculative design fiction, not a usable tool, and concludes: “When you have a fat stack of agents churning through code tasks, development time is no longer the bottleneck.” Design is: “imagining what you want to create and then figuring out all the gnarly little details required to make your imagination into reality.” Her own holdups are architecture, feel, look, whether a transition is subtle enough. Language is “a poor medium for designing easing curves and describing aesthetic feelings”; she always touches the CSS, and an agent asked for a diagram cannot really see what it makes. Her biggest criticism is that Gas Town was not designed ahead of time; as a commenter she quotes put it, “it was vibe designed too.” The three voices agree. Steve built a surface where the model’s output is a movable, drawable object, not a transcript. Amelia explains why that helps thinking. Maggie warns that thinking is now the scarce part. Give models and people the same spatial place to meet, and design it so the human keeps the pencil. Someone still has to decide what the drawing means. --- # Drawing a perfect stroke · Canvases and tools for thought ### One function, one polygon [perfect-freehand](https://github.com/steveruizok/perfect-freehand) is Steve Ruiz’s library for the line a pen leaves: “Draw perfect pressure-sensitive freehand lines.” The package is one function, `getStroke`, which takes input points and returns the points of a polygon. Per the README it “creates a set of spline points” from the input, then “creates outline points” around them; the closed polygon is a **stroke** (perfect-freehand: the outline points returned by getStroke form a polygon, called a stroke, that surrounds the input points.), and you fill it with SVG, canvas, WebGL, anything. The library computes geometry and stops. > Figure. TypeScriptperfect-freehand README (defaults) ### Pressure and the knobs Ink comes from pressure. “The appearance of a stroke is effected by the pressure associated with each input point,” and by default getStroke simulates it from the distance between points, which is the speed of the hand. A point’s third number is real pressure, defaulting to .5; to honour a pen, pass it and set **simulatePressure** (perfect-freehand option: whether to simulate pressure based on velocity. Default true.) to false. > Figure. TypeScriptperfect-freehand README The defaults are the figure’s baseline. `size` is the base diameter, 8. **thinning** (perfect-freehand option: the effect of pressure on the stroke's size. Default .5.) is pressure’s effect on size, `smoothing` softens the edges, and **streamline** (perfect-freehand option: how much to streamline the stroke. Default .5.) streamlines the stroke, each .5. `easing` maps each pressure, default `t => t`. `start` and `end` take a `cap` (default true), a `taper` distance (default 0; `true` means the whole length, and cap has no effect once taper is above zero), and their own easing. `last`, default true, draws the end at the last input point rather than slightly behind it. Two README tips: thinning 0 gives a steady line; negative thinning gets thinner under pressure. The rest is taste, so turn the knobs below with a mouse, finger, or pen. Move fast then slow and the width follows. Push streamline up and the line lags your hand and loses the tremor; at 0 every jitter returns. Turn simulated pressure off on a trackpad and the line goes flat, because no real pressure is arriving. > Figure 1. A pressure-sensitive stroke. Draw, then change thinning and streamline and watch the same input become a different line. Thinning 0 gives a steady line; a negative thinning thins under pressure instead of thickening.Constants from the source ### From outline to path The figure renders with the README’s `getSvgPathFromStroke`: `M` at the first point, a `Q` through the second to the midpoint of the second and third, `T` through each later midpoint, then `Z`; fewer than four points returns an empty string. On a 2D canvas the string goes into a `Path2D`. > Figure. JavaScriptperfect-freehand README The outline can cross itself, so the README shows flattening with polygon-clipping. It also exports `getStrokePoints` (point, pressure, vector, distance, running length; the last point’s running length is the total), `getStrokeOutlinePoints`, and `StrokeOptions`. Built for hand movement, but “you can pass any set of points into the library’s functions,” as the Feather icons example shows. Ports exist in Dart, Odin, Python, and Rust, plus a Figma plugin. Try it Draw a long loop with thinning at .5 and simulation on, then again at -0.5. The relationship between speed and width inverts. ### Engineering imperfection Freehand lines are half of what makes tldraw look drawn rather than plotted. The other half is [Engineering imperfection with draw shapes](https://tldraw.dev/blog/engineering-imperfection-with-draw-shapes) (2026): geometric shapes get “a hand-drawn style through intentionally designed imperfections,” which “loosens up wireframes.” The variety must be narrow enough that a rectangle is still a rectangle, broad enough that no two match, and stable through resizing and transformation. `Math.random()` at render time jitters on every render, so tldraw seeds a small xorshift-style generator with each shape’s stable id. For ink density each path is drawn in two passes by default, the seed modified per pass, “thicker and more textured than a single wobbly line.” Corners are softened with quadratic Beziers, rounded by angle (a 90 degree corner needs a lot, one near 180 little) and clamped to a quarter of the segment length. Steve admits the offsets are normalised in x and y, so the offset area is a square, not a circle: “Seems our randomness could be more imperfect still.” Take two things. Separate geometry from rendering as getStroke does: a function that returns points is testable and portable across SVG and canvas. And make imperfection deterministic, seeded with identity rather than time, or the character flickers away on the next render. --- # Prototypes that become products · Canvases and tools for thought ### Making stuff with the wrong tools Steve Ruiz’s [about page](https://steveruiz.me/about) calls him “a developer, designer, and now startup founder in London” with “a background in visual art,” and states this section’s thesis: “I build lots of prototypes. Sometimes those prototypes turn into products.” His open source list (tldraw, “a tiny little drawing app”; globs; perfect-freehand; perfect-arrows; state-designer) reads like a lab notebook. In 2022 he formed a company around the **infinite canvas** (Steve Ruiz: 'The first is the canvas. You can think of this as a fixed plane of infinite dimensions.' tldraw is his infinite canvas SDK for React.) SDK of the same name; the demo at tldraw.com became an app with close to 500,000 monthly active users. A 2021 post on [Figma’s Interactive Components](https://steveruiz.me/posts/it-wasnt-made-to-do-that) shows the temperament: “Personally, I’m a big fan of making stuff with the wrong tools.” A Figma prototype once tracked one piece of state, the current Frame, and the limits “do make for some excellent creative constraints.” ### Canvas, camera, screen, viewport [Creating a Zoom UI](https://steveruiz.me/posts/zoom-ui) (2021) names four things: the canvas, “a fixed plane of infinite dimensions”; the camera, “suspended in front of this plane”; the screen, “where we see what the camera sees”; and the viewport, “the part of the canvas that is visible on the screen,” extending down and right from the camera rather than centring on it. The camera has a point and a zoom, where 1 is 100%, and the two coordinate systems convert in four lines. > Figure. TypeScriptSteve Ruiz, Creating a Zoom UI A pan moves the camera point by the delta divided by the zoom, so it feels the same at every magnification. A zoom is toward a canvas point: convert the pointer to canvas space under the old camera and the new one, and shift the camera by the difference so the point under the cursor stays put. Both arrive as wheel events, the control key marking a zoom (a MacBook trackpad pinch fires a WheelEvent with `ctrlKey: true`). The result is a CSS transform where “the order is: first scale, then translate.” > Figure. TypeScriptSteve Ruiz, Creating a Zoom UI ### Drag from the origin, not the last event [Perfect Dragging](https://steveruiz.me/posts/perfect-dragging) says there is a wrong way: adding the pointer’s movement since the last event to the shape’s current position. Instead keep the original position and the drag’s origin, and set position to original plus the delta from that origin. That buys a dead zone, updates while scrolling, restore on cancel, and a delta you can bend for snapping, precision mode, or elastic bounds. “The only way to implement these features is to never rely on the shape’s ‘current’ position.” > Figure. TypeScriptIllustration [Dead Zone Dragging](https://steveruiz.me/posts/dead-zone) builds the first item. A **dead zone** (Steve Ruiz: a minimum distance needed before a shape will begin to drag, which prevents accidental drags during clicks.) is “a minimum distance needed before a shape will begin to drag,” a three-state machine: idle, pointing, dragging. In pointing, movement does nothing; once the pointer leaves the zone the shape jumps to origin plus delta, and the pointer should sit where it did relative to the shape at the press. Two or three pixels is enough: a frame or two, still catching slips on touch and stylus. Source The incremental approach fails here: the zone would equal a single move, so a slow pointer could stay inside it forever. Steve Ruiz, Dead Zone Dragging (2021). [Fixing the Drift in Shape Rotations](https://steveruiz.me/posts/rotating-shapes) finds the same kind of invariant. Figma, Excalidraw, and tldraw all pivot around the selection’s average centre, which moves after the first rotation, so rotating back lands elsewhere. The fix holds the centre until a new selection, as Canva appears to do. The two Reordering posts ([arrays](https://steveruiz.me/posts/reordering), [tables and fractional indexing](https://steveruiz.me/posts/reordering-fractional-indices)) treat Send to Back as array moves, then as a table problem where renumbering one item can rewrite every index: database writes, multiplayer packets, renders. **Fractional indexing** (Steve Ruiz: an index only needs to ensure that, when our items are sorted by their index, the items end up in the right order; the values do not have to be integers or evenly distributed.), credited to Figma’s article, only needs sorting by index to give the right order. Indices start at 1 because “we can’t cut zero into fractions,” and since a JavaScript number splits 52 times before losing precision, the durable version sorts strings like `a0`, `a1`, `a2a`, after David Greenspan. > Figure. TypeScriptSteve Ruiz, Reordering Part 2 ### The same craft at company scale For [An exhaustive review of design tool hover areas](https://tldraw.dev/blog/a-review-of-design-tool-hover-areas) (2026), nothing shows the **hover areas** (Steve Ruiz: the regions around a selection where a drag inside the box translates, a drag on the edges resizes along that axis, a drag from the corner resizes along both, and a drag further out rotates.) around a selection, so a Hammerspoon script moved the mouse in a 50x50 grid, logged the cursor, and rendered a PNG. tldraw’s resize corner is a square slightly offset from the geometry corner; Figma’s edges are bigger and its rotate area an arc around the corner; Excalidraw is “a beacon of rationality” with one size for both; Miro’s corner is smaller than its overlapping edges; Spline’s edges taper; Rive’s arc looks rotated by degrees where radians were meant. If the SDK diffuses to thousands of apps, “perhaps we’ll define the next conventions.” [Erasing shapes](https://tldraw.dev/blog/erasing) fixes a bug in FigJam and many others: the eraser is a point, fast pointer samples land far apart, so a stroke can cross a shape with no sample near it. Game developers call it tunneling; “an eraser is a bullet you drag around with your hand.” tldraw tests line segments against each outline via the geometry system (Rectangle2d, Circle2d, Polyline2d, CubicBezier2d), with the margin divided by zoom to stay constant on screen, and nothing deleted until release: “Erasing is a proposal until the moment you let go.” [Back to Content](https://tldraw.dev/blog/back-to-content) is the opposite: two near-identical lists, not visible shapes and culled shapes (never selected or editing ones), the button on the wrong one, a bug alive more than 20 months. “The bug came from using the wrong concept for the job.” Two posts are about time. In [Debugging a physical race condition with modifier keys](https://tldraw.dev/blog/adding-delays-to-modifier-keys) (with Ani Krishnan), Shift constrains, Alt duplicates, Ctrl snaps, all changeable mid-drag; releasing key and mouse “at the same time” sometimes sent keyup first and cancelled the effect, “a physical race condition based on the imprecision of our bodies.” A modifier now reads as released only after 150ms. [Redesigning the laser tool](https://tldraw.dev/blog/redesigning-lasers) replaces a self-consuming polyline with marks that stay until you stop, then fade together, on the scribble system (ephemeral lines above shapes, below cursors). Consumption is modulated so every session takes the same time and eased to start slowly, since linear progress looks like it slows at the end, with a manual cancel because “it’s never nice to get locked into waiting.” > Figure. TypeScriptSteve Ruiz, Redesigning the laser tool Each post isolates one interaction, names the quantity that must not change (the pointer’s offset, the pivot, the sort order, the eraser’s size on screen), and builds the code around preserving it. When you cannot see what a competitor did, build the instrument that makes it visible. --- # Tools for thought as cultural practices · Canvases and tools for thought ### Read the phrase literally Maggie Appleton’s [Tools for Thought as Cultural Practices, not Computational Objects](https://maggieappleton.com/tools-for-thought) (2021, with talks in 2020 and 2022) starts with a phrase that had become “a new rallying point.” People from personal knowledge management, note-taking, networked thought, CSCW, or HCI were reframing their work as **tools for thought** (Maggie Appleton: 'tools that help humans think thoughts; potentially new, different, and better kinds of thoughts than we currently think.'). It is a category tag in venture databases and a landing-page promise of notes, connections, dynamic views, and “a kind of emergent wisdom. An enchanting promise.” She reads the words literally: “the phrase tool for thought doesn’t have the word ‘computer’ or ‘digital’ anywhere in it.” So what does any of this have to do with computers? ### Thinking before transistors Her list of tools that helped humans think before a single transistor: written language (3200 BCE), drawing (around 73,000 years ago), maps (700 BCE), Hindu-Arabic numerals (400 BCE), epic poetry as oral history, the Socratic method (500 BCE), the scientific method, Cartesian coordinates (1637), Zettelkastens (1500s), Aboriginal songlines (around 60,000 years ago), spreadsheets, and data visualisation (1785). “Each of these examples profoundly transformed the kinds of thoughts humans can think.” Most are not objects but **cultural practices** (Maggie Appleton: cultural practices and techniques are primary ways of doing; specific ways of thinking and acting that result in greater cognitive abilities, passed down through culture.) and techniques, “specific ways of thinking and acting that result in greater cognitive abilities,” passed down through culture and predating digital computers by centuries or millennia. One distinction to keep: mediums communicate a thought, tools are a means of working in a medium, and “tools and mediums require each other.” Cameras are a tool for photography, blogs for written language, JavaScript for programming. ### The computational lineage She tells the computational history fairly. Kenneth Iverson used the phrase in work on programming notation through the 1950s and 60s; Notation as a Tool for Thought (1979) argued shared notation relieves working memory and compresses meaning. Vannevar Bush proposed the Memex in As We May Think (1945). Engelbart’s 1962 definition is about approaching complex problems, not amplifying intelligence in the abstract. Alan Kay in 1989 described a medium whose use “would change the thought patterns of an entire civilization,” and now says the personal computing revolution has not happened yet. Matuschak and Nielsen (2019): “a context in which the user can have new kinds of thought.” The New Media Reader is, several people told her, the bible of the field. All of them treat the computer as vital, and the canonical list (Iverson, Licklider, Bush, Kay, Taylor, Engelbart, Papert, Victor, Rheingold) is male, white, North American, and tied to a few prestigious technical universities. Tools for thought “is a community scene as much as it’s a concept.” Source Seven years before Rheingold’s Tools for Thought, the biologist and philosopher C.H. Waddington published a 1977 book of the same name about complex systems. Maggie uses it as evidence the idea was never only computational. Against that lineage she sets the cognitive scientists and philosophers the computer scientists rarely cite. Andy Clark’s 2003 Natural-born Cyborgs argues humans have “always been cyborgs”: the mind is a process between body and environment, so “intelligence emerges at the intersection of humans and tools.” Honest usage would rename the field computational mediums for thought, or “computational mediums for white-collar knowledge work.” The field’s own story casts the nineties and early oughts as fallow, then a second wave from the 2019 Matuschak and Nielsen essay and an inflection in mid-2020 when note-taking apps multiplied. Yet the guides for those apps “are only superficially about the application they’re presented in.” They teach Zettelkasten, spaced repetition, critical thinking. Practices, not software. ### What practice does this carry? For builders the conclusion lands on the product page: “This question of developing better tools for thought can and should cover a much wider scope than developing novel note-taking software.” An app does not make anyone think better by existing. A practice does, and an app is good to the degree it carries one: gives it a place, lowers its cost, lets it be taught. [Gathering Structures](https://maggieappleton.com/gathering-structures) (2024) applies the idea to rooms. “Inadvertently gathering people” for about fifteen years and running the London Future of Coding meetup, she catalogues structures that shape interaction: seven-minute demos (no minimum; the limit “isn’t enough time to waffle”), rotating hosts for groups under about 20, an unconference wall of post-its voted with sticker dots, the fishbowl with its one always-empty chair, positive exclusion. Start small, since people and problems scale linearly and her ideal is eight to twelve: “what you need is a time, a place, an intention, and some people.” Structures are the tool, the meetup the medium, the community the practice. Her last line: “No one else will organise the group you most want to be a part of.” Return to the canvas with that lens. tldraw’s SDK, Make Real, and perfect-freehand are computational objects, and good ones. But Steve Ruiz’s posts are about the practice they carry: how a drag feels, where the handles are by convention, what an eraser does before you let go. The hover-area survey is an ethnography of canvas software; the hope to “define the next conventions” is a hope about practice. Amelia’s proposals encode what people already do by hand. Maggie’s warning about Gas Town is that generating faster than you can think is a practice too, just a bad one. So ask of every canvas, editor, or tool you build: what practice does this carry, and who is it for? If the honest answer is a demo, the work is not done. Drawing is older than writing by tens of thousands of years on Maggie’s list; the software’s job is to be a surface the practice survives contact with. Build it with the care of the dead zone and the seeded wobble. Then remember the drawing was always the point. --- # The career This chapter describes the job from inside it: what the person who built design engineering at DoorDash says the role demands, how Vercel and Linear and a dozen other writers describe where it lives, the argument for why it should exist at all, why the strongest portfolio a design engineer has is their own website, and where to keep learning once the book is closed. Every description here comes from someone who holds, or built, the role. ## 5 sections 1. [The attributes of a design engineer](https://learn-ui.com/chapters/career/attributes) 2. [Where the role lives](https://learn-ui.com/chapters/career/where-the-role-lives) 3. [The case for design engineers](https://learn-ui.com/chapters/career/the-case) 4. [Your own site as proof](https://learn-ui.com/chapters/career/your-own-site) 5. [Where to go next](https://learn-ui.com/chapters/career/where-to-go-next) --- # The attributes of a design engineer · The career Kathryn Gonzalez joined DoorDash in 2015 as its first full-time product designer and frontend engineer, when it was “only a handful of us working out of an old Animal Hospital in Palo Alto.” She led product design, started DoorDash Drive, led frontend engineering, then spent six years building the Design Infrastructure org (design systems, design engineering, prototyping, accessibility), ending as a manager of managers over twenty-five people. She [left in January 2023](https://www.ryngonzalez.com/blog/goodbye-doordash) and a year later published [The Attributes of a Design Engineer](https://www.ryngonzalez.com/blog/the-attributes-of-a-design-engineer), “My definition of design engineering after building the practice at DoorDash.” A photo in it marks 2017, when she officially became a design engineer there: “CEO approved!” ### Outcomes, not tools The post opens on “Design Engineering seems to be having a moment” (Vercel had just published its account, David Hoang had written about the decade ahead) and deflates the novelty: creative technologists, Flash developers, design technologists, and UX engineers were the same role with different tools. Then it refuses the usual test: “are they a designer who knows how to sling some React? Or are they an engineer that has an eye for design and is comfortable in Figma?” She defines it by outcomes. **Design engineering** (Kathryn Gonzalez's definition: living at the intersection of design and engineering, and using a broad understanding of both sides to build with significant autonomy, practice and teach great software craft, and elevate the final fidelity of what is made from start to end.) is living at the intersection of both practices and using a broad understanding of each to **build with significant autonomy** (The first of Kathryn Gonzalez's three attributes: taking full ownership of what ships, the outcome rather than the design deliverable, and acting as an owner end to end.), **practice and teach great software craft** (The second attribute: an obsession with the materials of software and the affordances of the medium, paired with helping others understand them.), and **elevate the final fidelity of what’s made** (The third attribute: using the fact that much of the process of building software can live in one person to raise the fidelity of what ships, directly and through infrastructure that raises everyone else's.). Those three fit design systems roles, prototyping roles, and product roles with craft at the core. She has held all three. ### Autonomy: own what ships The autonomy story is an origin story, told honestly. “In truth, it started because they hired me as their first product designer, and quickly, I made it known that I didn’t see the scope of my role being just a person who lived in Sketch (pre-Figma).” Her responsibility was “the full ownership of what we shipped,” the outcome, not the deliverable. DoorDash had no full-time product designers or frontend engineers, so she filled both gaps: the internal menu editor, the web consumer site, and the first Merchant tools, end to end. The DoorDash.com of 2017 was hers. Startups, she concludes, want owners end to end, and design engineers are that mindset as a practice. ### Craft: the materials of software “Great design engineers are obsessed with understanding the materials of software, all the specific affordances of the medium, and the tools you use to shape them.” She calls them “software makers,” and the tell is what they learn: tools others find too intimidating (shaders, 3D materials, physics-based animations) or too wasteful for anyone shipping anything that worked “but not the right thing executed exceptionally well.” Her examples: micro-interactions prototyped in Principle, Framer, and code; in 2015, migrating DoorDash’s Backbone, vanilla JS, and Angular 1 to React. The teaching half followed. She had learned at Fetchnotes how hard a fluid web-stack mobile app is, shared that with the full-stack engineers, and helped hire frontend engineers with the same attention to detail. Source The three attributes are the section headings of The Attributes of a Design Engineer (April 2024). The DoorDash timeline is from her home page, Goodbye, DoorDash, and her Config 2023 talk intro. ### Fidelity: where the role lives “One of the unique aspects of design engineering is that you’ve got the potential to have much of the full process of building software contained in one person.” Her favourite projects were explorations no static design could express: “Selling a vision to customers, or other people in your company, sometimes requires a magic trick.” The same skill builds infrastructure that raises everyone else’s fidelity, which is why design engineers cluster at large companies on infrastructure and systems teams. “We were a leading system by the time I left.” In a [2020 interview](https://www.ryngonzalez.com/blog/design-leadership-interview-at-doordash) she wanted hires “really strong at bridging the gap between design and engineering”; the open iOS Design Technologist role had to know UIKit’s pain points and “love and appreciate the craftsmanship in building UIs.” Her 2018 post [Design Systems and Infrastructure](https://www.ryngonzalez.com/blog/design-systems-and-infrastructure) framed the goal as “a home where people who love both design and engineering can use their skills” and defined **design infrastructure** (Kathryn Gonzalez's name for the function at the intersection of product design and engineering that supports both sides through tools, systems, communication, and shared empathy.) as supporting both sides “through our tools, systems, communication and most importantly, our shared empathy of design and engineering.” The close: “Design engineering is not just a designer who codes or an engineer who has an eye for design and the courage to edit a Figma file.” It brings an organisation “better software, more truthfully expressed.” Footnotes promise posts on design engineers as founders and on why the career “can be precarious,” and a [travel essay](https://www.ryngonzalez.com/blog/how-do-you-want-to-live) wonders whether she could “again be the one that coded and designed the thing.” None of the attributes is a tool, so practise them now: own an outcome, learn the material well enough to teach it, find where higher fidelity would change a decision. The title came two years after the behaviour. --- # The case for design engineers · The career Jim Nielsen has blogged for fifteen years and says “Design Engineer” is the job-title bucket closest to his sense of self, “that or just plain old ‘Web Designer’.” His three-part case is the most quoted argument for the role, and it is about process, not skills. ### Too many artifacts [The Case for Design Engineers](https://blog.jim-nielsen.com/2022/the-case-for-design-engineers/) (26 May 2022) reacts to Jason Grigsby’s “Traditional Web Design Process is Fundamentally Broken.” For responsive design “there are Too. Many. Artifacts.”: sketches, wireframes, mockups, prototypes, each in at least three sizes, up to sixty per iteration by Grigsby’s count, with iOS alone at thirteen breakpoints, and none capture how the design behaves in the browser. That “helps show why design engineers are worth their weight in gold.” They know the medium, so they make one or two artifacts and hold the rest in their head, and they need not document every state “because they are the ones downstream of the designs.” He calls this **declarative design** (Jim Nielsen's contrast: declarative feature design is a couple of mocks, a few rules, and a design engineer; imperative feature design is innumerable mocks and rules with a strict waterfall between designers and developers.): a couple of mocks, a few rules, and a design engineer, versus a strict waterfall. “At what quantity does a set of declarative rules begin to look like imperative instructions?” ### Feel cannot be specced [Pt. II](https://blog.jim-nielsen.com/2024/the-case-for-design-engineers-pt-ii/) (12 February 2024) is about feel. You get a note: the line between two containers should be draggable. “Perhaps that note is all you get.” Open questions: is there a resize affordance, on mouse in or mouse down, immediately or delayed, on the line or in a target area and how big, with snapping? His own build “felt off” until he saw the trigger area was asymmetrical between the two boundaries. “Sometimes you just have to feel it, use it, to understand the nuances.” So “you need someone who can do design work with code.” Pixels from a GUI tool are “a static representations of a dynamic form,” a picture of him versus the moving him; designing in code makes the artifact the deliverable in embryo, and review becomes sending links. He allows two people, if they are close enough that the thing “feels designed all the way through.” [Pt. III](https://blog.jim-nielsen.com/2024/the-case-for-design-engineers-pt-iii/) (27 March 2024) borrows Christopher Nolan’s Writer/Director credit: films, like websites, are drafted outside their final medium, so meanings are found in production. “The creative process is not an assembly line,” and with narrow roles, “if what was planned on paper doesn’t work in reality, you’re stuck.” [Making Films and Making Websites](https://blog.jim-nielsen.com/2024/making-films-and-making-websites/) states **the only source of truth** (Jim Nielsen's rule that the only source of truth is the website people access and use; design system components, Figma mocks, and research data are tools in service of that final form.): the website people use. “People come to watch films, not read scripts. People come to use websites, not look at mocks.” [The Figma to Browser Chasm](https://blog.jim-nielsen.com/2023/figma-to-browser-chasm/) (2023) is the business version: a Figma file that never reaches the browser means “you’re throwing away time and money,” unless “you’ve got a design engineer who can do both.” Source Dates from the posts and Jim’s #designEngineer tag: Pt. I 2022-05-26, Pt. II 2024-02-12, Pt. III 2024-03-27, Making Films and Making Websites 2024-03-19. ### The same case, run for years Kathryn Gonzalez’s systems writing is the role inside a company. [Design Systems and Infrastructure](https://www.ryngonzalez.com/blog/design-systems-and-infrastructure) (July 2018) lists a Design Language System for web, Android, and iOS sharing type, colour, and spacing through tokens, and components that made “the hard, tedious, error-prone work of building things like modals” no effort. Design had two halves: generative exploration, then **productionizing** (Kathryn Gonzalez's term for taking explorations and making them work in the context of the design and engineering systems, accounting for edge cases and existing patterns.), making micro-interactions “repeatable and low-cost” by engineering them once. [How to Build a Modal](https://www.ryngonzalez.com/blog/how-to-build-a-modal) (2017) is the ground truth: a z-index problem (a LayerManager with its own stacking context), focus management (the WAI-ARIA examples “are your friend”), an iOS scroll lock overflow: hidden could not provide, and “Always test with real devices.” The system “is made of processes as much as components,” and her [Config 2023](https://www.ryngonzalez.com/blog/design-systems-in-transition-anxiety-ai-and-where-we-go) line, that the extra ten percent of polish makes “your designers truly trust your system,” is Jim’s argument at organisational scale: built once by someone who could do both, handed to everyone. ### How the role is received In [Interdisciplinary Website Maker](https://blog.jim-nielsen.com/2024/interdisciplinary-website-maker/) (April 2024) interviewers “look at me strange and stammer”: “Why would we need a designer that codes? We have designers. We have coders.” Now “any cross-disciplinary interest is easily interpreted as a lack of specialization.” He borrows Paul Ford’s “the interdisciplinarian is essentially an exile” and floats “Interdisciplinary Website Maker,” as Maggie Appleton calls herself a website maker. An earlier post on the [tension between logic and creativity](https://blog.jim-nielsen.com/2023/logic-of-code-and-illogic-of-creativity/) says design engineers “have developed a muscle for holding these tensions in balance.” The coda is sober. In [The Tumultuous Evolution of the Design Profession](https://blog.jim-nielsen.com/2025/tumult-in-design/) (May 2025) he accepts that “bad design doesn’t hurt profit margins,” or nothing proves it does, while cost savings always show; he quotes Elizabeth Goodspeed’s “Less craft, more optics” and adds that optics are often better for your career than building. Kathryn’s “precarious” footnote says the same from the other side. The case is strong; organisations do not automatically make it. When you must, use Jim’s three moves: count the artifacts one responsive feature produces, build the interaction that has a note instead of a spec and send the link, and when a plan fails in the browser, say so and change it. --- # Where the role lives · The career ### Vercel: three workflows, no handoff [Design Engineering at Vercel](https://vercel.com/blog/design-engineering-at-vercel) (29 March 2024; Glenn Hitchcock, Henry Heffernan, John Pham, Rauno Freiberg, Yasmin Pessoa) calls the role “both confusing and exciting” and defines it in two sentences: “Design Engineers at Vercel blend aesthetic sensibility with technical skills. This allows us to deeply understand a problem, then design, build, and ship a solution autonomously.” What they care about is mostly not visual (“There is a lot of work behind the pretty pixels”): - Delightful user interactions and affordances - Building reusable components/primitives - Page speed - Cross-browser support - Support for inclusive input modes (touch, pointers, etc.) - Respecting user preferences - Accessible to users of assistive technology Three workflows. Design collaboration has no handoff: a designer “sketches the start and iterates with a Design Engineer in Figma or code,” who weighs cost against impact (“some animations are unnecessary because they are not the main focus”), decides one-off versus reusable, and prototypes animations, keyboard controls, and touch, which “are better implemented in code.” Product team integration embeds a design engineer on a feature taking more than a month to build the UI while the team builds the API. Independent ownership is a pain point fixed in days to weeks: sketch, socialise, ship. Sitting in Design makes room for work an engineering backlog would sink: the Geist font and glyph playground, the design system docs, the Design Team homepage, dashboard “delighters.” “There’s no fixed toolset for a Design Engineer. There’s no best background,” the skill list (Figma, code, browser performance, GLSL, copy, Three.js, Blender, video) is collective, and the role “is about shifting from owning a specific part of the product development process to owning results.” [Rauno Freiberg](https://rauno.me), Staff Design Engineer there (previously Arc at The Browser Company), shows it in [What will you ship?](https://rauno.me/craft/vercel): in October 2023 four people shipped a new homepage, and if an animation “didn’t perform well, felt pompous, or out of rhythm relative to the page, we didn’t build it.” ### Linear and the public roster Linear employs design engineers without listing the title. Its [careers page](https://linear.app/careers) has Product Designer and Product Engineer roles, but its statement of intent is the closest thing the role has to a job description: “We believe that there is a lost art of building software. A craftsmanship that yields products of an exceptional, almost magical, quality,” unmeasurable “but you can feel it when it’s there.” [Emil Kowalski](https://emilkowal.ski) is on its Web team and [Paco Coursey](https://paco.me) is “Webmaster at Linear,” both after Vercel; one of Paco’s [posts](https://paco.me/writing/safari-favicon-showing-white-background) records changing Linear’s favicon from #6E79D6 to #8299FF to fix a white background in Safari’s dark mode. Maggie Appleton noticed that public design engineers come mostly from “a small set of companies like Vercel, Linear, The Browser Company and Replit.” Her [A Collection of Design Engineers](https://maggieappleton.com/design-engineers) (March 2024) calls the title “the latest label we’re chucking onto the pile of obfuscatory design titles,” worth it because it names “a person who sits squarely at the intersection of design and engineering, and works to bridge the gap between them.” Then she lists people: Rauno Freiberg (Vercel), Paco Coursey (Linear), Szymon Kaliski (Replit), Amelia Wattenberger (GitHub), Andy Allen (Not Boring Software), Alex Obenauer, Bret Victor (“much more than a design engineer”), Emil Kowalski (then Vercel), Steve Ruiz (tldraw, “master of the arrows”), and Bartosz Ciechanowski, “not a Design Engineer as a profession” but a good example of the blend. She counts herself a hobbyist and warns that public work is not day-to-day work: shiny creations, not design-system advocacy. Aside The list is public-only on purpose. “I’m sure there are a thousand and one exceptional design engineers buried in the basement of Apple, but we’ll never get to see their work or learn from them.” ### Definitions that disagree at the edges Sean Voisen, who leads design engineering teams inside Adobe Design, is the most procedural in [Design engineering, a working definition](https://sean.voisen.org/writing/design-engineering-working-definition). He lists the synonyms (UI engineer, UX engineer, design technologist, experience developer, design prototyper, creative technologist), dismisses “designers who code” as “semi-tautological and not particularly helpful,” and names three jobs: prototype so designers can validate assumptions; build tools and design systems; build the interfaces other engineers “can’t or won’t.” The role is “design first, engineering second,” not web-only, and strongest in direct manipulation, where dropped frames show at once. His [Adobe Design piece](https://adobe.design/stories/leading-design/should-you-pursue-a-career-in-design-engineering) counts “more than two dozen design engineers and managers” doing high-fidelity prototyping as a discipline, deeply **T-shaped** (Adobe Design's description of design engineers: a broad understanding of design paired with deep technical know-how in user interface engineering practices like rendering, animation, and layout.), once called “unicorns.” Chris Coyier’s [post](https://frontendmasters.com/blog/design-engineers/) (March 2024) is plainest: engineer means HTML, CSS, JavaScript; design means look and experience; “Web Design Engineer” would keep it apart from mechanical engineering. Trys Mudford, who [found the name in 2021](https://www.trysmudford.com/blog/i-think-im-a-design-engineer/), says “CSS is the primary language of the design engineer” and names the gulf where “a huge wealth of design intention can disappear out of sight.” Jeremy Keith, [the same week](https://adactio.com/journal/17838), dislikes calling unqualified people engineers “but I accept that that particular ship has sailed.” Rune Madsen’s [The Gulf Between Design and Engineering](https://designsystems.international/ideas/the-gulf-between-design-and-engineering/) supplies the shared diagnosis: the **design handover** (Rune Madsen's name for the supposedly magic moment where design has finished and engineering begins, which he calls the root cause of many collaboration problems on product teams.), “this supposedly magic moment where design has finished and engineering begins,” is the root cause of most collaboration problems, and code, not the Figma file, is the real design product. ### Where the term came from David Luhr traced it in [The origins of design engineering](https://luhr.co/blog/2024/02/26/the-origins-of-design-engineering/) (February 2024). January 2019, Chris Coyier’s “The Great Divide”; autumn 2019, Natalya Shelburne’s “CSS at the intersection” (“Roles are arbitrary things we decided”); 2020, Shelburne, Adekunle Oduye, Kim Williams, and Eddie Lou write the [Design Engineering Handbook](https://marketing.invisionapp-cdn.com/www-assets.invisionapp.com/epubs/InVision_DesignEngineeringHandbook.pdf), Lou having formed one of the earliest teams at Indeed and Shelburne having coined the term with Aarron Walter in Sydney; February 2021, Brad Frost coins **front-of-the-front-end** (Brad Frost's term, via Jeremy Keith, for a web developer who specialises in HTML, CSS, and presentational JavaScript, as opposed to the back-of-the-front-end developer who writes the JavaScript that makes an application function.), Mudford follows a day later, Keith responds, and a Clearleft podcast features Tobias Ahlin of GitHub; 2022, Jim Nielsen makes the case; 2023, job listings; early 2024, a significant increase. The Handbook’s sentence is the ancestor: the discipline that “finesses the overlap between design and engineering to speed delivery and idea validation.” Side by side, the agreement outweighs the vocabulary: everyone puts the person at the intersection, ties the role to owning an outcome (“owning results,” “full ownership of what we shipped”), and refuses to define it by a tool. The differences are emphasis: Voisen serves design, Vercel ships product from the Design team, Kathryn finds it in infrastructure teams, Coyier keeps it on the web. So look for the workflow (no handoff, prototype in code, own the result); Product Engineer or Webmaster may mean the same work. --- # Where to go next · The career ### Three hubs [Design Engineering Resources](https://designengineering.arun.is/) (designengineering.arun.is, Arun Venkatesan) hosts nothing; every item links out. Posts: Benji Taylor’s Family Values, Kathryn’s Attributes, Vercel’s post, David Hoang’s Proof of Concept, Luhr’s origins, Rauno’s Invisible Details. Conversations: a Dive Club deep dive with Glenn Hitchcock and John Pham, an 8VC chat with Ramp and Vercel. Courses with prices: SVG Animations ($119), Emil’s Animations on the web ($119), The Joy of React ($249), three.js journey ($95), the W3C’s web accessibility intro (free). One example (Basement Studio’s lab), one job board ([designengineer.io](https://designengineer.io)), and two guides: [Easing Graphs](https://www.easing.dev/), 28 named curves with their cubic-beziers, five custom by Lochie Axon including Anticipate, cubic-bezier(1, -0.4, 0.35, 0.95), and Snappy Out, cubic-bezier(0.19, 1, 0.22, 1); and Rauno’s [Web Interface Guidelines](https://interfaces.rauno.me/), “a non-exhaustive list of details that make a good (web) interface.” [desengs.com](https://desengs.com/) is one flat feed tagged Read, Watch, Listen, Browse, Use, Build, Learn, Join, Follow, Apply. Use is a toolbox (NumberFlow, Sonner, cmdk, Transitions.dev, OKLCH.fyi, The Component Gallery, Laws of UX, Devouring Details); Read overlaps this book; Follow lists Jakub Krehel, floguo, Rauno, and Emil; Join has the [Design Engineering Club](https://designeng.club/); Apply is live listings (Autumn, Zed, Rockstar New York at the time of reading). Its [talent network](https://desengs.com/talent-network) wants people who “care deeply about craft,” “move comfortably between design and code,” and “have a portfolio showcasing their work,” not those “still building your first projects.” Sean Voisen’s annotated [list](https://seanvoisen.com/writing/design-engineering-resources/) (January 2025) adds Karl Emil James Koch’s Become a Design Engineer, Emil Widlund on the career as an investment, David Darnes on whether 2025 is the year of the title, and one book, the [Design Engineering Handbook](https://marketing.invisionapp-cdn.com/www-assets.invisionapp.com/epubs/InVision_DesignEngineeringHandbook.pdf) (2020), “perhaps the most thorough, in-depth resource on design engineering in existence.” Aside Hoang’s Proof of Concept issue is paywalled. Its line that design engineers are this decade’s data scientists reaches this book through Voisen’s note on it. ### Three courses, and this book Emil Kowalski’s [animations.dev](https://animations.dev) has four base modules (animation theory in eight lessons, CSS, Motion, good versus great) and four walkthroughs (the Family drawer, the Dynamic Island, a navigation menu, SVG), more than 35 lessons and 40 exercises; it opened as a presale in January 2024 aiming for a thousand students, and 11,632 had taken it at the time of reading. Rauno Freiberg’s [Devouring Details](https://devouringdetails.com) is “an interactive reference manual for interaction-curious designers,” 23 chapters with 23 downloadable React components. Amelia Wattenberger’s [Fullstack D3](https://www.newline.co/fullstack-d3) is a book ($129) and a masterclass of 52+ lessons; “Charts are like an x-ray for your data.” In this book, the [People](https://learn-ui.com/chapters/people) appendix collects everyone the chapters draw on, [Further reading](https://learn-ui.com/chapters/reading) lists every primary source by kind, and the [glossary](https://learn-ui.com/chapters/glossary) quotes each term in its author’s words. ### What to do tomorrow Voisen’s [Adobe piece](https://adobe.design/stories/leading-design/should-you-pursue-a-career-in-design-engineering) gives three starts that need no new job: join the prototyping process, contribute to the design system, take small UI-focused engineering projects. “Act with more autonomy and more opportunities will naturally come your way.” Jim says build it, click around, and sand until you cannot give yourself another splinter. Kathryn says share openly and consistently. Maggie says follow the people who work in public. Emil, in the README for his [skills](https://github.com/emilkowalski/skill), calls them “a side-effect of domain-expertise”: “So learn to code, design, or develop expertise in any other field.” Vercel says apply without the title. And Rauno’s footer, for the order of operations: make it fast, make it beautiful, make it consistent, make it carefully, make it timeless, make it soulful. Make it. --- # Your own site as proof · The career Maggie Appleton’s method was to “find and follow people doing design engineering work in public,” and her [collection](https://maggieappleton.com/design-engineers) lists only people who publish. A personal site is an interface you designed, built, and shipped alone; by Jim Nielsen’s rule that the only source of truth is the website people use, it is where your taste (what you chose to make) and your craft (down to the unit the font size is set in) are on the record at once. ### The site as the demo Andrew Swank’s [site](https://andrewswank.com) is the most literal. “A designer and engineer by design,” he opens a “This site” section with “I invite you to play with this site. I’ve built this from scratch and welcome feedback.” The listed features are decisions: layout and type sized with vmin and rem to set the baseline font size; max() and round() to snap to a 4-pixel grid; HSL custom properties so colours animate without dulling (“hover over the logo”); Roboto Flex animated with font-variation-settings. > Figure. CSSIllustration The project pages do the same. For [Assistant](https://andrewswank.com/project/assistant/), as a UX Engineer, he built a no-code voice prototyping toolkit “reaching 400+ cross-functional users and powering 8000+ voice prototypes”: a Chrome extension for Google Slides, a speech service, a React component library. For [Google Flights](https://andrewswank.com/project/datepicker/) he made the mobile datepicker “later selected as the Google standard, used by billions,” adopted by Material Design and MUI; his reference implementations cut engineering time by more than half. The page runs a “fairly faithful” recreation: start with departure or return, and if the return precedes the departure “the system automatically swaps them to create a valid range”; days show the cheapest round trip before you pick and the trip total after. Demonstrated, not described. Aside Swank’s numbers are his own. The recreation omits optimisations (pseudo-elements, view recycling) and features (dates in search params, low-price highlights), “but from an interaction point-of-view, this is accurate.” ### Shrine and restraint Kathryn Gonzalez’s [Personal Website, Personal Shrine](https://www.ryngonzalez.com/blog/personal-website-personal-shrine) (July 2023) is about what a site is for. Rebuilt “a half-dozen or so times over the last 15 years,” each version is “a reflection set in a particular time” of where she is; after eight years of neglect she set three principles: share openly and consistently, reflect the fullness of who she is, and play. The build: Notion through react-notion-x, pre-rendered with Next.js, a /bits page for weekly learnings, Framer Motion stickers “to introduce fun, physical moments.” She closes with Clay Shirky on Shinto shrines, lasting because of the rebuilding, and names Lee Byron, who “somehow straddled design and engineering,” and Petter Nilsson: “Two colors, left-aligned, one font-size.” Paco Coursey’s [Redesign 2021](https://paco.me/writing/redesign-2021) stripped paco.me to documents and links: “Instead of adding as many animations, features, and case studies as possible, this iteration reflects my values of performance, simplicity, and craft.” It was hard because “it feels like everything I build must use some novel interaction” (an infinite canvas, a little OS, weather per page), but the old site “felt disingenuous and abandoned,” and “If you leave your home unlocked, it is no longer a home, but an exhibition.” The colophon is the craft: Inter, Söhne, Newsreader, Next.js with JavaScript disabled. The interactions live on a [craft page](https://paco.me/craft): exclusion tabs after Stripe, an iOS 16 dropdown expanding behind a clip-path, three approaches to blur, Linear’s timeline with native scrolling. ### Logs, gardens, verbs Rauno Freiberg’s [craft page](https://rauno.me/craft) is a dated log: 78 entries from 2021 to 2026, each Read Essay, View Prototype, or View Production, no case studies, and a footer standard: “Make it fast. Make it beautiful. Make it consistent. Make it carefully. Make it timeless. Make it soulful. Make it.” Maggie Appleton’s [garden](https://maggieappleton.com) is “imperfect notes, essays, and ideas growing slowly over time,” [built herself](https://maggieappleton.com/colophon) in Astro and MDX, Canela, a Utopia fluid type scale, and a **growth stage** (Maggie Appleton's label on every post for how complete it is: seedlings for rough early ideas, budding for work cleaned up and clarified, evergreen for work that is reasonably complete.) (seedling, budding, evergreen) on every post; her design engineers note is budding. Jim Nielsen’s [about page](https://blog.jim-nielsen.com/about/) counts 805 posts and 580k words; his [home page](https://www.jim-nielsen.com) is verbs (I’m Blogging, I’m Collecting iOS Icons, I’m Baking Pies). Emil Kowalski’s [home page](https://emilkowal.ski) is a few sentences, four projects (animations.dev, Sonner, aiforui.dev, Vaul), and a writing list. Each reads as a portfolio without containing one. Jim’s [Job Screening Blog Post](https://blog.jim-nielsen.com/2024/design-engineer-job-screener/) (November 2024) is two GIFs of a button click; in one the heading shifts up a pixel. “Can you tell the difference between them? Do you care? If not, we might not be a good fit.” The screen runs both ways. [Sanding UI](https://blog.jim-nielsen.com/2024/sanding-ui/), where he fixes the dead click zone a flexbox gap left between a radio and its label, shows what he notices better than a résumé line. Kathryn says of her [2015 piece](https://www.ryngonzalez.com/blog/designing-search-for-doordash) on DoorDash search: “This is the article that got me the most important job of my life (so far).” So build your own site, not from a template, because the choices are the point. Make one page where a component runs. Keep a dated log. Write up the splinter, not just the finish; nobody has to take your word for it. --- # Components A toast, a drawer, a command menu, a modal, and a theme switch. None of them is hard to describe and all of them are hard to get right. This chapter reads the write-ups of the people who built well-known versions of each, because each of them wrote down every decision, and the decisions turn out to be small, numerous, and deliberate. ## 5 sections 1. [A toast that stacks](https://learn-ui.com/chapters/components/toast) 2. [A drawer that follows the finger](https://learn-ui.com/chapters/components/drawer) 3. [A command menu with pages](https://learn-ui.com/chapters/components/command-menu) 4. [A modal that respects focus](https://learn-ui.com/chapters/components/modal) 5. [Dark mode without the flash](https://learn-ui.com/chapters/components/dark-mode) --- # A command menu with pages · Components Maggie Appleton catalogues the pattern in [Command K Bars](https://maggieappleton.com/command-bar) (November 2022). **Command bars** (Command bars are command-line bars that pop up in the middle of the screen when you hit a certain keyboard shortcut; also known as command palettes, command launchers, or omniboxes, traditionally on CMD + K.) “are command-line bars that pop up in the middle of the screen when you hit a certain keyboard shortcut,” traditionally CMD + K, with CMD + E and CMD + / as contenders. Her examples are Linear, Todoist, Framer, Tana, Raycast, and Lazy; the lineage runs to Apple’s Spotlight in MacOS 10.4 Tiger (2005, CMD + Space) and Quicksilver. ### Why a bar beats a menu GUIs make affordances visible, but “they don’t scale very well to complex systems with hundreds of commands”; Cinema 4D is her counter-example. With a bar, “rather than remembering which sub-sub-sub menu a function lives in, users need only remember its name,” and fuzzy search means not even that. Rare items stashed in the bar clear screen space; commandbar.com, kbar, and cmdk are ready-made. ### cmdk and what it costs Paco Coursey’s **cmdk** (⌘K is a command menu React component that can also be used as an accessible combobox. You render items, it filters and sorts them automatically.) [README](https://github.com/pacocoursey/cmdk) says: “⌘K is a command menu React component that can also be used as an accessible combobox. You render items, it filters and sorts them automatically.” Written in 2019, used by Rauno Freiberg for the Vercel command menu in 2020, rewritten in 2022 with help from Shu. On [Devouring Details](https://devouringdetails.com) Rauno calls it “downloaded millions of times per week.” > Figure. TSXPaco Coursey, cmdk README Each part forwards props and ref and carries a cmdk- data attribute for styling; Dialog composes Radix’s Dialog. Items infer value from textContent; you can pass a filter, keywords, shouldFilter false, and loop. The FAQ: accessible, yes, tested with VoiceOver; virtualization, no, but good to 2,000 to 3,000 items; listen for ⌘K, no, “do it yourself to have full control over keybind context.” The [ARCHITECTURE document](https://github.com/pacocoursey/cmdk/blob/main/ARCHITECTURE.md) explains the cost. The library “is born from a simple constraint: can you write a combobox with filtering and sorting using the compound component approach?” For a combobox it is “a terrible, terrible constraint that we’ve spent 2 years fighting.” Every item stays in the React tree and adds or removes itself from the DOM; “the DOM is authoritative,” so selection order follows render order. He rejected React.Children (cannot peek inside composed components), object arrays (their interface grows with edge cases), and render props (inelegant). Selection moved from index to value because Strict Mode runs effects twice. The price: 2,000 items filtered to 2 still allocate 2,000 Item instances, though the DOM shrinks to 2. His [original Command Menu](https://paco.me/craft/command) (2021) tested 249 items, then aimed at 2,000. Source The constraint, the DOM-is-authoritative rule, and the rejected alternatives are from cmdk’s ARCHITECTURE.md, which opens by warning that it is a work in progress. ### Depth through pages The README’s example: “selecting ‘Change theme…’ should show new items ‘Dark theme’ and ‘Light theme’. We call these sets of items ‘pages’, and they can be implemented with simple state,” with Escape or Backspace on an empty search popping out. Maggie sees the same move in Tana. Rauno’s [craft index](https://rauno.me/craft) has Command Menu (November 2021) and ⌘K Breadcrumbs (December 2022), the trail that says which page you are on. > Figure. TSXPaco Coursey, cmdk README The figure is a command menu with two pages: items ending in an ellipsis open a page, the breadcrumb row changes, and Backspace on an empty input goes back. > Figure 2. A command menu with pages. Type to filter, or pick an item with the arrow keys and Enter. Items ending in an ellipsis open a nested page; the breadcrumbs show where you are, and Backspace on an empty input or Escape steps back out. The list keeps a fixed height so the card never jumps between pages.Illustrative numbers ### Do not animate it The figure does not animate its opening, by rule. In [Invisible Details of Interaction Design](https://rauno.me/craft/interaction-design) Rauno makes command menus his example of when not to animate: at “hundreds of times a day, it does start to feel more like cognitive burden after seeing the same animation for the hundredth time.” Emil Kowalski’s skill file puts the command palette toggle in the 100-plus-times-a-day row: “No animation. Ever.” See [Frequency and novelty](https://learn-ui.com/chapters/invisible-details/frequency-and-novelty). Instead, be fast and keyboard-first: filter as you type, keep the selection stable, make Escape and Backspace the way back up a page, and put the shortcut next to the action, as Maggie notes Todoist does. cmdk refuses to decide the keybinding, the styling, and the items. Those are yours. --- # Dark mode without the flash · Components A theme switch is two lines of CSS and a long tail of things that go wrong: a flash of light before dark, a choice that ignores the system, colours animating at different speeds, a tab icon that stops matching. Paco Coursey’s **next-themes** (An abstraction for themes in your React app. (next-themes README)) handles that tail; its [README](https://github.com/pacocoursey/next-themes) lists the problems as features: “Perfect dark mode in 2 lines of code,” prefers-color-scheme, “No flash on load (both SSR and SSG),” sync across tabs, forced themes, and a useTheme hook. ### Two lines and the defaults “Adding dark mode support takes 2 lines of code”: wrap the app in ThemeProvider, a client component. By default it sets data-theme on the html element. > Figure. app/layout.jsxPaco Coursey, next-themes README The defaults say what a theme should do when you say nothing. defaultTheme is ‘system’ (earlier versions: light); enableSystem is true, and with it off the default is light; enableColorScheme is true, so native inputs follow; the attribute is ‘data-theme’, or class, or any data-\*; storageKey is ‘theme’ in localStorage; themes is \[‘light’, ‘dark’\], overridden by your own list, since the library is “completely CSS independent”; disableTransitionOnChange is false. forcedTheme pins a page without touching the saved setting, and then you should disable your switching UI. useTheme returns theme, setTheme, resolvedTheme (what ‘system’ resolved to), systemTheme, and themes with ‘system’ appended. ### Known before first paint No flash means a script injected before paint, with two caveats. The server cannot know the theme, so useTheme values are undefined until the client mounts, and rendering from them earlier is a hydration mismatch; the README suggests a skeleton until mounted, and suppressHydrationWarning on html because next-themes edits that element. And Cloudflare’s Rocket Loader breaks the injected script, hence scriptProps and nonce. ### Switch without transitions disableTransitionOnChange links to Paco’s 2020 post [Disable transitions on theme toggle](https://paco.me/writing/disable-theme-transitions). Against the instinct to transition every colour: “Adding a CSS transition to every element negatively impacts rendering performance, and it also won’t work for images, icons, and CSS properties that don’t support transitions,” and differing durations would feel inconsistent. So he injects a stylesheet setting transition: none !important on everything, with manual browser prefixes since the CSS is not preprocessed, toggles the theme, forces a repaint, and removes it. requestAnimationFrame proved unreliable; getComputedStyle works on every major browser “because it forcibly applies all active stylesheets.” He credits Guillermo for the idea. > Figure. JavaScriptPaco Coursey, Disable transitions on theme toggle ### The favicon and the temperament Dark mode reaches into the browser chrome. In 2023 Paco wrote [Safari favicon showing white background on dark mode](https://paco.me/writing/safari-favicon-showing-white-background): as recently as Safari 16.4, a favicon failing Safari’s contrast requirements sits on a white background in dark mode. He could not pin the requirements down; AA 4.5:1 or AAA 7:1 against both #000 and #282828, Safari’s default dark tab bar, gave no consistent behaviour. The fix is a brighter primary colour, less white space, or a border. For Linear he changed #6E79D6 to #8299FF. That these posts are short and specific is not an accident. In [Redesign 2021](https://paco.me/writing/redesign-2021) Paco strips his site to documents and links: “this iteration reflects my values of performance, simplicity, and craft.” It runs Next.js with JavaScript disabled, because “you don’t need it to read documents.” The same temperament produces a library whose pitch is two lines and stop thinking about it. Try it This site runs on next-themes with the class attribute, system as the default, and disableTransitionOnChange set. Press D anywhere outside a text field to flip the theme and notice that nothing fades. A theme switch is not a colour change; it is a state that must be known before first paint, follow the system, persist and sync, not animate element by element, and reach the favicon. Each is a small decision with a documented default, and the person who wrote them down chose, every time, the quiet option. --- # A drawer that follows the finger · Components Emil Kowalski’s second library is **Vaul** (Vaul is a drawer component for React, built by Emil Kowalski to recreate the feel of Apple's iOS Sheet on the web.), “A drawer component for React.” [Building a drawer component](https://emilkowal.ski/ui/building-a-drawer-component) opens with the motive: “Using Apple’s Sheet component on iOS feels natural, I wanted to create the same experience, but for the web.” He prefers a drawer to a modal on mobile. Vercel’s existing one lacked drag-to-dismiss and had input problems, so he built a new one and open-sourced it for the feedback. ### Borrowed anatomy, written feel Vaul sits on Radix’s Dialog primitive, which “ensures the component is accessible, handles focus management etc.” The API mirrors Radix: Drawer.Root, Trigger, Portal, Content, Overlay, plus Handle, Title, Description, and Close on the [API page](https://vaul.emilkowal.ski/api). What Emil wrote is the feel, starting with one line of CSS. The curve “closely matches the one used in iOS; it’s from the Ionic Framework,” and 500 ms “is also supposed to mimic iOS’s Sheet.” His thesis: “Using the right easing and duration makes a big difference in terms of how this, and any other component, feels.” Note that 500 ms exceeds the under-300 ms rule he gives elsewhere; a drawer is large and imitates a system component with its own timing. > Figure. CSSEmil Kowalski, Building a drawer component Source The curve, the duration, and the Ionic attribution are in the Motion section of the post. The under-300 ms rule is from You Don’t Need Animations and 7 Practical Animation Tips, covered in [the Motion chapter](https://learn-ui.com/chapters/motion/practical-tips). ### Dragging without dropping frames “Not losing frames while dragging is a good start, but I already failed there.” Past roughly 20 list items, dragging lagged with no re-renders to blame. Each update wrote a CSS variable feeding translateY, and CSS variables are inheritable, so every child recalculated style. Writing the transform directly on the element fixed it, a quick fix in retrospect that took hours. > Figure. TypeScriptEmil Kowalski, Building a drawer component Then momentum, so a flick closes the drawer, and damping at the top, where it moves less the further you pull: “things in real life don’t suddenly stop, they slow down first.” A shouldDrag function refuses the drag unless content is scrolled to the top, as on iOS, and since fast scrolling overshoots, a 100 ms timeout after reaching the top forbids dragging. Touches after the first are ignored until release so a second finger does not make the drawer jump. “They are ‘invisible’ because they align with users’ inherent expectations.” ### Reaching outside the sheet scaleBackground makes the body look like another sheet: Vaul finds \[vaul-drawer-wrapper\] and applies a transform and border radius that follow drag progress, so 40% down sets the radius to 60% of its maximum. **Snap points** (Checkpoints in a drawer you can drag to and it will snap to; Emil Kowalski describes them as a common pattern on iOS and points to Apple Maps.) are a fraction of the viewport or fixed pixels, snapped to the closest on release and momentum-based; fixed values keep an input sticking out evenly on every device. Apple Maps is the model. Inputs get the Visual Viewport API: Vaul listens for visualViewport resize and sets the drawer’s height and bottom from the new height, so it sits above the keyboard and stays scrollable. The cost is a slight delay, since the event fires once the keyboard is fully visible. One idea did not ship: dimming Safari’s theme-color bar with the overlay. The meta tag cannot transition or take semi-transparent colors, so he computed the opaque equivalent, built 50 interpolated colors, and updated the tag every 10 ms to match the 500 ms transition, eased with the same bezier via bezier-easing. It stays out of Vaul because it drifts when frames drop. His last point is testing: a real phone on a cable with Safari’s devtools, or the Xcode Simulator, never a shrunken desktop window. The README now calls the repo unmaintained; the decisions stand. Vaul is a short list of numbers chosen to match a reference. --- # A modal that respects focus · Components Kathryn Gonzalez led design infrastructure at DoorDash, and in November 2017 she wrote [How to Build a Modal](https://www.ryngonzalez.com/blog/how-to-build-a-modal): “While building a modal can seem simple from the start, there are a lot of cases and issues to discover once you release and iterate on it.” Three stories about one modal taught her team about z-index management, accessibility obligations, and a gap in testing. ### Stacking contexts, not z-index First, a support ticket: event sign-ups collapsed on desktop only, days after a coworker moved an RSVP flow into the new modal. On mobile the guest-count dropdown was a native select; on desktop the custom dropdown rendered behind the modal. She quotes MDN on stacking contexts, “a three-dimensional conceptualization of HTML elements along an imaginary z-index relative to the user.” A child in one context cannot out-stack a child in another, whatever z-index you give it. Her takeaway: create new stacking contexts for application content and for modal content, so z-index changes in either stay contained. At DoorDash a LayerManager component, built on react-gateway, renders modal content into its own stacking context so the modal is guaranteed to sit above the app. ### Focus goes in and comes back Six months later an ADA audit found keyboard accessibility “pretty bad,” chiefly because opening a modal did not move focus into it. She condenses MDN’s dialog guidance: at least one focusable control; focus moves to the default control on open; focus returns to where it was on dismiss; and the tab order wraps inside the dialog. role=“dialog” gives you none of this; you implement it or a library does. Hence a **focus trap** (In Kathryn Gonzalez's description, focus-trap is a small library that will manage saving the last focused element, finding and focusing on the first focus-able element of the modal, keeping focus within the modal, and restoring focus to the last focused element once the modal is unmounted.). focus-trap “will manage saving the last focused element, finding and focusing on the first focus-able element of the modal, keeping focus within the modal, and restoring focus to the last focused element once the modal is unmounted.” DoorDash uses focus-trap-react inside its modal; re-implementing this per feature is a path to madness and missed edge cases. > Figure. JavaScriptKathryn Gonzalez, How to Build a Modal (focus-trap example) Source The four focus requirements are MDN’s dialog-role guidance as quoted in the post. Kathryn adds that the WAI-ARIA documentation and examples “are your friend.” ### Scroll lock and the real viewport Third, two tickets about scrolling: the page behind the modal kept scrolling, and on mobile a confirm button fixed to the bottom hid behind the browser’s controls. Viewport-height units are not the visible area on mobile; she cites a survey of URL bar behaviour and a Safari contributor explaining that iOS uses the larger size because relayout during scroll at 60 FPS is not practical. Her fix was a calc for the pixels Safari hides. And **scroll lock** (Preventing the page behind a modal from scrolling; Kathryn Gonzalez found overflow: hidden insufficient on iOS, where the reliable options are position: fixed on the body or preventing touchmove.) is not overflow: hidden: “On iOS, there are only two reliable ways of doing this: Setting position: fixed on the document.body, or adding event listeners that prevent the default behavior of touchmove on the body content.” They chose position: fixed. The team had tested mobile only in Chrome’s responsive mode. “Always test with real devices.” ### Four takeaways and the motion Her takeaways: consider accessibility from the start and test with screen readers; know the content the modal will hold; “Design systems, for all they are in technology, are also about processes”; and make the component a tool to distribute best practices, so scroll locking, focus, and mobile behaviour are solved once. She does not discuss how the modal moves, and Emil Kowalski fills that in. His duration table puts modals and drawers at 200 to 300 ms, and his [skill file](https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md) exempts modals from origin-aware scaling: “modals should keep transform-origin: center because they are not anchored to a specific trigger.” Both are in [Practical tips](https://learn-ui.com/chapters/motion/practical-tips). > Figure. CSSIllustration --- # A toast that stacks · Components In 2023 Emil Kowalski built a toast library and told the story in [Building a Toast Component](https://emilkowal.ski/ui/building-a-toast-component). **Sonner** (Sonner is an opinionated toast component for React, built by Emil Kowalski in 2023 and downloaded over 40,000,000 times per week from npm.) is downloaded over 40,000,000 times a week from npm and used by Cursor, X, and OpenAI. The market was crowded; his answer to why people chose it is a list of small decisions. The first was the name: react-toast and its kind felt cheap, so he chose the French sonner, “to ring,” trading discoverability for elegance. ### Transitions, not keyframes The second was the animation: “I believe Sonner took off immediately because of the stacking animation which was done by some companies before, but never open sourced.” The launch video he chose focused on that motion. His first version used CSS keyframes, and they broke when toasts arrived quickly: older toasts jumped into position because keyframes are not **interruptible** (CSS transitions can be interrupted and retargeted, even before the first transition has finished, which is what lets a toast change its destination mid-flight; keyframes cannot do this.). Transitions retarget mid-flight, so he switched to one rule, transition: transform 400ms ease. A transition needs a start state, so a useEffect sets a mounted flag after first render and writes it to a data attribute; he notes **@starting-style** (A CSS at-rule Emil Kowalski points to as a simpler way to declare the starting state of an enter transition, replacing the mounted data attribute trick.) would now make this much simpler. > Figure. toast.cssEmil Kowalski, Building a Toast Component Source The keyframes-versus-transitions story, the data-mounted snippet, and the @starting-style remark are in the Animations section of Building a Toast Component. ### The stacking arithmetic Every toast is position: absolute, offset by the gap times its index, and scaled down by 0.05 times its index for depth. The post’s diagram reads Y(0) scale(1), Y(-14px) scale(0.95), Y(-28px) scale(0.9), matching the [Toaster’s defaults](https://sonner.emilkowal.ski/toaster) of gap 14 and visibleToasts 3. Two custom properties drive it. > Figure. CSSEmil Kowalski, Building a Toast Component Toasts of different heights stick out unevenly, so every toast takes the height of the front one while stacked. The figure builds that stack: add toasts quickly and toggle Transitions/Keyframes to feel the jump Emil describes. Its swipe readouts matter next. > Figure 1. How a toast stack works. Add several toasts quickly in both modes: keyframes cannot be retargeted, so older toasts jump, while transitions pick up from wherever they are. Change the gap and the scale step, hover to expand, and flick the front toast down to dismiss it. The gap, scale step, visible count, 4 s duration, and 0.11 px/ms velocity are Sonner's numbers; the distance threshold here is illustrative.Constants from the source ### Swipe with momentum Swipe to dismiss is a pointer listener writing the drag distance into a --swipe-amount variable used by translateY. Removal is **momentum-based** (A swipe where you do not have to drag past a distance threshold to dismiss; if the swipe is fast enough the element is removed even when the distance is short.): distance over elapsed time gives a velocity, and the toast goes if the swipe passes SWIPE\_THRESHOLD or the velocity passes 0.11, “just a number that I ended up on through trial and error.” A short fast flick clears it where a long slow drag would not. > Figure. TypeScriptEmil Kowalski, Building a Toast Component Hover expands the stack. The expanded offset is index times gap plus the heights of the toasts before it, a reduce over a heights array written to an --offset variable; the expand prop makes that the resting state. ### Details and developer experience State avoids React Context through the **Observer pattern** (To avoid using React's Context, Emil Kowalski manages Sonner's state via the Observer Pattern: the Toaster subscribes to an observable object, and whenever toast() is called the Toaster is notified and updates its state.): the Toaster subscribes, toast() notifies, the list renders with a map. No hooks, no providers. The toast.promise API, one promise plus copy for loading, success, and error, drew Theo’s “like React Query for toasts.” The API follows Timo’s react-hot-toast “because it’s simply very good,” and **developer experience** (Emil Kowalski's term for how easy a component is to use; if the component is not easy to use, people will give up before they even try it.) included a custom docs site with interactive examples. > Figure. TypeScriptEmil Kowalski, Building a Toast Component Then the big little details. A toast lasts 4 seconds unless hovered, and a useIsDocumentHidden hook watching document.hidden pauses the timer in a hidden tab. An :after pseudo-element fills the gaps between toasts so hover does not flicker. A drag captures all future pointer events, and dragging upward is slowed with friction rather than blocked, “nicer than just stopping the toast immediately.” He borrows Paul Graham: “a thousand barely audible voices all singing in tune.” His verdict is developer experience plus looks, the real differentiator: “Beauty is generally underutilized in software so you can use it as leverage to stand out.” --- # Craft Jim Nielsen says code is not just how you implement a design, it is how you find one. This chapter takes that seriously and follows it into the material: why starting from HTML buys you more than it costs, what it means to sand an interface until it has no splinters, how the grid and type decisions behind two well-built marketing sites were made in code, and the accessibility and performance work nobody sees but everybody feels. ## 6 sections 1. [Coding is designing](https://learn-ui.com/chapters/craft/coding-is-designing) 2. [HTML first](https://learn-ui.com/chapters/craft/html-first) 3. [Sanding the interface](https://learn-ui.com/chapters/craft/sanding-ui) 4. [Grids and fluid type](https://learn-ui.com/chapters/craft/grids-and-type) 5. [Accessibility as craft](https://learn-ui.com/chapters/craft/accessibility) 6. [Performance and reduced motion](https://learn-ui.com/chapters/craft/performance-and-reduced-motion) --- # Accessibility as craft · Craft It is obvious to give images and videos alternative text. The less obvious cases are illustrations built from HTML and CSS, code blocks, and focus. ### Label an illustration as one image In [Crafting the Next.js Website](https://rauno.me/craft/nextjs) Rauno Freiberg notes that a screen reader walks through many elements of an HTML illustration and may still not convey it. His fix, credited to Adrian, is `aria-hidden` on the inner HTML and a custom `aria-label` on the group, so the user reaches one element and gets a description. The Vercel site in [What will you ship?](https://rauno.me/craft/vercel) applies it everywhere: `role="img"`, a label with just enough detail, and a hidden inner tree. The pixel icons, drawn in Figma and extracted by a Ruby script, render to a hidden canvas inside a labelled wrapper, because “we treat the icons as images.” > Figure. JSXRauno Freiberg, What will you ship? ### An accessible code block The team went over the page with VoiceOver dozens of times, and three problems surfaced in the code block: the file icon announced itself as “image”; the copy button described neither its purpose nor gave feedback; and the line numbers were noise that could be mistaken for code. The icon got `aria-hidden`, the copy button an `aria-label`, and feedback came from an **ARIA live region** (An element whose dynamic content changes are exposed to screen readers as they happen, so a message can be announced without moving focus.) with `role="log"` and `aria-live="polite"` carrying the visually hidden text “Copied code to clipboard”, hidden without `display` or `visibility`. The block became an `aside` with a high-level label so a reader can skip it. Line numbers are pseudo elements driven by a CSS counter, and with no DOM node you cannot `aria-hidden` one. The answer is the second value of `content`, **alternative text for pseudo elements** (The second value of the CSS content property, after a slash, which supplies alternative text for a pseudo element; an empty string means nothing should be announced.). Combined, a screen reader gets more information on every example the component powers, hundreds of them. > Figure. CSSRauno Freiberg, What will you ship? Source Rauno Freiberg, What will you ship?, sections Accessible Code Blocks, Code Driven Visuals, and Pixelated Iconography; Crafting the Next.js Website, Explicit Accessibility Labelling and Focus States. ### Focus, hit areas, real devices The previous section covered Rauno’s double-shadow focus ring; the point to carry is that a reliable ring on every focusable thing across a shared surface area is the work. Emil Kowalski’s skill, excerpted in [Agents with Taste](https://emilkowal.ski/ui/agents-with-taste), adds two rules: a 44px minimum hit area for small buttons, drawn with a pseudo element, and body text capped at about 65ch. Jim Nielsen’s flexbox gap is the same rule from the other side: the target should be at least as big as the thing you see. Kathryn Gonzalez, who built and led DoorDash’s Design Infrastructure org, defines it plainly in a [2020 interview](https://www.ryngonzalez.com/blog/design-leadership-interview-at-doordash): accessibility is “a way of thinking and designing so that we’re not only building something that works for the narrow group of people that look like us, but for people with different kinds of mental and physical capabilities and circumstances.” Her 2017 [How to Build a Modal](https://www.ryngonzalez.com/blog/how-to-build-a-modal) adds: consider accessibility from the start, treat the WAI-ARIA examples as your friend, and test on real devices, because her team had tested only in Chrome’s responsive mode and found `overflow: hidden` did not stop body scrolling on iOS. A shared component distributes those practices to everyone. ### Sloppy UI is a security liability In [A Sloppy Interface Is a Security Liability](https://blog.jim-nielsen.com/2026/sloppy-ui-is-security-liability/) (August 2026), prompted by Feross Aboukhadijeh’s talk on the Axios npm phishing attack and its fake Microsoft Teams interface, Jim Nielsen proposes “interface and interaction design as a security control.” The easier it is to sloppily reproduce what you sloppily ship, the easier your brand becomes a vehicle for exploiting customers. “If everything you make was produced from a single prompt, then everyone else is one prompt away from imitating you.” The protection is what is hard to fake because it is hard to notice you need it: micro-interactions, loading behaviour, copy, edge cases, accessibility. The Vercel essay names what almost everyone experiences: page speed, legible typography, information honesty, layout stability, focus states, auditory feedback, DOM order. Invisible, so first traded away. Take the opposite stance. --- # Coding is designing · Craft In June 2026 Jim Nielsen published [Coding Is Designing](https://blog.jim-nielsen.com/2026/code-is-design/). Its first line: “Code isn’t just a way to implement a design, it’s a way to find one.” ### Code is how you find a design An interface, Jim writes, is something you have to use and poke at before you can see the relationships between its parts. Change one thing and another reacts; change the first again and the second reacts differently, until the elements settle into a whole. His closing line frames the chapter: “Design is ‘how it works’ and code is the tool to specify how it works.” In [The Figma to Browser Chasm](https://blog.jim-nielsen.com/2023/figma-to-browser-chasm/) (2023) he notes that “sometimes a Figma mock is too easily conflated with the end product,” and quotes Derek Briggs: “Users don’t see your Figma files, so they’re only as good as their implementations.” The **chasm** (Jim Nielsen's name for the gap between a Figma mock and its implementation in the browser; the mock is only as good as the code it becomes.) is a Pinterest fail meme: a beautiful abstraction meets the attempt to make the thing. You only capture a talented designer’s value with an equally talented engineer, or one person who does both. Source Jim Nielsen, Coding Is Designing (June 2026) and The Figma to Browser Chasm (March 2023). The Derek Briggs line is quoted in the second post. ### The website is the source of truth [Making Films and Making Websites](https://blog.jim-nielsen.com/2024/making-films-and-making-websites/) (2024) starts from Baldur Bjarnason’s claim that software is closer to media production than housebuilding. A screenplay is not a film; “what you use to make a website is not the website itself.” When each discipline pours care into its own deliverable, blame gets impersonal (“my mocks were pixel perfect!”) and nobody owns the experience. “People come to use websites, not look at mocks.” [Designing Between the Lines](https://blog.jim-nielsen.com/2021/designing-between-the-lines/) (2021) opens with a line attributed to Matisse, “I don’t paint things. I paint the difference between things,” and ends: “don’t merely design things. Design the relationships between things.” Ken Kocienda, quoted in between, explains why A/B tests find a button colour that gets clicks but not an integrated whole. [The Unseen Work of Design](https://blog.jim-nielsen.com/2021/unseen-work-of-design/) (2021) adds that “the final product isn’t produced but discovered.” ### Holding logic and creativity together In [The Tension Between Logical Reasoning & Illogical Creativity](https://blog.jim-nielsen.com/2023/logic-of-code-and-illogic-of-creativity/) (2023) Jim argues that programming demands logic at every step, and when that leaks into ideation it limits your capacity to imagine new connections. He borrows John Cleese’s definition of a new idea, “connecting two hitherto separate ideas in a way that generates new meaning,” and values design engineers for holding both demands in balance. [Interdisciplinary Website Maker](https://blog.jim-nielsen.com/2024/interdisciplinary-website-maker/) (2024) describes interviewers who stammer when he says he wants to do design and code, and quotes Paul Ford: “The interdisciplinarian is essentially an exile.” Websites are like trees: every discipline is needed to grow them. [Craft and Satisfaction](https://blog.jim-nielsen.com/2025/craft-and-satisfaction/) (2025) quotes Sean Voisen (“Maybe nobody will notice those details, but it doesn’t matter. We care, we notice, we get joy from the aesthetics of the craft.”) and finds satisfaction in intimate understanding of your material. AI can run that in reverse, so he asks: “do I care more or less about what I’ve made when I’m done using AI to help make it?” ### A worked example in code Rauno Freiberg’s [Crafting the Next.js Website](https://rauno.me/craft/nextjs) (April 2023) records design decisions made in code. Built in February 2023 with Glenn on design and Alasdair, with “no swanky mesh gradients, obnoxious artifical shines, or overuse of gimmicks,” the static version shipped as soon as it beat production and animations followed. The hero’s blinking switchboard began as a vector illustration that rendered inconsistently across browsers, so he built it in code: the medium pushed back and the design was found in the material. The page ends by noting that no artificial intelligence was used. Treat the running interface as the design artifact. --- # Grids and fluid type · Craft The Vercel homepage that shipped in October 2023 is documented in [What will you ship?](https://rauno.me/craft/vercel) (December 2023), presented by Rauno Freiberg with Henry Heffernan, Glenn, and Alasdair Monk. The north stars were performance, constraint in visual flair, and bridging pages aesthetically. ### A literal frame on every page The foundation was a typeface family Basement made for Vercel that year, Swiss inspired and optimised for displays. Asking what pairs with a grotesque sans led to the Swiss design movement, “the raw exposure to the creation of design; blocks, grids, modularity,” and to a metaphor: Vercel is infrastructure for frameworks, so show a literal frame on every page. Design began after Guillermo Rauch’s Config 2023 talk, so Figma variables carried Kevin Rupert’s accessibility-optimised colour system. The frame does work. Kept in place across navigation, it shows what content swaps out and how fast, lessens pseudo layout shift, and “highlights incredible performance of server rendering.” Crosshairs inspired by print center marks guide the eye. At 1080 wide, columns of 360 give a readable line length for 14 to 16px text, and because everything is a block the layout collapses into mobile. The hero gradient runs the full colour wheel as a metaphor for creativity. ### Drawing guides with display: contents Drawing the guides was the hard part of `Grid.System`. Bordering every cell on two sides lacks the grid’s own top and left borders and requires every cell to be filled. The answer was **display: contents** (A CSS display value that makes an element's children appear as if they were direct children of the element's parent, ignoring the element itself.) on a guides wrapper holding rows times columns absolutely positioned cells, so they do not interfere with real children. Passing `auto` as a row or column still works, crosses can sit on any cell, and the grid is server rendered. > Figure. CSSRauno Freiberg, What will you ship? Source What will you ship? (December 2023), sections Aesthetic Foundation, Grid System, and Visual Rhythm. The Grid System section reads as written by a collaborator on the component. The grid also sets a rhythm. “If every element made repetitive use of a strong accent color, the color would no longer feel as significant,” and the same holds for the cross motif and for animation. The essay maps the page orange for high novelty (a graph tooltip animating a long distance, icons pixelating on hover) and blue for low (floating cursors, icons scaling on hover); each animation gets an interlude, and high-novelty ones never sit in consecutive sections. That is **visual rhythm** (Rauno Freiberg's term for pacing novelty across a page: when every element in a section signals itself as novel or attractive, the novelty is diminished.) as a layout decision. ### Grid lines and fluid type on Next.js The grid lines on the Next.js site, from [Crafting the Next.js Website](https://rauno.me/craft/nextjs), are absolutely positioned pseudo elements that flex with content. Rauno borrowed the dotted line from Stripe: a repeating linear gradient gives more control than a dotted border, and a mask fades the ends. > Figure. CSSRauno Freiberg, Crafting the Next.js Website The same essay holds his first use of `clamp`. He had always adjusted type at manual breakpoints; the hero instead scales between 48px and 76px at 5vw, which “helps to responsively adjust any property between a minimum and maximum value.” In the figure below, watch where the line goes flat at each end. > Figure 1. Fluid type with clamp(). Drag the viewport and watch the size move through three regimes: pinned at the minimum, scaling with the viewport, pinned at the maximum. The defaults are the Next.js site's hero values.Constants from the source ### Container, viewport, reader setting The Vercel visuals answer to their container. All are built in code without external libraries, for pristine quality, granular control, and true responsiveness. With **container queries** (A CSS query that adapts an element's children to the size of a declared containment context rather than the window width.) stable, a widget responds to the space it actually has. The orbit rings move an element on `offset-path: content-box`, which uses the parent as trajectory and respects its radius; as of 2023 it misbehaved in Safari and Firefox, Safari 17.2 fixed it on 12/12, and an SVG circle path string was the fallback. > Figure. CSSRauno Freiberg, What will you ship? Andrew Swank’s [personal site](https://andrewswank.com) is built from scratch “to show how design and engineering can work together to create a better experience for both parties.” Its features are CSS decisions: layout and type sized from the viewport with `vmin` and `rem`; “Predictable sizing via max() and round() to snap to a 4-pixel grid”; HSL custom properties so colours animate without dulling; and Roboto Flex animated with `font-variation-settings`. What `rem` is relative to is Paco Coursey’s subject in [px vs rem in font-size](https://paco.me/writing/px-vs-rem) (2022). On `html` there is no parent, so the reference is the browser’s font scaling, 16px by default but adjustable from 9 to 72; zoom (⌘+ and ⌘-) scales additively on top. Almost all sites ignore scaling; cnn.com did it well, scaling main content with `rem` and leaving navigation alone. [Get the browser default font size](https://paco.me/writing/browser-default-font-size) (2023) gives the probe: `font-size: medium` resolves to the default, typically 16px; with Chromium set to Very Large it reads 24px. If you reach for `rem`, leave the root size alone so that setting reaches the page. > Figure. CSSPaco Coursey, Get the browser default font size --- # HTML first · Craft Jim Nielsen runs two icon gallery sites, and until recently each list of icons shipped a widget to resize them. ### Make the interaction a navigation In [Out With the JS, In With the HTML](https://blog.jim-nielsen.com/2026/out-with-js-in-with-html/) (May 2026) the original was a web component, ``, whose size took `sm | md | lg | xl`, mapped to dimensions such as 64×64 or 512×512, and whose JavaScript rewrote the child `img` elements on click. On a pre-rendered static site that duplicated templating logic over the wire, with bugs like “I updated this one small part of how my icon list renders on the server, but forgot to tweak it on the client.” The fix: instead of one page at `/colors/red/` with JavaScript, four pages at `/colors/red/{sm|md|lg|xl}`. Once he supported CSS **view transitions** (A browser feature that animates between two document states, including between two separate HTML pages, so a navigation can look like an in-page transition.), he got “a cool effect amongst the icons for free,” by removing code. His question: “Could I remove some client-side JS and get a better overall experience?” ### Lots of little HTML pages In [Building Websites With LLMS](https://blog.jim-nielsen.com/2025/lots-of-little-html-pages/) (March 2025) the acronym is “(L)ots of (L)ittle ht(M)l page(S).” A filter he expected to be list items toggled by JavaScript grew data attributes and sorting logic; each filter became its own page. He calls this the **grain of the web** (Jim Nielsen's phrase for building with, rather than against, what the web does natively: treating on-page interactivity as HTML page navigations enhanced by cross-document CSS transitions.). The post-mortem a year later, [Reminder: You Can Stitch Together Lots of Little HTML Pages With Navigations For Interactions](https://blog.jim-nielsen.com/2026/small-html-pages/), still likes it: multi-page navigations enhanced with view transitions, plus a dash of JS where prudent. His menu navigates to a page of options. Newer browsers get the effect; older ones still work, because “If you can follow a link … it will work.” Closing is a link to `/` that runs `history.back()` when `document.referrer` is set, so the menu adds no history entries. It took thinking about what was essential and keeping page size small: “the approach shaped the design.” > Figure. HTMLJim Nielsen, Reminder: You Can Stitch Together Lots of Little HTML Pages Source Jim Nielsen, Out With the JS, In With the HTML (May 2026); Building Websites With LLMS (March 2025); and the May 2026 post-mortem. ### View transition gotchas In [Gotchas in Naming CSS View Transitions](https://blog.jim-nielsen.com/2025/view-transition-name-gotchas/) (January 2025), a `view-transition-name` must be a ``: no quotes (quoted, it is a string), no forward slash, no leading number. His working value was `title-2024i-love-kitkats`. Bramus later pointed him to `attr()` in Chrome 133 and up, and to `auto`, Safari-only at the time. > Figure. CSSBramus, via Jim Nielsen, Gotchas in Naming CSS View Transitions In [Aspect Ratio Changes With CSS View Transitions](https://blog.jim-nielsen.com/2025/aspect-ratio-in-css-view-transitions/) (February 2025), an active-tab outline grew in width but not height between pages. “It’s small. Many people might not even notice it. But I do and it’s bugging me.” He slowed `::view-transition-old()` right down to see it, found an AI answer that looked right and was wrong, and landed on Jake Archibald’s [View transitions: Handling aspect ratio changes](https://jakearchibald.com/2024/view-transitions-handling-aspect-ratio-changes/), a one-line fix with the visuals to explain why. ### Fault tolerance and the quality bar HTML and CSS suit this because of their **fault tolerance** (The property of HTML and CSS that browsers keep parsing as best they can when they meet syntax they do not understand, instead of failing outright the way JavaScript does on a SyntaxError.), from [A Subtle Nicety of Fault Tolerance in HTML & CSS](https://blog.jim-nielsen.com/2024/fault-tolerance-html-css/) (January 2024). Browsers ignore CSS they do not understand, so to try a layout without a rule Jim adds a `z` in front and toggles one character. A very little thing, but it is also why progressive enhancement is easy here. > Figure. HTMLJim Nielsen, A Subtle Nicety of Fault Tolerance in HTML & CSS The bar comes from [As Good as HTML](https://blog.jim-nielsen.com/2023/as-good-as-html/) (November 2023), quoting Jan Miksovsky: “Adopting a quality bar of being as good as HTML is pretty hard.” In Jan’s work a listbox shares roughly 85% of its code with a carousel, HTML’s composability showing through. Robin Rendle asks “what would html do?”, with `select` reusing `hr` for dividers. [Quality Means The Flexibility to Change](https://blog.jim-nielsen.com/2024/easy-changes/) (October 2024) adds Dave Farley’s test, via Ben Nadel: easy to change is high quality. “Whatever you do, make it easy to change.” Four static pages are easier to change than a component that re-renders one. --- # Performance and reduced motion · Craft The blinking switchboard on the Next.js site glows. How the glow is drawn, and how a page behaves when a reader asks for less motion, are the invisible half of craft. ### Animate opacity and transform In [Crafting the Next.js Website](https://rauno.me/craft/nextjs) Rauno Freiberg explains that the glow is a CSS shadow but only opacity and transform animate. Animating `box-shadow` would trigger a **repaint** (The browser redrawing pixels for an element; animating box-shadow forces one on every frame of the animation.) every frame, which modern computers absorb but older phones may not. So he toggles the opacity of pseudo elements that already carry a shadow, keyed on a `data-state` of off, medium, or high. The hover that spells NEXT replaces cherry-picked indices in sequence. > Figure. CSSRauno Freiberg, Crafting the Next.js Website Emil Kowalski states the rule in [Great Animations](https://emilkowal.ski/ui/great-animations): “If our animations won’t run at 60 frames per second, everything else we’ve talked about becomes useless.” Transform and opacity only trigger composite; padding or margin trigger layout, paint, and composite. When the main thread is busy, use hardware-accelerated CSS or the Web Animations API; his example is a Vercel dashboard tab transition that dropped frames during page load until it moved to CSS. ### Layer so the essence paints first The Vercel hero in [What will you ship?](https://rauno.me/craft/vercel) is stacked, descending, as heading, SVG triangle, CSS grid lines, SVG rays, CSS rainbow gradient, and a GLSL shader, and needs no client-side code to show its essence. The shader is **progressive enhancement** (Building the core of an experience so it works without a capability, then layering the capability on top for browsers and devices that can handle it.): it fades in after load, can be code split, and light hardware detection skips it on low-powered devices. The pixel icons follow: pixel data renders as canvas for a smaller DOM and animation, with a base64 placeholder of about 1kb per icon, or as SVG above the fold. Paco Coursey’s [SVG Caching with ](https://paco.me/writing/svg-caching-with-use) (2020) is a related economy: reuse rendered icon DOM through `use` with a stable hashed id, about 40% less markup in his example, as long as the id matches between server and client. > Figure. HTMLPaco Coursey, SVG Caching with Source Rauno Freiberg, Crafting the Next.js Website (Blinking Switchboard) and What will you ship? (Hero Composition, Pixelated Iconography, Reduced Motion); Emil Kowalski, Great Animations. ### Pause loops, leave interactions alone Reduced motion on the Vercel page draws a distinction worth copying. Looping complementary animations, the floating cursors and blinking carets, are paused under `prefers-reduced-motion`. Interactions are not, because they are explicit inputs with no extravagant movement. The loops are CSS keyframes, so rather than `animation: none` the page uses `animation-play-state: paused`. And a detail no one sane has reason to notice: the caret’s opacity is forced to 1, so the blink cannot pause while invisible. > Figure. CSSRauno Freiberg, What will you ship? Emil’s reason for the media query is blunt: animations can make some people feel sick or distracted, and his example animates opacity only under reduced motion. ### Slow it down and look Emil’s skill, [emil-design-eng](https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md), adds two constraints. Blur can mask an imperfect transition, but “Keep blur under 20px. Heavy blur is expensive, especially in Safari.” To see what the eye only senses, increase durations to 2 to 5 times normal, step frame by frame in the Chrome DevTools Animations panel, and test on real devices; in [Good vs Great Animations](https://emilkowal.ski/ui/good-vs-great-animations), “playing the animation frame by frame, or in slow motion, helps you spot it.” Jim Nielsen slowed `::view-transition-old()` to see an outline bug, and Kathryn Gonzalez learned to test on real devices. Three people, same tool. The Vercel essay names the trade-off: “if an animation or interaction didn’t perform well, felt pompous, or out of rhythm relative to the page, we didn’t build it.” Rauno would rather polish a spring than chase a slow initial load, then asks: “is having a slow website with immaculate attention to visual craft desirable?” Invisible work is the easiest to trade away. That is where the chapter lands: a glow that does not repaint, a hero that paints before its shader, a caret that pauses visible, designs found only in code. A site that feels fast to everyone is better craft than one immaculate only on the newest hardware. --- # Sanding the interface · Craft Jim Nielsen describes how he develops in [Sanding UI](https://blog.jim-nielsen.com/2024/sanding-ui/) (September 2024): build something, click around a ton, tweak, click around more, until done. The clicking is the important part. ### Sand until no splinters For a page transition that means going back and forth every way a person might: back button, context menu Back, in-app navigation, keyboard shortcut. He prefers the woodworking picture to QA: belt sander, then hand sander, then run your hand over it and feel for splinters, “until I finally cannot give myself any more splinters.” That is **sanding UI** (Jim Nielsen's name for using an interface over and over, tweaking after each pass, until no rough interaction remains: sand it, feel the grain, get a splinter, sand again, and repeat until smooth.). His example: a radio and its label in a flexbox with `gap`, and the gap was a dead spot where clicking did not toggle the control. Removing the gap and padding the label made the whole thing clickable. “Lots of small splinters lead to an agonizing experience.” In [Sanding UI, pt. II](https://blog.jim-nielsen.com/2025/sanding-ui-pt-ii/) (February 2025) a thumbs up/down widget, clicked a lot, selects its SVG as if it were text; one fix is `user-select: none`. > Figure. CSSJim Nielsen, Sanding UI Aside His [Job Screening Blog Post](https://blog.jim-nielsen.com/2024/design-engineer-job-screener/) (November 2024) is two GIFs of a button being clicked. In one the heading shifts up by 1px. “Can you tell the difference between them? Do you care? If not, we might not be a good fit.” ### Focus rings at the declaration level Rauno Freiberg’s [Crafting the Next.js Website](https://rauno.me/craft/nextjs) sands at the level of CSS declarations. Tab through any site and you find rings in different colours and shapes. His model is the Discord web app: always a custom blue, matching the trigger’s radius, offset with padding, a radius even on links, never clipped by a container. One page is easy; the difficulty is a surface area shared by many teams. His own **focus ring** (The visible outline a browser or a stylesheet draws around the element that currently has keyboard focus.) is two box-shadows on `:focus-visible`: the first pads the element in the page background colour, the second draws a 2px outline. It assumes the element sits on the app background, barely noticeable when false. `outline` would do, but Safari did not follow the radius until 16.4, and Safari updates are tied to macOS. For links, a 2px radius, 2px of padding, and a negative margin that cancels it improve the focus state even though the radius is invisible until focused. > Figure. CSSRauno Freiberg, Crafting the Next.js Website ### Quote marks, data attributes, underlines Two more from Rauno: testimonial quote marks set in Georgia rather than Inter, a detail from the Radix UI site, hung with `text-indent: -0.4em` (credited to Shu); and styling against a `data-variant` attribute instead of mapping variants to class names. Neither shows in a screenshot. Paco Coursey’s [Custom text underlines](https://paco.me/writing/custom-text-underlines) (2020) sands a single line. With `text-decoration: underline` giving too little control while the CSS Text Decoration Module was pending, he draws the line as a `linear-gradient` background. Move it with `background-position` (`left 1.05em`), thicken it with the height (`100% 0.25em`), hide it around descenders with a `text-shadow` in the background colour (and `text-shadow: none` in `::selection`), dash it with a `repeating-linear-gradient` sized `1ch`, the width of the zero glyph. It wraps across lines. > Figure. CSSPaco Coursey, Custom text underlines His [px vs rem in font-size](https://paco.me/writing/px-vs-rem) (2022) turns the same care on a habit: since nearly every site hard-codes a size on `html` or uses `px`, “when browser scaling is ignored, there’s no a11y reason to use rem over px.” The unit is not the virtue; respecting the reader’s setting is. ### Good for who Sanding has a direction, from Jim’s [Good Design](https://blog.jim-nielsen.com/2022/good-design/) (2022). Design is about intent, so ask: good for who? An unsubscribe button that dodges the cursor is good for whoever wants you subscribed and bad for you. Dribbble shots may be good design if the intent is likes, but “It’s hard to know whether a static picture depicting dynamic software helps a real-world human achieve a particular goal.” Where owner and user diverge, state a priority of constituencies. So decide who you are sanding for, then use the thing the way they will, through every entry and exit. The agonizing experience is made of the splinters you skipped. --- # Explaining with interaction Some interfaces do not sit in front of an explanation; they are the explanation. This chapter reads three people who work that way: Bartosz Ciechanowski, whose articles open with a machine you can drag; Amelia Wattenberger, who turns data and code into things you can see and steer; and Maggie Appleton, whose digital garden is both an argument about publishing and a catalogue of interface patterns. The figure is the argument. ## 4 sections 1. [Explorable explanations](https://learn-ui.com/chapters/explaining/explorable-explanations) 2. [Data into meaning](https://learn-ui.com/chapters/explaining/data-into-meaning) 3. [Digital gardens and visual essays](https://learn-ui.com/chapters/explaining/digital-gardens) 4. [Interface patterns worth knowing](https://learn-ui.com/chapters/explaining/interface-patterns) --- # Data into meaning · Explaining with interaction [Amelia Wattenberger](https://wattenberger.com) introduces herself in one sentence: “I create things on the web, explore novel interfaces, turn data into meaning, and empower devs with AI.” She is “a Principal Research Engineer exploring novel UIs + playing with ML on a tiny R&D team within GitHub,” GitHub Next; Maggie Appleton’s collection lists her as “Research & development at GitHub. Previously Designer at Adept.” Her 2019 archive says what she taught front-end developers for years: Combining React and D3, Use the d3 force, The CSS Cascade, Scaling SVG Elements, Thinking in React Hooks, How to learn D3.js. ### Charts as an x-ray Before GitHub she was a front-end developer at The Pudding, and [Fullstack D3 and Data Visualization](https://www.newline.co/fullstack-d3) condenses “the past ten years that I’ve been visualizing data.” “Charts are like an x-ray for your data,” the book is “not a reprint of the API docs,” and “Within the first 10 minutes you’ll be creating your own custom D3 charts.” It covers design principles and when to use which chart, not only code; readers quoted on the page name the bar chart and Sankey chapters, the enter-exit-update pattern, and `join()`; the course runs to more than five hours of video across more than fifty lessons. The thread through everything after is data into meaning, with the reader in control of the view. ### Code you can see Her GitHub Next work applies the same instinct to code. The [repo-visualizer](https://githubnext.com/projects/repo-visualization/) draws “each file and folder as a circle,” colour for type and size for size, a “fingerprint” redrawn by a GitHub Action on every change. [GitHub Blocks](https://blocks.githubnext.com) argued that “READMEs don’t have to be static.” [Collaborative coding workspaces](https://githubnext.com/projects/workspaces/) held that “Remote collaboration isn’t about multiple cursors, it’s about sharing context.” [Code Brushes](https://githubnext.com/projects/code-brushes/) in Copilot Labs made editing feel like painting: “select a few lines, choose your brush, and see your code update.” [Copilot for Docs](https://githubnext.com/projects/copilot-for-docs/) asked “What would it feel like to have an expert on hand?” and insisted on citations into the docs, “Instead of acting like an oracle.” [Code Atlas](https://githubnext.com/projects/code-atlas/) took the tension of the moment, that LLMs bring **fluid reasoning** (The biggest revolution from Large Language Models (LLMs) is the introduction of fluid reasoning.) while “we still need rigid reasoning for trust, safety, and reliability,” and made the model build its answer as a visible workflow of small JavaScript blocks with inputs and outputs, so “the user can play with it at almost no cost” (counting letters, which models struggle with, is easy in a snippet). The Blocks, Copilot Labs, and Copilot for Docs previews all ended on December 15, 2023; the ideas did not. ### Why chatbots are not the future [Why Chatbots Are Not the Future](https://wattenberger.com/thoughts/boo-chatbots) gives four reasons. Affordance: gloves are hand-shaped, but a chat box “looks the same as a Google search box, a login form, and a credit card field.” Context: “the burden to learn what works still lies with every single user. When it could instead be baked into the interface.” Isolation: comparing two responses means scrolling line by line, and the lack of a **working buffer** (I can't help but see the inability to have a 'working buffer' as a complete non-starter.) is “a complete non-starter.” The craft loop: a painter alternates between smooshing paint and stepping back, and “Good tools let the user choose when to switch between implementation and evaluation.” The essay ends on a spectrum from human task to machine with a **No man’s land** (There's a No man's land where the human is still required to make decisions, but they're not in control of the outcome.) between, and a position: “I want to see more tools and fewer operated machines.” Three shorter essays sharpen it. [Our interfaces have lost their senses](https://wattenberger.com/thoughts/our-interfaces-have-lost-their-senses) says the digital world is “Reduced to text under glass screens,” lists outputs (text, visualizations, sound, haptics) and inputs (typing, clicking and dragging, tapping and swiping, gesturing, speaking), and concludes “We made painting feel like typing, but we should have made typing feel like painting.” [Fish eyes](https://wattenberger.com/thoughts/fish-eye) borrows from maps and proposes the **fish eye** (A fish eye lens doesn't ask us to choose between focus and context): a detailed article in the centre with broader, similar, narrower, and related topics around it, or an editor where “the function you’re working on is fully expanded, related functions are summarized nearby.” A chatbot answer is “as if you opened a book to one random sentence, read it, and closed the book again”; “Is 42 a high number? A low one? Without context, it’s impossible to say.” [Putting knowledge in its place](https://wattenberger.com/thoughts/this-is-not-a-rant-about-chatbots) likens follow-up questions to “searching a dark room by pointing a flashlight and turning it on for a second at a time”; show the chosen pizza in the distribution of prices and ratings and the reader is oriented. ### From critique to construction [LLMs as a tool for thought](https://wattenberger.com/thoughts/llms-as-a-tool-for-thought) says most people use chatbots “only as a way to steer somewhere,” but “A good tool for thought is an extension of your mind” that matches the cadence of thinking. [Bridging the hard and the soft](https://wattenberger.com/thoughts/hard-and-soft) frames interfaces as the meeting of soft humans and hard machines; ChatGPT “can feel too soft,” and her model is a spine, hard segments joined by soft material: hard-coded modules “to give the user solid ground to stand on,” and interfaces that start rigid and loosen with familiarity. [Getting creative with embeddings](https://wattenberger.com/thoughts/yay-embeddings-math) builds PenPal, a writing app “In defiance of the ‘AI will write everything for us’ narrative,” around “making the implicit explicit”: her 2020 tool mapped sentence lengths to a colour scale; with embeddings she averages examples of each extreme into two points and places a sentence on the vector between them, so “a sentence with a score of 0.5 is halfway between the two examples.” [Code was our medium for thought](https://wattenberger.com/thoughts/code-is-a-medium-for-thought) turns to agentic coding: “We thought code was the output,” she writes, “but code was also where we did our thinking,” and asks, “What if agents created a custom whiteboard or playground for us, as soon as we started working?” Aside Maggie Appleton agrees from her side. In [Language Model Sketchbook](https://maggieappleton.com/lm-sketchbook) she calls the chatbot “the lazy solution” and “only the obvious tip of the iceberg,” and [her Enlightenment essay](https://learn-ui.com/chapters/explaining/digital-gardens) blames “the generic interface of the helpful chatbot assistant.” Read together, these are one argument in different materials: a chart is data made visible and steerable, a repo drawn as circles is a codebase made visible, Code Atlas is a model’s reasoning made visible and editable, and the chatbot critique says a text box shows none of that. The practical test is hers: when a tool you build shows a result, can the reader see where it sits (the distribution, the neighbours, the structure above and below) and reach in to adjust it without starting over? If the answer is a scroll of text, you have built an oracle where a tool was needed. --- # Digital gardens and visual essays · Explaining with interaction [Maggie Appleton](https://maggieappleton.com) describes herself on her [about page](https://maggieappleton.com/about) as “Designer, anthropologist, and mediocre developer,” working “at the intersection of design, anthropology, and web development” under “the umbrellas of design engineering, product design, and visual interface design.” The career runs from Egghead (illustrator, art director, UX designer, with a “robust process for visualising complex programming concepts through graphic design, metaphors, and cultural symbols”), through Head of Design at HASH, founding product designer at Elicit (“a research tool that uses language models to speed up the systematic review process”), and Lead Design Engineer at Normally, to Staff Research Engineer at GitHub Next since October 2025. In a 2026 talk: “I’m actually a designer. Or I was, back when that was still a separate thing to engineering.” ### The garden and the stream Her site is a **digital garden** (A digital garden is a collection of imperfect notes, essays, and ideas growing slowly over time.), and her 2020 essay [A Brief History & Ethos of the Digital Garden](https://maggieappleton.com/garden-history) defines it: “A garden is a collection of evolving ideas that aren’t strictly organised by their publication date,” linked by association, published half-finished, “less rigid, less performative, and less perfect than the personal websites we’re used to seeing.” The history runs from Mark Bernstein’s 1998 Hypertext Gardens, “the first recorded mention of the term,” to Mike Caulfield’s 2015 The Garden and the Stream: a Technopastoral, “the original source of digital gardening.” The stream is the feed, “the Zeitgeisty ideas of the last 24 hours,” and is “not designed to accumulate knowledge, connect disparate information, or mature over time.” “The garden is our counterbalance,” it is “not about specific tools,” and “No one owns The Official Definition.” ### Six patterns of gardening Instead of a definition she offers six patterns. Topography over timelines: “Many entry points but no prescribed pathways.” Continuous growth: “You post ideas while they’re still ‘seedlings,’ and tend them regularly until they’re fully grown, respectable opinions.” Imperfection and **learning in public** (Learn in Public; the practice of sharing what you learn as you're learning it, not a decade later once you're an 'expert.'), which “requires that we make the status of our notes clear to readers.” Playful, personal, and experimental, built in “the native languages of the web,” HTML, CSS, and JavaScript. Intercropping: podcasts, videos, diagrams, illustrations, interactive animations, papers, tweets, sketches, and code snippets all in one garden. Independent ownership: “claiming a small patch of the web for yourself,” with web-native formats and flat markdown backups. She names the cost: experimentation “requires knowing a non-trivial amount of HTML, CSS, and JS,” and no-code tools are “pre-fab houses instead of raw building materials.” Source The six patterns are headings in A Brief History & Ethos of the Digital Garden (June 2020): Topography over Timelines; Continuous Growth; Imperfection & Learning in Public; Playful, Personal, and Experimental; Intercropping & Content Diversity; Independent Ownership. ### A garden that practises it Her own site calls itself “a collection of imperfect notes, essays, and ideas growing slowly over time” and sorts growth by kind: Essays (“Opinionated, long-form narrative writing with an agenda”), Notes (“Loose notes on things I don’t entirely understand yet”), Patterns, Smidgeons, Talks, Podcasts, a Library and an Antilibrary of “Books I like the idea of having read,” plus Now, About, and Colophon. Every post carries a growth stage (“They start as seedlings, grow into buddings, and finally end up as evergreens”) and the dates it was planted and last tended; some open with an assumed audience “to make explicit who I’m writing for.” Status, provenance, and audience on every idea: the ethos made visible. The [colophon](https://maggieappleton.com/colophon): “I designed and built this site myself. Everything is open source and published on GitHub.” Astro “does most of the heavy lifting,” every note is MDX, Vercel hosts it, “Animations are mostly CSS, with some more complex ones done in Motion,” and earlier versions on Gatsby and Next.js are “neither of which I would recommend.” Headings are Canela Display, body Canela Text, Lato for sans-serif, on a fluid scale from Utopia; the CMS is “just a bunch of flat files and folders,” and ideas “start and marinate in my Tana.” Why build rather than rent: working in the native medium of the web “gives me fine-grained control,” and “Text isn’t the only way to represent ideas.” ### Two essays that stage an argument [The Dark Forest and Generative AI](https://maggieappleton.com/ai-dark-forest) (December 31, 2022) starts from Yancey Strickler’s **dark forest theory of the web** (The dark forest theory of the web points to the increasingly life-like but life-less state of being online.): public spaces “overrun with bots, advertisers, trolls, data scrapers, clickbait,” so humans hide in “invite-only Slack channels, Discord groups, email newsletters, small-scale blogs, and digital gardens.” Language models “are poised to flood the web with generic, generated content,” so “Our new challenge as little snowflake humans will be to prove we aren’t language models.” Five ways to pass follow: triangulate objective reality (models “cannot go outside and touch grass”); be original, critical, and sophisticated (model text “sounds like a B+ college essay”); develop language quirks, dialects, memes, and jargon (Saussure’s la parole); institutional verification, “fraught with problems”; and showing up in meatspace, which “still feels like a loss.” [A Treatise on AI Chatbots Undermining the Enlightenment](https://maggieappleton.com/ai-enlightenment) (August 5, 2025) starts from a New York Times op-ed by Professor David A. Bell: chatbots undermine “active intellectual engagement, sceptical inquiry, and challenging received wisdom,” and ChatGPT “has never responded: ‘That’s the wrong question.’” It becomes a design argument: a less sycophantic character “is well within the range of what we can prompt,” but “Putting the onus on the user sidesteps the problem,” and the problem is partly “the generic interface of the helpful chatbot assistant,” an “all-in-one text box” for which “the fawning, deferential assistant personality is the lowest common denominator.” She predicts specialist areas “will eventually get their own dedicated interfaces to AI”; her first pass is a toggle between “give me the gist” and “help me rigorously think about this.” The postscript: “AI wrote none of the words in this piece, but Harsh Claude helped critique it during the draft stages.” Both essays open with an assumed audience; the Treatise names “People building software with language models who want to consider the implications of their design choices.” What to take from her: a personal site can be an instrument rather than a brochure. Put a status on what you publish so you can publish early. Link by association, not by date. Build in the medium you are writing about. And when you argue, stage it: order the sections, draw the concepts, name who they are for, which is what a good interface does with a task. The next section reads the patterns catalogue, the part of her garden most useful to a design engineer. --- # Explorable explanations · Explaining with interaction [ciechanow.ski](https://ciechanow.ski) has no about page: a name, a blog, an [archive](https://ciechanow.ski/archives/), and links to Patreon, X, Instagram, e-mail, and RSS. The archive holds seventeen interactive articles from 2019 to 2024 and five “earlier articles” from 2014 on iOS and graphics programming (Mesh Transforms, Exposing NSDictionary, Exposing NSMutableArray, Drawing Bezier Curves, Exploring GPGPU on iOS). Maggie Appleton’s [A Collection of Design Engineers](https://maggieappleton.com/design-engineers) lists him tenth, “Not a Design Engineer as a profession, but a good example of blending design and engineering for educational content.” The genre is called explorable explanations: the reader operates the subject instead of reading about it. ### The demo comes first Every one of the seventeen opens with a working model and an instruction to touch it. [Mechanical Watch](https://ciechanow.ski/mechanical-watch/) (May 2022): “You can drag the device around to change your viewing angle, and you can use the slider to peek at what’s going on inside.” [Moon](https://ciechanow.ski/moon/) (December 2024) opens the same way, with the slider controlling date and time. The explanation then ramps from simple to real: GPS will “step-by-step improve upon it,” Cameras and Lenses builds a camera “from first principles,” Bicycle starts with a wooden box and a force slider, Exposing Floating Point starts “at the shallow end of the pool.” He says when the model lies: Sound “simplifies things a little,” Bicycle removes friction and air resistance, and Lights and Shadows keeps a flawed ray analogy because “despite its flaws, it will serve us as a valuable tool.” Source Article list and dates are from the archive page; opening lines from the first screens of Mechanical Watch and Moon; ramp quotes from GPS, Cameras and Lenses, Bicycle, and Exposing Floating Point. ### What your hands are asked to do The task varies by subject. In [Gears](https://ciechanow.ski/gears/) (February 2020) a slider sets a desk fan’s speed, then you scrub time on a disc while painted points trace their paths. In [Curves and Surfaces](https://ciechanow.ski/curves-and-surfaces/) you drag control points and tap one to see its influence, “the redder the section of the curve the more influenced it is by that control point.” In [Airfoil](https://ciechanow.ski/airfoil/) you tap a flow to drop a marker. Moon’s “cosmic playground” lets you aim a planet’s velocity arrow and release it with predicted trajectories drawn. [Sound](https://ciechanow.ski/sound/) has keyboards played with the W, E, and R keys. In [GPS](https://ciechanow.ski/gps/) you move a yellow figurine around three landmarks while its area of uncertainty grows, on the way to **trilateration** (The process of calculating a location of a point using measurement of distances is called trilateration.). Color Spaces refuses the textbook opening: “A dry definition of a color space is not a good way to kick things off.” The subjects range widely; the method does not. The run starts in January 2019 with [Exposing Floating Point](https://ciechanow.ski/exposing-floating-point/) (companion to his tool float.exposed), then [Color Spaces](https://ciechanow.ski/color-spaces/), Alpha Compositing, Earth and Sun, and Tesseract; 2020 Gears, [Lights and Shadows](https://ciechanow.ski/lights-and-shadows/), and [Cameras and Lenses](https://ciechanow.ski/cameras-and-lenses/); 2021 Internal Combustion Engine, Naval Architecture, and Curves and Surfaces; 2022 GPS, Mechanical Watch, and Sound; 2023 [Bicycle](https://ciechanow.ski/bicycle/); 2024 Airfoil and Moon. The first three are a graphics programmer’s concerns, like the 2014 posts; after that the subjects are machines, natural phenomena, and geometry, each given a model you can hold, a promise of scope, and a slow build. ### Legibility is engineered Your hands do the noticing: “Notice that as soon as you let go of the arbor by releasing the slider, the mainspring will turn the arbor right back.” Airfoil scales arrow lengths to stop overlap but keeps them proportional, so twice as long is twice as fast. Moon toggles between real and ten-times-larger body sizes, Sound slows time and flashes colliding particles red, and numbers are waved away when they do not matter. He also respects the reader’s machine: animations pause globally “if you find them distracting, or if you want to save power,” units switch between imperial and metric, copy swaps between click and tap, and Moon uses geolocation only “If your browser allows it.” Every article ends in Final Words that hand the subject back to daily life (bicycle riders will “conceptualize some of those invisible forces”) and a line pointing at [Patreon](https://www.patreon.com/ciechanowski), which in August 2026 listed 543 paid members at tiers “Starting at $3 /article.” Airfoil’s close justifies the genre: “by seeing how all the pieces fit together, you’ll find the whole thing even more magical.” ### Hand them the controls Gears is the article to start with if you want the method small: from **angular velocity** (Angular velocity describes how quickly an object rotates relative to some point.) through transmission and torque to the shape of a tooth. The figure below is this book’s homage in that spirit, not a reproduction: two gears, two tooth counts, one input speed. Drag the tooth sliders and watch the ratio follow; give the driven gear fewer teeth than the driver and it outruns the input. The model is two lines, and the rest is controls and drawing. > Figure. TypeScriptIllustration > Figure 1. A gear pair you can change. Drag the tooth sliders and watch the ratio follow the tooth count: every tooth that passes the contact point on one gear moves exactly one tooth on the other, so the gear with more teeth turns slower. Give the driven gear fewer teeth than the driver and it spins faster than the input. The spoke on each gear marks one revolution.Illustrative numbers A diagram of two gears with an arrow tells you the ratio is a fact; the figure lets you find it. That is why this book’s figures are meant to be operated, with the prose saying what to do and what to notice, as his articles do. Next time you explain a behaviour, notice whether you are drawing a picture of the answer or handing over the controls. A slider, a handle, and a number that responds teach what a paragraph cannot: a model, a set of controls, and a promise that what you see is true enough to learn from. --- # Interface patterns worth knowing · Explaining with interaction Maggie Appleton’s [patterns](https://maggieappleton.com/patterns) are “Design patterns gathered from my own observations and research.” Each page has the same shape: The Context, which names the tension, then The Pattern, then history, examples, and references. This section walks seven; the eighth, Command K Bars (“Command line bars you can quickly summon with a keyboard shortcut”), is covered in [A command menu with pages](https://learn-ui.com/chapters/components/command-menu). Each names a behaviour users already want, and a design engineer who recognises the pattern can prototype it in an afternoon. ### Portals and folk interfaces [Programming Portals](https://maggieappleton.com/programming-portals) (October 2022) are **programming portals** (Programming portals are small, scoped areas within a graphical interface that give users access to command lines and text-based programming.): “small, scoped areas within a graphical interface that give users access to command lines and text-based programming.” The context is the mid-1980s split, when the Macintosh GUI “created two distinct categories: end users and programmers” and hiding the command line “took away access to powerful primitives.” Examples: HyperCard (“the grand OG example,” Bill Atkinson, Apple, 1987, with HyperTalk commands like find, calculate, and go to), Fermat, an early pre-launch Notion that exposed CSS and JavaScript, and Ink & Switch’s Inkbase, where “Any quickly scrawled doodle can be turned into a set of ad-hoc interface controls.” Her imaginary app Drawper has a formula bar that sets a stroke conditional on size: “We’re writing dynamic rules, not the absolute properties of a static image.” [Folk Interfaces](https://maggieappleton.com/folk-interfaces) (August 2022) are “when users reappropriate existing software to solve their own problems,” a term from Cristobal Scuitto’s experiments using the browser as a media interface for local files. Examples: the browser console as a JavaScript runtime, Dylan Tallchief’s digital audio workstation in Excel, spreadsheet pixel art, a Dungeons & Dragons dashboard in Google Sheets, and, outside software, Victor Papanek’s tin can radio and the Mingei movement. An interface is either “a clearly signposted user journey” or “a collection of functions and affordances to repurpose,” and “None of these uses cases could have been predicted or catered for by the Microsoft Excel product team.” The **folk interface** (Folk interfaces are when users reappropriate existing software to solve their own problems.) is a test of generosity: does what you made have enough raw affordance to be misused well? ### Presence and trails [Ambient Co-presence](https://maggieappleton.com/ambient-copresence) (December 2023) names **ambient co-presence** (Ambient co-presence is the sensation of sharing a space or context with other people, without directly interacting or continuously communicating with them.), “the sensation of sharing a space or context with other people, without directly interacting or continuously communicating with them.” Multiplayer cursors (Google Docs first, as far as she knows, then Notion, Figma, Miro, and Mural) “don’t scale”: “Seeing exactly which word or design mock your manager is focused on isn’t the chill background sensation we’re going for.” Softer proposals: a heatmap rather than a pointer, spatial audio as in Gather Town, and annotation layers like Medium highlights or Hypothesis. She cites PartyKit’s Cursor Party and Leisa Reichelt’s 2007 Ambient Intimacy. If you are adding presence to a product, this page argues for turning it down. [Historical Trails](https://maggieappleton.com/historical-trails) (December 2023) starts from the in-flight map: where am I, where am I going, where have I been. Interfaces handle the first two (active states, progress bars, steppers) and fail the third: breadcrumbs “don’t scale well beyond ~7 steps,” and Chrome’s history “is a flat list that runs for eternity.” Good **historical trails** (Good historical trails should show people where they've been, even when the journey has been complex, looping, and divides into multiple branches of exploration.) survive journeys that are “complex, looping, and divides into multiple branches” and let you “start at a macro level view and zoom into micro level items.” Git, Gitkraken, and Sourcetree are her model; Patryk Adaś’ 2017 Lossless Web Navigation with Trails argued for trails instead of tabs; Szymon Kaliski’s Cartographist pairs a branching trail sidebar with stacked windows. Any exploratory task longer than a dozen steps needs this pattern and mostly lacks it. ### Notebooks and notes [Computational Notebooks](https://maggieappleton.com/computational-notebooks) (April 2023) calls **computational notebooks** (They're made up of 'cells' that each have an input and an output.) “one of the best solutions to the problem of unshareable, unexplainable code trapped in cumbersome local development environments.” Cells of code or prose, each with input and output, make them “ideal for tutorials or walkthroughs”; the interleaving is Knuth’s literate programming from 1984. Examples: Observable (JavaScript, for data visualisation designers), DeepNote, Google Colab, Jupyter, Wolfram Mathematica. A notebook is a document whose figures run, a cousin of this book and of [Bartosz Ciechanowski’s articles](https://learn-ui.com/chapters/explaining/explorable-explanations). Aside The notebooks page is one of the few with an assumed audience that warns readers off: “You probably won’t understand this if you haven’t done any programming.” [Daily Notes Pages](https://maggieappleton.com/daily-notes) (May 2022) and [Programmable Notes](https://maggieappleton.com/programmatic-notes) (March 2022) are a pair. The **Daily Notes Page** (The Daily Notes Page (colloquially, the DNP) is one of the most popular solutions to the problem of balancing frictionless input with future discoverability.) balances “frictionless input with future discoverability”: a blank page with today’s date needs no filing decision, and “tomorrow the page will automatically be swept away into the archives.” Examples: Remnote, Roam Research, Craft’s unsorted page, Obsidian and Logseq templates that fetch unfinished to-dos as “programmable attention”; the cost is “large piles of unstructured cruft.” **Programmable notes** (Programmable notes are note-taking systems that allow you to write programmatic rules that facilitate particular ways of working with your notes.) let you “write programmatic rules that facilitate particular ways of working with your notes,” triggered by conditions, input, or time of day, because most note software “acts as a passive storage container.” Examples: Roam Smartblocks, Obsidian and Logseq plug-ins, Coda automations, Gordon Brander’s Subconscious geists, and Elicit; her rules read like specs (“When I state a claim ask what evidence I have to back it up”). This is “end-user programming in action,” because app makers “will never be able to create systems that suit the needs of everyone’s particular knowledge management workflows.” ### A canvas and a to-do list One more pattern belongs here, from Amelia Wattenberger. [Evolving the infinite canvas](https://wattenberger.com/thoughts/evolving-the-infinite-canvas) observes that “Infinite canvases marry the easy manipulation of the digital world with the spatial strengths of the physical world,” which is why we use them for “complex, unsorted, or exploratory tasks.” She proposes hardcoding how we already organise into the canvas (prevent overlap; group like magnets that “pull fast enough and they detach”), encoding Gestalt rules of similarity, order, and proximity into exported data, and refusing the usual choice: “Are we going to give users a text document, a spreadsheet, a timeline, or a canvas? But what if we didn’t have to choose?” That question is where [the next chapter](https://learn-ui.com/chapters/canvases) begins, with Steve Ruiz’s tldraw. Keep the catalogue within reach. When a brief asks for collaboration, check it against ambient co-presence before adding cursors. When a flow branches, remember that breadcrumbs stop at about seven. When users do something strange with your tool, read it as a folk interface before reading it as a bug. When you want to hide power behind menus, ask whether a small programming portal would serve the one in a hundred who needs it. Maggie wrote these pages as observation and research; for a design engineer they are also a to-do list. --- # Glossary Every term of art in this book, defined once. Search covers both the terms and their definitions, so the concept works even when the name does not come to mind. ## # @starting-style — This can now also be solved with the @starting-style CSS at-rule, which would make the implementation much simpler. (Emil Kowalski, Building a Toast Component) 4-pixel grid — Predictable sizing via max() and round() to snap to a 4-pixel grid (Andrew Swank, andrewswank.com) ## A Ambient co-presence — Ambient co-presence is the sensation of sharing a space or context with other people, without directly interacting or continuously communicating with them. (Maggie Appleton, Ambient Co-presence) Angular velocity — Angular velocity describes how quickly an object rotates relative to some point. (Bartosz Ciechanowski, Gears) ARIA live region — We can use ARIA live regions to expose dynamic content changes to screen readers. (Rauno Freiberg, What will you ship?) As good as HTML — Adopting a quality bar of being as good as HTML is pretty hard. (Jan Miksovsky, quoted by Jim Nielsen, As Good as HTML) ## B Blurred backdrop — It's fairly common in products and operating systems to dim the backdrop when launching an overlay. This is another opportunity to add dimensionality to an interface by simulating depth of field that our eyes have naturally evolved to expect. (Rauno Freiberg, Designing Depth) Bounce — Bounce communicates brand personality the same way easing intensity does. More bounce means more playful. Zero bounce means more professional. (Emil Kowalski, Train Your Judgement) Build with significant autonomy — Startups are highly motivated to hire people who can act as an owner, end to end, of the things they produce and design engineers are strong examples of how that mindset manifests in a practice. (Kathryn Gonzalez, The Attributes of a Design Engineer) ## C Camera — Suspended in front of this plane is the camera. It points at the canvas. (Steve Ruiz, Creating a Zoom UI) Choreography — In my mind, choreography is deliberately orchestrating when something happens in a structured sequence. (Rauno Freiberg, Designing Depth) Clip-path — The clip-path property is used to clip an element into a specific shape. We create a clipping region with it, content outside of this region will be hidden, while content inside will be visible. (Emil Kowalski, The Magic of Clip Path) cmdk (⌘K) — ⌘K is a command menu React component that can also be used as an accessible combobox. You render items, it filters and sorts them automatically. (Paco Coursey, cmdk README) Coding is designing — Code isn't just a way to implement a design, it's a way to find one. (Jim Nielsen, Coding Is Designing) Command K bar — Command bars are command-line bars that pop up in the middle of the screen when you hit a certain keyboard shortcut. They're also known as 'command palettes', 'command launchers', or 'omniboxes' Traditionally CMD + K, hence the moniker 'Command K bars.' (Maggie Appleton, Command K Bars) Compound component — ⌘K is born from a simple constraint: can you write a combobox with filtering and sorting using the compound component approach? (Paco Coursey, cmdk ARCHITECTURE.md) Computational notebook — They're made up of 'cells' that each have an input and an output. You type programming syntax into the cell and then 'run' it, which compiles the code and produces an output. (Maggie Appleton, Computational Notebooks) Container queries — Since CSS container queries are now stable in modern browsers, we can build truly independently dynamic widgets instead of relying on the window width which is not reflective of how much space a component really has to display itself. (Rauno Freiberg, What will you ship?) Contrasting aesthetics — Unexpected displays of art that tastefully reject the notion of a clean, singularly defined style, yet bridges many. (Rauno Freiberg, Contrasting Aesthetics) Cultural practice — Most of the examples I listed above are cultural practices and techniques. They are primary ways of doing; specific ways of thinking and acting that result in greater cognitive abilities. (Maggie Appleton, Tools for Thought as Cultural Practices, not Computational Objects) Custom easing curves — The built-in easing curves in CSS are usually not strong enough, which is why I almost never use them. (Emil Kowalski, 7 Practical Animation Tips) ## D Daily Notes Page — The Daily Notes Page (colloquially, the DNP) is one of the most popular solutions to the problem of balancing frictionless input with future discoverability. (Maggie Appleton, Daily Notes Pages) Damping (drag) — When you drag upwards while already at the top of the drawer, the drawer will damp the drag, meaning the more you drag, the less the drawer will move. It makes the interaction feel more natural, as things in real life don't suddenly stop, they slow down first. (Emil Kowalski, Building a drawer component) Dark forest theory of the web — The dark forest theory of the web points to the increasingly life-like but life-less state of being online. (Maggie Appleton, The Dark Forest and Generative AI) Dead zone — This post will cover implementing a 'dead zone': a minimum distance needed before a shape will begin to drag. (Steve Ruiz, Dead Zone Dragging) Declarative feature design — this idea of 'declarative' feature design (a couple mocks, a few rules, and a design engineer) vs. 'imperative' feature design (innumerable mocks and rules along with a strict, waterfall process between designers and developers). (Jim Nielsen, The Case for Design Engineers) Design bottleneck — When you have a fat stack of agents churning through code tasks, development time is no longer the bottleneck. Design becomes the limiting factor: imagining what you want to create and then figuring out all the gnarly little details required to make your imagination into reality. (Maggie Appleton, Gas Town's Agent Patterns, Design Bottlenecks, and Vibecoding at Scale) Design engineer (Appleton) — Design engineer captures something simple, important, and worth distinguishing: a person who sits squarely at the intersection of design and engineering, and works to bridge the gap between them. (Maggie Appleton, A Collection of Design Engineers) Design engineer (Gonzalez) — A design engineer is someone who sits at the intersection of both practices and who loves the craft and the materiality of building software. It's a role that requires a mindset of autonomy, and an excitement about being an end-to-end software maker. (Kathryn Gonzalez, The Attributes of a Design Engineer) Design engineer (Vercel) — Design Engineers at Vercel blend aesthetic sensibility with technical skills. This allows us to deeply understand a problem, then design, build, and ship a solution autonomously. (Vercel, Design Engineering at Vercel) Design engineering (Design Engineering Handbook) — Design engineering is the name for the discipline that finesses the overlap between design and engineering to speed delivery and idea validation. (Natalya Shelburne, Design Engineering Handbook, as quoted by Trys Mudford in I think I might be a design engineer) Design handover — The design handover, this supposedly magic moment where design has finished and engineering begins, is the root cause of many of the collaboration problems that product teams have. (Rune Madsen, The Gulf Between Design and Engineering) Design infrastructure — Design Infrastructure is at the intersection of product design and engineering, and we support both sides through our tools, systems, communication and most importantly, our shared empathy of design and engineering. (Kathryn Gonzalez, Design Systems and Infrastructure) Design work with code — You need someone who can do design work with code. (Jim Nielsen, The Case for Design Engineers, Pt. II) Developer experience — If the component is not easy to use, people will give up before they even try it. Developer experience is key. (Emil Kowalski, Building a Toast Component) Digital garden — A digital garden is a collection of imperfect notes, essays, and ideas growing slowly over time. (Maggie Appleton, maggieappleton.com) display: contents — This property causes an element's children to appear as if they were direct children of the element's parent, ignoring the element itself. (Rauno Freiberg, What will you ship?) DOM is authoritative — The DOM is authoritative. Item selection order is based on the DOM order, which is based on the React render order, which the consumer provides. (Paco Coursey, cmdk ARCHITECTURE.md) Duration rule of thumb — As a rule of thumb, UI animations should generally stay under 300ms. (Emil Kowalski, You Don't Need Animations) Duration scales with distance — Duration should scale with the distance traveled. Bigger elements are "heavier" and should animate slower. The same way a truck takes longer to stop than a bicycle. (Emil Kowalski, Train Your Judgement) ## E Ease-in-out — Since we're moving something that is already on the screen, the motion should mimic natural acceleration and deceleration, just like a car. This curve does exactly that. (Emil Kowalski, Good vs Great Animations) Ease-out — If you are animating something that is entering or exiting the screen, use ease-out. It accelerates at the beginning which gives the user a feeling of responsiveness. (Emil Kowalski, 7 Practical Animation Tips) Easing — Easing, which describes the rate at which something changes over a period of time, is the most important part of any animation. (Emil Kowalski, 7 Practical Animation Tips) Elevate the final fidelity of what's made — One of the unique aspects of design engineering is that you've got the potential to have much of the full process of building software contained in one person. (Kathryn Gonzalez, The Attributes of a Design Engineer) Explicit accessibility labelling — Instead, we can set aria-hidden on the inner HTML, and write a custom aria-label for the whole group. (Rauno Freiberg, Crafting the Next.js Website) Explicit input — The keyboard, mouse, touch, voice are all explicit inputs. (Rauno Freiberg, Invisible Details of Interaction Design) ## F Fault tolerance — HTML and CSS are designed to be fault tolerant. When it comes to CSS, browsers will ignore syntax they don't understand. (Jim Nielsen, A Subtle Nicety of Fault Tolerance in HTML & CSS) Fidgetability — Behaviors like this are considered fidgeting. In other words, repetitive movements that apparently help release situational stress, or even enhance concentration. (Rauno Freiberg, Invisible Details of Interaction Design) Fish eye — A fish eye lens doesn't ask us to choose between focus and context (Amelia Wattenberger, Fish eye for text) Fitts's law — Fitts's Law states that the time to click on something depends on distance and size. (Rauno Freiberg, Invisible Details of Interaction Design) Fluid morphing — We're all familiar with the beautifully fluid, interruptible gestures of iOS to quickly navigate apps. Swiping up morphs the full screen app into its icon (Rauno Freiberg, Invisible Details of Interaction Design) Fluid reasoning — The biggest revolution from Large Language Models (LLMs) is the introduction of fluid reasoning. (Amelia Wattenberger, Code Atlas, GitHub Next) Fluid typography (clamp) — It helps to responsively adjust any property between a minimum and maximum value (Rauno Freiberg, Crafting the Next.js Website) Focus ring (shadow technique) — The first shadow would create padding around the element, and the second would then offset and display a 2px outline. (Rauno Freiberg, Crafting the Next.js Website) Focus trap — focus-trap is a small library that will manage saving the last focused element, finding and focusing on the first focus-able element of the modal, keeping focus within the modal, and restoring focus to the last focused element once the modal is unmounted. (Kathryn Gonzalez, How to Build a Modal) Folk interface — Folk interfaces are when users reappropriate existing software to solve their own problems. Rather than using applications in the ways designers and developers intended, they creatively reconfigure them to do unexpected things. (Maggie Appleton, Folk Interfaces) Fractional indexing — In this strategy, an index only needs to ensure that, when our items are sorted by their index, the items end up in the right order. (Steve Ruiz, Reordering Part 2: Tables and Fractional Indexing) Frequency and novelty — My working hypothesis was that the more commonly an user interface action is performed, the less rewarding or satisfying any novel visual or motion treatment on it becomes. (Rauno Freiberg, Novelty) Frequency tiers — How often users will see an animation is a key factor in deciding whether to animate or not. (Emil Kowalski, You Don't Need Animations) Friction — So we still need friction. It forces us to use our judgement, and it filters out the ideas that don't deserve to be built. (Emil Kowalski, Friction as a Feature) Friction (drag) — Instead of just not allowing the toast to be dragged upwards, you can still drag it, but it will slow down and eventually stop. It's nicer than just stopping the toast immediately. (Emil Kowalski, Building a Toast Component) Front-of-the-front-end — A front-of-the-front-end developer is a web developer who specializes in writing HTML, CSS, and presentational JavaScript code. A back-of-the-front-end developer is a web developer who specializes in writing JavaScript code necessary to make a web application function properly. (Brad Frost, as quoted by Jeremy Keith, Design engineer) ## G Good design — Design is about purpose and intent. To answer, 'Is this good design?' We must also answer: good for who? (Jim Nielsen, Good Design) Grain of the web — It's really easy to build a simple website when you can shift your perspective to viewing on-page interactivity as simple HTML page navigations powered by cross document CSS transitions (rather than doing all of that as client-side JS). (Jim Nielsen, Building Websites With LLMS) Growth stages — Every post on this site has a growth stage indicating how complete and comprehensive it is. They start as seedlings, grow into buddings, and finally end up as evergreens. (Maggie Appleton, Colophon) ## H Historical trail — Good historical trails should show people where they've been, even when the journey has been complex, looping, and divides into multiple branches of exploration. (Maggie Appleton, Historical Trails) Hover area — When a user has one or more shapes selected, we display an interactive overlay that allows the user to transform their selection: a drag inside the box will translate the selection; a drag on the edges will resize along that axis; a drag from the corner will resize along both axes; and a drag from further out on the corners will rotate the selection. (Steve Ruiz, An exhaustive review of design tool hover areas) ## I Implicit input — When an interface makes use of context as input and can infer what you're trying to do without asking, it truly feels magical. (Rauno Freiberg, Invisible Details of Interaction Design) Infinite canvas — The first is the canvas. You can think of this as a fixed plane of infinite dimensions. In a creative app, the canvas holds the user's artboards, shapes or other content. (Steve Ruiz, Creating a Zoom UI) Intent — What is the intent of someone using the product? And how much novelty are they willing to accept? (Rauno Freiberg, Novelty) Interaction design — Interaction design is an artform to make experiences that fluidly respond to human intent. (Rauno Freiberg, Invisible Details of Interaction Design) Interdisciplinary website maker — Even 'Design Engineer' doesn't feel adequate. It deliberately mixes two disciplines, which is great, but also leaves out all the others. (Jim Nielsen, Interdisciplinary Website Maker) Interruptability — Great interactions are modeled after properties from the real world, like interruptability. (Rauno Freiberg, Invisible Details of Interaction Design) Interruptible — Interruptibility helps your animations feel more natural and responsive. It allows the user to change the state of the animation at any time while maintaining a smooth transition. (Emil Kowalski, Great Animations) Interruptible transitions — That's one downside of keyframes: you can't smoothly change the end position while the animation is running. CSS transitions, on the other hand, can be interrupted and retargeted, even before the first transition has finished (Emil Kowalski, Building a Toast Component) Iterate to Greatness — Iterate to Greatness is one of Vercel's principles, allowing us to balance business goals with craft by shipping continuous improvements and avoiding the perfection trap. (Vercel, Design Engineering at Vercel) ## J Judgement — Putting into words why something feels right trains your ability to articulate your judgment, a skill that will be incredibly valuable in the AI era. (Emil Kowalski, Train Your Judgement) ## L Layered entry animations — Avoid layered entry animations to save time and keep the user in their flow. (Emil Kowalski, Train Your Judgement) Learn in public — Learn in Public; the practice of sharing what you learn as you're learning it, not a decade later once you're an 'expert.' (Maggie Appleton, A Brief History & Ethos of the Digital Garden) Literate programming — This approach of interleaving documentation and source code is called literate programming and was first proposed by Donald Knuth in 1984. (Maggie Appleton, Computational Notebooks) Lots of little HTML pages — Avoid in-page interactions that require JavaScript in favor of multi-page navigations that rely on HTML and are enhanced with CSS view transitions (and a dash of JS if/where prudent). (Jim Nielsen, Reminder: You Can Stitch Together Lots of Little HTML Pages With Navigations For Interactions) ## M Magic corners — Operating systems make use of "magic corners" on the edges of the screen because the target area is infinitely large. (Rauno Freiberg, Invisible Details of Interaction Design) Make Real — Ever wanted to just sketch an interface, press a button, and get a working website? Well, now you can at makereal.tldraw.com. (Steve Ruiz, make real, the story so far) Metaphor reuse — Great interaction design rewards learning by reusing metaphors. You can use most touch interfaces with just two gestures: tapping and swiping. (Rauno Freiberg, Invisible Details of Interaction Design) Momentum-based swipe — The swipe is momentum-based, meaning you don't have to drag the toast past a specific threshold to dismiss it. If the swipe is fast enough, the toast will still be removed even if the distance is short, because the velocity is high enough. (Emil Kowalski, Building a Toast Component) ## N next-themes — An abstraction for themes in your React app. (Paco Coursey, next-themes README) No man's land — There's a No man's land where the human is still required to make decisions, but they're not in control of the outcome. (Amelia Wattenberger, Why Chatbots Are Not the Future) Novelty — Novelty is the equivalent of an exclamation mark. Akin to seasoning, you don't want too much of it. (Rauno Freiberg, Novelty) Novelty as contrast — Novelty is the contrast to sameness. And novelty works best as a contrast. It becomes overwhelming otherwise. (Rauno Freiberg, Novelty) Novelty tax — There's this novelty tax that you get when you try a new product. (The Browser Company, quoted by Rauno Freiberg in Novelty) ## O Observer pattern — To avoid using React's Context, I manage the state via the Observer Pattern. I subscribe to the observable object in the component. Whenever the toast() function is called, the component (the subscriber) is notified and updates its state. (Emil Kowalski, Building a Toast Component) Origin-aware — When we click on a button that opens a dropdown, we expect the dropdown to animate from where the button is. This feels natural, it then doesn't appear out of nowhere, it has a clear origin. (Emil Kowalski, Good vs Great Animations) Owning results — Design Engineering at Vercel means more than being a designer and an engineer. It's about shifting from owning a specific part of the product development process to owning results. (Vercel, Design Engineering at Vercel) ## P Pages (command menu) — Often selecting one item should navigate deeper, with a more refined set of items. For example selecting 'Change theme…' should show new items 'Dark theme' and 'Light theme'. We call these sets of items 'pages', and they can be implemented with simple state (Paco Coursey, cmdk README) perfect-freehand — Draw perfect pressure-sensitive freehand lines. (Steve Ruiz, perfect-freehand README) Physical race condition — Rather than two software operations that might occur out of order, this was a physical race condition based on the imprecision of our bodies. (Steve Ruiz and Ani Krishnan, Debugging a physical race condition with modifier keys) Pointer capture — Once I start dragging, I set the toast to capture all future pointer events. This ensures that even if the mouse or your thumb moves outside the toast while dragging, the toast remains the target of the pointer events. (Emil Kowalski, Building a Toast Component) popLayout — Default AnimatePresence keeps the exiting element in flow until its animation completes, which delays the reflow. popLayout removes it from flow on the first frame so the siblings can start moving right away. (Emil Kowalski, Train Your Judgement) Practice and teach great software craft — Great design engineers are obsessed with understanding the materials of software, all the specific affordances of the medium, and the tools you use to shape them. (Kathryn Gonzalez, The Attributes of a Design Engineer) Productionizing — Design Infrastructure will make productionizing (taking our explorations and making them work in the context of our design & engineering systems) easier: building tools for finding, understanding, and using existing design decisions & patterns (Kathryn Gonzalez, Design Systems and Infrastructure) Programmable attention — These templates work as a kind of programmable attention. You are directed to answer specific questions each morning, log certain kinds of thoughts, record daily activities, or track your habits. (Maggie Appleton, Daily Notes Pages) Programmable notes — Programmable notes are note-taking systems that allow you to write programmatic rules that facilitate particular ways of working with your notes. (Maggie Appleton, Programmable Notes) Programming portal — Programming portals are small, scoped areas within a graphical interface that give users access to command lines and text-based programming. They open a little window into the underlying functionality of an interface. (Maggie Appleton, Programming Portals) Progressive enhancement — With layering we can progressively enhance the hero with a GLSL shader that gracefully fades in after the page has loaded. (Rauno Freiberg, What will you ship?) Pseudo element alt text — Instead, theres a second value for content which is alternative text for pseudo elements. By setting the content to an empty string we effectively are saying that nothing should be announced for this element (Rauno Freiberg, What will you ship?) Purposeful animation — Before you start animating, ask yourself: what's the purpose of this animation? (Emil Kowalski, You Don't Need Animations) ## R Radial menu — Radial menus are an exemplary case of Fitts's Law. They spawn around the pointer making the size and distance towards any target the same for all actions. (Rauno Freiberg, Invisible Details of Interaction Design) Reduced motion (pause, not none) — These are animated with CSS keyframes and we can pause them gracefully by using the animation-play-state property, instead of abruptly interrupting the animation by setting it to none. (Rauno Freiberg, What will you ship?) Repaint — Animating box-shadow would not be ideal since it would trigger a browser re-paint on every frame of the animation. (Rauno Freiberg, Crafting the Next.js Website) Responsive gestures — Truly fluid gestures are immediately responsive. (Rauno Freiberg, Invisible Details of Interaction Design) Reverse Turing test — Our new challenge as little snowflake humans will be to prove we aren't language models. It's the reverse turing test. (Maggie Appleton, The Dark Forest and Generative AI) ## S Sanding UI — So my recipe is: sand it, feel the grain, get a splinter, sand again, and repeat until smooth. (Jim Nielsen, Sanding UI) Screen space and page space — 'Screen space' is actual pixels on the user's display. 'Page space' is positions within the infinite canvas. (Steve Ruiz, Back to Content) Scribble — The tldraw SDK has a scribble system for managing scribbles, which are ephemeral freehand lines that are shown as an overlay on top of shapes but behind cursors. (Steve Ruiz, Redesigning the laser tool for better annotations) Scroll landmark — I made a tiny prototype where double tapping the scrollbar will place a landmark for the current scroll position. (Rauno Freiberg, Invisible Details of Interaction Design) Scroll lock — overflow: hidden isn't sufficient for preventing the body content from scrolling. On iOS, there are only two reliable ways of doing this: Setting position: fixed on the document.body, or adding event listeners that prevent the default behavior of touchmove on the body content. (Kathryn Gonzalez, How to Build a Modal) Semantic satiation — In psychology, there's this phenomenon called semantic satiation in which repetition of a word or phrase causes it to temporarily lose meaning. (Rauno Freiberg, Novelty) simulatePressure — Whether to simulate pressure based on velocity. (Steve Ruiz, perfect-freehand README, options table, default true) Skill file — My way of getting there is to create a skill file for each aspect of the interface. If you know what great feels like, describe the rules, then give them to your agents so they can follow them. (Emil Kowalski, Agents with Taste) Snap points — You can have multiple "checkpoints" in your drawer, meaning you can drag it to a certain point and it will snap to it. This is a common pattern on iOS. (Emil Kowalski, Building a drawer component) Sonner — Sonner is an opinionated toast component for React. (Emil Kowalski, Sonner README) Source of truth — Similarly, in making websites, the only source of truth is the website people access and use. (Jim Nielsen, Making Films and Making Websites) Spatial consistency — Because it comes from and leaves in the same direction, it creates spatial consistency, making the swipe-down-to-dismiss gesture feel more intuitive. (Emil Kowalski, You Don't Need Animations) Spring — Springs feel more natural than duration-based animations because they simulate real physics. (Emil Kowalski, emil-design-eng SKILL.md) Stacking context — The stacking context is a three-dimensional conceptualization of HTML elements along an imaginary z-index relative to the user, who is assumed to be facing the viewport or the webpage. (MDN, as quoted by Kathryn Gonzalez in How to Build a Modal) Stagger — Uniform stagger removes any sense of hierarchy and makes the movement feel artificial. Think about which elements deserve the most attention. Ensure the delays are not the same to make the motion feel more organic. (Emil Kowalski, Train Your Judgement) Staggering — Taking inspiration from nature for interfaces, we can sometimes stagger the behavior of sibling items that look similar. (Rauno Freiberg, Designing Depth) streamline — How much to streamline the stroke. (Steve Ruiz, perfect-freehand README, options table, default .5) Stroke — The getStroke function will return a new array of outline points. These outline points will form a polygon (called a 'stroke') that surrounds the input points. (Steve Ruiz, perfect-freehand README) Sycophancy — Sycophancy, meaning insincere flattery, is a well established problem in models that the foundation labs are actively working on. (Maggie Appleton, A Treatise on AI Chatbots Undermining the Enlightenment) ## T T-shaped design engineer — Design engineers tend to be deeply 'T-shaped,' with a broad understanding of design, and deep technical know-how in critical user interface engineering practices like rendering, animation, and layout. (Sean Voisen, Should you pursue a career in design engineering?, Adobe Design) Taste — Good taste is not personal preference. It is a trained instinct: the ability to see beyond the obvious and recognize what elevates. (Emil Kowalski, emil-design-eng skill, restating Developing Taste) Tastemaker — Practice your craft. Create things. A designer should design, a writer should write. This will make you not only a good judge of taste, but also, with time, a tastemaker. (Emil Kowalski, Developing Taste) The AI aesthetic — There are other aesthetics my brain associates with AI, like beige/cream colors, orange accents, and serif typefaces as well as whack-a-mole UI controls. (Jim Nielsen, The AI Aesthetic) The taste gap — The things you'll create probably won't be good at first, but that's a good sign. Your taste is good enough to tell that your work is not on par yet. (Emil Kowalski, Developing Taste, citing Ira Glass) The three activities of design engineering — Design engineers solve the particular problems that arise where design and engineering overlap. Specifically, design engineering enhances, improves and supports user experience design through three primary activities: Prototyping new product experiences to help designers learn about designs and validate design assumptions; Building tools and infrastructure that allows design to operate at scale and smooths designer-developer workflows (e.g. design systems); Building user interfaces and product experiences that other engineers can't or won't (for various reasons) be able to build while staying true to design intent (Sean Voisen, Design engineering, a working definition) thinning — The effect of pressure on the stroke's size. (Steve Ruiz, perfect-freehand README, options table, default .5) Three color rule — Filmmakers use the "three color rule" to create pleasing visuals. It generally means that about 60% of the frame is the primary color, about 30% is a secondary color, and the remaining 10% is an accent color. (Rauno Freiberg, Novelty) Tool and medium — Mediums are a means of communicating a thought or expressing an idea. Tools are a means of working in a medium. (Maggie Appleton, Tools for Thought as Cultural Practices, not Computational Objects) Tools for thought — It's simply meant to refer to tools that help humans think thoughts; potentially new, different, and better kinds of thoughts than we currently think. (Maggie Appleton, Tools for Thought as Cultural Practices, not Computational Objects) Topography over timelines — Gardens are organised around contextual relationships and associative links; the concepts and themes within each note determine how it's connected to others. (Maggie Appleton, A Brief History & Ethos of the Digital Garden) Touch content visibility — On touch interfaces, sometimes a finger might obfuscate what's happening on the screen which makes it hard to perform gestures at pixel-level precision. Commonly, the interface would then render a temporary representation of what's underneath the finger. (Rauno Freiberg, Invisible Details of Interaction Design) Transform-origin — A way to make your popovers feel better is to make them origin-aware. They should scale in from the trigger. You'll need CSS's transform-origin for this, but its default value is center, which is wrong in most cases. (Emil Kowalski, 7 Practical Animation Tips) Transitions vs keyframes — That's one downside of keyframes: you can't smoothly change the end position while the animation is running. CSS transitions, on the other hand, can be interrupted and retargeted, even before the first transition has finished (Emil Kowalski, Building a Toast Component) Tunneling — Game developers know this problem as tunneling, where a fast-moving bullet passes through a wall because no frame ever caught it inside the wall. In tldraw, an eraser is a bullet you drag around with your hand. (Steve Ruiz, Erasing shapes) ## U UI splinters — You can ensure any rough edges are smoothed out, and any 'UI splinters' are ones you get (and fix) in place of your users. (Jim Nielsen, Sanding UI, pt. II) Uniform stagger — Uniform stagger removes any sense of hierarchy and makes the movement feel artificial. (Emil Kowalski, Train Your Judgement) ## V Vaul — Using Apple's Sheet component on iOS feels natural, I wanted to create the same experience, but for the web. That's how Vaul was born. (Emil Kowalski, Building a drawer component) Vibe code — A key part of the definition of vibe coding is that the user accepts code without full understanding. (Wikipedia, quoted by Maggie Appleton in Vibe Code is Legacy Code) Viewport — The viewport is the part of the canvas that is visible on the screen. (Steve Ruiz, Creating a Zoom UI) Visual rhythm — When every element on a given section is signalling itself as novel or attractive, the novelty is diminished. (Rauno Freiberg, What will you ship?) ## Z Zoom UI — This pattern lets a user explore a 'canvas' of content by panning around the canvas or zooming in on a specific point. (Steve Ruiz, Creating a Zoom UI) --- # Introduction This book reads the work of people who design interfaces by building them: their essays, their components, their own sites. It is about the details that make software feel right, why they are hard to see, and how to learn to see them anyway. Every claim points back to a source. ## 3 sections 1. [A role between two rooms](https://learn-ui.com/chapters/introduction/a-role-between-two-rooms) 2. [Why the details are invisible](https://learn-ui.com/chapters/introduction/why-the-details-are-invisible) 3. [How to read this book](https://learn-ui.com/chapters/introduction/how-to-read-this-book) --- # A role between two rooms · Introduction Nobody agrees on what to call the job. Four people who do it have written down what it is, and they agree on more than they differ. ### The intersection Maggie Appleton, in [A Collection of Design Engineers](https://maggieappleton.com/design-engineers), calls “design engineer” the latest label on a pile that already holds interface designer, UX engineer, and front-of-the-front-end engineer. She keeps it because it names something worth distinguishing: “a person who sits squarely at the intersection of design and engineering, and works to bridge the gap between them.” Such a person can decide how something should work, look, and feel, and has the engineering skill to ship it, iterating between design exploration, research, and live code. ### Defined by output Vercel’s team, in [Design Engineering at Vercel](https://vercel.com/blog/design-engineering-at-vercel), says its **design engineers** (A person who sits at the intersection of design and engineering, able to decide how something should work, look, and feel, and to build it; the definitions in this section are from Maggie Appleton, Vercel, Kathryn Gonzalez, and Jim Nielsen.) “blend aesthetic sensibility with technical skills” so they can understand a problem, then design, build, and ship autonomously. What they care about is not a list of pixels: interactions and affordances, reusable primitives, page speed, cross-browser support, touch and pointer input, user preferences, assistive technology. “There is a lot of work behind the pretty pixels.” There is no handoff. A designer sketches a start and iterates with a design engineer in Figma or code, and animation, keyboard control, and touch are prototyped in the browser because rebuilding them from another medium wastes the effort. ### Three attributes Kathryn Gonzalez built the practice at DoorDash, from first product designer to leading design infrastructure. Her [The Attributes of a Design Engineer](https://www.ryngonzalez.com/blog/the-attributes-of-a-design-engineer) refuses the easy version (“a designer who knows how to sling some React”) and names three attributes: build with significant autonomy, practise and teach great software craft, and elevate the final fidelity of what gets made. A design engineer “loves the craft and the materiality of building software.” The lineage is long: creative technologists, Flash developers, design technologists, UX engineers. Where they cluster Appleton observes that the people she follows come mostly from Vercel, Linear, The Browser Company, and Replit. Several authors in this book have worked at more than one. ### The economic case Jim Nielsen, in [The Case for Design Engineers](https://blog.jim-nielsen.com/2022/the-case-for-design-engineers/), counts the artifacts a responsive design produces when designers and developers work in sequence, up to sixty per iteration, and observes that a design engineer collapses the pile. They hold the medium’s constraints in their head, so they produce one or two artifacts. “There’s no need to explicitly design and document all possible states for whoever is downstream of the designs because they are the ones downstream of the designs.” Read together: the role is ownership of an outcome rather than a slice of a process, fluency in the material rather than a tool, and care for details most people never consciously notice. The book is organised around those details in five parts. **Feel**: [Invisible details](https://learn-ui.com/chapters/invisible-details) and [Motion](https://learn-ui.com/chapters/motion). **Build**: [Components](https://learn-ui.com/chapters/components) and [Craft](https://learn-ui.com/chapters/craft). **Judge**: [Taste](https://learn-ui.com/chapters/taste). **Explain**: [Explaining with interaction](https://learn-ui.com/chapters/explaining) and [Canvases](https://learn-ui.com/chapters/canvases). **Work**: [The career](https://learn-ui.com/chapters/career). --- # How to read this book · Introduction The chapters run in an order, and the order is an argument: how interactions should respond, then how motion should be used, then how the pieces are built, then how the whole is judged. But every section stands alone, and the [glossary](https://learn-ui.com/chapters/glossary), [people](https://learn-ui.com/chapters/people), and [reading list](https://learn-ui.com/chapters/reading) let you enter anywhere. ### Figures are the point Each figure does the thing its section teaches: set a spring’s stiffness and watch it overshoot, swipe a card and see when the action commits, stack toasts and discover why keyframes fail. Every figure states where its numbers come from. “Constants from the source” means the defaults are the ones the cited essay or library documents; “illustrative numbers” means the ranges are yours to explore and no claim rests on them. > Figure 1. A figure that responds. Drag the slider. The number animates with a spring, the bar follows, and the explanation below swaps between two states that are both always mounted, so nothing under the figure moves.Illustrative numbers ### The rules the site holds itself to Nothing in a figure shifts the page: every state stays mounted and the tallest sets the height. Animations respect reduced motion. Controls work from the keyboard. Code appears when it says more than prose, with its source named in the header: > Figure. CSSEmil Kowalski, 7 Practical Animation Tips Ask AI The chat in the header answers from this site’s own pages and cites the section. It will quiz you if you ask. It does not invent numbers. ### A word on quotation Chapter prose is original. Short quotes appear where an author’s wording is the point, always attributed, and the glossary quotes verbatim by design. The sources are better than any summary; if a section makes you want to read the essay it draws on, that is the intended effect. Start with [the first gesture you were ever taught](https://learn-ui.com/chapters/invisible-details/metaphors). --- # Why the details are invisible · Introduction The best interaction work is the work you cannot see. That is a problem for anyone trying to learn it. ### No science, only digging Rauno Freiberg opens [Invisible Details of Interaction Design](https://rauno.me/craft/interaction-design) by admitting that design can feel like there is no science to it, and that even researchers treat interaction design as a black box. Searching the web yields recycled content about personas and Venn diagrams. The substance reveals itself only “to those willing to fanatically dig for them,” in long research papers or by replaying hundreds of slow motion screen recordings. His method: make something, fill your head with the problem, go for a walk. ### Invisible on purpose A gesture that retains momentum, a menu that skips animation because you open it a hundred times a day, a loupe that disappears when your finger no longer covers the caret: each is a decision made so you would not have to think. Emil Kowalski, in [Building a Toast Component](https://emilkowal.ski/ui/building-a-toast-component): “Not all of these details are noticed by the user, but that’s okay. These details add up.” He borrows Paul Graham’s line about unseen details combining “like a thousand barely audible voices all singing in tune.” Source Jim Nielsen, The Unseen Work of Design (2021): the finished product is the outside perception of design; the process of getting there is what constitutes it. ### Take it apart If you cannot learn the work by looking at finished products, you take them apart. Freiberg closes his essay with the observation that articulating why something feels right “does not come as intuitively as designing something to feel right. But they are two sides of the same coin.” Analysing beyond “it feels nice” is what nurtures taste. Kowalski’s method is the same: two versions side by side, pick one, say why. That is this book’s method. Each chapter takes work by people who did the digging, quotes them where wording is the point, and puts a figure next to the prose so you operate the idea instead of reading about it. Where a number appears, a source states it (a 0.05 scale step per stacked toast, a 300 millisecond rule of thumb, a 90 to 10 split between familiar and novel). Where no source states one, none appears. Bartosz Ciechanowski, whose articles are read in [Explaining with interaction](https://learn-ui.com/chapters/explaining/explorable-explanations), is the proof of the premise: an explanation you can drag teaches something a diagram cannot. --- # Invisible details Rauno Freiberg’s essay Invisible Details of Interaction Design is a close reading of gestures you perform hundreds of times a day without noticing. This chapter walks through it: the metaphors an interface reuses, the physics it borrows, when a swipe should commit, how motion says where things live, why some actions should not animate at all, and what Fitts’s law says about where a target belongs. ## 7 sections 1. [Metaphors and learned gestures](https://learn-ui.com/chapters/invisible-details/metaphors) 2. [Kinetic physics and swipe gestures](https://learn-ui.com/chapters/invisible-details/kinetic-physics) 3. [Responsive gestures](https://learn-ui.com/chapters/invisible-details/responsive-gestures) 4. [Spatial consistency and fluid morphing](https://learn-ui.com/chapters/invisible-details/spatial-consistency) 5. [Frequency and novelty](https://learn-ui.com/chapters/invisible-details/frequency-and-novelty) 6. [Fitts's law](https://learn-ui.com/chapters/invisible-details/fitts-law) 7. [Touch, context, and fidgetability](https://learn-ui.com/chapters/invisible-details/touch-and-context) --- # Fitts's law · Invisible details **Fitts’s law** (Fitts's Law states that the time to click on something depends on distance and size.) states that the time to click on something depends on distance and size. Rauno Freiberg’s gloss in [Invisible Details of Interaction Design](https://rauno.me/craft/interaction-design) is that the bigger the target, and the closer to where your pointer already is, the better. The law comes from Paul Fitts’s 1954 paper on the information capacity of the human motor system; Rauno also lists Kevin Hale’s 2010 Visualizing Fitts’s Law. Figure 3 lets you turn the two variables. Change distance and width, press Move, and watch difficulty rise as the target shrinks or moves away. Then turn on the edge target and notice the width reads as unbounded. Finally switch on the radial menu, where six wedges spawn around the pointer. The two switches are Rauno’s two examples. > Figure 3. Fitts's law. Change the distance and the width and watch the difficulty move. Then turn on the edge target and the radial menu to see the two ways designers cheat it. The move timing is illustrative: it only grows with the index of difficulty.Illustrative numbers ### Magic corners are infinite targets Operating systems use **magic corners** (Operating systems make use of magic corners on the edges of the screen because the target area is infinitely large.) because the target area there is infinitely large: the pointer cannot overshoot past the corner, so the precision required is very low and reaching any corner becomes a quick flick of the mouse. That is why commonly used menus, like the Apple menu, sit in corners. The target’s size in pixels did not change; its effective size did. ### Radial menus spawn at the pointer **Radial menus** (Radial menus are an exemplary case of Fitts's Law. They spawn around the pointer making the size and distance towards any target the same for all actions.) spawn around the pointer, making the size of and distance to every target the same for every action. Nothing is far, small, or privileged by position. Over time muscle memory kicks in and you can select purely by distance and direction, without reading labels. His own demo, published separately as the Radial Menu prototype (January 2023), carries the instruction “Hold and rotate from anywhere”: the whole affordance in four words. The menu does not have a place; it appears where you are. Source Paul Morris Fitts, The information capacity of the human motor system in controlling the amplitude of movement (1954). Kevin Hale, Visualizing Fitts’s Law (2010). Both are in the essay’s resources list, alongside the 1987 Apple Human Interface Guidelines. ### Three levers, no numbers The App Switcher and the Dynamic Island are about where things come from; Fitts’s law is about where they should be when you need them. Both are spatial arguments decided before any animation is chosen, and the radial menu is where they meet: a menu that spawns where you are has nothing to travel, so the only motion left is your hand’s. The law gives you three levers and nothing to memorise. Make frequent targets bigger. Put them where the pointer will be when the need arises, near the trigger or at an edge it cannot pass. And when an action has several equal options, consider spawning them around the pointer, so distance and direction can become the interface once the hand has learned them. --- # Frequency and novelty · Invisible details “As a designer, I love to animate everything,” Rauno Freiberg writes in [Invisible Details of Interaction Design](https://rauno.me/craft/interaction-design). Object permanence, a focal point, and delight are good reasons; what is not obvious is when not to. His first clue is the input: pressing a key feels less visceral, more mechanical, than touching glass, so mouse and keyboard interactions can often go unanimated. ### Hundreds of times a day His case is the command menu, the pattern Maggie Appleton catalogues as the [Command K bar](https://maggieappleton.com/command-bar). It is tempting to throw an opacity and scale fade on the overlay, but at hundreds of uses a day the hundredth viewing feels like cognitive burden, and the novelty is gone; you are not doing anything peculiar that deserves a flourish. He later names this **frequency and novelty** (The more commonly an user interface action is performed, the less rewarding or satisfying any novel visual or motion treatment on it becomes.). He tested it on himself. Building bmrks.com, he animated the active indicator and list items being added and removed. After a couple of days they felt sluggish, even made snappier, when working from the keyboard. He removed motion from the core interactions and “suddenly felt like I was moving much faster.” macOS agrees. Context menus appear without motion, thousands of times a day, yet fade out subtly while the selected item blinks the accent colour to confirm. The App Switcher overlay never animates, and a short enough Command-Tab switches focus without showing the menu at all. ### Never animate keyboard actions Emil Kowalski reaches the same rule in [You Don’t Need Animations](https://emilkowal.ski/ui/you-dont-need-animations): he uses Raycast hundreds of times a day, it has no animation, and that is optimal, because he has a clear goal and does not need delighting. Hover effects used many times a day likely benefit most from no animation, and for keyboard-initiated actions, “You should never animate them.” In [7 Practical Animation Tips](https://emilkowal.ski/ui/7-practical-animation-tips) the range is “tens, maybe even hundreds of times a day.” His skill turns the rule into tiers. > Figure. SKILL.mdEmil Kowalski, emil-design-eng skill Source bmrks.com, the context menu blink, and the Command-Tab delta are from the Frequency & Novelty section of the essay. The frequency tiers are from Emil’s emil-design-eng SKILL.md. ### Ninety percent familiar, ten novel In February 2026 Rauno picked the thread up in [Novelty](https://rauno.me/craft/novelty). He connects the hypothesis to **semantic satiation** (In psychology, there's this phenomenon called semantic satiation in which repetition of a word or phrase causes it to temporarily lose meaning.), where a repeated word temporarily loses meaning, and argues the same happens to extravagant animation in common use. **Novelty** (Novelty is the equivalent of an exclamation mark. Akin to seasoning, you don't want too much of it.) “is the equivalent of an exclamation mark. Akin to seasoning, you don’t want too much of it.” From cinematography he borrows the three colour rule (about 60% of the frame primary, 30% secondary, 10% accent) and proposes 90% familiar, 10% novel for software, offered with a grain of salt. Where should the 10% go? Onboarding, because you onboard once. His product Devouring Details plays a login-to-welcome transition only right after logging in; reload and the page appears instantly. A cookie set on login makes a Next.js rewrite serve an animated index page, then the cookie is cleared. > Figure. middleware.tsRauno Freiberg, Novelty Paco Coursey’s site staggers on first load but not on return. The iOS Home Screen staggers its icons after you unlock, not when you return already unlocked; in Designing Depth Rauno calls that **staggering** (Taking inspiration from nature for interfaces, we can sometimes stagger the behavior of sibling items that look similar.) and says it makes a primitive swipe feel three-dimensional. ### Novelty as contrast Novelty is the contrast to sameness and works best as contrast. A dramatic route transition he would not want on every page suits a microsite of interviews because the sibling pages are static. Stripe Press is more experimental than the rest of Stripe: “the novelty hits hard because most of the pages aren’t such experiences.” Intent matters too; someone playing a game is there to be entertained and is receptive. The cautionary case is Arc. The Browser Company built it into a saxophone and found it hard to turn into a piano anyone could play. Their name for the reason is the **novelty tax** (There's this novelty tax that you get when you try a new product.): tabs over here, Spaces, Pin Tabs unlike Bookmarks, too much new to learn. How much novelty you can get away with depends on your audience. Not Boring found a smaller, passionate one that values beauty and game-feel, and builds novel versions of photos, habits, timers, and calculators for it. His takeaway: “Make most things familiar, do something unexpected.” Strip motion from actions performed hundreds of times a day, especially keyboard ones, and spend the novelty on moments that happen once. The taste-level version is in [Novelty and contrast](https://learn-ui.com/chapters/taste/novelty-and-contrast). --- # Kinetic physics and swipe gestures · Invisible details The lock screen on iOS slides up. Rauno Freiberg reads that as a lesson: the lock screen is just an overlay dismissed by swiping up, and within that framing so is an app. In [Invisible Details of Interaction Design](https://rauno.me/craft/interaction-design) he watches an app dismissed into the Dynamic Island. The gesture retains the momentum and angle at which it was thrown, never perfectly centred or consistent in timing. ### A card, not a simulation His comparison is a playing card swiped across a table, with limits: a real card would bounce less, being conceptually lighter, and does not magnetically morph into something at the end. The interface is not simulating a card; it borrows enough of the card’s behaviour that your hand already knows what to expect. ### Lightweight actions fire mid-swipe When does a swipe trigger an action? The naive model is press, move, release, then act. After building touch interactions in SwiftUI, Rauno realised that lightweight actions, such as displaying overlays or opening search, feel more natural triggered during the swipe after an arbitrary distance. His SwiftUI prototype of Jason Yuan’s MercuryOS unlocks the moment the titles snap into place: “It feels expected to trigger an action when elements moving during the gesture reach their logical, final position.” Waiting for the gesture to end would feel broken and give less affordance. ### Destructive actions wait for release The iOS App Switcher will never dismiss an app before the gesture ends, however far you have dragged. Dismissing is destructive, and it would not feel nice to vanish halfway through a swipe: change your mind, cross the threshold by accident, lose progress. Triggering on gesture end, regardless of distance, makes the interface respond to what you meant. Source Both rules are from the Swipe Gestures section of the essay. The MercuryOS prototype is his SwiftUI recreation of Jason Yuan’s 2019 concept. The same rule buys you peeking: nothing commits until you let go, so you can drag another screen into view while scanning for an app, and interrupt by changing direction. In Figure 1, drag the card past the dashed line in each mode and watch when the action fires; then cross the line and drag back before letting go. > Figure 1. When a swipe should commit. Drag the card past the dashed line in each mode and notice when the action fires. A lightweight action like showing an overlay can trigger during the swipe, once you have moved far enough. A destructive action like dismissing waits for release, so the interface responds to intent rather than distance.Illustrative numbers ### Momentum as a third trigger Distance is not the only signal. Emil Kowalski’s Sonner toast, described in [Building a Toast Component](https://emilkowal.ski/ui/building-a-toast-component), is momentum-based: a fast swipe dismisses even when the distance is short. He divides the absolute drag distance by the elapsed time to get a velocity and removes the toast if either clears its limit. The velocity limit, 0.11, came from trial and error. > Figure. TypeScriptEmil Kowalski, Building a Toast Component Trigger timing is a decision, and the right answer depends on the cost of being wrong. Cheap to undo: respond as soon as the moving elements reach their final position. Expensive: keep the gesture reversible and commit on release. Either way, let the thing you drag keep the momentum and angle you gave it; a gesture that lands identically every time stops feeling like yours. --- # Metaphors and learned gestures · Invisible details Rauno Freiberg opens [Invisible Details of Interaction Design](https://rauno.me/craft/interaction-design) (July 2023) with an admission. Design can feel like there is no science to it, “only feel and intuition,” and even researchers treat the practice as a black box (he cites a 2011 CHI paper by Goodman, Stolterman, and Wakkary). The web returns recycled personas and UI/UX Venn diagrams; the substance shows itself only to people willing to read obscure papers or replay hundreds of slow motion screen recordings. ### Observation, not guidelines The essay is “not a tutorial nor a collection of guidelines,” but an observation of details in interactions he uses often and rarely thinks about. His revelations surface from making something, then going for a walk. Like recreating interfaces, this reflection builds design intuition and vocabulary. Source The black box claim is footnoted to E. Goodman, E. Stolterman, and R. Wakkary, Understanding Interaction Design Practices (CHI 2011). The resources list also names Apple’s 2018 WWDC session Designing Fluid Interfaces, Jason Yuan’s MercuryOS, and Brian Lovin’s App Dissection. His definition is short. **Interaction design** (Interaction design is an artform to make experiences that fluidly respond to human intent.) is “an artform to make experiences that fluidly respond to human intent.” It is not painting: people use a product to get something done, so beauty of form is not enough, and the satisfaction comes from a holistic balance of form and function. His questions are this chapter’s: when does a swipe trigger an action, do gestures retain momentum, what happens when a finger covers content, how can an interface predict intent from context. ### Two gestures teach the rest The first answer is metaphor. “Great interaction design rewards learning by **reusing metaphors** (Great interaction design rewards learning by reusing metaphors.).” Most touch interfaces need two gestures, tapping and swiping, and on iOS the only one you are explicitly taught is swiping up to open. That one swipe unlocks much of the interface. The sliding motion is also structural: the interface is stacked layers, like a deck of cards, and swiping down reveals layers of system functionality. The knowledge compounds across the Apple ecosystem, and every surface that honours the metaphor costs nothing to learn. ### Borrowing properties, not looks Why does swiping horizontally move between pages? Because that is how we have interfaced with books for thousands of years. The metaphor brings real-world properties with it, and the one he singles out is **interruptability** (Great interactions are modeled after properties from the real world, like interruptability.). Flipping a page is obviously interruptible, which sounds silly until you imagine the page turn as an animation you had to wait for. Pinching is subtler. Zooming is an act of precision, adjusting the amount of detail visible, and the interface first has to establish an anchor point, which is easier and more precise to pick with the fingers pinched together. Starting apart usually means zooming out, where the exact origin matters less. Deliberate precision wants two fingers close together, “kind of like grabbing an object.” ### The question to ask He closes with the sentence that names the essay: hundreds of design decisions are made by someone obsessing over the tiniest margins so that, when they work, nobody has to think about them. Many tap into instinctive behaviour. So before you invent a gesture or a transition, ask which metaphor it borrows and whether it keeps that metaphor’s properties. A swipe that cannot be interrupted, a layer that does not slide, a zoom with no anchor: each breaks a promise the user did not know they were relying on. --- # Responsive gestures · Invisible details “Truly fluid gestures are immediately responsive.” That sentence from Rauno Freiberg’s [Invisible Details of Interaction Design](https://rauno.me/craft/interaction-design) is the whole section; the rest is what it rules out. A gesture can have a trigger threshold, but that does not license playing an animation from 0 to 1 once it is crossed. **Responsive gestures** (Truly fluid gestures are immediately responsive.) track the finger from the first millimetre. ### Feedback first, then commit His example is pinching a card. A naive implementation does nothing until a threshold, then zooms all at once. Rauno is fair to it: pinching enough to get the animation does not feel exactly broken. But the interface gives zero affordance that the card is pinchable when you move slowly, and the gesture is not satisfying to perform. The better version applies the scale delta immediately, so the card grows under your fingers, and performs the animation once the threshold is passed. The first part is feedback; the second is the commit. > Figure. TypeScriptIllustration ### Interruptible means listening He finds the counterexample inside iOS. Navigating Settings does not feel as responsive as the App Switcher: a layer slides in from the right, which correctly says it can be dismissed by swiping left, but if you mistap and swipe back immediately the animation does not interrupt. You wait for it to finish. Same platform, same gesture vocabulary, a noticeable difference in how much the interface listens. Emil Kowalski makes the same demand of pointers. In [Train Your Judgement](https://emilkowal.ski/ui/train-your-judgement) he compares two sidebar hover highlights, one fading in smoothly and one instant. Move the mouse quickly and the smooth one trails the cursor, “always one step behind.” The instant one tracks perfectly: “There’s no delay between your intention and the interface’s response.” Feedback that arrives after the threshold is not feedback; it is a result. ### The input device is part of the gesture Rauno’s Scrolling section adds a variable. On most operating systems you can scroll any region even when its window is not active, which is great until another window scrolls by accident. With the Magic Mouse he can scroll one window, move the pointer over a second to click or find something, and the scroll events do not register there; scrolling is cancelled explicitly, by focusing another window. With a traditional mouse like the Logitech MX Master 3, the first window’s scroll is hijacked by the second, and he finds it frustrating daily. The Magic Trackpad and Magic Mouse also unlock direct manipulation on the desktop, like adjusting a slider by scrolling over it in a single interaction. Source The pinch and the Settings back-swipe are from the Responsive Gestures section; the Magic Mouse and MX Master observations are from the Scrolling section near the end of the essay. Two habits follow. Wire the continuous part of a gesture to the continuous part of the input: scale follows pinch distance, offset follows drag, before any threshold logic runs. And make every in-flight animation interruptible by the gesture that started it, so a mistap costs one reversed motion rather than a wait. --- # Spatial consistency and fluid morphing · Invisible details Motion can tell you where something lives. Rauno Freiberg’s example in [Invisible Details of Interaction Design](https://rauno.me/craft/interaction-design) is the Dynamic Island. Tap it and the app slides out from under the Island to cover the screen. But if the Island is expanded, which says your intent is to receive more detail, the app launches from its icon if the icon is visible, and otherwise slides in from the right. ### Direction carries information Launching Spotify from its icon makes it clearer where the audio is playing from: with three music apps on one row, the motion ties the player to its source. Sliding in from the right says the app lives in the App Switcher, and right rather than left says it is now first on the stack. This is **spatial consistency** (Because it comes from and leaves in the same direction, it creates spatial consistency, making the swipe-down-to-dismiss gesture feel more intuitive.): the direction an element arrives from matches where it came from. The exception proves it. The Clock app always jumps out from the Island, even when expanded, because its timer module belongs to one app and there is nothing to disambiguate. Emil Kowalski gives the web version in [You Don’t Need Animations](https://emilkowal.ski/ui/you-dont-need-animations): Sonner’s toast enters from the direction it later leaves in, and that consistency makes swipe-down-to-dismiss feel intuitive. In code it is a mounted flag and a transition from below. > Figure. CSSEmil Kowalski, Building a Toast Component Source Spotify, the right-edge slide, and the Clock exception are from the Spatial Consistency section of the essay. The toast CSS is from Emil’s Building a Toast Component. ### Fluid morphing and the 10 point crop Swiping up morphs the full screen app into its icon, which Rauno calls **fluid morphing** (Swiping up morphs the full screen app into its icon; the icon is intentionally stretched from the bottom to fill the frame as it fluidly morphs its shape from a vertical rectangle to a uniform square.). The icon is intentionally stretched from the bottom to fill the frame as the shape goes from tall rectangle to square. That assumes icons follow Apple’s guidelines. The Bluesky icon ignores the safe zone, so its bottom roughly 10 points are cropped, duplicated, and stretched into a strange repeating image. A system motion decision leaks into every third-party asset. Figure 2 shows the principle on the web: a compose pill that either grows into a panel or is replaced by it. In Morph mode your eye never loses the element, the object permanence Rauno names as a reason to animate at all. In Cut mode the panel simply appears. > Figure 2. Morph versus cut. Click Compose. In Morph mode the pill grows into the panel, so your eye never loses the element. Switch to Cut and the panel simply appears. Slow motion shows what the spring is doing.Illustrative numbers ### Motion that says a layer still works A year later, in [Designing Depth](https://rauno.me/craft/depth) (July 2024), Rauno shows motion telling you what a surface still does. On iPadOS, swiping right on the Home Screen opens the Today View as a full screen overlay and the Dock slides out of view, not blurred but keeping its opacity, which says it retains interactivity and can be swiped back. Moving it respects your intent to use the surface you swiped for. His check that this is deliberate: Control Centre is also a full screen overlay, and there the Dock is blurred with the Home Screen while the Home Bar surfaces above as its own layer to indicate dismissability. Same Dock, two treatments, each matched to what you can do next, and the sliding one reinforces the stacked layers metaphor from the first section of this chapter. Before an element appears, decide where it is coming from and make the motion say so. A panel that lives inside a button grows from that button; a sheet that leaves downward arrives from below. An element that stays interactive while something covers it should behave like its own layer, by sliding or keeping its opacity, rather than blurring with the rest. --- # Touch, context, and fidgetability · Invisible details A finger is opaque. Rauno Freiberg points out in [Invisible Details of Interaction Design](https://rauno.me/craft/interaction-design) that on touch interfaces the finger sometimes obscures exactly what you are manipulating, which makes pixel-level precision hard. The common answer is **touch content visibility** (On touch interfaces, sometimes a finger might obfuscate what's happening on the screen which makes it hard to perform gestures at pixel-level precision. Commonly, the interface would then render a temporary representation of what's underneath the finger.): render a temporary representation of what is underneath. ### Proxies that leave when done On iOS, dragging the text caret brings up a magnifying loupe above the touch point, and when the finger moves down and no longer covers the caret, the loupe disappears. It exists only while needed. The keyboard does the same in miniature: pressing a key shows an enlarged copy, confirming the interface understood you. Mirroring is not always right. Sliders can be tiny and vanish under a thumb; there the useful detail is that the drag does not cancel when the thumb drifts off while still pressing. Video scrubbing is the case nothing rescues: seeking is mostly visual, and Rauno describes “an unintelligible level of discomfort” in handling an element you cannot see. ### Context as input Keyboard, mouse, touch, and voice are all **explicit inputs** (The keyboard, mouse, touch, voice are all explicit inputs.), a natural extension of ourselves when dialled in. But is the mother of all inputs not no input at all? **Implicit input** (When an interface makes use of context as input and can infer what you're trying to do without asking, it truly feels magical.) is when an interface uses context and infers what you want without asking. Apple Maps shows the active route when you look at the screen, without unlocking. Apple Wallet raises the brightness when you present a pass. Spotify adapts its interface while you drive. And some iOS apps blur their contents in the App Switcher: not a performance optimisation, as he first assumed, but deliberate concealment of sensitive data like medical records or a bank statement. Context can hide as well as reveal. Source The loupe, keyboard popups, sliders, and scrubbing are from Touch Content Visibility; Maps, Wallet, Spotify, and the blurred switcher are from Implicit Input, both in the second half of the essay. ### Finding your place, and fidgeting On macOS you find the pointer by shaking the mouse, which Rauno likes because it taps into the frustration people already feel when they lose it. His own reading problem: halfway down a page he wants to check something above, but scrolling up loses a precious scroll position. His prototype lets you double tap the scrollbar to place a **scroll landmark** (I made a tiny prototype where double tapping the scrollbar will place a landmark for the current scroll position.), wander, and double tap the landmark to return. It feels familiar because the scrollbar is already interactive on touch: long-pressing makes it draggable. His older minimap prototype, inspired by games with a bird’s eye view, came from the same instinct. The last detail has no practical purpose. “Wonderful interactions don’t have to be entirely practical.” Playing with an AirPods case, or twisting an Apple Pencil tip, is **fidgeting** (Behaviors like this are considered fidgeting. In other words, repetitive movements that apparently help release situational stress, or even enhance concentration.): repetitive movement that apparently releases situational stress or enhances concentration. He footnotes that no research supports the claim, but holds that fidgetability still feels like part of intentional design. The AirPods case is “uncannily satisfying to play with,” and assuming coincidence would be very generous. The Pencil tip is unscrewable for replacement, and twisting it gives a satisfying friction to play with while thinking. ### Two sides of the same coin Understanding why something feels right, he admits, does not come as intuitively as designing it to feel right, “but they are two sides of the same coin. There must be a reason.” It can be as simple as a spring curve or as innate as a metaphor, and analysing details beyond “it feels nice” nurtures taste and raises execution. Emil Kowalski, on multi-touch in [Building a drawer component](https://emilkowal.ski/ui/building-a-drawer-component), says why these details are called invisible: they align with inherent expectations, so when a feature works as you assume, you proceed without a second thought. His drawer ignores every touch after the first until release, so a second finger cannot make it jump. > Figure. TypeScriptIllustration Three habits. When a finger or pointer will cover the thing it manipulates, show a proxy and remove it when it is not needed. Ask what the interface already knows before asking the user; context can protect as well as help. And when you cannot explain why an interaction feels right, treat that as work left to do, the work [the Taste chapter](https://learn-ui.com/chapters/taste) is about. --- # Motion Emil Kowalski built two React libraries that rely on animation, downloaded together more than 90 million times a week from npm, and then wrote an essay titled You Don’t Need Animations. That is the whole chapter in one sentence. What follows is how he, Rauno Freiberg, and a few others decide when motion earns its place, and how they choose the curve, the duration, the spring, and the clip when it does. ## 7 sections 1. [You don't need animations](https://learn-ui.com/chapters/motion/you-dont-need-animations) 2. [Easing: where the speed goes](https://learn-ui.com/chapters/motion/easing) 3. [Springs and duration](https://learn-ui.com/chapters/motion/springs) 4. [Practical tips](https://learn-ui.com/chapters/motion/practical-tips) 5. [The magic of clip-path](https://learn-ui.com/chapters/motion/clip-path) 6. [Choreography and depth](https://learn-ui.com/chapters/motion/choreography-and-depth) 7. [Friction as a feature](https://learn-ui.com/chapters/motion/friction) --- # Choreography and depth · Motion Rauno Freiberg’s [Designing Depth](https://rauno.me/craft/depth) (July 2024) starts with composition: distilling a three-dimensional world into a two-dimensional frame while keeping story and depth. ### Dirtying the frame Filmmakers call one answer “dirtying the frame”: props, out-of-focus foreground obstructions, or unconventional framing between camera and subject, because the pristine head-on shot carries less. In software this means adding ambient foreground and background objects. His example is a Vercel marketing visual that fell flat because the browser frame and the surfaces over it had no depth. The fix: blur the inner background to lower it on the Z-axis, fade the container’s bottom edge so the boundary feels infinite, and add offset browser frames and out-of-focus objects chosen so the layers themselves communicate an abundance of Preview Deployments. The same instinct explains the **blurred backdrop** (Dimming or blurring the layer behind an overlay, which adds dimensionality by simulating the depth of field our eyes expect and signals that only the overlay is actionable.) behind an overlay, which Rauno reads as depth of field, the thing “our eyes have naturally evolved to expect.” It is also information: an iOS context menu without de-emphasis behind it would suggest the whole app grid is still interactive when only the menu is. ### The swipe-down, in four states **Choreography** (In my mind, choreography is deliberately orchestrating when something happens in a structured sequence. (Rauno Freiberg)) is “deliberately orchestrating when something happens in a structured sequence,” and he draws the parallel to dirtying the frame: both add layers to a narrative. In animation the instruments are time and artificial delay, used so the result feels true to nature, where you rarely see every leaf of a tree move at once. His production example is the iOS Home Screen swipe-down. Rather than one keyframed animation, the gesture has four states: the Home Screen blurs; the Siri suggestions are revealed as another layer; the Search button becomes an input while the keyboard is partially revealed; on gesture end the keyboard pops up. The first row of apps and the suggestions share the same space, so the blur must land before the suggestions surface, and the reveal is deliberately delayed. The keyboard is held back, he assumes, so it does not compete with the suggestions, and the first feedback appears near the top, where the gesture originates. Tap the Search button instead and the choreography reverses: the input comes first, the suggestions after a very slight delay, because you prioritise the transition nearest the trigger “to promptly communicate that the interface understood you.” The staggering section, covered in 2.4, adds Control Centre’s rubber banding, where each row responds with a slightly staggered spring configuration. Source The four states, the Search-tap reversal, and the iPadOS Dock are all from Designing Depth; its image alt text enumerates the four states. ### Motion as affordance On iPadOS, swiping right on the Home Screen opens the Today View as a full-screen overlay, and the Dock slides out of view keeping its opacity instead of blurring with the Home Screen. Rauno reads that as a message: the Dock “retains interactivity and can be brought back with a swipe gesture,” reinforcing the metaphor of stacked layers. In Control Centre, another full-screen overlay, the Dock does not slide; it is blurred with the Home Screen, and the Home Bar surfaces above to show the overlay can be dismissed. The Dock moves only when it is layered above the surface you swiped for: the slide respects your intent. Read beside Emil Kowalski there is a tension worth naming. Emil’s [Train Your Judgement](https://emilkowal.ski/ui/train-your-judgement) calls a side panel that slides in and then trickles its items “two layers of entrance animation” and prefers the content simply there. Rauno’s examples are system gestures and first-contact moments. The test they share: if sequencing tells the user something, which layer is on top, where the gesture came from, what is still interactive, it is choreography. If it only makes the entrance longer, it is a layer to remove. --- # The magic of clip-path · Motion Emil Kowalski’s [The Magic of Clip Path](https://emilkowal.ski/ui/the-magic-of-clip-path) starts from a property most people file under shapes. “`clip-path` is often used for trimming a DOM node into specific shapes, like triangles. But what if I told you that it’s also great for animations?” ### A property that skips layout **clip-path** (The clip-path property is used to clip an element into a specific shape. We create a clipping region with it, content outside of this region will be hidden, while content inside will be visible. (Emil Kowalski)) defines a clipping region: inside is visible, outside is hidden. What makes it an animation tool is that it has no effect on layout: a clipped element occupies the same space as an unclipped one, “just like transform,” so animating it moves nothing around it. The coordinate system starts top left. `inset()` takes top, right, bottom, and left offsets of a rectangle: `inset(100%)` hides the whole element, `inset(0px 50% 0px 0px)` hides its right half. > Figure. CSSEmil Kowalski, The Magic of Clip Path The examples are all the same move. A comparison slider is two images overlaid, the top one clipped with `inset(0 50% 0 0)` and the value adjusted as you drag, which beats two divs with overflow hidden because it is hardware-accelerated and needs no extra DOM. The text variant splits a dashed word and a solid one at the mouse position. “It’s just a matter of creativity.” ### The image reveal The image starts fully clipped and animates open over one second with `cubic-bezier(0.77, 0, 0.175, 1)`, the In Out Quart curve from 2.2. You could animate height, but clip-path is hardware-accelerated, and because the image is already there and only clipped, revealing it causes no layout shift. > Figure. CSSEmil Kowalski, The Magic of Clip Path To run it on scroll he uses Framer Motion’s `useInView`, firing once and only when at least 100px of the image is in view, and drives the animation through WAAPI to keep the logic in one place. If you are not already using Framer Motion, use Intersection Observer; the library is heavy. > Figure. TypeScriptEmil Kowalski, The Magic of Clip Path The scroll-progress line in the same post is the same trick: a div clipped from the bottom, with `useScroll` mapped through `useTransform` from 100% to 0%, so it looks like an SVG being drawn. Below, press Toggle and watch the edge travel; nothing fades, the panel is uncovered in place. Then turn on the opacity comparison and watch the same panel dissolve with nothing for the eye to follow. > Figure 4. Clip-path reveal. Press Toggle and watch the edge of the shape move. The panel is not fading; it is being uncovered in place. Turn on the opacity comparison to see the same panel dissolve instead, with nothing for the eye to track.Illustrative numbers ### Tabs, theme switch, and a rule The tabs transition solves a problem color transitions never quite do: the active tab has a different text color, and animating the color while the highlight slides always feels slightly off. His fix is to duplicate the tab list, style the duplicate as active, clip it to the active tab, and animate the clip on change; `round 17px` keeps the pill’s corners. The result is seamless, “and we don’t have to worry about timing the color transition, which would never be seamless anyway.” He credits a tweet by Paco Coursey and recommends Radix Tabs underneath for accessibility. > Figure. CSSEmil Kowalski, The Magic of Clip Path In [Good vs Great Animations](https://emilkowal.ski/ui/good-vs-great-animations) he revisits it as knowing your tools: slow the tabs down and the highlight and the color change fail to agree; clip-path makes them agree. Back in 2021 he used the same reveal keyframes to animate a theme switch by duplicating the whole page, which he calls hacky; the View Transitions API now does it without duplication. Vercel’s security page uses the trick, and Tuple’s comparison could. The hold-to-delete pattern from his skill file is covered in [Friction](https://learn-ui.com/chapters/motion/friction). Source Reveal keyframes, useInView options, and the tabs clip are quoted from The Magic of Clip Path. The rule is short. When something must be revealed, wiped, or filled without the layout around it moving, reach for clip-path before height, width, or opacity. --- # Easing: where the speed goes · Motion Once something should move, the next decision is not how long it moves but where the speed goes. **Easing** (Easing, which describes the rate at which something changes over a period of time, is the most important part of any animation. (Emil Kowalski)) is the curve that distributes motion over time, and Emil Kowalski calls it, in [7 Practical Animation Tips](https://emilkowal.ski/ui/7-practical-animation-tips), “the most important part of any animation.” ### Ease-out is the default His justification is a demonstration. Two dropdowns open over an identical 300ms; the left uses ease-in, which starts slow, the right ease-out, which starts fast. The left feels slower, and nothing else differs. “That’s the difference easing makes.” **Ease-out** (A curve that starts fast and slows down at the end, which gives the impression of a quick response while keeping the transition smooth; Emil Kowalski's default for elements entering or exiting the screen.) accelerates at the beginning, and that early speed reads as responsiveness, so he uses it for anything entering or leaving the screen; in [Train Your Judgement](https://emilkowal.ski/ui/train-your-judgement) he adds that the gentle deceleration into place is what makes an entering toast elegant. Ease-in speeds up at the end, and “this easing is just not made for UI animations”; his [skill file](https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md) makes it a rule. **Ease-in-out** (A curve that accelerates and then decelerates, which Emil Kowalski recommends for something already on screen that moves or morphs, because the motion should mimic natural acceleration and deceleration like a car.) is for the third case: in [Good vs Great Animations](https://emilkowal.ski/ui/good-vs-great-animations) something already on screen that moves should accelerate and decelerate “just like a car.” Even so, default to ease-out. He collapsed those judgements into a flowchart, shown in [Agents with Taste](https://emilkowal.ski/ui/agents-with-taste) and in his post on building the course, strict on purpose: “It just follows the flowchart and picks the right easing according to my philosophy.” Plain ease survives as an exception for simple hover changes such as a background color. Source The 300ms ease-in versus ease-out dropdown is tip 4 of 7 Practical Animation Tips. The flowchart is quoted in Agents with Taste and in Building an animation course. > Figure. Easing Decision FlowchartEmil Kowalski, Agents with Taste ### Keywords are too weak The second thing Emil insists on: “The built-in easing curves in CSS are usually not strong enough, which is why I almost never use them.” Custom curves feel more energetic, and he points readers at easings.co and easing.dev. In the explorer below, start with the ease-out preset, then push the handles so the curve rises far more steeply at the start. Distance and time do not change; only the distribution does. > Figure 1. Easing explorer. Pick a CSS keyword, a named curve, or move the handles with the sliders, then play. The same distance in the same time feels different depending on where the speed goes. The named curves and their values are from easing.dev; Drawer is the Ionic curve Emil Kowalski uses in Vaul.Constants from the source ### Named curves and tokens [Easing Graphs](https://www.easing.dev/) (easing.dev), by Alex Vanderzon and Lochie Axon, lists 28 curves with their cubic-bezier values. Out Quint is `cubic-bezier(0.23, 1, 0.32, 1)`, the exact value Emil ships as `--ease-out`. In Out Quart, `cubic-bezier(0.77, 0, 0.175, 1)`, is his `--ease-in-out` and the curve behind his clip-path reveals. Snappy Out, `cubic-bezier(0.19, 1, 0.22, 1)`, is identical to Out Expo. Anticipate, `cubic-bezier(1, -0.4, 0.35, 0.95)`, dips below zero before it travels; Overshoot Out, `cubic-bezier(0.175, 0.885, 0.32, 1.275)`, passes its target and comes back; both are by Lochie Axon. The keyword `ease` is In Out Base, `cubic-bezier(0.25, 0.1, 0.25, 1)`. Emil’s third token, `--ease-drawer`, came from the Ionic Framework because it closely matches iOS. > Figure. CSSEmil Kowalski, emil-design-eng SKILL.md He also keeps a private set. His course ships 18 custom easings “that I use in my own projects,” and the first six are visible on the page about [building the course](https://emilkowal.ski/ui/building-an-animation-course). The names matter more than the numbers: a named curve gets reused, and reuse is what makes a product cohesive. > Figure. CSSEmil Kowalski, Building an animation course In [Great Animations](https://emilkowal.ski/ui/great-animations) he chooses against his own default: Sonner is a bit slower than usual and uses ease rather than ease-out, because that felt more elegant and matched the toast design, the page design, even the name. So: ease-out unless the element is already on screen, a named custom curve instead of a keyword, and the choice written down as a token. --- # Friction as a feature · Motion Emil Kowalski’s short essay [Friction as a Feature](https://emilkowal.ski/ui/friction-as-a-feature) begins with the consensus: “We treat friction as something bad. It makes us slow, inefficient, messy. Products brag about removing friction.” ### Friction in the act of building His argument is that **friction** (Resistance that slows an action down; Emil Kowalski argues it does a second job of forcing judgement, and in gestures he uses it so a drag slows and stops instead of halting abruptly.) was doing a second job all along: “it made us think before we built.” Before AI, code was expensive, so the cost of building set a threshold on which ideas survived. AI removed that cost, and the bar dropped with it. He is fair to the other side. Building A and B and comparing them often validates better than theorising, and “Prototyping is thinking.” But only if you validate, and with no friction nothing stops you shipping both. That is why people dislike the flood of vibe-coded apps and UI libraries: no friction forced a thought, so “They don’t feel designed, they just exist.” Friction forces judgement and filters the ideas that do not deserve to be built: “It’s a feature, not a bug.” He credits the framing to tweets by Swami and Drazen. Source The essay is about friction in the act of building. The interface examples that follow come from Building a Toast Component, Building a Drawer Component, and the emil-design-eng SKILL.md. ### Friction in gestures The same idea runs through the interfaces he builds, the one place in this chapter where motion slows someone down on purpose. In [Building a Toast Component](https://emilkowal.ski/ui/building-a-toast-component) he describes dragging a Sonner toast the wrong way: “you can still drag it, but it will slow down and eventually stop. It’s nicer than just stopping the toast immediately.” [Vaul](https://emilkowal.ski/ui/building-a-drawer-component) does the same at the top of a drawer: the drag is damped, so the more you pull the less it moves, because “things in real life don’t suddenly stop, they slow down first.” The skill file names the pattern in two lines, friction instead of hard stops and damping at boundaries; Rauno Freiberg’s Control Centre example is the same physics on iOS. Friction can also be the whole interaction. The skill file’s hold-to-delete pattern, also a course exercise, makes a deletion cost two seconds of sustained pressure: the fill transitions to `inset(0 0 0 0)` over 2s with linear timing, and if you let go early it snaps back in 200ms with ease-out. The slow fill gives the person time to notice and a cheap way out. > Figure. CSSIllustration ### Friction only in front of decisions Most of the time you are removing friction, and Emil is the first to say so. Raycast gets no animation in 2.1 because he wants to work “with no unnecessary friction.” Sonner’s swipe is momentum-based, so a fast flick dismisses even a short drag. Vaul lets you flick a drawer shut and skip snap points. Subsequent tooltips open instantly. > Figure. TypeScriptEmil Kowalski, Building a Toast Component The skill file’s asymmetric timing rule is the same judgement in one sentence: slow where the user is deciding, fast where the system is responding. Friction belongs in front of decisions, never in front of work. That is also the shape of the chapter. Animate less, and when something earns motion, mean it: an ease-out that lands gently, a duration that respects distance, a spring that survives interruption, a clip that reveals without shifting layout, a sequence that tells the user which layer they are touching, and a little friction exactly where a decision lives. Emil’s line from the toast post is the standard: the less users notice, the better, because it means the thing is intuitive. --- # Practical tips · Motion Emil Kowalski’s [7 Practical Animation Tips](https://emilkowal.ski/ui/7-practical-animation-tips) answers his own early belief that animation is an art you either get or you do not. The order is his. ### Tips 1 to 3: scale and tooltips One: scale your buttons. The interface “should feel as if it’s listening to the user,” and the cheapest feedback is `transform: scale(0.97)` on `:active`, which his skill file pairs with a 160ms ease-out transition. In [Train Your Judgement](https://emilkowal.ski/ui/train-your-judgement) 0.9, a tenth of the size, is too much: “If you can clearly see the button shrinking, the scale is too aggressive.” > Figure. CSSEmil Kowalski, emil-design-eng SKILL.md Two: do not animate from `scale(0)`. Start from 0.9 or above (his demo uses 0.93, his skill table 0.95): a deflated balloon still has a shape, and an element growing from nothing looks like it came out of nowhere. Three: do not delay subsequent tooltips. The first waits to prevent accidental activation; the next opens with no delay and no animation. Radix and Base UI skip the delay; Base UI’s `data-instant` lets you zero the transition too. > Figure. CSSEmil Kowalski, 7 Practical Animation Tips ### Tips 4 to 7: easing, origin, speed, blur Four is the easing argument from the last section, ease-out for enter and exit. Five: make popovers **origin-aware** (Animating an element out of its trigger, like a popover growing from the button that opened it instead of from its own center, which is the CSS default.). A dropdown should scale in from the button that opened it; the default `transform-origin: center` is wrong in most cases. Radix and Base UI expose variables for this and shadcn/ui wires them; modals keep the center origin because they have no trigger. Whether anyone notices matters less than you would think: “In the aggregate, unseen details become visible, they compound.” > Figure. CSSEmil Kowalski, 7 Practical Animation Tips Six: keep animations fast, which is 2.1 again (the spinner, 180ms versus 400ms, under 300ms), plus: remove animations or hover effects entirely if they are seen tens or hundreds of times a day. Seven: use blur when nothing else works. His demo crossfades a button between two states, once plain and once with 2px of `filter: blur()`; the blur “bridges the visual gap between the old and new states.” The skill file caps it under 20px; heavy blur is expensive, especially in Safari. Train Your Judgement adds two. Motion’s AnimatePresence keeps an exiting chip in flow until its animation ends, so siblings wait and then slide; `mode="popLayout"` pulls it out on the first frame so siblings move in parallel with the exit. And for anything toggled rapidly, prefer transitions over keyframes: keyframes jump mid-play, transitions retarget. Source Tips 1 through 7 follow the order of 7 Practical Animation Tips. The 0.9 versus 0.97 comparison, popLayout, and the interruption exercise are from the hidden breakdowns in Train Your Judgement. ### Stagger, short and ranked On **stagger** (Animating several sibling items one after another with a small delay between each, creating a cascade.) Emil keeps delays at 30 to 80ms, because long delays make the interface feel slow, and insists stagger is decorative: never block interaction while it plays. His hero exercise is about hierarchy: staggering every element with identical timing feels artificial, “the same effect on motion as a linear easing,” while the better version gives the title the most screen time and lets the least important element just fade. Rauno Freiberg, in [Designing Depth](https://rauno.me/craft/depth), reaches for nature: a school of fish mesmerises through slight timing differences among identical-looking things. OpenAI staggers the fade-in of grid content, which does not feel slower but stops the user wondering how many items changed; the iPhone unlock staggers the Home Screen apps and makes “a primitive swipe feel three-dimensional.” In the playground, watch the delay multiply by the count: pleasant for four rows, a drag for forty. > Figure 3. Stagger playground. Replay and watch the list enter. The per-item delay multiplies by the count, so a delay that feels right for four items drags for forty. The number shows how long the last item waits before it settles.Illustrative numbers ### Stagger only at first contact The boundary is frequency again. Rauno calls the Home Screen stagger a first point of contact, “a great moment to especially dial the novelty of animations up a notch,” and in [Novelty](https://rauno.me/craft/novelty) notes that iOS staggers it only after the first unlock and Paco Coursey’s site only on first load. Emil’s side-panel exercise is the negative case: a panel that slides in and then trickles its items is two layers of entrance, and the better version has the content simply there. “Sometimes the best animation is no animation.” --- # Springs and duration · Motion Duration is the part of an animation people argue about most and think about least. Emil Kowalski’s numbers are consistent across everything he has written, and when they run out he reaches for physics. ### The duration tables The rule of thumb from [You Don’t Need Animations](https://emilkowal.ski/ui/you-dont-need-animations) is under 300ms. The skill excerpt in [Agents with Taste](https://emilkowal.ski/ui/agents-with-taste) breaks that down. > Figure. Duration GuidelinesEmil Kowalski, Agents with Taste The fuller table in his [skill file](https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md) is more generous at the top: button press feedback 100 to 160ms, tooltips and small popovers 125 to 200ms, dropdowns and selects 150 to 250ms, modals and drawers 200 to 500ms, marketing animation longer. The course’s agent rules say it plainer: never longer than a second unless illustrative, most around 0.2s to 0.3s. ### Size and distance Two rules keep the table from being mechanical: larger elements animate slower, and duration should match distance. In [Train Your Judgement](https://emilkowal.ski/ui/train-your-judgement) a full-screen mobile menu at sub-300ms feels jarring because the distance is so much larger; bigger elements are heavier, “the same way a truck takes longer to stop than a bicycle.” His drawer, [Vaul](https://emilkowal.ski/ui/building-a-drawer-component), is the production example: 500ms, because that mimics the iOS sheet, with the Ionic curve from the last section. Source The duration tables are from the Agents with Taste skill excerpt and the emil-design-eng SKILL.md. The truck and bicycle line is the hidden breakdown of the first Train Your Judgement exercise. > Figure. CSSEmil Kowalski, Building a Drawer Component ### Springs instead of clocks The other way to set duration is to stop setting it. A **spring** (An animation described by physical parameters such as stiffness, damping, and mass rather than by a fixed duration, so it settles the way a real object would.) is described by physics rather than time; the skill file says springs feel more natural because they simulate real physics and settle by their parameters rather than a clock. In [Great Animations](https://emilkowal.ski/ui/great-animations) he points at the Dynamic Island, which “feels natural, almost like a living organism,” against web apps where changes happen instantly, which feels artificial because nothing around us appears or disappears instantly. He built a visualizer with stiffness, damping, and mass sliders for that post; the playground below is the same idea. Stiffness up tightens the curve; damping down makes it overshoot. > Figure 2. Spring playground. A spring has no duration. Its stiffness, damping, and mass decide how it settles, and the curve and the dot are the same equation. Move a slider, watch the curve, then play.Illustrative numbers ### Config, bounce, interruption His configurations are modest. The skill file gives two ways to write a spring in Motion: in time, or in physics. > Figure. TypeScriptEmil Kowalski, emil-design-eng SKILL.md Bounce, when used, stays at 0.1 to 0.3; avoid it in most UI and save it for drag-to-dismiss and playful interactions. Train Your Judgement makes it a matter of brand: a bouncy accordion feels approachable in a learning app and unserious in a finance app, so “no bounce should be your default.” In Good vs Great Animations a component that follows the mouse feels artificial when it snaps to the pointer, so he runs the value through `useSpring`, then qualifies it: that works because the effect is decorative, and a functional graph in a banking app should have no animation. The last reason to prefer springs and transitions over keyframes is that they can be **interrupted** (Able to be changed mid-flight: an animation that can smoothly retarget to a new value while it is still running instead of jumping or restarting.). In [Building a Toast Component](https://emilkowal.ski/ui/building-a-toast-component) Sonner first used keyframes, and when toasts were added quickly the older ones jumped to their new positions, because a keyframe cannot change its end value while it plays. CSS transitions “can be interrupted and retargeted, even before the first transition has finished,” so he switched. Train Your Judgement generalises it to menus, modals, accordions, and drawers; the skill file adds that springs keep their velocity when interrupted where keyframes restart from zero. Put together: start from the table, let distance and size pull the number, use a spring or transition for anything gesture-driven or rapidly toggled, keep bounce near zero, and time asymmetrically, “slow where the user is deciding, fast where the system is responding.” --- # You don't need animations · Motion Emil Kowalski opens [You Don’t Need Animations](https://emilkowal.ski/ui/you-dont-need-animations) by granting the case for motion before he takes most of it away. Done right, animations make an interface feel “predictable, faster, and more enjoyable to use.” Done wrong, they cost you the user’s trust. ### Every animation needs a job The first filter is whether the animation has a job: “Before you start animating, ask yourself: what’s the purpose of this animation?” A **purposeful animation** (An animation that exists to do a specific job for the user, such as explaining, giving feedback, or keeping space consistent, rather than to decorate.) can answer that in one sentence. His four examples cover different jobs. A marketing animation for Linear’s Product Intelligence explains the feature inside the first viewport. A subtle scale-down on button press gives feedback and “helps the interface feel more alive and responsive.” Sonner’s toast enters from the direction it later leaves, and that spatial consistency makes swipe-to-dismiss intuitive. The fourth is the honest one: a morphing feedback component exists to delight, which is fine “as long as the user will rarely interact with it.” ### Frequency decides That last example becomes the organising rule: “How often users will see an animation is a key factor in deciding whether to animate or not.” Emil uses Raycast hundreds of times a day; it has no launch animation, and he calls that optimal, because he opens it with a goal and does not need to be delighted. Keyboard-initiated actions, repeated hundreds of times a day, feel “slow, delayed, and disconnected” when animated, so “You should never animate them.” His [skill file](https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md) turns this into **frequency tiers** (Emil Kowalski's table that maps how often an interaction happens to how much animation it should get, from none at all to deliberate delight.). > Figure. SKILL.mdEmil Kowalski, emil-design-eng Rauno Freiberg arrived at the same place. In [Invisible Details of Interaction Design](https://rauno.me/craft/interaction-design) he admits he loves to animate everything, then notes that a command menu fade at hundreds of uses a day “does start to feel more like cognitive burden.” On bmrks.com he animated the active indicator and list items, found them sluggish after a couple of days even after making them snappier, and once removed “suddenly felt like I was moving much faster.” macOS context menus and the App Switcher never animate either; a keypress feels mechanical, so leaving motion out is not jarring. See [Frequency and novelty](https://learn-ui.com/chapters/invisible-details/frequency-and-novelty). Source The four examples and the frequency argument are in the “Purposeful animations” and “Frequency of use” sections of You Don’t Need Animations. The tier table is from his public design engineering skill file. ### Fast, and under 300ms The other half of the essay is speed. Outside marketing sites, animations have to be fast: they improve perceived performance and keep the interface connected to what the user just did. A faster-spinning spinner makes an app seem to load faster though load time is unchanged, and a 180ms dropdown feels more responsive than a 400ms one. His **duration rule of thumb** (Emil Kowalski's guideline that UI animations should generally stay under 300ms, with marketing and explanatory animation as the exception.) is under 300ms. > Figure. CSSIllustration Tooltips get a note: delay the first to prevent accidental activation, but once one is open the next should appear with no delay and no animation, which “feels faster without defeating the purpose of the initial delay.” shadcn, quoted in Emil’s post about his course, put it in one line: design engineering “is mostly deciding what not to animate.” The habit: before you add a transition, write down its purpose and estimate how many times a day the same person sees it. If the purpose is “it looks nice” and the count is high, delete it; the goal “is not to animate for animation’s sake, it’s to build great user interfaces.” The rest of this chapter is about the other case: real purpose, low count, made fast. --- # People The chapters read these people closely: their essays, their components, their sites. This page says who they are in their own words and points at the work, so you can go to the source instead of taking this book’s word for it. ## Rauno Freiberg [rauno.me](https://rauno.me) Staff Design Engineer at Vercel; previously The Browser Company (Arc). Estonian interaction designer; maker of Devouring Details. Describes himself as an Estonian interaction designer working with Vercel and Devouring Details. At Vercel he works on the platform, design system, marketing pages, and Next.js Dev Tools; before that he designed and built the Arc browser at The Browser Company. His craft page is a dated log of prototypes and production work going back to 2021, and his essays (Invisible Details of Interaction Design, Designing Depth, Novelty, Contrasting Aesthetics, Crafting the Next.js Website, What will you ship?) are the spine of Chapters 1, 2, 4, and 5. He also shipped cmdk with Paco Coursey, the Web Interface Guidelines, and Devouring Details, an interactive reference manual with 23 chapters and 23 downloadable React components. - [Invisible Details of Interaction Design](https://rauno.me/craft/interaction-design) - [Craft](https://rauno.me/craft) - [Designing Depth](https://rauno.me/craft/depth) - [Novelty](https://rauno.me/craft/novelty) - [Devouring Details](https://devouringdetails.com) - [Web Interface Guidelines](https://interfaces.rauno.me) - [History of Software Design](https://historyofsoftware.org) Read in[Invisible details](https://learn-ui.com/chapters/invisible-details)[Motion](https://learn-ui.com/chapters/motion)[Craft](https://learn-ui.com/chapters/craft)[Taste](https://learn-ui.com/chapters/taste) ## Emil Kowalski [emilkowal.ski](https://emilkowal.ski) Design engineer on the Web team at Linear; previously the design team at Vercel. Author of Sonner, Vaul, and animations.dev. Says he likes to build things for designers and developers and to think deeply about how an interface looks, feels, and behaves. At Vercel he developed the design system and dashboard; at Linear he works on the web team. He created Sonner, an opinionated toast component for React, and Vaul, a drawer component, which together are downloaded over ninety million times a week from npm. His course animations.dev opened for presale in January 2024 with a goal of a thousand students and has enrolled more than ten thousand. His essays on when not to animate, practical animation tips, clip-path, taste, and judgement anchor Chapters 2, 3, and 5. - [You Don't Need Animations](https://emilkowal.ski/ui/you-dont-need-animations) - [Building a Toast Component](https://emilkowal.ski/ui/building-a-toast-component) - [Developing Taste](https://emilkowal.ski/ui/developing-taste) - [Sonner](https://sonner.emilkowal.ski) - [Vaul](https://vaul.emilkowal.ski) - [animations.dev](https://animations.dev) Read in[Motion](https://learn-ui.com/chapters/motion)[Components](https://learn-ui.com/chapters/components)[Taste](https://learn-ui.com/chapters/taste) ## Maggie Appleton [maggieappleton.com](https://maggieappleton.com) Staff Research Engineer at GitHub Next; previously Lead Design Engineer at Normally, founding product designer at Elicit, Head of Design at HASH, illustrator and UX designer at Egghead. Introduces herself as a designer, anthropologist, and mediocre developer, sitting at the intersection of design, anthropology, and web development. Her work fits under design engineering, product design, and visual interface design, with cultural analysis, writing, and illustration on top. Her site is a digital garden of essays, notes, patterns, smidgeons, talks, and a library, designed and built by her in Astro and MDX, with growth stages from seedling to evergreen. Her note A Collection of Design Engineers is this book's starting definition of the role; her patterns catalogue and her essays on tools for thought and generative AI carry Chapters 6 and 7. - [A Collection of Design Engineers](https://maggieappleton.com/design-engineers) - [Tools for Thought as Cultural Practices](https://maggieappleton.com/tools-for-thought) - [Patterns](https://maggieappleton.com/patterns) - [The Dark Forest and Generative AI](https://maggieappleton.com/ai-dark-forest) - [A Brief History and Ethos of the Digital Garden](https://maggieappleton.com/garden-history) Read in[Introduction](https://learn-ui.com/chapters/introduction)[Explaining with interaction](https://learn-ui.com/chapters/explaining)[Canvases and tools for thought](https://learn-ui.com/chapters/canvases)[The career](https://learn-ui.com/chapters/career) ## Bartosz Ciechanowski [ciechanow.ski](https://ciechanow.ski) Author of interactive explanations at ciechanow.ski; supported on Patreon. Publishes long interactive articles that explain how things work by letting you drag them: Gears, Lights and Shadows, Cameras and Lenses, Internal Combustion Engine, Naval Architecture, Curves and Surfaces, GPS, Mechanical Watch, Sound, Bicycle, Airfoil, Moon, among others, plus earlier graphics programming posts from 2014. Each opens with a demo you can manipulate, switches between metric and imperial units, and ends with further reading and an invitation to support the next article on Patreon. Maggie Appleton lists him as not a design engineer by profession but a good example of blending design and engineering for educational content. Chapter 6 reads his method. - [Mechanical Watch](https://ciechanow.ski/mechanical-watch/) - [Gears](https://ciechanow.ski/gears/) - [GPS](https://ciechanow.ski/gps/) - [Moon](https://ciechanow.ski/moon/) - [Archives](https://ciechanow.ski/archives/) Read in[Explaining with interaction](https://learn-ui.com/chapters/explaining) ## Kathryn Gonzalez [www.ryngonzalez.com](https://www.ryngonzalez.com) Independent Design and Engineering Director; formerly DoorDash's first designer and frontend engineer, then Head of Design Infrastructure. Joined DoorDash in 2015 as its first designer and frontend engineer, led product design across Consumer and Merchant products, started DoorDash Drive, led frontend engineering, and then spent six years building and leading the Design Infrastructure organisation (design systems, design engineering, prototyping, accessibility), ending as a manager of managers over twenty-five people. Now works independently, offering fractional design and engineering leadership and hands-on execution to early-stage companies. Her essay The Attributes of a Design Engineer, her design systems writing, and her How to Build a Modal guide anchor Chapters 3 and 8. - [The Attributes of a Design Engineer](https://www.ryngonzalez.com/blog/the-attributes-of-a-design-engineer) - [Design Systems and Infrastructure](https://www.ryngonzalez.com/blog/design-systems-and-infrastructure) - [Design Systems in Transition](https://www.ryngonzalez.com/blog/design-systems-in-transition-anxiety-ai-and-where-we-go) Read in[Introduction](https://learn-ui.com/chapters/introduction)[Components](https://learn-ui.com/chapters/components)[The career](https://learn-ui.com/chapters/career) ## Jim Nielsen [blog.jim-nielsen.com](https://blog.jim-nielsen.com) Web designer and developer who identifies closest to "design engineer"; blogging for fifteen years, more than eight hundred posts. Has blogged for fifteen years and more than eight hundred posts about HTML, CSS, the web as a medium, design process, and the design engineer role. Holds an interdisciplinary degree that was more graphic design than programming, and writes that Design Engineer has come to feel like the right fit because it is deliberately cross-discipline. Collects iOS and macOS app icons and helped turn the collection into a book. His three-part The Case for Design Engineers, Coding Is Designing, Out With the JS In With the HTML, Sanding UI, and The AI Aesthetic run through Chapters 4, 5, and 8. - [The Case for Design Engineers](https://blog.jim-nielsen.com/2022/the-case-for-design-engineers/) - [Out With the JS, In With the HTML](https://blog.jim-nielsen.com/2026/out-with-js-in-with-html/) - [Sanding UI](https://blog.jim-nielsen.com/2024/sanding-ui/) - [The AI Aesthetic](https://blog.jim-nielsen.com/2026/ai-aesthetic/) - [jim-nielsen.com](https://www.jim-nielsen.com) Read in[Introduction](https://learn-ui.com/chapters/introduction)[Craft](https://learn-ui.com/chapters/craft)[Taste](https://learn-ui.com/chapters/taste)[The career](https://learn-ui.com/chapters/career) ## Paco Coursey [paco.me](https://paco.me) Webmaster at Linear; previously developed the Vercel design system, website, and dashboard. Author of cmdk and next-themes. Describes his work as crafting interfaces, building polished software and web experiences, and experimenting with magical details in user interfaces. His site is set in Inter, Söhne, and Newsreader and built with Next.js with JavaScript disabled because you do not need it to read documents. He wrote cmdk, the composable command menu component, and next-themes for dark mode without a flash, and keeps a craft page of implemented interactions. His posts on the 2021 redesign, disabling transitions on theme toggle, and rem versus px feed Chapters 3 and 4. - [cmdk](https://cmdk.paco.me) - [next-themes](https://github.com/pacocoursey/next-themes) - [Redesign 2021](https://paco.me/writing/redesign-2021) - [Craft](https://paco.me/craft) Read in[Components](https://learn-ui.com/chapters/components)[Craft](https://learn-ui.com/chapters/craft)[The career](https://learn-ui.com/chapters/career) ## Steve Ruiz [steveruiz.me](https://steveruiz.me) Founder of tldraw (infinite canvas SDK for React, Series A, London); previously Play and Framer. Author of perfect-freehand and perfect-arrows. A developer, designer, and startup founder in London with a background in visual art who works primarily in creative tools for the web, builds lots of prototypes, and notes that some of those prototypes turn into products. Formed tldraw in 2022 around his infinite canvas SDK; its demo at tldraw.com became an end-user application with close to half a million monthly active users. Earlier he helped design a mobile-first design app at Play and made educational content for Framer. His open source includes perfect-freehand, perfect-arrows, globs, and state-designer. Chapter 7 reads his engineering posts and the stroke algorithm. - [tldraw](https://tldraw.dev) - [perfect-freehand](https://github.com/steveruizok/perfect-freehand) - [perfect-arrows](https://github.com/steveruizok/perfect-arrows) - [make real, the story so far](https://tldraw.dev/blog/make-real-the-story-so-far) Read in[Canvases and tools for thought](https://learn-ui.com/chapters/canvases) ## Amelia Wattenberger [wattenberger.com](https://wattenberger.com) Principal Research Engineer exploring novel UIs and ML on the R&D team at GitHub (GitHub Next); author of Fullstack D3 and Data Visualization. Says she creates things on the web, explores novel interfaces, turns data into meaning, and empowers developers with AI. At GitHub Next she has built Code Atlas, Copilot for Docs, Brushes in Copilot Labs, GitHub Blocks, collaborative coding workspaces, and codebase visualisations. Her book and course Fullstack D3 and Data Visualization distil ten years of visualising data. Her essays (Why Chatbots Are Not the Future, Our interfaces have lost their senses, Fish eye for text, LLMs as a tool for thought, Evolving the infinite canvas) are read in Chapters 6 and 7. - [Why Chatbots Are Not the Future](https://wattenberger.com/thoughts/boo-chatbots) - [Fullstack D3 and Data Visualization](https://www.newline.co/fullstack-d3) - [GitHub Next](https://githubnext.com) Read in[Explaining with interaction](https://learn-ui.com/chapters/explaining)[Canvases and tools for thought](https://learn-ui.com/chapters/canvases) ## Andrew Swank [andrewswank.com](https://andrewswank.com) Designer and engineer at the intersection of business outcomes, design, and product engineering; formerly UX Engineer at Google. Describes himself as a designer and engineer by design who guides cross-functional teams to build products with impact for users and organisations. At Google, as a UX Engineer, he built the voice prototyping toolkit that let Assistant designers prototype without code and was used for more than eight thousand voice prototypes, and the Google Flights mobile datepicker that became the Material Design standard. His own site is built from scratch as a demonstration: viewport-based sizing with vmin and rem, max() and round() to snap to a four pixel grid, HSL variables for colour animation, and a variable font animated with font-variation-settings. Chapters 4 and 8 read it. - [Improving Access to Voice-based Prototyping](https://andrewswank.com/project/assistant/) - [Google Flights Mobile Datepicker](https://andrewswank.com/project/datepicker/) Read in[Craft](https://learn-ui.com/chapters/craft)[The career](https://learn-ui.com/chapters/career) 10 people Roles and descriptions are taken from each person’s own site at the time of writing. Their sites are the primary sources; this page is a map, not a substitute. --- # Further reading The primary sources. Anything worth understanding properly is better read there than summarized here, and most of these are readable in an evening. ## Essays and talks The writing and talks the chapters draw on. - [*7 Practical Animation Tips*Emil Kowalski's seven tricks: button scale, no scale(0), instant subsequent tooltips, easing, transform-origin, speed, and blur.](https://emilkowal.ski/ui/7-practical-animation-tips) - [*A Brief History & Ethos of the Digital Garden*Maggie Appleton, 2020: the history of digital gardens and the six patterns of gardening.](https://maggieappleton.com/garden-history) - [*A Sloppy Interface Is a Security Liability*Jim Nielsen, 2026; interface quality as a security control against impersonation.](https://blog.jim-nielsen.com/2026/sloppy-ui-is-security-liability/) - [*A Subtle Nicety of Fault Tolerance in HTML & CSS*Jim Nielsen, 2024; prefixing a CSS rule with a character to toggle it while prototyping.](https://blog.jim-nielsen.com/2024/fault-tolerance-html-css/) - [*A Treatise on AI Chatbots Undermining the Enlightenment*Maggie Appleton, 2025: on chatbot sycophancy and the case for more critical interfaces.](https://maggieappleton.com/ai-enlightenment) - [*Agents with Taste*Emil Kowalski on packaging animation judgement into skill files, with his easing flowchart and duration tables.](https://emilkowal.ski/ui/agents-with-taste) - [*Airfoil*Bartosz Ciechanowski, 2024: the physics of flight, with flow fields you can drop markers into.](https://ciechanow.ski/airfoil/) - [*Ambient Co-presence*Maggie Appleton, 2023: a pattern for a subtle, peripheral sense of shared space on the web.](https://maggieappleton.com/ambient-copresence) - [*An exhaustive review of design tool hover areas*Steve Ruiz, 2026: a scripted survey of selection hit areas across tldraw, Figma, Excalidraw, Miro, Spline, and Rive.](https://tldraw.dev/blog/a-review-of-design-tool-hover-areas) - [“Apple Human Interface Guidelines (1987)”Apple, 1987; the original HIG, listed in Rauno's resources.](https://andymatuschak.org/files/papers/Apple%20Human%20Interface%20Guidelines%201987.pdf) - [*As Good as HTML*Jim Nielsen, 2023; HTML's composability as a quality bar for components.](https://blog.jim-nielsen.com/2023/as-good-as-html/) - [*Aspect Ratio Changes With CSS View Transitions*Jim Nielsen, 2025; a subtle outline bug and the one-line fix from Jake Archibald.](https://blog.jim-nielsen.com/2025/aspect-ratio-in-css-view-transitions/) - [*Back to Content*Steve Ruiz and Ani Krishnan, 2026: a 20-month bug from confusing not-visible shapes with culled shapes.](https://tldraw.dev/blog/back-to-content) - [*Bicycle*Bartosz Ciechanowski, 2023: the invisible forces that make a bicycle ride, built up from a wooden box and a slider.](https://ciechanow.ski/bicycle/) - [*Bridging the hard and the soft*Amelia Wattenberger: rigid and flexible interface parts, with strategies borrowed from nature.](https://wattenberger.com/thoughts/hard-and-soft) - [*Building a drawer component*Emil Kowalski on Vaul: the iOS sheet curve and 500 ms duration, drag performance, scroll guards, snap points, and the theme-color bar experiment.](https://emilkowal.ski/ui/building-a-drawer-component) - [*Building a Toast Component*Emil Kowalski's account of building Sonner: naming, the stacking animation, transitions over keyframes, momentum swipe, and the Observer pattern.](https://emilkowal.ski/ui/building-a-toast-component) - [*Building an animation course*Emil Kowalski's behind-the-scenes of animations.dev, including the easing flowchart and his 18 custom easings.](https://emilkowal.ski/ui/building-an-animation-course) - [*Building Websites With LLMS*Jim Nielsen, 2025; lots of little HTML pages linked and enhanced with cross-document view transitions.](https://blog.jim-nielsen.com/2025/lots-of-little-html-pages/) - [*Cameras and Lenses*Bartosz Ciechanowski, 2020: a camera built from first principles, sensor first.](https://ciechanow.ski/cameras-and-lenses/) - [*cmdk ARCHITECTURE.md*Paco Coursey's notes on the compound-component constraint behind cmdk and the alternatives he rejected.](https://github.com/pacocoursey/cmdk/blob/main/ARCHITECTURE.md) - [*Code was our medium for thought*Amelia Wattenberger: what agentic coding loses when code stops being where thinking happens.](https://wattenberger.com/thoughts/code-is-a-medium-for-thought) - [*Coding Is Designing*Jim Nielsen, 2026; a short post arguing code is a way to find a design, not just implement one.](https://blog.jim-nielsen.com/2026/code-is-design/) - [*Color Spaces*Bartosz Ciechanowski, 2019: RGB color spaces explained by playing with two color pickers that disagree.](https://ciechanow.ski/color-spaces/) - [*Command K Bars*Maggie Appleton's 2022 pattern write-up: what command bars are, why they scale where GUIs do not, and the apps that use them.](https://maggieappleton.com/command-bar) - [*Computational Notebooks*Maggie Appleton, 2023: a pattern for shareable, browser-based documents that run code.](https://maggieappleton.com/computational-notebooks) - [*Contrasting Aesthetics*Rauno Freiberg, January 2024, on aesthetic intersections and how the right amount of contrast invites curiosity.](https://rauno.me/craft/contrasting-aesthetics) - [*Craft and beauty: The business value of form in function*Stripe Sessions 2024 talk cited by Emil Kowalski for the commoditisation argument.](https://stripe.com/sessions/2024/craft-and-beauty-the-business-value-of-form-in-function) - [*Craft and Satisfaction*Jim Nielsen, 2025, asking whether AI help changes how much you care about what you made.](https://blog.jim-nielsen.com/2025/craft-and-satisfaction/) - [*Crafting the Next.js Website*Rauno Freiberg, 2023; grid lines, switchboard, focus rings, serif quotes, clamp, and gradient tracing from the Next.js site.](https://rauno.me/craft/nextjs) - [*Creating a Zoom UI*Steve Ruiz, 2021: the canvas, camera, screen, and viewport model and the math for pan and zoom.](https://steveruiz.me/posts/zoom-ui) - [*Creative Output*Paco Coursey, 2019, on being unhappy with his own work, remixing, and the inspiration phase.](https://paco.me/writing/creative-output) - [*Curves and Surfaces*Bartosz Ciechanowski, 2021: Bezier curves, splines, and subdivision surfaces through draggable control points.](https://ciechanow.ski/curves-and-surfaces/) - [*Custom text underlines*Paco Coursey, 2020; linear-gradient underlines with position, weight, dashes, and descender skipping.](https://paco.me/writing/custom-text-underlines) - [*Daily Notes Pages*Maggie Appleton, 2022: a pattern for frictionless daily capture in knowledge tools.](https://maggieappleton.com/daily-notes) - [*Dead Zone Dragging*Steve Ruiz, 2021: a minimum distance before a drag begins, built as a three-state machine.](https://steveruiz.me/posts/dead-zone) - [*Debugging a physical race condition with modifier keys*Steve Ruiz and Ani Krishnan, 2026: a 150ms release delay for modifier keys.](https://tldraw.dev/blog/adding-delays-to-modifier-keys) - [*Design engineer*Jeremy Keith, 2021; embracing the title despite misgivings about the word engineer.](https://adactio.com/journal/17838) - [*Design Engineering at Vercel*Glenn Hitchcock, Henry Heffernan, John Pham, Rauno Freiberg, and Yasmin Pessoa, 2024; what Vercel's design engineers care about and how the work is organised.](https://vercel.com/blog/design-engineering-at-vercel) - [“Design Engineering Handbook”Natalya Shelburne, Adekunle Oduye, Kim Williams, and Eddie Lou, 2020; the InVision PDF that Voisen calls the most thorough resource on the role.](https://marketing.invisionapp-cdn.com/www-assets.invisionapp.com/epubs/InVision_DesignEngineeringHandbook.pdf) - [*Design engineering, a working definition*Sean Voisen; the three activities of design engineering, from running the practice inside Adobe Design.](https://sean.voisen.org/writing/design-engineering-working-definition) - [*Design Engineers*Chris Coyier, Frontend Masters blog, 2024; the engineer half and the design half, and a vote for Web Design Engineer.](https://frontendmasters.com/blog/design-engineers/) - [*Design Leadership Interview at DoorDash*Kathryn Gonzalez, 2020; how the Design Infrastructure team came about and what she looked for when hiring.](https://www.ryngonzalez.com/blog/design-leadership-interview-at-doordash) - [*Design Systems and Infrastructure*Kathryn Gonzalez, 2018; what Design Infrastructure at DoorDash does and why it is a home for people who love both sides.](https://www.ryngonzalez.com/blog/design-systems-and-infrastructure) - [*Design Systems in Transition: Anxiety, AI, and Where We Go*Kathryn Gonzalez, Config 2023 talk; busywork, the extra ten percent, and design systems as the language AI tools consume.](https://www.ryngonzalez.com/blog/design-systems-in-transition-anxiety-ai-and-where-we-go) - [*Designing Between the Lines*Jim Nielsen, 2021; design the relationships between things, not just the things.](https://blog.jim-nielsen.com/2021/designing-between-the-lines/) - [*Designing Depth*Rauno Freiberg's 2024 essay on dirtying the frame, blurred backdrops, choreography, staggering, and affordance through motion.](https://rauno.me/craft/depth) - [*Designing Fluid Interfaces*C. Karunamuni, N. Vries, M. Alonso, WWDC 2018; Apple's session listed in Rauno's resources.](https://developer.apple.com/videos/play/wwdc2018/803/) - [*Designing Search for DoorDash*Kathryn Gonzalez, 2015; the article she says got her the most important job of her life.](https://www.ryngonzalez.com/blog/designing-search-for-doordash) - [*Developing Taste*Emil Kowalski on why taste matters and how to train it: exposure, analysis, practice.](https://emilkowal.ski/ui/developing-taste) - [*Disable transitions on theme toggle*Paco Coursey, 2020, on temporarily removing all CSS transitions while switching themes and forcing a repaint with getComputedStyle.](https://paco.me/writing/disable-theme-transitions) - [*Engineering imperfection with draw shapes*Steve Ruiz, 2026: seeded randomness, multi-pass strokes, and corner rounding for hand-drawn shapes.](https://tldraw.dev/blog/engineering-imperfection-with-draw-shapes) - [*Erasing shapes*Steve Ruiz, 2026: treating eraser input as line segments to avoid tunneling.](https://tldraw.dev/blog/erasing) - [*Evolving the infinite canvas*Amelia Wattenberger: proposals for hardcoding spatial behaviours and Gestalt rules into canvases.](https://wattenberger.com/thoughts/evolving-the-infinite-canvas) - [*Exposing Floating Point*Bartosz Ciechanowski, 2019: IEEE 754 floating point, a companion to his tool float.exposed.](https://ciechanow.ski/exposing-floating-point/) - [*Figma's Interactive Components Were Not Designed For This*Steve Ruiz, 2021: what Figma prototypes could not model and why the constraints are useful.](https://steveruiz.me/posts/it-wasnt-made-to-do-that) - [*Fish eye for text*Amelia Wattenberger: focus and context at once, from maps to Wikipedia to the code editor.](https://wattenberger.com/thoughts/fish-eye) - [*Fixing the Drift in Shape Rotations*Steve Ruiz, 2021: why rotating a selection back leaves it elsewhere, and the held-pivot fix.](https://steveruiz.me/posts/rotating-shapes) - [*Folk Interfaces*Maggie Appleton, 2022: a pattern for people reappropriating software to solve their own problems.](https://maggieappleton.com/folk-interfaces) - [*Friction as a Feature*Emil Kowalski's short essay arguing that friction forces judgement and filters ideas that do not deserve to be built.](https://emilkowal.ski/ui/friction-as-a-feature) - [*Gas Town's Agent Patterns, Design Bottlenecks, and Vibecoding at Scale*Maggie Appleton, January 2026, on Steve Yegge's vibecoded system as design fiction and why design becomes the bottleneck.](https://maggieappleton.com/gastown) - [*Gathering Structures*Maggie Appleton, 2024: structures for running meetups and communities, from the London Future of Coding meetup.](https://maggieappleton.com/gathering-structures) - [*Gears*Bartosz Ciechanowski, 2020: an interactive article on rotational motion, torque, and tooth shape.](https://ciechanow.ski/gears/) - [*Get the browser default font size*Paco Coursey, 2023; read the browser default with font-size: medium.](https://paco.me/writing/browser-default-font-size) - [*Getting creative with embeddings*Amelia Wattenberger, 2023: using embeddings to place sentences on interpretable scales in a writing app.](https://wattenberger.com/thoughts/yay-embeddings-math) - [*Good Design*Jim Nielsen, 2022; good design for who, and a priority of constituencies.](https://blog.jim-nielsen.com/2022/good-design/) - [*Good vs Great Animations*Emil Kowalski's practical tips for going from good to great: origin, easing, custom curves, springs, knowing your tools.](https://emilkowal.ski/ui/good-vs-great-animations) - [*Good Writers*Paco Coursey, 2019, learning to recognise good writing by pulling apart a first sentence.](https://paco.me/writing/good-writers) - [*Goodbye, DoorDash*Kathryn Gonzalez, 2023; leaving after almost eight years, from an old animal hospital to a post-IPO product.](https://www.ryngonzalez.com/blog/goodbye-doordash) - [*Gotchas in Naming CSS View Transitions*Jim Nielsen, 2025; what a view-transition-name custom-ident can and cannot contain.](https://blog.jim-nielsen.com/2025/view-transition-name-gotchas/) - [*GPS*Bartosz Ciechanowski, 2022: builds a positioning system from a draggable figurine up to trilateration and satellite signals.](https://ciechanow.ski/gps/) - [*Great Animations*Emil Kowalski's principles for animations that feel natural, fast, purposeful, performant, interruptible, and accessible.](https://emilkowal.ski/ui/great-animations) - [*Historical Trails*Maggie Appleton, 2023: a pattern for showing people where they have been on a branching journey.](https://maggieappleton.com/historical-trails) - [*How Do You Want to Live?*Kathryn Gonzalez, 2023; a travel essay on what comes after the role.](https://www.ryngonzalez.com/blog/how-do-you-want-to-live) - [*How to Build a Modal*Kathryn Gonzalez, 2017, on what a design-system modal really takes: stacking contexts, focus management, scroll locking, and real-device testing.](https://www.ryngonzalez.com/blog/how-to-build-a-modal) - [*Interdisciplinary Website Maker*Jim Nielsen, 2024; how interviewers react to a designer who codes, and why Design Engineer almost fits.](https://blog.jim-nielsen.com/2024/interdisciplinary-website-maker/) - [*Invisible Details of Interaction Design*Rauno Freiberg's 2023 essay; its Frequency and Novelty section argues that command menus used hundreds of times a day should not animate.](https://rauno.me/craft/interaction-design) - [*Job Screening Blog Post*Jim Nielsen, 2024; two GIFs, a heading that shifts by one pixel, and one question: do you care?](https://blog.jim-nielsen.com/2024/design-engineer-job-screener/) - [*Language Model Sketchbook, or Why I Hate Chatbots*Maggie Appleton, 2023: sketches of non-chat interfaces to language models.](https://maggieappleton.com/lm-sketchbook) - [*Lights and Shadows*Bartosz Ciechanowski, 2020: light, power, angles, and shadows in a scene you can drag around.](https://ciechanow.ski/lights-and-shadows/) - [*LLMs as a tool for thought*Amelia Wattenberger: language models as a brainstorming partner rather than a way to steer somewhere.](https://wattenberger.com/thoughts/llms-as-a-tool-for-thought) - [*make real, the story so far*Steve Ruiz, 2023: how Make Real came about and what putting generated websites back on the canvas showed.](https://tldraw.dev/blog/make-real-the-story-so-far) - [*Making Films and Making Websites*Jim Nielsen, 2024; the only source of truth is the website people use; everything else is a tool in service of it.](https://blog.jim-nielsen.com/2024/making-films-and-making-websites/) - [*Mechanical Watch*Bartosz Ciechanowski, 2022: a watch movement you can rotate and slice open, explained part by part.](https://ciechanow.ski/mechanical-watch/) - [*Moon*Bartosz Ciechanowski, 2024: the Moon, orbits, tides, and eclipses, starting from a draggable sky.](https://ciechanow.ski/moon/) - [*Novelty*Rauno Freiberg's 2026 essay on how much novelty an interface can carry, including first-load-only staggers.](https://rauno.me/craft/novelty) - [*On Design Engineering: I think I might be a design engineer*Trys Mudford, 2021; finding the name in the Design Engineering Handbook, the design to engineering gulf, and CSS as the primary language.](https://www.trysmudford.com/blog/i-think-im-a-design-engineer/) - [*On taste, part 3*Julie Zhuo's essay, cited by Emil Kowalski for building a curated list of tastemakers.](https://medium.com/the-year-of-the-looking-glass/on-taste-part-3-d7d9f069f0b2) - [*Our interfaces have lost their senses*Amelia Wattenberger: a case for multimodal interfaces and tangible artifacts over chat logs.](https://wattenberger.com/thoughts/our-interfaces-have-lost-their-senses) - [*Out With the JS, In With the HTML*Jim Nielsen, 2026; replacing a JS resize widget with four pre-rendered pages and view transitions.](https://blog.jim-nielsen.com/2026/out-with-js-in-with-html/) - [*Perfect Dragging*Steve Ruiz, 2021: why a drag should use the delta from its origin, not the last pointer event.](https://steveruiz.me/posts/perfect-dragging) - [*Personal Website, Personal Shrine*Kathryn Gonzalez, 2023; why she rebuilt her site, the three principles behind it, and the sites that inspired it.](https://www.ryngonzalez.com/blog/personal-website-personal-shrine) - [*Programmable Notes*Maggie Appleton, 2022: a pattern for note systems that run user-written rules and prompts.](https://maggieappleton.com/programmatic-notes) - [*Programming Portals*Maggie Appleton, 2022: a pattern for small, scoped programming areas inside graphical interfaces.](https://maggieappleton.com/programming-portals) - [*Putting knowledge in its place*Amelia Wattenberger: on giving the human user context around an answer, not just the model.](https://wattenberger.com/thoughts/this-is-not-a-rant-about-chatbots) - [*px vs rem in font-size*Paco Coursey, 2022; rem only matters if you respect browser font scaling.](https://paco.me/writing/px-vs-rem) - [*Quality Means The Flexibility to Change*Jim Nielsen, 2024; quality as ease of change, via Dave Farley and Ben Nadel.](https://blog.jim-nielsen.com/2024/easy-changes/) - [*Redesign 2021*Paco Coursey, 2021; stripping a personal site down to documents and links in the name of performance, simplicity, and craft.](https://paco.me/writing/redesign-2021) - [*Redesigning the laser tool for better annotations*Steve Ruiz, 2026: from a self-consuming polyline to grouped fading scribbles.](https://tldraw.dev/blog/redesigning-lasers) - [*Reminder: You Can Stitch Together Lots of Little HTML Pages With Navigations For Interactions*Jim Nielsen, 2026; post-mortem on the multi-page approach, including the history.back() menu close.](https://blog.jim-nielsen.com/2026/small-html-pages/) - [*Reordering Part 1: Arrays*Steve Ruiz, 2022: Send to Back, Bring Forward and friends as array operations.](https://steveruiz.me/posts/reordering) - [*Reordering Part 2: Tables and Fractional Indexing*Steve Ruiz, 2022: fractional indices for ordering items in tables and multiplayer documents.](https://steveruiz.me/posts/reordering-fractional-indices) - [*Safari favicon showing white background on dark mode*Paco Coursey, 2023, on Safari's favicon contrast behaviour and the colour change that fixed Linear's icon.](https://paco.me/writing/safari-favicon-showing-white-background) - [*Sanding UI*Jim Nielsen, 2024; build, click around a ton, tweak, repeat, and the dead click zone a flexbox gap left behind.](https://blog.jim-nielsen.com/2024/sanding-ui/) - [*Sanding UI, pt. II*Jim Nielsen, 2025; an SVG selected as text, fixed with user-select: none.](https://blog.jim-nielsen.com/2025/sanding-ui-pt-ii/) - [*Should you pursue a career in design engineering?*Sean Voisen on the Adobe Design blog; the role at Adobe, T-shaped people, and three ways to get started.](https://adobe.design/stories/leading-design/should-you-pursue-a-career-in-design-engineering) - [*Some Miscellaneous Thoughts on Visual Design Prodded By The Sameness of AI Company Logos*Jim Nielsen, 2025, on homogeneity at scale and why the work of individuals and small teams keeps its soul.](https://blog.jim-nielsen.com/2025/visual-design-homogeneity-at-scale/) - [*Sound*Bartosz Ciechanowski, 2022: air, pressure waves, and tones you play on little keyboards.](https://ciechanow.ski/sound/) - [*Stay away from my trash!*Steve Ruiz, 2026: why tldraw began closing external pull requests after an influx of AI-generated ones.](https://tldraw.dev/blog/stay-away-from-my-trash) - [*SVG Caching with *Paco Coursey, 2020; reuse rendered icon DOM with SVG use and hashed ids.](https://paco.me/writing/svg-caching-with-use) - [*Taste is Eating Silicon Valley*Anu Atluru's essay, quoted by Emil Kowalski: in a world of abundance, we treasure taste.](https://www.workingtheorys.com/p/taste-is-eating-silicon-valley) - [*Text is not enough*Steve Ruiz, 2026: tldraw's MCP App puts a canvas inside a conversation with an agent.](https://tldraw.dev/blog/text-is-not-enough) - [*The AI Aesthetic*Jim Nielsen, 2026, cataloguing the design idioms of the AI moment: sparkles, streaming and shimmering text, tiny icons, cream and orange and serif.](https://blog.jim-nielsen.com/2026/ai-aesthetic/) - [*The Attributes of a Design Engineer*Kathryn Gonzalez, 2024; her definition of the role after building the practice at DoorDash: autonomy, craft, and fidelity.](https://www.ryngonzalez.com/blog/the-attributes-of-a-design-engineer) - [*The Browser Company on the novelty tax*Video cited by Rauno Freiberg in Novelty; Arc as a saxophone that was hard to turn into a piano.](https://www.youtube.com/watch?v=pzF7S8zc1IQ&t=652s) - [*The Case for Design Engineers*Jim Nielsen, 2022; why the artifact explosion of responsive design makes design engineers worth their weight in gold.](https://blog.jim-nielsen.com/2022/the-case-for-design-engineers/) - [*The Case for Design Engineers, Pt. II*Jim Nielsen, 2024; a draggable divider shows why look and feel cannot be specced in a design tool.](https://blog.jim-nielsen.com/2024/the-case-for-design-engineers-pt-ii/) - [*The Case for Design Engineers, Pt. III*Jim Nielsen, 2024; Christopher Nolan's Writer/Director credit and why the creative process is not an assembly line.](https://blog.jim-nielsen.com/2024/the-case-for-design-engineers-pt-iii/) - [*The curious case of user interfaces*Rasmus Andersson, Figma, 2023; a talk listed in Rauno's resources.](https://www.youtube.com/watch?v=76b3c_ssyPQ&ab_channel=Figma) - [*The Dark Forest and Generative AI*Maggie Appleton, 2022: proving you are human on a web flooded with generated content.](https://maggieappleton.com/ai-dark-forest) - [*The Figma to Browser Chasm*Jim Nielsen, 2023; a Figma file is only as good as its implementation.](https://blog.jim-nielsen.com/2023/figma-to-browser-chasm/) - [*The Gulf Between Design and Engineering*Rune Madsen, Design Systems International; the design handover as the root cause, and code as the real design product.](https://designsystems.international/ideas/the-gulf-between-design-and-engineering/) - [“The information capacity of the human motor system in controlling the amplitude of movement”Paul Morris Fitts, 1954; the paper behind Fitts's law.](https://en.wikipedia.org/wiki/Fitts%27s_law) - [*The Magic of Clip Path*Emil Kowalski's guide to animating with clip-path: comparison sliders, image reveals, scroll progress, and tabs.](https://emilkowal.ski/ui/the-magic-of-clip-path) - [*The origins of design engineering*David Luhr, 2024; a timeline of the term from Coyier's Great Divide and Shelburne's 2019 talk to the 2024 job listings.](https://luhr.co/blog/2024/02/26/the-origins-of-design-engineering/) - [*The Taste Gap (Ira Glass)*Clip of Ira Glass on the gap between taste and ability, posted by Emil Kowalski and cited in Developing Taste.](https://x.com/emilkowalski/status/1765004718131068971) - [*The Tension Between Logical Reasoning & Illogical Creativity*Jim Nielsen, 2023; design engineers hold the logic of code and the illogic of ideation in balance.](https://blog.jim-nielsen.com/2023/logic-of-code-and-illogic-of-creativity/) - [*The Tumultuous Evolution of the Design Profession*Jim Nielsen, 2025; on Elizabeth Goodspeed's essay, profit margins, and the optics of building.](https://blog.jim-nielsen.com/2025/tumult-in-design/) - [*The Unseen Work of Design*Jim Nielsen, 2021; the final product is discovered through unseen refinement.](https://blog.jim-nielsen.com/2021/unseen-work-of-design/) - [*Tools for Thought as Cultural Practices, not Computational Objects*Maggie Appleton, 2021: a historical and anthropological reading of the tools for thought field.](https://maggieappleton.com/tools-for-thought) - [*Train Your Judgement*Emil Kowalski's side-by-side exercises on duration, easing, scale, stagger, popLayout, interruptions, and layered motion.](https://emilkowal.ski/ui/train-your-judgement) - [“Understanding Interaction Design Practices”E. Goodman, E. Stolterman, R. Wakkary, CHI 2011; the paper Rauno cites on treating practice as a black box.](https://summit.sfu.ca/_flysystem/fedora/sfu_migrate/15215/2011_CHI_Understanding_Goodman_vy-edited.pdf) - [*Vibe Code is Legacy Code*Maggie Appleton, August 2025, agreeing with Steve Krouse that vibe code is code nobody understands.](https://maggieappleton.com/2025-08-vibe-legacy-code) - [*View transitions: Handling aspect ratio changes*Jake Archibald, 2024; explains and fixes aspect ratio changes in view transitions.](https://jakearchibald.com/2024/view-transitions-handling-aspect-ratio-changes/) - [*Visualizing Fitts's Law*Kevin Hale, 2010; an illustrated article on the law, listed in Rauno's resources.](http://www.particletree.com/features/visualizing-fittss-law/) - [*What will you ship?*Rauno Freiberg with Glenn, Henry, and Alasdair, 2023; shipping the Vercel homepage with performance and constraint as north stars.](https://rauno.me/craft/vercel) - [*Why Chatbots Are Not the Future*Amelia Wattenberger, 2023: the case for tools with affordances and controls instead of a bare text box.](https://wattenberger.com/thoughts/boo-chatbots) - [*Why do AI company logos look like buttholes?*Radek Sienkiewicz's piece on logo sameness that prompted Jim Nielsen's post on homogeneity.](https://velvetshark.com/ai-company-logos-that-look-like-buttholes) - [*Write it down*Paco Coursey, 2019; the policy of writing every idea down, every time.](https://paco.me/writing/write-it-down) - [*You Don't Need Animations*Emil Kowalski's essay on why you are animating more often than you should: purpose, frequency of use, and perceived speed.](https://emilkowal.ski/ui/you-dont-need-animations) ## Tools and libraries The things you will actually install. - [*AI Skills for Design Engineers*Emil Kowalski's free skill files for coding agents: design engineering, animate, review-animations, and more.](https://emilkowal.ski/skill) - [*cmdk*Paco Coursey's composable command menu React component; the README doubles as the documentation site.](https://github.com/pacocoursey/cmdk) - [*cmdk*Rauno Freiberg, 2022; the command menu component behind many Command K bars, downloaded millions of times per week.](https://cmdk.paco.me) - [*Code Atlas*GitHub Next exploration by Amelia Wattenberger: a model's answer as an editable workflow of code blocks.](https://githubnext.com/projects/code-atlas/) - [*Code Brushes*GitHub Next exploration in Copilot Labs (preview ended December 2023): select lines, pick a brush, see the code change.](https://githubnext.com/projects/code-brushes/) - [*Collaborative coding workspaces*GitHub Next exploration: remote collaboration as sharing context, not just cursors.](https://githubnext.com/projects/workspaces/) - [*Copilot for Docs*GitHub Next exploration (preview ended December 2023): documentation answers with citations.](https://githubnext.com/projects/copilot-for-docs/) - [*Easing Graphs*Alex Vanderzon and Lochie Axon; 28 named easing curves with their cubic-bezier values and CSS snippets.](https://www.easing.dev/) - [*Emil Kowalski's design engineering skills*Skill files encoding Emil Kowalski's animation and component rules, including the duration table and the modal transform-origin exception.](https://github.com/emilkowalski/skill/blob/main/skills/emil-design-eng/SKILL.md) - [*emilkowalski/skill*The repository behind Emil Kowalski's skills; the README explains why agents do not have great taste.](https://github.com/emilkowalski/skill) - [*GitHub Blocks*GitHub Next exploration (preview ended December 2023): custom, interactive blocks for files, folders, and repositories.](https://blocks.githubnext.com) - [*Make Real*tldraw: sketch an interface on the canvas and get a working website back.](https://makereal.tldraw.com) - [*Minimap*Rauno Freiberg, 2024; the minimap scroll prototype inspired by games.](https://rauno.me/craft/minimap) - [*next-themes*Paco Coursey's theme abstraction for React apps: no flash on load, system preference, and a documented set of defaults.](https://github.com/pacocoursey/next-themes) - [*perfect-arrows*Steve Ruiz: functions for drawing arrows between points and shapes.](https://github.com/steveruizok/perfect-arrows) - [*perfect-freehand*Steve Ruiz: a library that draws perfect pressure-sensitive freehand lines from input points.](https://github.com/steveruizok/perfect-freehand) - [*Radial Menu*Rauno Freiberg, 2023; the prototype embedded in the Fitts's law section, hold and rotate from anywhere.](https://rauno.me/craft/radial-menu) - [*repo-visualizer*Amelia Wattenberger's GitHub Action that draws a codebase as nested circles and redraws on every change.](https://githubnext.com/projects/repo-visualization/) - [*skill-creator*Anthropic's skill for writing skills, which Emil Kowalski uses to package taste decisions.](https://github.com/anthropics/skills/blob/main/skills/skill-creator/SKILL.md) - [*Sonner*Emil Kowalski's opinionated toast component for React, with documented defaults for gap, visible toasts, and duration.](https://sonner.emilkowal.ski) - [*tldraw SDK*tldraw: an infinite canvas SDK for React, with the tldraw.dev blog.](https://tldraw.dev) - [*Vaul*Emil Kowalski's drawer component for React, built on Radix Dialog and modelled on the iOS sheet.](https://vaul.emilkowal.ski) - [*Web Interface Guidelines*Rauno Freiberg; a non-exhaustive list of details that make a good web interface.](https://interfaces.rauno.me/) ## People and sites Personal sites that are portfolios in themselves. - [*(Basic) Bookmarks*Rauno Freiberg, 2023; the bookmarking tool where he removed motion from core interactions.](https://bmrks.com) - [*Amelia Wattenberger*Essays on novel interfaces, data visualization, and AI tools, plus her GitHub Next work.](https://wattenberger.com) - [*amo*The social app whose wordmark animates through contrasting typefaces, cited in Contrasting Aesthetics.](https://get.amo.co/en) - [*Andrew Swank*Designer and engineer by design; a site built from scratch as a demo, with project pages for Google Assistant and Google Flights.](https://andrewswank.com) - [*App Dissection*Brian Lovin's close studies of apps, cited by Emil Kowalski as a model of studying rather than using.](https://brianlovin.com/app-dissection) - [*Bartosz Ciechanowski*Interactive articles on machines, physics, and graphics, each opening with a model you can drag.](https://ciechanow.ski) - [*Emil Kowalski*Design engineer at Linear, formerly Vercel; creator of Sonner, Vaul, and animations.dev.](https://emilkowal.ski) - [*Jim Nielsen*Fifteen years of blogging, 805 posts, and icon galleries; his home page and blog.](https://www.jim-nielsen.com) - [*Kathryn Gonzalez*Independent design and engineering director, formerly Head of Design Infrastructure at DoorDash; her site and writing.](https://www.ryngonzalez.com) - [*Linear careers*Linear's careers page and its statement on the lost art of building software.](https://linear.app/careers) - [*Maggie Appleton*A digital garden of notes, essays, and patterns, designed and built by her and published as open source.](https://maggieappleton.com) - [*MercuryOS*Jason Yuan, 2019; the concept OS Rauno recreated in SwiftUI for the swipe-trigger example.](https://www.mercuryos.com/) - [*Not Boring*Apps for everyday functions that are novel for people who value beauty and game-feel; cited in Novelty.](https://notbor.ing/) - [*Paco Coursey*Webmaster at Linear, formerly Vercel; a site of documents and links, plus a craft page of interaction experiments.](https://paco.me) - [*Paco Coursey's craft page: Command Menu*The 2021 playground that became cmdk, with a 249-item test set and a 2,000-item performance goal.](https://paco.me/craft/command) - [*PP Foundry bitmap fonts*The NeueBit and Mondwest page that pairs a bitmap typeface with Leonardo's Annunciation.](https://pangrampangram.com/products/bitmap-fonts) - [*Radix UI*Where Rauno Freiberg first saw serif quote marks paired with Inter.](https://www.radix-ui.com/) - [*Rauno Freiberg*Rauno Freiberg's site: essays, the craft log, projects, and a running diary; the site itself is an argument for its subject.](https://rauno.me) - [*Rauno Freiberg's craft index*Rauno Freiberg's index of prototypes and essays, including Command Menu (2021) and ⌘K Breadcrumbs (2022).](https://rauno.me/craft) - [*Raw Materials*The studio whose logo has four animations, one per visit; cited in Contrasting Aesthetics.](https://www.therawmaterials.com/) - [*Steve Ruiz*Steve Ruiz's site and blog, with the design tool micro-UX posts.](https://steveruiz.me) - [*Stripe Press*Stripe; an intentionally experimental site cited in Novelty as novelty working through contrast.](https://press.stripe.com/) - [*Vercel homepage*The October 2023 Vercel homepage documented in What will you ship?](https://vercel.com/home) ## Hubs and resources Collections that map the field and keep it current. - [*A Collection of Design Engineers*Maggie Appleton, 2024; a short definition and a roster of ten people who do design engineering work in public.](https://maggieappleton.com/design-engineers) - [*Animations on the Web*Emil Kowalski; a course on easing, timing, springs, and taste, with four walkthroughs and more than 35 lessons.](https://animations.dev) - [*Bartosz Ciechanowski on Patreon*Where every ciechanow.ski article asks readers to support the work.](https://www.patreon.com/ciechanowski) - [*desengs.com*Curated by Maze Heart; a tagged feed of tools, articles, people, communities, and jobs for design engineers.](https://desengs.com/) - [*Design Engineer Jobs*Moe Amaya; a job board dedicated to design engineering.](https://designengineer.io) - [*Design Engineering Club*A design engineering community, listed on desengs.com.](https://designeng.club/) - [*Design Engineering Resources*Arun Venkatesan; a curated list of posts, conversations, courses, tools, and a job board, contributable on GitHub.](https://designengineering.arun.is/) - [*Design engineering resources*Sean Voisen, updated 2025; an annotated list of articles, the Handbook, podcasts, and communities.](https://seanvoisen.com/writing/design-engineering-resources/) - [*Devouring Details*Rauno Freiberg; an interactive reference manual for interaction-curious designers, 23 chapters with 23 React components.](https://devouringdetails.com) - [*Fullstack D3 and Data Visualization*Amelia Wattenberger's book and course on building charts with D3, design principles included.](https://www.newline.co/fullstack-d3) - [*Maggie Appleton's patterns catalogue*Design patterns gathered from observation and research, each with context, pattern, and examples.](https://maggieappleton.com/patterns) 197 sources Links go to the primary sources; anything worth understanding properly is better read there than summarized here. --- # Taste Taste is a practice, not a gift. This chapter reads the people who say so in writing: Emil Kowalski on how judgement is built and trained, Rauno Freiberg on how much novelty an interface can carry and where contrast earns its place, and Jim Nielsen and Maggie Appleton on what happens when generated interfaces all start to look the same. The through line is that every decision that feels like instinct has a reason underneath it, and the work is learning to say what it is. ## 4 sections 1. [Developing taste](https://learn-ui.com/chapters/taste/developing-taste) 2. [Training judgement](https://learn-ui.com/chapters/taste/training-judgement) 3. [Novelty and contrast](https://learn-ui.com/chapters/taste/novelty-and-contrast) 4. [The AI aesthetic](https://learn-ui.com/chapters/taste/the-ai-aesthetic) --- # Developing taste · Taste Emil Kowalski opens [Developing Taste](https://emilkowal.ski/ui/developing-taste) with a car. Nobody cared about the first one’s colour or silhouette, because the competition was a horse; now that cars are commoditised, details matter more than ever. Software is at the same point: shipping something that works is no longer a differentiator, “especially now with AI.” He borrows Anu Atluru’s line: “In a world of scarcity, we treasure tools. In a world of abundance, we treasure taste.” ### Three ways to train it **Taste** (Good taste is not personal preference. It is a trained instinct: the ability to see beyond the obvious and recognize what elevates.), in Emil’s definition, is commonly mistaken for personal preference but is a trained instinct, “the ability to see beyond the obvious and recognize what elevates.” If it is trained, the question is how, and his essay gives three answers. The first is exposure: a designer should look at great designs, a writer should read great books, and Steve Jobs is quoted on trying “to expose yourself to the best things that humans have done.” The practical version, credited to Julie Zhuo’s [On taste, part 3](https://medium.com/the-year-of-the-looking-glass/on-taste-part-3-d7d9f069f0b2), is to find people respected in their field, see who they admire, and build a curated list of tastemakers to surround yourself with. The second is analysis, with a rule: while calibrating your taste, do not label things good or bad. Rationalise why something feels great instead of trusting the gut. Study apps rather than use them, asking why an interaction feels good, as Brian Lovin’s [App Dissection](https://brianlovin.com/app-dissection) does; a filmmaker should ask why the director made each choice. “Go beyond the surface level. Be curious.” The third is practice. Create things and seek feedback, because good critique from the right person beats trial and error; with time you become a **tastemaker** (This will make you not only a good judge of taste, but also, with time, a tastemaker.), not only a judge. Your early work probably will not be good, “but that’s a good sign”: your taste can already tell the work is not on par. That distance is the **taste gap** (The things you'll create probably won't be good at first, but that's a good sign. Your taste is good enough to tell that your work is not on par yet.), footnoted to Ira Glass. The phase is normal. Do not quit. Source The footnotes of Developing Taste link to the Stripe Sessions 2024 talk [Craft and beauty: The business value of form in function](https://stripe.com/sessions/2024/craft-and-beauty-the-business-value-of-form-in-function) for the commoditisation argument, and to a clip of Ira Glass on the taste gap that Emil [posted](https://x.com/emilkowalski/status/1765004718131068971). ### The why is the work Rauno Freiberg arrives from the other direction. The closing thoughts of [Invisible Details of Interaction Design](https://rauno.me/craft/interaction-design) admit that articulating why something feels right comes less naturally to him than making it feel right, but they are two sides of one coin: “There must be a reason. It can be as simple as a particular spring curve or something more innate, like metaphors.” Analysing details beyond “it feels nice” nurtures taste; so, he says earlier, does recreating interfaces. Paco Coursey wrote from inside the gap. In [Creative Output](https://paco.me/writing/creative-output) (2019) he is consistently unhappy with his output, not good at designing from scratch despite the title, and everything he makes feels like a remix. He quotes Mark Dalgleish: developers who find design hard are skipping the inspiration phase of looking at other designs and taking the good ideas. Two months later, in [Good Writers](https://paco.me/writing/good-writers), he pulls apart an opening sentence that glued him to an article: “I’m learning to recognize good writing.” His [Write it down](https://paco.me/writing/write-it-down) policy, every idea, every time, is the low-tech end of the same habit. ### What to schedule Keep a list of people whose work you trust and look at it on purpose. When something feels good, write one sentence about why. Show what you make to someone whose critique you respect, and when it is worse than what you admired, read that as your judgement being ahead of your hands, which is the order you want. --- # Novelty and contrast · Taste Rauno Freiberg’s [Contrasting Aesthetics](https://rauno.me/craft/contrasting-aesthetics) (January 2024) begins with a confession. He is increasingly stimulated by **aesthetic intersections** (Unexpected displays of art that tastefully reject the notion of a clean, singularly defined style, yet bridges many.), art that rejects a single clean style and bridges many with “authoring intent, purpose, and a sense of iteration”; minimalism can leave him feeling nothing. The toaster may ignore this, but novelty is most often found where unrelated disciplines meet. ### The tick primer He runs a primer with a row of tick marks. Equal ticks have equal conceptual weight. To call for attention we traditionally apply colour, a brand colour or an error state; form works too, and rotating one tick says “this one is different, and more important for a reason.” Make every tick different and you are back where you started, nothing standing out, the only harmony equal width and height. Dialled back to hand-drawn ticks, a new contrasting aesthetic, the row feels uniform yet slightly playful. **Just the right amount of contrast** (Just the right amount of contrast invites curiosity.) invites curiosity. Figure 2 reproduces the primer; notice where your eye goes. > Figure 2. How much contrast invites curiosity. Step through the states. One difference draws the eye; twelve differences cancel each other out.Illustrative numbers ### Intersections of eras and styles PP Foundry’s page for the bitmap typeface NeueBit pairs it with Leonardo da Vinci’s Annunciation, painted hundreds of years before computers. You expect an ornamented serif beside a Renaissance painting, so the bitmap face leaves Rauno “unsettled, yet pleasantly surprised,” and a Leonardo communicates mastery of craft. Not for productivity software, but right for first impressions and tone. amo animates its wordmark through several typefaces while keeping word, casing, sizing, positioning, and colour constant: kinship, and the diversity of a group of friends. Raw Materials, whose mantra is that when everything is the same, different is the greatest of opportunities, serves one of four logo animations per visit: ASCII 3D saying one of their materials is code, soft rounded shapes, a brutalist wireframe of typography. Off screen, people contrast Nordic minimalism with analog furniture, and Loïc Nottet’s Mélodrame is an orchestral ballad until 1:55, when drum machine beats arrive. Steve Ruiz’s [Engineering imperfection with draw shapes](https://tldraw.dev/blog/engineering-imperfection-with-draw-shapes) is the hand-drawn tick in production. tldraw gives geometric shapes intentional imperfections because subtle variation adds character and sits better beside freehand sketches. The variety had to keep each shape recognisable, make no two alike, and stay stable, so each shape’s ID seeds the random generator instead of Math.random on every render, which would jitter. ### A budget for novelty Two years later, in [Novelty](https://rauno.me/craft/novelty) (February 2026), Rauno puts a budget on this. His hypothesis since 2023 is that the more often an action is performed, the less rewarding any novel treatment becomes (see [frequency and novelty](https://learn-ui.com/chapters/invisible-details/frequency-and-novelty)), which he likens to **semantic satiation** (In psychology, there's this phenomenon called semantic satiation in which repetition of a word or phrase causes it to temporarily lose meaning.), a repeated word losing its meaning. **Novelty** (Novelty is the equivalent of an exclamation mark. Akin to seasoning, you don't want too much of it.) is an exclamation mark, or seasoning. He borrows the cinematographer’s three colour rule, roughly 60 percent primary, 30 secondary, 10 accent, treats the 10 as the novelty colour, and proposes the software analogue: 90 percent familiar, 10 percent novel. “Novelty is the contrast to sameness. And novelty works best as a contrast.” Onboarding is a good place to spend it because it happens once: the Devouring Details login-to-welcome transition plays only right after logging in, via a cookie and a rewrite to an animated route. > Figure. middleware.tsRauno Freiberg, Novelty His other examples are a route transition he would not want on every page but which works on a microsite about interviews against static siblings, and Stripe Press, which hits hard because the rest of Stripe’s pages are not like it. Aside Rauno asks that Novelty be read with a grain of salt: he had a hard time tying the observations together and does not offer them as prescriptions. The 90/10 split is a framework he could see making sense, not a measurement. ### Intent, tax, and rhythm Then he adds intent: how much novelty will the person accept? A game player is receptive. The Browser Company built Arc into a saxophone and struggled to make it a piano anyone could play; their reason was a **novelty tax** (There's this novelty tax that you get when you try a new product.), the average person with a job could not handle how much was new. Successful novel products are novel in the aspects their smaller, more passionate audience cares about; Not Boring builds photos, habits, timers, and calculators for people who value beauty and game-feel. “Make most things familiar, do something unexpected.” The budget applies within a page. In the Visual Rhythm section of [What will you ship?](https://rauno.me/craft/vercel), on the October 2023 Vercel homepage, an accent colour would stop feeling significant if every element used it, and the same goes for animation. **Visual rhythm** (When every element on a given section is signalling itself as novel or attractive, the novelty is diminished.) meant high-novelty sections (a graph tooltip animating a long distance, icons pixelating on hover) never appear consecutively, only paired with low-novelty ones (floating cursors, icons scaling on hover). The tick primer is a test for any screen: count the things asking for attention, and if the answer is everything, the answer is nothing. Spend novelty where it is seen once and keep the paths walked hundreds of times familiar. When you do something unexpected, make it one thing with a reason you could say out loud. --- # The AI aesthetic · Taste Jim Nielsen’s [The AI Aesthetic](https://blog.jim-nielsen.com/2026/ai-aesthetic/) (July 2026) starts from zeitgeists: each brings design idioms unique to its challenges, and some bake themselves into software for good. The hamburger menu spread under mobile screen constraints. The sparkle emoji, whose earlier connotations he cannot name, now means AI. ### Idioms of a zeitgeist Some patterns belong to the technology, like streaming text, made for chat. Others spread: shimmering text, which in AI land implies thinking, is being repurposed for any asynchronous task. Tiny, thin icons in desktop Electron AI apps clash with the system grain of native macOS apps beside them. Then the list that names the post: the aesthetics his brain associates with AI are **beige and cream colours, orange accents, serif typefaces** (There are other aesthetics my brain associates with AI, like beige/cream colors, orange accents, and serif typefaces as well as whack-a-mole UI controls.), and “whack-a-mole UI controls,” where clicking a toggle repaints the interface so you have to chase it. ### Why sameness happens A year earlier, in [Some Miscellaneous Thoughts on Visual Design Prodded By The Sameness of AI Company Logos](https://blog.jim-nielsen.com/2025/visual-design-homogeneity-at-scale/), prompted by Radek Sienkiewicz on the sameness of AI company logos, Jim gave a second cause. Code either works or it does not, so however bad it is you can say “Yeah, but it’s working.” Visual design is subjective forever, so decisions go to whoever has the best language or the most senior title, and the bad logo emerges from everyone’s feedback without anyone suggesting it. Individuals and small teams “have a sense of taste that doesn’t dilute through the structure and processes of a larger organization.” In [The Tumultuous Evolution of the Design Profession](https://blog.jim-nielsen.com/2025/tumult-in-design/) he adds the economics: bad design does not visibly hurt margins, so designers rise into “performing taste.” Less craft, more optics. Maggie Appleton describes the production side. In [Vibe Code is Legacy Code](https://maggieappleton.com/2025-08-vibe-legacy-code) she agrees with Steve Krouse that **vibe code** (A key part of the definition of vibe coding is that the user accepts code without full understanding.) and legacy code are both code nobody understands, and admits the pull to let the agent go. Her note on [Gas Town](https://maggieappleton.com/gastown) (January 2026), Steve Yegge’s vibecoded agent orchestration system, reads it as speculative design fiction: once agents churn through code, design becomes the limiting factor. Her own blockers are never build time but “Is that transition subtle enough? How composable should this be? Is this the right metaphor?”, decisions agents cannot make without your context and taste. Gas Town’s biggest flaw is that it was poorly designed, vibe designed as well as vibe coded. Language is a poor medium for easing curves, and she always needs to touch the CSS. Aside Jim’s [Craft and Satisfaction](https://blog.jim-nielsen.com/2025/craft-and-satisfaction/) asks the personal version: craft drives you into the essence of your materials, AI can reverse that so you care only about what comes out, and he wonders whether he cares more or less about what he made when AI helped. ### Write the rules down The response is that taste can be articulated and therefore transferred. In [Agents with Taste](https://emilkowal.ski/ui/agents-with-taste) Emil Kowalski says agents do not know what great feels like, so “if you know what great feels like, describe the rules, then give them to your agents.” His unit is a **skill** (My way of getting there is to create a skill file for each aspect of the interface. If you know what great feels like, describe the rules, then give them to your agents so they can follow them.) file per aspect of the interface. The argument is the balloon again: “almost every taste decision has a logical reason if you look close enough,” so it can be written down. > Figure. SKILL.mdEmil Kowalski, Agents with Taste The Easing Decision Flowchart is deliberately strict so the agent does not invent rules; a typography excerpt caps body text at about 65ch and puts tabular numerals on price columns. Any taste decision can be packaged this way, layout, icons, colour, and he writes them with Anthropic’s [skill-creator](https://github.com/anthropics/skills/blob/main/skills/skill-creator/SKILL.md). > Figure. SKILL.mdEmil Kowalski, Agents with Taste His demo has Claude Code audit a dialog animation against the rules and return a before and after table. The whole blog became one design engineering skill at [emilkowal.ski/skill](https://emilkowal.ski/skill), and the [repository](https://github.com/emilkowalski/skill) README states the limit: the skills are a side effect of domain expertise, which AI amplifies rather than replaces, “a shortcut to stand out in a sea of slop.” ### Review is part of the loop Kathryn Gonzalez said something compatible at Config 2023, in [Design Systems in Transition](https://www.ryngonzalez.com/blog/design-systems-in-transition-anxiety-ai-and-where-we-go): AI can bridge the gap between our taste, intentions, and ability to execute, and a design system becomes the language by which AI tools understand your design, so systems matter more, not less. She defines taste as critical judgement paired with deep domain expertise, used to set an organisation’s standards, and predicts more people will design, code, and build. Maggie’s bet is the most specific: code-must-be-close for serious work today, drifting toward code at a distance as harnesses mature, made safe by validation loops, tests, and specialised reviewing agents, because “the more agents can validate their own work, the better the results.” Emil’s review skill is one such loop. Jim has a two-frame test. His [Job Screening Blog Post](https://blog.jim-nielsen.com/2024/design-engineer-job-screener/) is two GIFs of a button being clicked; in one the heading shifts up a pixel, in the other it does not. “Can you tell the difference between them? Do you care? If not, we might not be a good fit.” Taste is noticing the pixel, caring, and being able to say why; generated interfaces only raise the price of the third. So, what to practise. Do Emil’s exercises and write the reason before reading his. When a rule you repeat in review is stable, write it down with its why, as an agent could follow it; you will learn which preferences have reasons and which are habits. And when the screen is beige, orange, serif, shimmering, and shifting by a pixel, notice it, care, and say what you would change. --- # Training judgement · Taste Emil Kowalski’s [Train Your Judgement](https://emilkowal.ski/ui/train-your-judgement) turns the previous section into a drill. Its first line: “AI can write animation code. What it can’t do is know what feels right.” Each exercise shows two animations; you pick the better one, write down why, then read his breakdown, because putting it into words trains your **judgement** (Putting into words why something feels right trains your ability to articulate your judgment, a skill that will be incredibly valuable in the AI era.). The figure rebuilds three of his eleven comparisons with his values. Do them first; the walkthrough spoils them. > Figure 1. Which feels better. Three of Emil Kowalski's side-by-side comparisons, rebuilt with his values. Replay both, decide, then read his reasoning. The point is not to be right; it is to notice what you noticed.Constants from the source ### Duration, easing, and scale A full-screen mobile menu at two durations: keep UI animations under 300ms holds for tooltips, dropdowns, and buttons, but a full-screen menu travels much further, so a short duration feels jarring. Duration scales with distance; bigger elements are heavier, “the same way a truck takes longer to stop than a bicycle.” A toast entering with ease-in versus ease-out: ease-in starts slow and feels sluggish; ease-out gives instant feedback, decelerates into place, and feels faster because the curve is sharp at the start. An element scaling in from 0 versus 0.9: scale(0) looks like it came from nowhere, while a higher start resembles the real world, “just like a balloon, even when deflated it has a visible shape.” Start from 0.90 to 0.95. > Figure. CSSIllustration ### Context and frequency An accordion with and without bounce is where Emil refuses to pick: for a learning app the bounce adds energy, for a finance app it feels unserious. Bounce communicates personality the way easing intensity does, so default to zero and add it when the brand calls for it. A hover highlight in a list, instant versus faded: the fade looks smoother in a demo, but move quickly and it trails your cursor. For something touched hundreds of times a day the direct connection matters more; Raycast, which Emil uses that often, does not animate on open because delight would become annoyance (see [frequency and novelty](https://learn-ui.com/chapters/invisible-details/frequency-and-novelty)). ### Press, removal, interruption A button pressed to scale 0.9 loses a tenth of its size, too much in most cases; at 0.97 the compression is barely visible but still felt, and “subtlety reads as quality.” Removing a chip compares Motion’s AnimatePresence in default mode, where the exiting chip stays in flow until its animation ends and the siblings slide over afterwards, with `mode="popLayout"`, which pulls it out of flow on the first frame so the siblings move during the exit. > Figure. TSXIllustration Handling interruptions: keyframes jump to their new position when toggled mid-animation, CSS transitions retarget smoothly. For anything toggled rapidly, menus, modals, accordions, drawers, prefer transitions. Source The reasoning for each exercise is hidden behind the picker on Train Your Judgement until you commit to an answer. The breakdowns summarised here are Emil’s, including the takeaway lines. ### Origin, stagger, and layers A popover that animates in from nowhere has no connection to its button; one that comes from the button says “I clicked this, and this appeared from it.” The default transform-origin of center is wrong for almost every triggered element; Radix UI and Base UI expose CSS variables for the trigger position. A hero staggered with identical timing feels artificial, like a linear easing; better to show the title first, delay the subtitle and buttons increasingly, and only fade the small pill. A side panel that slides in and then staggers its items is two layers of entrance; one could call it delightful, Emil writes, but the panel that arrives with its content already there is faster. “Sometimes the best animation is no animation.” The same criteria appear as principles in [Great Animations](https://emilkowal.ski/ui/great-animations): natural (springs, the Dynamic Island), fast (ease-out, usually under 300ms), purposeful (never animate keyboard-initiated actions), performant (transform and opacity), interruptible, accessible under prefers-reduced-motion, and cohesive, which is why Sonner’s toast is slightly slower and uses ease. [Good vs Great Animations](https://emilkowal.ski/ui/good-vs-great-animations) adds ease-in-out for things already on screen, custom curves because the built-in ones are too weak, springs for decorative mouse-driven changes but none for a functional banking graph, and a tabs highlight that only looks wrong in slow motion, which clip-path fixes. Two habits follow: play the animation frame by frame, and review it the next day. The drill has three moves. Recreate, because as Emil says in [Building an animation course](https://emilkowal.ski/ui/building-an-animation-course), students have to feel the difference themselves, “like touching a physical object to understand its texture.” Compare versions side by side. Articulate the reason before reading anyone else’s; the last section of this chapter is about why that move now matters more. --- # Developers # Learn UI for developers and agents The chapter and section index behind this site is also a small public JSON API: no account, no API key, and no request quota to buy. It is read-only, so the live endpoints below are already safe to try. ## Quickstart List every chapter: ``` curl https://learn-ui.com/api/v1/chapters ``` Get one chapter and its sections: ``` curl https://learn-ui.com/api/v1/chapters/introduction ``` The full surface is described machine-readably at [/openapi.json](https://learn-ui.com/openapi.json) (OpenAPI 3.1), with typed request and response schemas an agent can load directly into a function-calling tool definition. ## MCP server The same index is also an MCP server at `https://learn-ui.com/api/mcp`, for MCP-native clients like Claude Desktop or Claude Code. It exposes two tools: `list_chapters` and `get_chapter`, no authentication required. ``` { "mcpServers": { "learn-ui": { "url": "https://learn-ui.com/api/mcp" } } } ``` It also publishes an [MCP server card](https://learn-ui.com/.well-known/mcp-server-card) for automatic discovery, per the draft [SEP-2127](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2127) proposal. ## Errors Every non-2xx response, including an unknown path under `/api/` and an unsupported method on a real one, is JSON in the same shape: a stable `code`, a human-readable `message`, and usually a `hint` naming the next call to make. ``` curl https://learn-ui.com/api/v1/chapters/not-a-real-slug { "error": { "code": "chapter_not_found", "message": "No chapter matches slug \"not-a-real-slug\".", "hint": "GET /api/v1/chapters for the list of valid slugs." } } ``` ## Versioning and rate limits The API is versioned in the URL path (`/api/v1/...`). A breaking change ships under a new version prefix rather than changing this one in place; this version keeps working for at least 90 days after a new one ships, announced with a `Deprecation` response header and a `Sunset` date before removal. Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset` headers. Going over the limit returns `429` with a `Retry-After` header, in the same JSON error shape as above. ## Full text For reading rather than querying, every page is available as Markdown by appending `.md` to its URL, or by sending `Accept: text/markdown`. The whole book is one document at [/llms-full.txt](https://learn-ui.com/llms-full.txt), indexed at [/llms.txt](https://learn-ui.com/llms.txt). ## Reference - [OpenAPI 3.1 spec](https://learn-ui.com/openapi.json) - [GET /api/v1/chapters](https://learn-ui.com/api/v1/chapters) - [GET /api/v1/chapters/{slug}](https://learn-ui.com/api/v1/chapters/introduction) - [MCP server](https://learn-ui.com/api/mcp) - [llms.txt](https://learn-ui.com/llms.txt) - [llms-full.txt](https://learn-ui.com/llms-full.txt) - [sitemap.xml](https://learn-ui.com/sitemap.xml) --- # Privacy # Privacy Nothing here needs your name. No account, no email, nothing following you to the next site. This page is the actual mechanism, not a lawyer’s paraphrase of it. ## Ask AI Type a question and it travels to the model provider behind Ask AI (Cloudflare Workers AI), along with whatever page you’re reading, so the answer can be specific to it. It can only read pages already on this site. Not the web, not code execution, not the server’s files. The server hashes your IP before anything else touches it. That hash stops one browser from hammering the endpoint, nothing else, and the raw address is never written down. Your side of the conversation lives in local storage on your machine. The server keeps a matching copy under the same session, so a reply that was mid-stream when you reloaded can keep going. Clear the conversation and your copy disappears. ## Everything else Vercel Analytics and Speed Insights count visits and page-load speed in aggregate, no cookie involved. The API and MCP server need no key and rate-limit by IP in memory only, gone the moment the server restarts. Dark mode or light lives in local storage too. Fonts are baked into the site at build time, so even the first load never asks Google for anything.