{"id":"l-fig-4-1","courseId":"figma-ui-design","lang":"en","kind":"lesson","summary":"Prototype Steady’s check-in flow with triggers, actions and animations, make the check button an interactive component, open the New habit sheet as an overlay and use smart animate correctly.","html":"<p>A static mock-up shows what Steady looks like. A prototype shows how it feels: does tapping the check button give a satisfying response, does the New habit sheet come from where people expect, can someone find their way back? Testing those questions with a prototype costs an afternoon. Testing them after development costs a sprint.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">Interactions: trigger, action, animation</h2>\n<p>Switch the right sidebar to the <strong>Prototype</strong> tab. Select a layer, drag the connection handle that appears onto a destination frame, and you have created an <strong>interaction</strong>. Every interaction has three parts.</p>\n<p>The <strong>trigger</strong> is what the person does. At the time of writing, the triggers include On click/On tap, On drag, While hovering, While pressing, Key/Gamepad, Mouse enter, Mouse leave, Mouse down, Mouse up and After delay. For a phone app you mostly use On tap, plus On drag for swipe gestures.</p>\n<p>The <strong>action</strong> is what happens. The common ones are <strong>Navigate to</strong> another frame, <strong>Back</strong>, <strong>Change to</strong> another variant of a component, <strong>Open overlay</strong>, <strong>Swap overlay</strong>, <strong>Close overlay</strong> and <strong>Scroll to</strong>. Advanced prototypes can also set variables and use conditionals, which are plan-dependent.</p>\n<p>The <strong>animation</strong> is how it moves: Instant, Dissolve, Smart animate, or directional ones such as Move in, Push and Slide in, each with easing and a duration. For Steady, short and calm works best: Smart animate or Push, Ease out, about 250 to 300 ms.</p>\n<p>Here is the check-in flow you will build:</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 680 260\" role=\"img\" aria-labelledby=\"l-fig-4-1-t1\"><defs><marker id=\"arrow-l-fig-4-1-1\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\"><path d=\"M0 0 L10 5 L0 10 z\" class=\"d-arrowhead\"/></marker></defs>\n  <title id=\"l-fig-4-1-t1\">The Today screen is the starting point. Tapping a check button changes the row to Done inside the component. Tapping the add button opens the New habit sheet as an overlay, and Save closes it. Tapping a row navigates to Habit detail, and Back returns.</title>\n  <rect class=\"d-box-primary\" x=\"250\" y=\"90\" width=\"180\" height=\"70\" rx=\"14\"/>\n  <text class=\"d-label-strong\" x=\"340\" y=\"122\" text-anchor=\"middle\">Today</text>\n  <text class=\"d-label-muted\" x=\"340\" y=\"144\" text-anchor=\"middle\">flow starting point</text>\n  <rect class=\"d-box-success\" x=\"20\" y=\"20\" width=\"180\" height=\"56\" rx=\"12\"/>\n  <text class=\"d-label\" x=\"110\" y=\"45\" text-anchor=\"middle\">Row: Done</text>\n  <text class=\"d-label-muted\" x=\"110\" y=\"64\" text-anchor=\"middle\">Change to (in component)</text>\n  <path class=\"d-arrow\" d=\"M250 105 L202 66\" marker-end=\"url(#arrow-l-fig-4-1-1)\"/>\n  <rect class=\"d-box-accent\" x=\"480\" y=\"20\" width=\"180\" height=\"56\" rx=\"12\"/>\n  <text class=\"d-label\" x=\"570\" y=\"45\" text-anchor=\"middle\">New habit sheet</text>\n  <text class=\"d-label-muted\" x=\"570\" y=\"64\" text-anchor=\"middle\">Open overlay</text>\n  <path class=\"d-arrow\" d=\"M430 105 L478 66\" marker-end=\"url(#arrow-l-fig-4-1-1)\"/>\n  <rect class=\"d-box\" x=\"250\" y=\"200\" width=\"180\" height=\"50\" rx=\"12\"/>\n  <text class=\"d-label\" x=\"340\" y=\"230\" text-anchor=\"middle\">Habit detail</text>\n  <path class=\"d-arrow\" d=\"M320 160 L320 198\" marker-end=\"url(#arrow-l-fig-4-1-1)\"/>\n  <path class=\"d-arrow d-dashed\" d=\"M360 198 L360 162\" marker-end=\"url(#arrow-l-fig-4-1-1)\"/>\n  <text class=\"d-label-muted\" x=\"300\" y=\"184\" text-anchor=\"end\">tap row: Push</text>\n  <text class=\"d-label-muted\" x=\"380\" y=\"184\">Back</text>\n  <path class=\"d-arrow d-dashed\" d=\"M520 78 L430 128\" marker-end=\"url(#arrow-l-fig-4-1-1)\"/>\n  <text class=\"d-label-muted\" x=\"560\" y=\"110\">Save: Close overlay</text>\n</svg><figcaption>Steady’s check-in prototype flow</figcaption></figure>\n<h2 id=\"sec-2\" tabindex=\"-1\">Interactive components: the check button</h2>\n<p>You could draw a connection from every check button to a copy of the screen with that row checked. With five habits that is 32 combinations of screens. Instead, open the <strong>Check button</strong> component set and add the interaction <em>between its variants</em>: on the To do variant, On tap, <strong>Change to</strong> Done, Smart animate, 200 ms. Add the reverse on Done.</p>\n<p>Now every instance of the check button, on every screen, toggles on its own when tapped in the prototype. This is an <strong>interactive component</strong>, and it is why Lesson 3.2’s careful variants pay off twice.</p>\n<h2 id=\"sec-3\" tabindex=\"-1\">Overlays: the New habit sheet</h2>\n<p>The add button opens the New habit sheet, which slides up over Today rather than replacing it. Connect the add button to the sheet frame with <strong>Open overlay</strong>. In the overlay settings, choose a bottom center position, turn on closing when clicking outside, and add a background behind the overlay (a dark color at about 40% opacity dims the screen). Use a Move in from bottom animation.</p>\n<p>Overlay settings belong to the overlay frame, not to the connection, so every button that opens the sheet reuses them. Inside the sheet, wire Save habit and Cancel to <strong>Close overlay</strong>.</p>\n<h2 id=\"sec-4\" tabindex=\"-1\">Smart animate: matching layers</h2>\n<p>Smart animate looks at two frames, finds layers that match, and animates the differences. A layer matches when it has the <strong>same name</strong> and sits in the <strong>same place in the layer hierarchy</strong> in both frames. It can animate position, size, rotation, opacity and fills.</p>\n<p>For the streak celebration on Habit detail, duplicate the frame (duplicating keeps the names identical), then in the second frame enlarge the streak number and fade in a “New best!” badge. Connect with Smart animate, Ease out, 300 ms.</p>\n<aside class=\"callout callout-mistake\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/><path d=\"M12 9v4\"/><path d=\"M12 17h.01\"/></svg><span><span class=\"callout-kind\">Common mistake</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>Hidden layers and renamed layers</span></p>\n<p>Smart animate cannot fade in a layer that is hidden with the eye icon; there is no opacity to start from. Keep the badge visible and set its opacity to 0% in the first frame. And if you renamed the badge to <code dir=\"ltr\">Badge copy</code> in one frame or moved it into another group, smart animate sees two unrelated layers and the badge pops in. Named layers from Lesson 1.4 are what make this work.</p>\n</aside>\n<h2 id=\"sec-5\" tabindex=\"-1\">Presenting and scrolling</h2>\n<p>Set Today as a flow starting point and press the play button to present. On a long list, set the content frame to scroll vertically and keep the tab bar fixed in place, both from the Prototype tab at the time of writing. Test on a real phone with the Figma mobile app; a 300 ms animation that looks slow on a monitor often feels right in the hand.</p>\n<aside class=\"callout callout-tip\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5\"/><path d=\"M9 18h6\"/><path d=\"M10 22h4\"/></svg><span><span class=\"callout-kind\">Tip</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>Prototype the question, not the app</span></p>\n<p>Before wiring anything, write down what you want to learn: “Do people find the add button?” or “Is checking a habit satisfying?”. Prototype the screens that answer it and nothing else. A focused five-screen prototype gets better feedback than a forty-screen maze.</p>\n</aside>\n<p>Next you make sure the screens you just animated work for everyone, including people who cannot see the teal, cannot tap small targets or use a screen reader.</p>\n","toc":[{"id":"sec-1","text":"Interactions: trigger, action, animation","level":2},{"id":"sec-2","text":"Interactive components: the check button","level":2},{"id":"sec-3","text":"Overlays: the New habit sheet","level":2},{"id":"sec-4","text":"Smart animate: matching layers","level":2},{"id":"sec-5","text":"Presenting and scrolling","level":2}],"takeaways":["Every prototype interaction is a trigger (such as On tap) plus an action (such as Navigate to or Open overlay) plus an animation.","Interactive components put interactions between variants inside the component, so every instance of the check button toggles on its own.","Overlays show content such as a bottom sheet above the current screen, with settings for position, closing on outside tap and a background.","Smart animate pairs layers by name and position in the layer tree, then animates position, size, rotation, opacity and fills between them.","Prototype the moments you need to test or explain, not every screen, and keep each flow short enough to finish in a minute."],"further":[{"title":"Guide to prototyping in Figma","url":"https://help.figma.com/hc/en-us/articles/360040314193-Guide-to-prototyping-in-Figma"},{"title":"Prototype triggers","url":"https://help.figma.com/hc/en-us/articles/360040035834-Prototype-triggers"},{"title":"Smart animate layers between frames","url":"https://help.figma.com/hc/en-us/articles/360039818874-Smart-animate-layers-between-frames"},{"title":"Create overlays in your prototypes","url":"https://help.figma.com/hc/en-us/articles/360039818254-Create-overlays-in-your-prototypes"}],"quiz":[{"q":"<p>You want every habit row’s check button to toggle between To do and Done in the prototype, on every screen. What is the most efficient setup?</p>","options":[{"text":"Draw a connection from each check button on each screen to a copy of that screen with the button checked.","why":"That needs a new screen for every combination of checked rows, which explodes quickly."},{"text":"Add an On tap, Change to Done interaction between the variants inside the Check button component set.","why":"Correct. Interactions inside the component make every instance interactive, with no extra screens."},{"text":"Use After delay so buttons check themselves.","why":"Testers need to tap. A timed change does not test whether people find the button."},{"text":"Export the screens and add interactions in a video editor.","why":"A video cannot respond to taps, so you lose what makes a prototype useful."}],"answer":1},{"q":"<p>The New habit sheet should slide up from the bottom over the Today screen and close when someone taps the dimmed area. Which setup fits?</p>","options":[{"text":"Navigate to a copy of Today with the sheet drawn on it, using Instant.","why":"It looks similar but the sheet cannot be dismissed by tapping outside, and you maintain a second Today screen."},{"text":"Scroll to the sheet’s position on a long Today frame.","why":"Scrolling would move the whole screen, not slide a sheet over it."},{"text":"Open overlay with the sheet frame, positioned at the bottom center, with a background behind it and closing on outside click turned on.","why":"Correct. That is exactly what overlays are for, and the settings live on the overlay so every connection reuses them."},{"text":"Change to a variant of the Today frame.","why":"Change to works on component variants, and the Today screen is a frame, not a component set."}],"answer":2},{"q":"<p>In the first frame the streak badge is hidden with the eye icon. In the second it is visible. Smart animate makes it pop in instead of fading. What is the fix?</p>","options":[{"text":"Increase the duration to 2,000 ms.","why":"A longer duration does not help when there is no animatable change. Visibility toggles instantly."},{"text":"Switch the animation to Dissolve.","why":"Dissolve fades the whole frame, not the badge on its own."},{"text":"Rename the badge in the second frame.","why":"Different names would stop smart animate matching it at all. The names should be identical."},{"text":"Keep the badge visible in both frames and set its opacity to 0% in the first frame.","why":"Correct. Smart animate animates opacity values, but a hidden layer has no opacity to animate from."}],"answer":3}],"exercise":{"kind":"choice","multiple":true,"options":["names-differ","parent-differs","instant","duration","easing","trigger"],"correct":["names-differ","parent-differs","instant"],"title":"Why does the row jump instead of slide?","prompt":"<p>When a habit is checked, Steady should slide its row down into the Done group. The prototype jumps straight from Frame A to Frame B instead. Here are the two frames, the connection and the layer paths of the Read row in each.</p>\n<p>:::figure Two frames that should smart animate\n<svg viewBox=\"0 0 520 300\" role=\"img\" aria-labelledby=\"ex1\"></p>\n  <title id=\"ex1\">Frame A shows the habit list with the Read row at the top under To do. Frame B shows the Read row moved down into a separate Done group. An arrow labelled On tap, Instant connects them. Layer names are shown under each frame.</title>\n  <rect class=\"d-box\" x=\"20\" y=\"20\" width=\"200\" height=\"200\" rx=\"16\"/>\n  <text class=\"d-label-strong\" x=\"36\" y=\"46\">Frame A</text>\n  <rect class=\"d-box-primary\" x=\"36\" y=\"60\" width=\"168\" height=\"34\" rx=\"8\"/>\n  <text class=\"d-label\" x=\"48\" y=\"82\">Read</text>\n  <rect class=\"d-box\" x=\"36\" y=\"102\" width=\"168\" height=\"34\" rx=\"8\"/>\n  <text class=\"d-label\" x=\"48\" y=\"124\">Water</text>\n  <rect class=\"d-box\" x=\"300\" y=\"20\" width=\"200\" height=\"200\" rx=\"16\"/>\n  <text class=\"d-label-strong\" x=\"316\" y=\"46\">Frame B</text>\n  <rect class=\"d-box\" x=\"316\" y=\"60\" width=\"168\" height=\"34\" rx=\"8\"/>\n  <text class=\"d-label\" x=\"328\" y=\"82\">Water</text>\n  <rect class=\"d-box-success d-dashed\" x=\"310\" y=\"120\" width=\"180\" height=\"70\" rx=\"10\"/>\n  <rect class=\"d-box-primary\" x=\"316\" y=\"142\" width=\"168\" height=\"34\" rx=\"8\"/>\n  <text class=\"d-label\" x=\"328\" y=\"164\">Read</text>\n  <path class=\"d-arrow\" d=\"M222 120 L298 120\" marker-end=\"url(#arrow)\"/>\n  <text class=\"d-label-muted\" x=\"260\" y=\"110\" text-anchor=\"middle\">On tap</text>\n  <text class=\"d-label-muted\" x=\"260\" y=\"140\" text-anchor=\"middle\">Instant</text>\n  <text class=\"d-code\" x=\"20\" y=\"250\">List / Read row</text>\n  <text class=\"d-code\" x=\"300\" y=\"250\">List / Done group /</text>\n  <text class=\"d-code\" x=\"300\" y=\"272\">  Habit row/Read</text>\n</svg>\n:::\n<p>Select <strong>every</strong> cause that stops the row from sliding.</p>\n","hints":["Smart animate needs a matching layer: same name, same place in the hierarchy. Compare the two paths.","Look at the animation set on the connection too.","Three causes: the name, the parent, and the animation type."],"explanation":"<p>The connection uses <strong>Instant</strong>, so nothing could animate even with perfect layers; switch it to <strong>Smart animate</strong>. Then smart animate still needs a match: the row is called <code dir=\"ltr\">Read row</code> in Frame A and <code dir=\"ltr\">Habit row/Read</code> in Frame B (<strong>different names</strong>), and in Frame B it sits inside <code dir=\"ltr\">Done group</code> (a <strong>different parent</strong>). Give it the same name and keep it in the same parent in both frames, for example by keeping one list and changing the row’s position, or by moving the Done heading instead. Duration, easing and the On tap trigger are fine; they change how a match animates, not whether it exists.</p>\n","checkLabels":{},"optionText":{"names-differ":{"text":"The row is named differently in the two frames.","why":"Correct. Smart animate pairs layers by name, so <code dir=\"ltr\">Read row</code> and <code dir=\"ltr\">Habit row/Read</code> are two unrelated layers."},"parent-differs":{"text":"In Frame B the row sits inside a different parent group.","why":"Correct. Matching also depends on the layer’s place in the hierarchy. A new parent breaks the pairing."},"instant":{"text":"The connection’s animation is set to Instant.","why":"Correct. Instant never animates. Smart animate must be selected on the interaction."},"duration":{"text":"The duration should be at least 1,000 ms.","why":"Duration only changes the speed of an animation that is already happening. 250 to 300 ms suits a row move."},"easing":{"text":"The easing should be Linear instead of Ease out.","why":"Easing shapes the motion; it does not decide whether layers match. Ease out is a good default for things settling into place."},"trigger":{"text":"The trigger should be On click instead of On tap.","why":"On click and On tap are the same trigger, labelled for desktop and mobile."}}},"words":763,"readMinutes":4}