{"node":{"id":"8702376d-5485-4f66-bb7b-127ebcc5dfb3","handle":"8702","type":"note","authorName":"Vincent Yeung","intent":"learning","title":"Drawer 4: Behaviour","aiSummary":null,"content":"**Open it when:** you're working on forms, the states a control can be in, empty and error screens, interface wording, or what a first-time visitor sees.\n\n## What we know\n\n### Forms\n\n- One form can do several jobs. A booking button, a quote button and an upload-your-plans button can all open the same form, with its type already picked by the button that opened it. [our build]\n- Use labels that stay put. A placeholder is an example, not a label. Give format rules before the user submits. [impeccable]\n- Put errors inline, next to the field. Be specific, suggest a fix, and keep what the user typed. [impeccable]\n- Stop double submission: disable the button while it's working. [impeccable]\n- Never trust checks in the browser alone. Check again on the server. [impeccable]\n- On phones, inputs under 16px make iOS Safari zoom in, which breaks form layouts. [impeccable]\n- A switch is for settings that take effect at once. Anything that needs a submit uses a checkbox. [Astryx]\n- Form inputs are controlled: the value and the change handler live in your code. [Astryx]\n- Pick the control by the job. [Astryx]\n  - Short text such as names, emails, search: a text input.\n  - Longer text: a text area.\n  - One option from a list: a dropdown.\n  - Several from a known set: a checkbox dropdown, or chips you can remove.\n  - Files: a file input with drag and drop and checks on type, size and count.\n- A layout component places fields but doesn't handle state or sending. Wrap it in a real `<form>`. [Astryx]\n\n### States\n\n- Every interactive control has default, hover, focus, active, disabled, loading and error states. [impeccable]\n- Use one set of state names everywhere: hover, focus, active, disabled, selected, loading, error, warning, success, info. [impeccable]\n- Keep controls consistent. If \"save\" looks different in two places, one is wrong. [impeccable]\n- Use skeleton placeholders for loading, not spinners in the middle of content. [impeccable]\n- Menus and pop-ups must escape their container. A dropdown inside a box that hides overflow gets cut off. Use `<dialog>`, the popover API, `position: fixed` or a portal. [impeccable]\n- Don't reach for a modal first. Use one only when the task needs interruption or locked focus. [impeccable]\n- Don't use a badge as decoration. Use it only for distinct states. [Astryx]\n- Some awesome-design-md files have a no-hover rule: they document only the default and pressed states. Their \"Known Gaps\" section lists hover and other states the copying never saw. [awesome-design-md]\n- Never rely on hover for anything that matters. Touch users can't hover. [impeccable]\n- Interrupted gestures: if a drag is cancelled or the window loses focus, clear the drag state. The next tap must work without a reload. [impeccable]\n- Wait about 300 ms after typing before running a search, and run scroll handlers at most about every 100 ms. [impeccable]\n\n### Empty and error screens\n\n- An empty screen teaches the interface. It doesn't just say \"nothing here\". [impeccable]\n- Every empty screen says what will be here, why it matters, how to start, and where to get help. [impeccable]\n- Empty screens differ by cause. [impeccable]\n  - First use: show the value and offer a template.\n  - User cleared everything: a light touch, easy to recreate.\n  - No results: suggest a new search or clearing filters.\n  - No permission: explain.\n  - Error: offer a retry.\n- An empty screen needs a title and a next step, so the user isn't stuck. [Astryx]\n- A useful error says what failed, why (when that helps), and how to recover. No internal codes as the main message. [impeccable]\n- Match server errors to screens: 400 a validation message, 401 back to login, 403 a permission message, 404 a not-found screen, 429 a slow-down message, 500 a general error with a way to get help. [impeccable]\n- One broken part must not block the whole interface. [impeccable]\n- Test extremes: very long and very short text, emoji, right-to-left text, accents, huge numbers, a thousand items, no data. [impeccable]\n- Use logical CSS properties such as `margin-inline-start`, so right-to-left text lays out correctly. [impeccable]\n- Leave 30 to 40% extra room for translations. [impeccable] impeccable says German often runs 30% longer than English (asserted, no evidence shown).\n- Use the browser's Intl tools for dates, numbers and money, and a proper library for plurals. [impeccable]\n\n### Copy\n\n- Use the product's own words. Buttons name their action. Errors name the problem and the fix. [impeccable]\n- For each state, decide the one fact the user needs now, the next action, and the right tone. [impeccable]\n- Say each idea once. If the heading explains it, the intro adds something new or goes. [impeccable]\n- Labels say what will happen, not the gesture. Use the same word for the same thing everywhere. [impeccable]\n- Active voice: \"Save changes\", not \"Changes will be saved\". [impeccable]\n- A destructive action names the object and what happens to it. Prefer undo over a confirmation when recovery is safe. Never \"Yes\", \"No\", \"OK\" or \"Submit\" on a confirmation. [impeccable]\n- Loading text names the real job. Never fake progress. [impeccable]\n- Link text must make sense on its own. [impeccable]\n- Write whole messages that translate, not sentences stitched together from fragments. [impeccable]\n- Warmth is welcome around privacy, payment, deletion and lost access. Jokes are not. [impeccable]\n- Avoid marketing buzzwords such as streamline, empower, supercharge, world-class, cutting-edge. Say what the product literally does. [impeccable] impeccable calls these instant AI tells (asserted, no evidence shown).\n- Test copy at the target widths and at 200% zoom. Final copy is as short as it can be without losing meaning. [impeccable]\n\n### First use\n\n- Get people to first value fast. The job is not to teach the whole product. [impeccable]\n- Show, don't tell. Use the real product, not a separate tutorial mode. Teach one thing at a time. [impeccable]\n- Introduce one to three core ideas. Keep a tour to three to seven steps. [impeccable]\n- Supply sample data so a new user's first actions work. [impeccable]\n- Teach a feature when people need it. Empty screens are a chance to teach. [impeccable]\n- Let experienced users skip. Never hide the skip option. [impeccable]\n- Show onboarding once. Remember that it's done, and respect dismissals. [impeccable]\n- Ask for as little as possible at sign-up, and say why you need each thing. [impeccable]\n\n### Small pleasures\n\n- A delightful moment must belong to this product. A neighbouring product shouldn't be able to use it unchanged. [impeccable]\n- Match the celebration to the effort. A routine save should just feel certain. Never fake work to stage a flourish. [impeccable]\n- Generic whimsy is worse than plain clarity. [impeccable]\n\n## Tools in this drawer\n- **Survive real data and errors: `/impeccable harden <target>`.** Pick it before launch, when the screens only work with perfect data.\n- **Rewrite interface wording: `/impeccable clarify <target>`.** Pick it when buttons, errors or empty screens leave people unsure what to do.\n- **First use and empty states: `/impeccable onboard <target>`.** Pick it when new users stall or empty screens say \"nothing here\".\n- **Tool: Astryx forms.** Pick it when you build on React and need well-behaved form controls quickly.","capturedAt":"2026-10-29T09:31:21.512Z","createdAt":"2026-10-29T09:31:21.512Z","updatedAt":"2026-11-06T04:43:56.263Z","spanId":null,"contributor":null,"audiences":[{"kind":"public","createdAt":"2026-11-06T04:27:10.844Z"}],"fingerprint":"3410ba76e704aa17b24369274db790497faa4d19c466648552725a87c6f439fc","revisionNo":"2","structureHash":"333a308f19d9c0501d6ede7ccb1ef3ec6254d3806322959c7fea97d305bbe1b0","page":"https://lattris.com/by/b/memories/8702376d-5485-4f66-bb7b-127ebcc5dfb3"},"links":[{"direction":"out","verb":"references","reason":"Follow back to pick a different drawer.","hash":"0456b928ca7b38d78ef5abc933fbeecd8d0f460e5773cab1bb44987ad357ef48","node":{"id":"5f8b457d-b87a-4e61-9af2-3008deaf37a9","handle":"5f8b","type":"note","title":"Front-end design: the toolbox","aiSummary":null,"erased":false,"href":"https://lattris.com/api/lattris/by/b/memories/5f8b457d-b87a-4e61-9af2-3008deaf37a9?links=1","fingerprint":"49e1c7f41f22c466c7ef1a993cab80b6dcbedab4552d2ac684133d60dea7e60b","revisionNo":"2","structureHash":"64df670c7bd82572e0ad9b2e06b8829d3b2e509be134591c04ea1fa281fca3ef","intent":"learning","authorName":"Vincent Yeung","page":"https://lattris.com/by/b/memories/5f8b457d-b87a-4e61-9af2-3008deaf37a9"}},{"direction":"out","verb":"references","reason":"Pick it when you build on React and need well-behaved form controls quickly.","hash":"94e1b71b5b07bf733b1efc1571c1162bbe0bfbc25f27217ff45bd82f5409bdb8","node":{"id":"652bb4cd-0dc8-432d-b2c5-f571a5e308d2","handle":"652b","type":"note","title":"Tool: Astryx forms","aiSummary":null,"erased":false,"href":"https://lattris.com/api/lattris/by/b/memories/652bb4cd-0dc8-432d-b2c5-f571a5e308d2?links=1","fingerprint":"100abb4f344196d894688c0c46799e4f88d89b136b3ee53ff8f205f218929e35","revisionNo":"1","structureHash":"706bfddf88472bf50997bb2c0db60b9a8a8f2d11bc773b3ca071064762bd373e","intent":"learning","authorName":"Vincent Yeung","page":"https://lattris.com/by/b/memories/652bb4cd-0dc8-432d-b2c5-f571a5e308d2"}},{"direction":"out","verb":"references","reason":"only if you need to install impeccable before running one of the commands above, or check its cautions first","hash":"6b25e1db474cce7f51e31b4f32aed10af6f5b7e3acb684a35c2e7c60396aba0c","node":{"id":"7b1bf5e3-1c32-4b94-8e8a-1436409042a0","handle":"7b1b","type":"note","title":"Source: impeccable","aiSummary":null,"erased":false,"href":"https://lattris.com/api/lattris/by/b/memories/7b1bf5e3-1c32-4b94-8e8a-1436409042a0?links=1","fingerprint":"118dd05f30af956d68616de75423a1b8c7180a16da21f5788bf8e6589414c0bd","revisionNo":"3","structureHash":"32d1be7421efd06d67641aa60439c18dac3b6e676e9b31dc5ca978b397c949e0","intent":"learning","authorName":"Vincent Yeung","page":"https://lattris.com/by/b/memories/7b1bf5e3-1c32-4b94-8e8a-1436409042a0"}},{"direction":"out","verb":"references","reason":"Follow when a line marked [our build] needs its full context.","hash":"25a1ba3e33f1810b08183c8c7d5708385dffa178e2ffa8261feeb51a307b46e9","node":{"id":"ec50a07f-f1ee-4008-b3ce-b7e1a847d706","handle":"ec50","type":"note","title":"Pattern: building a website with AI","aiSummary":null,"erased":false,"href":"https://lattris.com/api/lattris/by/b/memories/ec50a07f-f1ee-4008-b3ce-b7e1a847d706?links=1","fingerprint":"62d9975e4cd521f59b3f3e71719dbcae5835d307e28597ea0104247bb6721bb2","revisionNo":"1","structureHash":"e63b54c083aa93ec272c5d03a5b587824c3c5a78373b8839600f59268a5f2083","intent":"learning","authorName":"Vincent Yeung","page":"https://lattris.com/by/b/memories/ec50a07f-f1ee-4008-b3ce-b7e1a847d706"}},{"direction":"in","verb":"references","reason":"Open it for forms, states, empty and error screens, interface wording, and a user's first visit.","hash":"915910789c03e290939041a7d411fde681538553f63ac8a2ca1f5e7739f83250","node":{"id":"5f8b457d-b87a-4e61-9af2-3008deaf37a9","handle":"5f8b","type":"note","title":"Front-end design: the toolbox","aiSummary":null,"erased":false,"href":"https://lattris.com/api/lattris/by/b/memories/5f8b457d-b87a-4e61-9af2-3008deaf37a9?links=1","fingerprint":"49e1c7f41f22c466c7ef1a993cab80b6dcbedab4552d2ac684133d60dea7e60b","revisionNo":"2","structureHash":"64df670c7bd82572e0ad9b2e06b8829d3b2e509be134591c04ea1fa281fca3ef","intent":"learning","authorName":"Vincent Yeung","page":"https://lattris.com/by/b/memories/5f8b457d-b87a-4e61-9af2-3008deaf37a9"}}],"dictionary":{"lattris":"A personal knowledge base — how a person captures what they know as linked blocks they own and control. To understand how this knowledge base works: https://lattris.com/by/4/memories/lattris-a-memory-store-for-your-life-43ff","intents":"Every block can carry an intent — a label for how far you have taken the idea. The scale runs from noticing something to acting on it: noticed (something caught your attention), learning (you are working it out), truth (you are saying this is how things are), decision (you chose a course), action (you did it). Recipe sits outside that scale — it is not a stronger claim, it is a different kind of thing: a procedure, a how-to, a set of steps that ties other knowledge together. Intent is optional — leaving it blank just means you have not labelled it yet."},"instructions_to_ai":"This is knowledge from a personal knowledge base. Read it and consider how it's relevant to what the person you're talking to needs. Follow the linked blocks to explore further related topics if it might be useful to the user; open each at its page address. Start by letting the user know what this is about and how it may be relevant to them."}