1"use strict";(self.webpackChunktheuxshop=self.webpackChunktheuxshop||[]).push([[3235],{8901:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>h,contentTitle:()=>c,default:()=>x,frontMatter:()=>d,metadata:()=>i,toc:()=>u});const i=JSON.parse('{"id":"patterns/onboarding","title":"Onboarding Patterns","description":"First-run experiences, progressive disclosure, and empty state design.","source":"@site/.tmp/docs-published/patterns/onboarding.mdx","sourceDirName":"patterns","slug":"/patterns/onboarding","permalink":"/patterns/onboarding","draft":false,"unlisted":false,"tags":[],"version":"current","sidebarPosition":4,"frontMatter":{"id":"onboarding","title":"Onboarding Patterns","description":"First-run experiences, progressive disclosure, and empty state design.","sidebar_position":4},"sidebar":"patternsSidebar","previous":{"title":"Forms Patterns","permalink":"/patterns/forms"},"next":{"title":"Interaction Feedback Patterns","permalink":"/patterns/interaction-feedback"}}');var t=s(4848),r=s(8453),l=s(9176),o=s(5920),a=s(5388);const d={id:"onboarding",title:"Onboarding Patterns",description:"First-run experiences, progressive disclosure, and empty state design.",sidebar_position:4},c="Onboarding Patterns",h={},u=[{value:"Principles of effective onboarding",id:"principles-of-effective-onboarding",level:2},{value:"Show value before requiring effort",id:"show-value-before-requiring-effort",level:3},{value:"Teach through doing",id:"teach-through-doing",level:3},{value:"Progressive disclosure",id:"progressive-disclosure",level:3},{value:"Make it skippable",id:"make-it-skippable",level:3},{value:"First-run experience patterns",id:"first-run-experience-patterns",level:2},{value:"Product tour",id:"product-tour",level:3},{value:"Setup wizard",id:"setup-wizard",level:3},{value:"Sample content / Template starts",id:"sample-content--template-starts",level:3},{value:"Inline tips and hints",id:"inline-tips-and-hints",level:3},{value:"Checklist approach",id:"checklist-approach",level:3},{value:"Empty state design",id:"empty-state-design",level:2},{value:"What empty states should do",id:"what-empty-states-should-do",level:3},{value:"Empty state components",id:"empty-state-components",level:3},{value:"Empty state variations",id:"empty-state-variations",level:3},{value:"Progressive disclosure",id:"progressive-disclosure-1",level:2},{value:"Levels of disclosure",id:"levels-of-disclosure",level:3},{value:"Disclosure patterns",id:"disclosure-patterns",level:3},{value:"Timing disclosure",id:"timing-disclosure",level:3},{value:"Measuring onboarding success",id:"measuring-onboarding-success",level:2},{value:"Key metrics",id:"key-metrics",level:3},{value:"Qualitative signals",id:"qualitative-signals",level:3}];function p(e){const n={a:"a",em:"em",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",ol:"ol",p:"p",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"onboarding-patterns",children:"Onboarding Patterns"})}),"\n",(0,t.jsx)(n.p,{children:"Onboarding shapes the crucial first impressions of your product. Good onboarding helps users understand value quickly; bad onboarding creates confusion and abandonment. This document covers patterns for effective first-run experiences."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.em,{children:"Last updated: May 2024"})}),"\n",(0,t.jsx)(n.h2,{id:"principles-of-effective-onboarding",children:"Principles of effective onboarding"}),"\n",(0,t.jsx)(n.h3,{id:"show-value-before-requiring-effort",children:"Show value before requiring effort"}),"\n",(0,t.jsx)(n.p,{children:"Users should experience why your product is useful before being asked to invest time (account creation, configuration, learning)."}),"\n",(0,t.jsx)(n.h3,{id:"teach-through-doing",children:"Teach through doing"}),"\n",(0,t.jsxs)(n.p,{children:["Interactive exploration beats passive instruction. Let users try things rather than reading about them. When written guidance is needed, it works best as a step-by-step walkthrough that helps users make a concrete first decision - as ",(0,t.jsx)(n.a,{href:"https://techitez.org/programming/beginners-guide-choosing-first-code-editor/",children:"Tech IT EZ's code editor guide"})," demonstrates with first-time tool selection - not a feature list they have to decode before they can start."]}),"\n",(0,t.jsx)(n.h3,{id:"progressive-disclosure",children:"Progressive disclosure"}),"\n",(0,t.jsx)(n.p,{children:"Reveal complexity gradually. Don't explain everything upfront - introduce features as they become relevant."}),"\n",(0,t.jsx)(n.h3,{id:"make-it-skippable",children:"Make it skippable"}),"\n",(0,t.jsx)(n.p,{children:"Some users want to explore on their own. Let them skip tutorials and onboarding flows (but make it easy to return)."}),"\n",(0,t.jsx)(n.h2,{id:"first-run-experience-patterns",children:"First-run experience patterns"}),"\n",(0,t.jsx)(n.h3,{id:"product-tour",children:"Product tour"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Description"}),": Guided walkthrough highlighting key features, typically with highlights and callouts."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"When to use"}),":"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Complex interfaces where key features might be missed"}),"\n",(0,t.jsx)(n.li,{children:'When specific actions lead to "aha moments"'}),"\n",(0,t.jsx)(n.li,{children:"New feature introduction for existing users"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Best practices"}),":"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Keep it short (3-5 steps maximum)"}),"\n",(0,t.jsx)(n.li,{children:"Focus on highest-value features, not comprehensiveness"}),"\n",(0,t.jsx)(n.li,{children:"Allow skip and exit at any point"}),"\n",(0,t.jsx)(n.li,{children:"Don't block access to the product"}),"\n",(0,t.jsx)(n.li,{children:"Show real interface, not separate screens"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Accessibility requirements"}),":"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Focus management for each step"}),"\n",(0,t.jsx)(n.li,{children:"Keyboard navigation throughout"}),"\n",(0,t.jsx)(n.li,{children:"Screen reader announcements for each step"}),"\n",(0,t.jsx)(n.li,{children:"Allow completion via keyboard"}),"\n"]}),"\n",(0,t.jsx)(l.A,{variant:"note",title:"Tour fatigue",children:(0,t.jsx)(n.p,{children:"Users often dismiss tours immediately. Don't invest heavily in elaborate tours - they may not be seen. Consider whether doing is better than touring."})}),"\n",(0,t.jsx)(n.h3,{id:"setup-wizard",children:"Setup wizard"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Description"}),": Multi-step flow that configures the product for the user's needs."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"When to use"}),":"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"When initial configuration is necessary"}),"\n",(0,t.jsx)(n.li,{children:"When personalization significantly improves experience"}),"\n",(0,t.jsx)(n.li,{children:"When users have distinct use cases requiring different setups"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Best practices"}),":"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Minimize steps - each step risks abandonment"}),"\n",(0,t.jsx)(n.li,{children:"Show progress (step 2 of 4)"}),"\n",(0,t.jsx)(n.li,{children:"Allow back navigation"}),"\n",(0,t.jsx)(n.li,{children:"Explain why each step matters"}),"\n",(0,t.jsx)(n.li,{children:"Save progress so users can return"}),"\n",(0,t.jsx)(n.li,{children:"Allow skipping non-essential steps"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Examples"}),":"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Selecting workspace theme/preferences"}),"\n",(0,t.jsx)(n.li,{children:"Connecting integrations"}),"\n",(0,t.jsx)(n.li,{children:"Choosing role or use case"}),"\n",(0,t.jsx)(n.li,{children:"Importing existing data"}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"sample-content--template-starts",children:"Sample content / Template starts"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Description"}),": Pre-populate the product with example content users can explore and modify."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"When to use"}),":"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"When an empty product is confusing"}),"\n",(0,t.jsx)(n.li,{children:"When examples demonstrate value better than explanation"}),"\n",(0,t.jsx)(n.li,{children:"Creative tools, project management, productivity apps"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Best practices"}),":"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Make sample content obviously sample (don't let users confuse it with their real data)"}),"\n",(0,t.jsx)(n.li,{children:"Make it easy to clear and start fresh"}),"\n",(0,t.jsx)(n.li,{children:"Samples should demonstrate product capabilities"}),"\n",(0,t.jsx)(n.li,{children:"Variety of samples can address different use cases"}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"inline-tips-and-hints",children:"Inline tips and hints"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Description"}),": Contextual tips that appear near relevant features as users encounter them."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"When to use"}),":"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"As a lighter alternative to full tours"}),"\n",(0,t.jsx)(n.li,{children:"For explaining features when first used"}),"\n",(0,t.jsx)(n.li,{children:"For introducing new features to existing users"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Best practices"}),":"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Appear only once (don't pester)"}),"\n",(0,t.jsx)(n.li,{children:"Dismissible immediately"}),"\n",(0,t.jsx)(n.li,{children:"Brief - one sentence if possible"}),"\n",(0,t.jsx)(n.li,{children:"Positioned near the feature they explain"}),"\n",(0,t.jsx)(n.li,{children:"Don't cover the thing being explained"}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"checklist-approach",children:"Checklist approach"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Description"}),": List of tasks that guide users through key setup and first actions."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"When to use"}),":"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"When several independent actions contribute to getting started"}),"\n",(0,t.jsx)(n.li,{children:"When users benefit from clear next steps"}),"\n",(0,t.jsx)(n.li,{children:"When gamification/progress can motivate"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Best practices"}),":"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Keep list short (5-7 items max)"}),"\n",(0,t.jsx)(n.li,{children:"Order by importance and logical sequence"}),"\n",(0,t.jsx)(n.li,{children:"Show completion progress"}),"\n",(0,t.jsx)(n.li,{children:"Allow items to be skipped"}),"\n",(0,t.jsx)(n.li,{children:"Celebrate completion appropriately"}),"\n",(0,t.jsx)(n.li,{children:"Consider hiding after completion"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"empty-state-design",children:"Empty state design"}),"\n",(0,t.jsx)(n.p,{children:"Empty states are part of onboarding - they're what users see before they have content."}),"\n",(0,t.jsx)(n.h3,{id:"what-empty-states-should-do",children:"What empty states should do"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Explain what belongs here"}),": What will this space contain once populated?"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Guide the first action"}),": Clear call-to-action for creating/adding"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Reduce intimidation"}),": Make starting feel easy, not overwhelming"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Set appropriate expectations"}),": What should users expect as they use this feature?"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"empty-state-components",children:"Empty state components"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Illustration or icon"}),": Visual interest, emotional tone"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Headline"}),": What this area is for"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Description"}
1),": Brief context or benefit"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Primary action"}),": Clear button/link to start"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Secondary options"}),": Alternative paths (import, templates, help)"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"empty-state-variations",children:"Empty state variations"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"First-time empty"}),": User has never used this feature"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Emphasize getting started"}),"\n",(0,t.jsx)(n.li,{children:"May include educational content"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Cleared empty"}),": User had content but removed it all"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Acknowledge the state"}),"\n",(0,t.jsx)(n.li,{children:"Provide quick action to add more"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Search/filter empty"}),": No results match criteria"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Explain why (no matches)"}),"\n",(0,t.jsx)(n.li,{children:"Suggest how to get results (broaden search)"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Error empty"}),": Content couldn't load"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Explain the problem"}),"\n",(0,t.jsx)(n.li,{children:"Offer retry or troubleshooting"}),"\n"]}),"\n",(0,t.jsx)(l.A,{variant:"tip",title:"Testing empty states",children:(0,t.jsx)(n.p,{children:"Test onboarding with people who've never seen your product. Your existing knowledge blinds you to confusion. Watch real first-time users struggle, and fix what they struggle with."})}),"\n",(0,t.jsx)(n.h2,{id:"progressive-disclosure-1",children:"Progressive disclosure"}),"\n",(0,t.jsx)(n.h3,{id:"levels-of-disclosure",children:"Levels of disclosure"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Level 1"}),": Essential features visible immediately. Core actions obvious."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Level 2"}),": Secondary features discoverable through exploration. Menus, settings, advanced options."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Level 3"}),": Power features available but hidden. Keyboard shortcuts, advanced settings, customization."]}),"\n",(0,t.jsx)(n.h3,{id:"disclosure-patterns",children:"Disclosure patterns"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Expandable sections"}),': "Advanced options" that expand on click\n',(0,t.jsx)(n.strong,{children:"Hover/focus reveals"}),": Additional controls appearing on interaction\n",(0,t.jsx)(n.strong,{children:"Mode switches"}),": Simple \u2192 Advanced mode toggles\n",(0,t.jsx)(n.strong,{children:"Just-in-time education"}),": Teaching features when first relevant"]}),"\n",(0,t.jsx)(n.h3,{id:"timing-disclosure",children:"Timing disclosure"}),"\n",(0,t.jsx)(n.p,{children:"Reveal features when:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"User has demonstrated need (repeated workaround behavior)"}),"\n",(0,t.jsx)(n.li,{children:"Context makes feature relevant (editing an item reveals edit controls)"}),"\n",(0,t.jsx)(n.li,{children:'User explicitly requests (clicking "More options")'}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Don't reveal:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Everything at once"}),"\n",(0,t.jsx)(n.li,{children:"Before users can understand"}),"\n",(0,t.jsx)(n.li,{children:"In ways that disrupt current tasks"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"measuring-onboarding-success",children:"Measuring onboarding success"}),"\n",(0,t.jsx)(n.h3,{id:"key-metrics",children:"Key metrics"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Activation rate"}),": Percentage completing key first actions\n",(0,t.jsx)(n.strong,{children:"Time to value"}),": How long until users experience core benefit\n",(0,t.jsx)(n.strong,{children:"Drop-off points"}),": Where users abandon during onboarding\n",(0,t.jsx)(n.strong,{children:"Feature adoption"}),": Whether users discover and use key features\n",(0,t.jsx)(n.strong,{children:"Return rate"}),": Whether users come back after first session"]}),"\n",(0,t.jsx)(n.h3,{id:"qualitative-signals",children:"Qualitative signals"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"User confusion during sessions"}),"\n",(0,t.jsx)(n.li,{children:"Support requests from new users"}),"\n",(0,t.jsx)(n.li,{children:'Feedback about "figuring out" the product'}),"\n",(0,t.jsx)(n.li,{children:"Workarounds indicating missed features"}),"\n"]}),"\n",(0,t.jsx)(o.A,{items:[{question:"How long should onboarding be?",answer:"As short as possible while achieving its goals. Users are impatient during onboarding - they came to use the product, not learn about it. Cut ruthlessly."},{question:"Should I require account creation before onboarding?",answer:"If possible, no. Let users experience value first. Account creation is a barrier - place it after users are convinced the product is worth the effort."},{question:"How do I onboard users to new features?",answer:"Similar patterns: announcements, inline tips, changelogs. But be more subtle - existing users didn't ask for education. One-time, dismissible, contextual hints work well."},{question:"What if users skip onboarding?",answer:"Make sure the product is usable without it. Provide ways to access onboarding content later (help menu, documentation). Don't punish skippers - respect their choice."},{question:"Should onboarding be mandatory?",answer:"Rarely. Mandatory onboarding frustrates users who want to explore. If certain setup is truly required, make it short and purposeful."}]}),"\n",(0,t.jsx)(a.A,{title:"Related resources",links:[{label:"Navigation Patterns",to:"/patterns/navigation"},{label:"Forms Patterns",to:"/patterns/forms"},{label:"Interaction Feedback",to:"/patterns/interaction-feedback"},{label:"UX Basics",to:"/guides/ux-basics"}]})]})}function x(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},9176:(e,n,s)=>{s.d(n,{A:()=>r});s(6540);var i=s(4164),t=s(4848);function r({variant:e="default",title:n,children:s}){return(0,t.jsxs)("div",{className:(0,i.A)("ux-callout","default"!==e&&`ux-callout--${e}`),children:[(0,t.jsx)("div",{className:"ux-callout__title",children:n||{default:"Note",tip:"Tip",warning:"Warning",note:"Field Note"}[e]}),(0,t.jsx)("div",{className:"ux-callout__content",children:s})]})}},5920:(e,n,s)=>{s.d(n,{A:()=>t});s(6540);var i=s(4848);function t({items:e}){return(0,i.jsx)("div",{className:"ux-faq",children:e.map((e,n)=>(0,i.jsxs)("div",{className:"ux-faq__item",children:[(0,i.jsx)("div",{className:"ux-faq__question",children:e.question}),(0,i.jsx)("div",{className:"ux-faq__answer",children:(0,i.jsx)("p",{children:e.answer})})]},n))})}},5388:(e,n,s)=>{s.d(n,{A:()=>r});s(6540);var i=s(6289),t=s(4848);function r({title:e="Related Resources",links:n}){return(0,t.jsxs)("div",{className:"ux-related",children:[(0,t.jsx)("div",{className:"ux-related__title",children:e}),(0,t.jsx)("ul",{className:"ux-related__list",children:n.map((e,n)=>(0,t.jsx)("li",{children:(0,t.jsx)(i.A,{to:e.to,className:"ux-related__link",children:e.label})},n))})]})}},8453:(e,n,s)=>{s.d(n,{R:()=>l,x:()=>o});var i=s(6540);const t={},r=i.createContext(t);function l(e){const n=i.useContext(r);return i.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:l(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.