[{"data":1,"prerenderedAt":2891},["ShallowReactive",2],{"navigation_docs":3,"-guide-ux-patterns-forms-and-actions":587,"-guide-ux-patterns-forms-and-actions-surround":2886},[4,50,155,441,504],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":49},"Get Started","i-lucide-rocket","\u002Fget-started","1.get-started",[10,15,20,25,30,35,40,45],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fget-started\u002Fintroduction","1.get-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fget-started\u002Finstallation","1.get-started\u002F2.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Project structure","\u002Fget-started\u002Fproject-structure","1.get-started\u002F3.project-structure","i-lucide-folder-tree",{"title":26,"path":27,"stem":28,"icon":29},"Configuration","\u002Fget-started\u002Fconfiguration","1.get-started\u002F4.configuration","i-lucide-settings",{"title":31,"path":32,"stem":33,"icon":34},"Authentication","\u002Fget-started\u002Fauthentication","1.get-started\u002F5.authentication","i-lucide-lock",{"title":36,"path":37,"stem":38,"icon":39},"Adding modules","\u002Fget-started\u002Fadding-modules","1.get-started\u002F6.adding-modules","i-lucide-puzzle",{"title":41,"path":42,"stem":43,"icon":44},"Database","\u002Fget-started\u002Fdatabase","1.get-started\u002F7.database","i-lucide-database",{"title":46,"path":47,"stem":48,"icon":6},"Deployment","\u002Fget-started\u002Fdeployment","1.get-started\u002F8.deployment",false,{"title":51,"icon":52,"path":53,"stem":54,"children":55,"page":49},"Guide","i-lucide-book-open","\u002Fguide","2.guide",[56,90,115,125],{"title":57,"icon":49,"path":58,"stem":59,"children":60,"page":49},"Concepts","\u002Fguide\u002Fconcepts","2.guide\u002F1.concepts",[61,66,71,76,80,85],{"title":62,"path":63,"stem":64,"icon":65},"Architecture","\u002Fguide\u002Fconcepts\u002Farchitecture","2.guide\u002F1.concepts\u002F1.architecture","i-lucide-blocks",{"title":67,"path":68,"stem":69,"icon":70},"Access control","\u002Fguide\u002Fconcepts\u002Fauth-and-scopes","2.guide\u002F1.concepts\u002F2.auth-and-scopes","i-lucide-shield-check",{"title":72,"path":73,"stem":74,"icon":75},"Extension points","\u002Fguide\u002Fconcepts\u002Fextension-points","2.guide\u002F1.concepts\u002F3.extension-points","i-lucide-plug",{"title":77,"path":78,"stem":79,"icon":44},"Database extensions","\u002Fguide\u002Fconcepts\u002Fdatabase-extensions","2.guide\u002F1.concepts\u002F4.database-extensions",{"title":81,"path":82,"stem":83,"icon":84},"Identity","\u002Fguide\u002Fconcepts\u002Fidentity","2.guide\u002F1.concepts\u002F5.identity","i-lucide-fingerprint",{"title":86,"path":87,"stem":88,"icon":89},"Glossary","\u002Fguide\u002Fconcepts\u002Fglossary","2.guide\u002F1.concepts\u002F6.glossary","i-lucide-book-a",{"title":91,"icon":49,"path":92,"stem":93,"children":94,"page":49},"UX patterns","\u002Fguide\u002Fux-patterns","2.guide\u002F2.ux-patterns",[95,100,105,110],{"title":96,"path":97,"stem":98,"icon":99},"Layouts and navigation","\u002Fguide\u002Fux-patterns\u002Flayouts-and-navigation","2.guide\u002F2.ux-patterns\u002F1.layouts-and-navigation","i-lucide-layout-template",{"title":101,"path":102,"stem":103,"icon":104},"Pages","\u002Fguide\u002Fux-patterns\u002Fpages","2.guide\u002F2.ux-patterns\u002F2.pages","i-lucide-table",{"title":106,"path":107,"stem":108,"icon":109},"Forms and actions","\u002Fguide\u002Fux-patterns\u002Fforms-and-actions","2.guide\u002F2.ux-patterns\u002F3.forms-and-actions","i-lucide-square-pen",{"title":111,"path":112,"stem":113,"icon":114},"Text and formatting","\u002Fguide\u002Fux-patterns\u002Ftext-and-formatting","2.guide\u002F2.ux-patterns\u002F4.text-and-formatting","i-lucide-type",{"title":116,"icon":49,"path":117,"stem":118,"children":119,"page":49},"Best practices","\u002Fguide\u002Fbest-practices","2.guide\u002F3.best-practices",[120],{"title":121,"path":122,"stem":123,"icon":124},"HTTP routes","\u002Fguide\u002Fbest-practices\u002Fhttp-routes","2.guide\u002F3.best-practices\u002F1.http-routes","i-lucide-route",{"title":126,"icon":49,"path":127,"stem":128,"children":129,"page":49},"Going further","\u002Fguide\u002Fgoing-further","2.guide\u002F4.going-further",[130,135,140,145,150],{"title":131,"path":132,"stem":133,"icon":134},"Use your own OAuth server","\u002Fguide\u002Fgoing-further\u002Fown-oauth-server","2.guide\u002F4.going-further\u002F1.own-oauth-server","i-lucide-key-round",{"title":136,"path":137,"stem":138,"icon":139},"Create an OAuth application","\u002Fguide\u002Fgoing-further\u002Foauth-application","2.guide\u002F4.going-further\u002F2.oauth-application","i-lucide-app-window",{"title":141,"path":142,"stem":143,"icon":144},"Signing keys","\u002Fguide\u002Fgoing-further\u002Fsigning-keys","2.guide\u002F4.going-further\u002F3.signing-keys","i-lucide-key-square",{"title":146,"path":147,"stem":148,"icon":149},"Stripe setup","\u002Fguide\u002Fgoing-further\u002Fstripe-setup","2.guide\u002F4.going-further\u002F4.stripe-setup","i-lucide-credit-card",{"title":151,"path":152,"stem":153,"icon":154},"Migrate to the permission model","\u002Fguide\u002Fgoing-further\u002Fmigrate-access-control","2.guide\u002F4.going-further\u002F5.migrate-access-control","i-lucide-arrow-right-left",{"title":156,"icon":157,"path":158,"stem":159,"children":160},"Modules","i-lucide-boxes","\u002Fmodules","3.modules",[161,163,244,273,320,375],{"title":156,"path":158,"stem":162},"3.modules\u002Findex",{"title":81,"icon":49,"path":164,"stem":165,"children":166,"page":49},"\u002Fmodules\u002Fidentity","3.modules\u002F1.identity",[167,190,194,198,220,224,240],{"title":168,"path":169,"stem":170,"children":171},"Auth","\u002Fmodules\u002Fidentity\u002Fauth","3.modules\u002F1.identity\u002F1.auth\u002Findex",[172,174,178,182,186],{"title":173,"path":169,"stem":170},"Overview",{"title":175,"path":176,"stem":177},"Server API","\u002Fmodules\u002Fidentity\u002Fauth\u002Fserver","3.modules\u002F1.identity\u002F1.auth\u002F2.server",{"title":179,"path":180,"stem":181},"Reference","\u002Fmodules\u002Fidentity\u002Fauth\u002Freference","3.modules\u002F1.identity\u002F1.auth\u002F3.reference",{"title":183,"path":184,"stem":185},"Client mode","\u002Fmodules\u002Fidentity\u002Fauth\u002Fclient-mode","3.modules\u002F1.identity\u002F1.auth\u002F4.client-mode",{"title":187,"path":188,"stem":189},"OAuth providers","\u002Fmodules\u002Fidentity\u002Fauth\u002Foauth-providers","3.modules\u002F1.identity\u002F1.auth\u002F5.oauth-providers",{"title":191,"path":192,"stem":193},"Users","\u002Fmodules\u002Fidentity\u002Fusers","3.modules\u002F1.identity\u002F2.users",{"title":195,"path":196,"stem":197},"Account","\u002Fmodules\u002Fidentity\u002Faccount","3.modules\u002F1.identity\u002F3.account",{"title":199,"path":200,"stem":201,"children":202},"Authorization","\u002Fmodules\u002Fidentity\u002Fauthorization","3.modules\u002F1.identity\u002F4.authorization\u002Findex",[203,204,208,212,216],{"title":173,"path":200,"stem":201},{"title":205,"path":206,"stem":207},"Roles and requirements","\u002Fmodules\u002Fidentity\u002Fauthorization\u002Froles-and-requirements","3.modules\u002F1.identity\u002F4.authorization\u002F2.roles-and-requirements",{"title":209,"path":210,"stem":211},"Policies","\u002Fmodules\u002Fidentity\u002Fauthorization\u002Fpolicies","3.modules\u002F1.identity\u002F4.authorization\u002F3.policies",{"title":213,"path":214,"stem":215},"Client","\u002Fmodules\u002Fidentity\u002Fauthorization\u002Fclient","3.modules\u002F1.identity\u002F4.authorization\u002F4.client",{"title":217,"path":218,"stem":219},"Admin","\u002Fmodules\u002Fidentity\u002Fauthorization\u002Fadmin","3.modules\u002F1.identity\u002F4.authorization\u002F5.admin",{"title":221,"path":222,"stem":223},"Preferences","\u002Fmodules\u002Fidentity\u002Fpreferences","3.modules\u002F1.identity\u002F5.preferences",{"title":225,"path":226,"stem":227,"children":228},"OAuth Server","\u002Fmodules\u002Fidentity\u002Foauth-server","3.modules\u002F1.identity\u002F6.oauth-server\u002Findex",[229,230,233,237],{"title":173,"path":226,"stem":227},{"title":175,"path":231,"stem":232},"\u002Fmodules\u002Fidentity\u002Foauth-server\u002Fserver","3.modules\u002F1.identity\u002F6.oauth-server\u002F2.server",{"title":234,"path":235,"stem":236},"Hooks","\u002Fmodules\u002Fidentity\u002Foauth-server\u002Fhooks","3.modules\u002F1.identity\u002F6.oauth-server\u002F3.hooks",{"title":179,"path":238,"stem":239},"\u002Fmodules\u002Fidentity\u002Foauth-server\u002Froutes-and-clients","3.modules\u002F1.identity\u002F6.oauth-server\u002F4.routes-and-clients",{"title":241,"path":242,"stem":243},"OAuth Resource","\u002Fmodules\u002Fidentity\u002Foauth-resource","3.modules\u002F1.identity\u002F8.oauth-resource",{"title":245,"icon":49,"path":246,"stem":247,"children":248,"page":49},"Commerce","\u002Fmodules\u002Fcommerce","3.modules\u002F2.commerce",[249,253,257],{"title":250,"path":251,"stem":252},"Stripe","\u002Fmodules\u002Fcommerce\u002Fstripe","3.modules\u002F2.commerce\u002F1.stripe",{"title":254,"path":255,"stem":256},"Payments","\u002Fmodules\u002Fcommerce\u002Fpayments","3.modules\u002F2.commerce\u002F2.payments",{"title":258,"path":259,"stem":260,"children":261},"Subscriptions","\u002Fmodules\u002Fcommerce\u002Fsubscriptions","3.modules\u002F2.commerce\u002F3.subscriptions\u002Findex",[262,263,266,270],{"title":173,"path":259,"stem":260},{"title":175,"path":264,"stem":265},"\u002Fmodules\u002Fcommerce\u002Fsubscriptions\u002Fserver","3.modules\u002F2.commerce\u002F3.subscriptions\u002F2.server",{"title":267,"path":268,"stem":269},"App","\u002Fmodules\u002Fcommerce\u002Fsubscriptions\u002Fapp","3.modules\u002F2.commerce\u002F3.subscriptions\u002F3.app",{"title":179,"path":271,"stem":272},"\u002Fmodules\u002Fcommerce\u002Fsubscriptions\u002Freference","3.modules\u002F2.commerce\u002F3.subscriptions\u002F4.reference",{"title":274,"icon":49,"path":275,"stem":276,"children":277,"page":49},"Features","\u002Fmodules\u002Ffeatures","3.modules\u002F3.features",[278,293,312,316],{"title":279,"path":280,"stem":281,"children":282},"Events","\u002Fmodules\u002Ffeatures\u002Fevents","3.modules\u002F3.features\u002F1.events\u002Findex",[283,284,287,290],{"title":173,"path":280,"stem":281},{"title":175,"path":285,"stem":286},"\u002Fmodules\u002Ffeatures\u002Fevents\u002Fserver","3.modules\u002F3.features\u002F1.events\u002F2.server",{"title":267,"path":288,"stem":289},"\u002Fmodules\u002Ffeatures\u002Fevents\u002Fapp","3.modules\u002F3.features\u002F1.events\u002F3.app",{"title":179,"path":291,"stem":292},"\u002Fmodules\u002Ffeatures\u002Fevents\u002Freference","3.modules\u002F3.features\u002F1.events\u002F4.reference",{"title":294,"path":295,"stem":296,"children":297},"Forms","\u002Fmodules\u002Ffeatures\u002Fforms","3.modules\u002F3.features\u002F2.forms\u002Findex",[298,299,303,306,309],{"title":173,"path":295,"stem":296},{"title":300,"path":301,"stem":302},"Definition","\u002Fmodules\u002Ffeatures\u002Fforms\u002Fdefinition","3.modules\u002F3.features\u002F2.forms\u002F2.definition",{"title":175,"path":304,"stem":305},"\u002Fmodules\u002Ffeatures\u002Fforms\u002Fserver","3.modules\u002F3.features\u002F2.forms\u002F3.server",{"title":267,"path":307,"stem":308},"\u002Fmodules\u002Ffeatures\u002Fforms\u002Fapp","3.modules\u002F3.features\u002F2.forms\u002F4.app",{"title":179,"path":310,"stem":311},"\u002Fmodules\u002Ffeatures\u002Fforms\u002Freference","3.modules\u002F3.features\u002F2.forms\u002F5.reference",{"title":313,"path":314,"stem":315},"Cookie Consent","\u002Fmodules\u002Ffeatures\u002Fcookie-consent","3.modules\u002F3.features\u002F3.cookie-consent",{"title":317,"path":318,"stem":319},"MCP","\u002Fmodules\u002Ffeatures\u002Fmcp","3.modules\u002F3.features\u002F4.mcp",{"title":321,"icon":49,"path":322,"stem":323,"children":324,"page":49},"Interface","\u002Fmodules\u002Finterface","3.modules\u002F4.interface",[325,350,353,357,361],{"title":326,"path":327,"stem":328,"children":329},"UI","\u002Fmodules\u002Finterface\u002Fui","3.modules\u002F4.interface\u002F1.ui\u002Findex",[330,331,335,339,343,347],{"title":173,"path":327,"stem":328},{"title":332,"path":333,"stem":334},"Page components","\u002Fmodules\u002Finterface\u002Fui\u002Fpage-components","3.modules\u002F4.interface\u002F1.ui\u002F2.page-components",{"title":336,"path":337,"stem":338},"App shell","\u002Fmodules\u002Finterface\u002Fui\u002Fapp-shell","3.modules\u002F4.interface\u002F1.ui\u002F3.app-shell",{"title":340,"path":341,"stem":342},"Form inputs","\u002Fmodules\u002Finterface\u002Fui\u002Fform-inputs","3.modules\u002F4.interface\u002F1.ui\u002F4.form-inputs",{"title":344,"path":345,"stem":346},"Composables and helpers","\u002Fmodules\u002Finterface\u002Fui\u002Fcomposables","3.modules\u002F4.interface\u002F1.ui\u002F5.composables",{"title":179,"path":348,"stem":349},"\u002Fmodules\u002Finterface\u002Fui\u002Freference","3.modules\u002F4.interface\u002F1.ui\u002F6.reference",{"title":217,"path":351,"stem":352},"\u002Fmodules\u002Finterface\u002Fadmin","3.modules\u002F4.interface\u002F2.admin",{"title":354,"path":355,"stem":356},"Menu","\u002Fmodules\u002Finterface\u002Fmenu","3.modules\u002F4.interface\u002F3.menu",{"title":358,"path":359,"stem":360},"Widget","\u002Fmodules\u002Finterface\u002Fwidget","3.modules\u002F4.interface\u002F4.widget",{"title":362,"path":363,"stem":364,"children":365},"Mobile","\u002Fmodules\u002Finterface\u002Fmobile","3.modules\u002F4.interface\u002F5.mobile\u002Findex",[366,367,371],{"title":173,"path":363,"stem":364},{"title":368,"path":369,"stem":370},"CLI and devices","\u002Fmodules\u002Finterface\u002Fmobile\u002Fcli-and-devices","3.modules\u002F4.interface\u002F5.mobile\u002F2.cli-and-devices",{"title":372,"path":373,"stem":374},"Splash screen","\u002Fmodules\u002Finterface\u002Fmobile\u002Fsplash-screen","3.modules\u002F4.interface\u002F5.mobile\u002F3.splash-screen",{"title":376,"icon":49,"path":377,"stem":378,"children":379,"page":49},"Platform","\u002Fmodules\u002Fplatform","3.modules\u002F5.platform",[380,402,406,423],{"title":381,"path":382,"stem":383,"children":384},"Module Kit","\u002Fmodules\u002Fplatform\u002Fmodule-kit","3.modules\u002F5.platform\u002F1.module-kit\u002Findex",[385,386,390,394,398],{"title":173,"path":382,"stem":383},{"title":387,"path":388,"stem":389},"Server toolkit","\u002Fmodules\u002Fplatform\u002Fmodule-kit\u002Fserver-toolkit","3.modules\u002F5.platform\u002F1.module-kit\u002F2.server-toolkit",{"title":391,"path":392,"stem":393},"Registries and menus","\u002Fmodules\u002Fplatform\u002Fmodule-kit\u002Fregistries-and-menus","3.modules\u002F5.platform\u002F1.module-kit\u002F3.registries-and-menus",{"title":395,"path":396,"stem":397},"Translations","\u002Fmodules\u002Fplatform\u002Fmodule-kit\u002Fi18n","3.modules\u002F5.platform\u002F1.module-kit\u002F4.i18n",{"title":399,"path":400,"stem":401},"Database helpers","\u002Fmodules\u002Fplatform\u002Fmodule-kit\u002Fdatabase","3.modules\u002F5.platform\u002F1.module-kit\u002F5.database",{"title":403,"path":404,"stem":405},"Notify","\u002Fmodules\u002Fplatform\u002Fnotify","3.modules\u002F5.platform\u002F2.notify",{"title":407,"path":408,"stem":409,"children":410},"Email Templates","\u002Fmodules\u002Fplatform\u002Femail-templates","3.modules\u002F5.platform\u002F3.email-templates\u002Findex",[411,412,416,419],{"title":173,"path":408,"stem":409},{"title":413,"path":414,"stem":415},"Email components","\u002Fmodules\u002Fplatform\u002Femail-templates\u002Fcomponents","3.modules\u002F5.platform\u002F3.email-templates\u002F2.components",{"title":175,"path":417,"stem":418},"\u002Fmodules\u002Fplatform\u002Femail-templates\u002Fserver","3.modules\u002F5.platform\u002F3.email-templates\u002F3.server",{"title":420,"path":421,"stem":422},"Module emails","\u002Fmodules\u002Fplatform\u002Femail-templates\u002Fmodule-emails","3.modules\u002F5.platform\u002F3.email-templates\u002F4.module-emails",{"title":424,"path":425,"stem":426,"children":427},"Base Layer","\u002Fmodules\u002Fplatform\u002Fbase-layer","3.modules\u002F5.platform\u002F4.base-layer\u002Findex",[428,429,433,437],{"title":173,"path":425,"stem":426},{"title":430,"path":431,"stem":432},"Content collections","\u002Fmodules\u002Fplatform\u002Fbase-layer\u002Fcontent-collections","3.modules\u002F5.platform\u002F4.base-layer\u002F2.content-collections",{"title":434,"path":435,"stem":436},"Layouts and routing","\u002Fmodules\u002Fplatform\u002Fbase-layer\u002Flayouts-and-routing","3.modules\u002F5.platform\u002F4.base-layer\u002F3.layouts-and-routing",{"title":438,"path":439,"stem":440},"Composables and utils","\u002Fmodules\u002Fplatform\u002Fbase-layer\u002Fcomposables-and-utils","3.modules\u002F5.platform\u002F4.base-layer\u002F4.composables-and-utils",{"title":442,"icon":443,"path":444,"stem":445,"children":446,"page":49},"Examples","i-lucide-code-xml","\u002Fexamples","4.examples",[447,466,476],{"title":448,"icon":49,"path":449,"stem":450,"children":451,"page":49},"Starters","\u002Fexamples\u002Fstarters","4.examples\u002F1.starters",[452,456,461],{"title":453,"path":454,"stem":455,"icon":6},"Workspace starter","\u002Fexamples\u002Fstarters\u002Fworkspace","4.examples\u002F1.starters\u002F1.workspace",{"title":457,"path":458,"stem":459,"icon":460},"Mobile starter","\u002Fexamples\u002Fstarters\u002Fmobile","4.examples\u002F1.starters\u002F2.mobile","i-lucide-smartphone",{"title":462,"path":463,"stem":464,"icon":465},"Standalone mobile starter","\u002Fexamples\u002Fstarters\u002Fmobile-standalone","4.examples\u002F1.starters\u002F3.mobile-standalone","i-lucide-tablet-smartphone",{"title":467,"icon":49,"path":468,"stem":469,"children":470,"page":49},"Apps","\u002Fexamples\u002Fapps","4.examples\u002F2.apps",[471],{"title":472,"path":473,"stem":474,"icon":475},"Frigear website app","\u002Fexamples\u002Fapps\u002Ffrigear-nu-website","4.examples\u002F2.apps\u002F1.frigear-nu-website","i-lucide-layout-dashboard",{"title":477,"icon":49,"path":478,"stem":479,"children":480,"page":49},"Tasks","\u002Fexamples\u002Ftasks","4.examples\u002F3.tasks",[481,485,489,494,499],{"title":482,"path":483,"stem":484,"icon":70},"Protect a route","\u002Fexamples\u002Ftasks\u002Fprotect-a-route","4.examples\u002F3.tasks\u002F1.protect-a-route",{"title":486,"path":487,"stem":488,"icon":475},"Add an admin page","\u002Fexamples\u002Ftasks\u002Fadd-an-admin-page","4.examples\u002F3.tasks\u002F2.add-an-admin-page",{"title":490,"path":491,"stem":492,"icon":493},"Sell event tickets","\u002Fexamples\u002Ftasks\u002Fsell-event-tickets","4.examples\u002F3.tasks\u002F3.sell-event-tickets","i-lucide-ticket",{"title":495,"path":496,"stem":497,"icon":498},"Build a form","\u002Fexamples\u002Ftasks\u002Fbuild-a-form","4.examples\u002F3.tasks\u002F4.build-a-form","i-lucide-clipboard-list",{"title":500,"path":501,"stem":502,"icon":503},"Send an email","\u002Fexamples\u002Ftasks\u002Fsend-an-email","4.examples\u002F3.tasks\u002F5.send-an-email","i-lucide-mail",{"title":505,"icon":506,"path":507,"stem":508,"children":509,"page":49},"Contribute","i-lucide-git-pull-request","\u002Fcontribute","5.contribute",[510,513,518,544,549,552,556,571],{"title":173,"path":511,"stem":512,"icon":506},"\u002Fcontribute\u002Foverview","5.contribute\u002F1.overview",{"title":514,"path":515,"stem":516,"icon":517},"Local development","\u002Fcontribute\u002Flocal-development","5.contribute\u002F2.local-development","i-lucide-terminal",{"title":519,"icon":49,"path":520,"stem":521,"children":522,"page":49},"Writing a module","\u002Fcontribute\u002Fwriting-a-module","5.contribute\u002F3.writing-a-module",[523,527,532,536,541],{"title":524,"path":525,"stem":526,"icon":39},"Scaffold a module","\u002Fcontribute\u002Fwriting-a-module\u002Fscaffold","5.contribute\u002F3.writing-a-module\u002F1.scaffold",{"title":528,"path":529,"stem":530,"icon":531},"Setup checklist","\u002Fcontribute\u002Fwriting-a-module\u002Fsetup-checklist","5.contribute\u002F3.writing-a-module\u002F2.setup-checklist","i-lucide-list-checks",{"title":533,"path":534,"stem":535,"icon":44},"Database tables","\u002Fcontribute\u002Fwriting-a-module\u002Fdatabase-tables","5.contribute\u002F3.writing-a-module\u002F3.database-tables",{"title":537,"path":538,"stem":539,"icon":540},"Testing","\u002Fcontribute\u002Fwriting-a-module\u002Ftesting","5.contribute\u002F3.writing-a-module\u002F4.testing","i-lucide-flask-conical",{"title":67,"path":542,"stem":543,"icon":70},"\u002Fcontribute\u002Fwriting-a-module\u002Faccess-control","5.contribute\u002F3.writing-a-module\u002F5.access-control",{"title":545,"path":546,"stem":547,"icon":548},"Publishing","\u002Fcontribute\u002Fpublishing","5.contribute\u002F4.publishing","i-lucide-package-check",{"title":448,"path":550,"stem":551,"icon":6},"\u002Fcontribute\u002Fstarters","5.contribute\u002F5.starters",{"title":553,"path":554,"stem":555,"icon":52},"Documentation","\u002Fcontribute\u002Fdocumentation","5.contribute\u002F6.documentation",{"title":557,"icon":49,"path":558,"stem":559,"children":560,"page":49},"Tooling","\u002Fcontribute\u002Ftooling","5.contribute\u002F7.tooling",[561,566],{"title":562,"path":563,"stem":564,"icon":565},"CLI","\u002Fcontribute\u002Ftooling\u002Fcli","5.contribute\u002F7.tooling\u002F1.cli","i-lucide-square-terminal",{"title":567,"path":568,"stem":569,"icon":570},"ESLint config","\u002Fcontribute\u002Ftooling\u002Feslint-config","5.contribute\u002F7.tooling\u002F2.eslint-config","i-lucide-spell-check",{"title":572,"icon":49,"path":573,"stem":574,"children":575},"Decisions","\u002Fcontribute\u002Fdecisions","5.contribute\u002F8.decisions\u002Findex",[576,578,583],{"title":572,"path":573,"stem":574,"icon":577},"i-lucide-scale",{"title":579,"path":580,"stem":581,"icon":582},"Session lifetimes per OAuth client","\u002Fcontribute\u002Fdecisions\u002Foauth-token-lifetimes","5.contribute\u002F8.decisions\u002F1.oauth-token-lifetimes","i-lucide-timer",{"title":584,"path":585,"stem":586,"icon":70},"One permission model","\u002Fcontribute\u002Fdecisions\u002Fpermission-model","5.contribute\u002F8.decisions\u002F2.permission-model",{"id":588,"title":106,"body":589,"description":2879,"extension":2880,"links":2881,"meta":2882,"navigation":2883,"path":107,"seo":2884,"stem":108,"__hash__":2885},"docs\u002F2.guide\u002F2.ux-patterns\u002F3.forms-and-actions.md",{"type":590,"value":591,"toc":2869},"minimark",[592,596,605,612,617,711,714,721,724,730,1647,1651,1658,1665,1682,1685,1689,1707,1724,1731,2618,2622,2633,2646,2715,2734,2738,2749,2760,2766,2770,2802,2809,2813,2816,2827,2833,2837,2865],[593,594,595],"p",{},"Every change a user makes should feel the same, whichever module owns the record. Writes follow one path: a button\nopens a form, the form resolves with the saved record, and one composable per entity owns the toasts and the refresh.\nThis page covers that path: create and edit forms, row menus, confirmations for destructive actions and feedback.",[597,598,600,604],"callout",{"icon":599},"i-lucide-users",[601,602,603],"strong",{},"For:"," module authors and app developers who add a screen that changes data.",[593,606,607,608,611],{},"The screens that show the results are on ",[609,610,101],"a",{"href":102},".",[613,614,616],"h2",{"id":615},"create-and-edit","Create and edit",[618,619,620,636,646,652,666,676,690],"ul",{},[621,622,623,626,627,631,632,635],"li",{},[601,624,625],{},"Slideover."," Create and edit forms open in a slideover (",[628,629,630],"code",{},"FormSlideover",") that holds a ",[628,633,634],{},"UForm"," with a zod schema.",[621,637,638,641,642,645],{},[601,639,640],{},"Modal."," A short yes or no choice is a modal (",[628,643,644],{},"UModal",").",[621,647,648,651],{},[601,649,650],{},"Never inline."," Never put a create form next to a table.",[621,653,654,657,658,661,662,665],{},[601,655,656],{},"Open through an overlay."," Open forms with ",[628,659,660],{},"useOverlay()",". The overlay resolves with the saved record, or ",[628,663,664],{},"false","\nwhen cancelled, so the caller can navigate to it.",[621,667,668,671,672,675],{},[601,669,670],{},"Buttons."," Cancel is a neutral outline button (",[628,673,674],{},"color=\"neutral\" variant=\"outline\"","). The primary action comes\nlast. The slideover component sets up both for you.",[621,677,678,681,682,685,686,689],{},[601,679,680],{},"Hints."," A hint goes in ",[628,683,684],{},"UFormField","'s ",[628,687,688],{},"description",", not in an extra paragraph.",[621,691,692,695,696,698,699,702,703,706,707,611],{},[601,693,694],{},"Layout."," Slideover forms stay vertical, with plain ",[628,697,684],{},"s. Inline settings forms in a ",[628,700,701],{},"SectionCard"," use\nhorizontal ",[628,704,705],{},"FormRow"," rows. See ",[609,708,710],{"href":709},"\u002Fguide\u002Fux-patterns\u002Fpages#detail-pages","Detail pages",[593,712,713],{},"A create form opens in a slideover over the list, with Cancel and the primary action at the bottom:",[593,715,716],{},[717,718],"img",{"alt":719,"src":720},"The New event slideover open over the events list, with a filled form and Cancel and Create draft buttons at the bottom.","\u002Fimages\u002Fux-patterns\u002Fforms-and-actions-create.png",[593,722,723],{},"An inline settings form puts label and control rows in a section card, with Save in the card's footer:",[593,725,726],{},[717,727],{"alt":728,"src":729},"An account settings page: section cards with label and control rows, each hint under its label, and the save button in the card footer.","\u002Fimages\u002Fux-patterns\u002Fforms-and-actions-settings.png",[731,732,737],"pre",{"className":733,"code":734,"language":735,"meta":736,"style":736},"language-vue shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003C!-- EventFormSlideover.vue -->\n\u003Cscript setup lang=\"ts\">\nconst props = defineProps\u003C{ event?: EventRow }>()\nconst emit = defineEmits\u003C{ close: [saved: EventRow | false] }>()\n\nconst t = useModuleT('events')\nconst { busy, run } = useAction()\nconst state = reactive({ title: props.event?.title ?? '' })\n\nconst save = () => run(async () => {\n  const saved = await $fetch\u003CEventRow>(props.event ? `\u002Fapi\u002Fadmin\u002Fevents\u002F${props.event.id}` : '\u002Fapi\u002Fadmin\u002Fevents', {\n    method: props.event ? 'PATCH' : 'POST',\n    body: state,\n  })\n  emit('close', saved)\n}, { success: t('admin.saved', 'Event saved') })\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CFormSlideover\n    form-id=\"event-form\"\n    :title=\"event ? t('admin.edit', 'Edit event') : t('admin.create', 'New event')\"\n    :submit-label=\"event ? t('admin.save', 'Save event') : t('admin.create', 'New event')\"\n    :loading=\"busy\"\n    @close=\"emit('close', false)\"\n  >\n    \u003CUForm id=\"event-form\" :state=\"state\" class=\"flex flex-col gap-4\" @submit=\"save\">\n      \u003CUFormField name=\"title\" :label=\"t('admin.title', 'Title')\" :description=\"t('admin.titleHint', 'Shown on the public page.')\">\n        \u003CUInput v-model=\"state.title\" \u002F>\n      \u003C\u002FUFormField>\n    \u003C\u002FUForm>\n  \u003C\u002FFormSlideover>\n\u003C\u002Ftemplate>\n","vue","",[628,738,739,748,781,816,861,868,895,923,971,976,1007,1083,1118,1131,1139,1160,1201,1211,1216,1226,1235,1251,1319,1379,1396,1428,1434,1495,1581,1608,1618,1628,1638],{"__ignoreMap":736},[740,741,744],"span",{"class":742,"line":743},"line",1,[740,745,747],{"class":746},"sHwdD","\u003C!-- EventFormSlideover.vue -->\n",[740,749,751,755,759,763,766,769,772,776,778],{"class":742,"line":750},2,[740,752,754],{"class":753},"sMK4o","\u003C",[740,756,758],{"class":757},"swJcz","script",[740,760,762],{"class":761},"spNyl"," setup",[740,764,765],{"class":761}," lang",[740,767,768],{"class":753},"=",[740,770,771],{"class":753},"\"",[740,773,775],{"class":774},"sfazB","ts",[740,777,771],{"class":753},[740,779,780],{"class":753},">\n",[740,782,784,787,791,793,797,800,803,806,810,813],{"class":742,"line":783},3,[740,785,786],{"class":761},"const",[740,788,790],{"class":789},"sTEyZ"," props ",[740,792,768],{"class":753},[740,794,796],{"class":795},"s2Zo4"," defineProps",[740,798,799],{"class":753},"\u003C{",[740,801,802],{"class":757}," event",[740,804,805],{"class":753},"?:",[740,807,809],{"class":808},"sBMFI"," EventRow",[740,811,812],{"class":753}," }>",[740,814,815],{"class":789},"()\n",[740,817,819,821,824,826,829,831,834,837,840,843,845,847,850,853,856,859],{"class":742,"line":818},4,[740,820,786],{"class":761},[740,822,823],{"class":789}," emit ",[740,825,768],{"class":753},[740,827,828],{"class":795}," defineEmits",[740,830,799],{"class":753},[740,832,833],{"class":757}," close",[740,835,836],{"class":753},":",[740,838,839],{"class":789}," [",[740,841,842],{"class":808},"saved",[740,844,836],{"class":753},[740,846,809],{"class":808},[740,848,849],{"class":753}," |",[740,851,852],{"class":808}," false",[740,854,855],{"class":789},"] ",[740,857,858],{"class":753},"}>",[740,860,815],{"class":789},[740,862,864],{"class":742,"line":863},5,[740,865,867],{"emptyLinePlaceholder":866},true,"\n",[740,869,871,873,876,878,881,884,887,890,892],{"class":742,"line":870},6,[740,872,786],{"class":761},[740,874,875],{"class":789}," t ",[740,877,768],{"class":753},[740,879,880],{"class":795}," useModuleT",[740,882,883],{"class":789},"(",[740,885,886],{"class":753},"'",[740,888,889],{"class":774},"events",[740,891,886],{"class":753},[740,893,894],{"class":789},")\n",[740,896,898,900,903,906,909,912,915,918,921],{"class":742,"line":897},7,[740,899,786],{"class":761},[740,901,902],{"class":753}," {",[740,904,905],{"class":789}," busy",[740,907,908],{"class":753},",",[740,910,911],{"class":789}," run ",[740,913,914],{"class":753},"}",[740,916,917],{"class":753}," =",[740,919,920],{"class":795}," useAction",[740,922,815],{"class":789},[740,924,926,928,931,933,936,938,941,944,946,949,951,954,957,960,963,966,969],{"class":742,"line":925},8,[740,927,786],{"class":761},[740,929,930],{"class":789}," state ",[740,932,768],{"class":753},[740,934,935],{"class":795}," reactive",[740,937,883],{"class":789},[740,939,940],{"class":753},"{",[740,942,943],{"class":757}," title",[740,945,836],{"class":753},[740,947,948],{"class":789}," props",[740,950,611],{"class":753},[740,952,953],{"class":789},"event",[740,955,956],{"class":753},"?.",[740,958,959],{"class":789},"title ",[740,961,962],{"class":753},"??",[740,964,965],{"class":753}," ''",[740,967,968],{"class":753}," }",[740,970,894],{"class":789},[740,972,974],{"class":742,"line":973},9,[740,975,867],{"emptyLinePlaceholder":866},[740,977,979,981,984,986,989,992,995,997,1000,1002,1004],{"class":742,"line":978},10,[740,980,786],{"class":761},[740,982,983],{"class":789}," save ",[740,985,768],{"class":753},[740,987,988],{"class":753}," ()",[740,990,991],{"class":761}," =>",[740,993,994],{"class":795}," run",[740,996,883],{"class":789},[740,998,999],{"class":761},"async",[740,1001,988],{"class":753},[740,1003,991],{"class":761},[740,1005,1006],{"class":753}," {\n",[740,1008,1010,1013,1016,1018,1022,1025,1027,1030,1033,1035,1038,1040,1042,1045,1048,1051,1054,1056,1058,1060,1062,1065,1068,1071,1074,1077,1079,1081],{"class":742,"line":1009},11,[740,1011,1012],{"class":761},"  const",[740,1014,1015],{"class":789}," saved",[740,1017,917],{"class":753},[740,1019,1021],{"class":1020},"s7zQu"," await",[740,1023,1024],{"class":795}," $fetch",[740,1026,754],{"class":753},[740,1028,1029],{"class":808},"EventRow",[740,1031,1032],{"class":753},">",[740,1034,883],{"class":757},[740,1036,1037],{"class":789},"props",[740,1039,611],{"class":753},[740,1041,953],{"class":789},[740,1043,1044],{"class":753}," ?",[740,1046,1047],{"class":753}," `",[740,1049,1050],{"class":774},"\u002Fapi\u002Fadmin\u002Fevents\u002F",[740,1052,1053],{"class":753},"${",[740,1055,1037],{"class":789},[740,1057,611],{"class":753},[740,1059,953],{"class":789},[740,1061,611],{"class":753},[740,1063,1064],{"class":789},"id",[740,1066,1067],{"class":753},"}`",[740,1069,1070],{"class":753}," :",[740,1072,1073],{"class":753}," '",[740,1075,1076],{"class":774},"\u002Fapi\u002Fadmin\u002Fevents",[740,1078,886],{"class":753},[740,1080,908],{"class":753},[740,1082,1006],{"class":753},[740,1084,1086,1089,1091,1093,1095,1097,1099,1101,1104,1106,1108,1110,1113,1115],{"class":742,"line":1085},12,[740,1087,1088],{"class":757},"    method",[740,1090,836],{"class":753},[740,1092,948],{"class":789},[740,1094,611],{"class":753},[740,1096,953],{"class":789},[740,1098,1044],{"class":753},[740,1100,1073],{"class":753},[740,1102,1103],{"class":774},"PATCH",[740,1105,886],{"class":753},[740,1107,1070],{"class":753},[740,1109,1073],{"class":753},[740,1111,1112],{"class":774},"POST",[740,1114,886],{"class":753},[740,1116,1117],{"class":753},",\n",[740,1119,1121,1124,1126,1129],{"class":742,"line":1120},13,[740,1122,1123],{"class":757},"    body",[740,1125,836],{"class":753},[740,1127,1128],{"class":789}," state",[740,1130,1117],{"class":753},[740,1132,1134,1137],{"class":742,"line":1133},14,[740,1135,1136],{"class":753},"  }",[740,1138,894],{"class":757},[740,1140,1142,1145,1147,1149,1152,1154,1156,1158],{"class":742,"line":1141},15,[740,1143,1144],{"class":795},"  emit",[740,1146,883],{"class":757},[740,1148,886],{"class":753},[740,1150,1151],{"class":774},"close",[740,1153,886],{"class":753},[740,1155,908],{"class":753},[740,1157,1015],{"class":789},[740,1159,894],{"class":757},[740,1161,1163,1166,1168,1171,1173,1176,1178,1180,1183,1185,1187,1189,1192,1194,1197,1199],{"class":742,"line":1162},16,[740,1164,1165],{"class":753},"},",[740,1167,902],{"class":753},[740,1169,1170],{"class":757}," success",[740,1172,836],{"class":753},[740,1174,1175],{"class":795}," t",[740,1177,883],{"class":789},[740,1179,886],{"class":753},[740,1181,1182],{"class":774},"admin.saved",[740,1184,886],{"class":753},[740,1186,908],{"class":753},[740,1188,1073],{"class":753},[740,1190,1191],{"class":774},"Event saved",[740,1193,886],{"class":753},[740,1195,1196],{"class":789},") ",[740,1198,914],{"class":753},[740,1200,894],{"class":789},[740,1202,1204,1207,1209],{"class":742,"line":1203},17,[740,1205,1206],{"class":753},"\u003C\u002F",[740,1208,758],{"class":757},[740,1210,780],{"class":753},[740,1212,1214],{"class":742,"line":1213},18,[740,1215,867],{"emptyLinePlaceholder":866},[740,1217,1219,1221,1224],{"class":742,"line":1218},19,[740,1220,754],{"class":753},[740,1222,1223],{"class":757},"template",[740,1225,780],{"class":753},[740,1227,1229,1232],{"class":742,"line":1228},20,[740,1230,1231],{"class":753},"  \u003C",[740,1233,1234],{"class":757},"FormSlideover\n",[740,1236,1238,1241,1243,1245,1248],{"class":742,"line":1237},21,[740,1239,1240],{"class":761},"    form-id",[740,1242,768],{"class":753},[740,1244,771],{"class":753},[740,1246,1247],{"class":774},"event-form",[740,1249,1250],{"class":753},"\"\n",[740,1252,1254,1257,1260,1262,1264,1266,1269,1272,1274,1276,1279,1281,1284,1286,1289,1291,1294,1296,1298,1300,1303,1305,1307,1309,1312,1314,1317],{"class":742,"line":1253},22,[740,1255,1256],{"class":753},"    :",[740,1258,1259],{"class":761},"title",[740,1261,768],{"class":753},[740,1263,771],{"class":753},[740,1265,953],{"class":789},[740,1267,1268],{"class":753}," ? ",[740,1270,1271],{"class":795},"t",[740,1273,883],{"class":753},[740,1275,886],{"class":753},[740,1277,1278],{"class":774},"admin.edit",[740,1280,886],{"class":753},[740,1282,1283],{"class":753},", ",[740,1285,886],{"class":753},[740,1287,1288],{"class":774},"Edit event",[740,1290,886],{"class":753},[740,1292,1293],{"class":753},") : ",[740,1295,1271],{"class":795},[740,1297,883],{"class":753},[740,1299,886],{"class":753},[740,1301,1302],{"class":774},"admin.create",[740,1304,886],{"class":753},[740,1306,1283],{"class":753},[740,1308,886],{"class":753},[740,1310,1311],{"class":774},"New event",[740,1313,886],{"class":753},[740,1315,1316],{"class":753},")",[740,1318,1250],{"class":753},[740,1320,1322,1324,1327,1329,1331,1333,1335,1337,1339,1341,1344,1346,1348,1350,1353,1355,1357,1359,1361,1363,1365,1367,1369,1371,1373,1375,1377],{"class":742,"line":1321},23,[740,1323,1256],{"class":753},[740,1325,1326],{"class":761},"submit-label",[740,1328,768],{"class":753},[740,1330,771],{"class":753},[740,1332,953],{"class":789},[740,1334,1268],{"class":753},[740,1336,1271],{"class":795},[740,1338,883],{"class":753},[740,1340,886],{"class":753},[740,1342,1343],{"class":774},"admin.save",[740,1345,886],{"class":753},[740,1347,1283],{"class":753},[740,1349,886],{"class":753},[740,1351,1352],{"class":774},"Save event",[740,1354,886],{"class":753},[740,1356,1293],{"class":753},[740,1358,1271],{"class":795},[740,1360,883],{"class":753},[740,1362,886],{"class":753},[740,1364,1302],{"class":774},[740,1366,886],{"class":753},[740,1368,1283],{"class":753},[740,1370,886],{"class":753},[740,1372,1311],{"class":774},[740,1374,886],{"class":753},[740,1376,1316],{"class":753},[740,1378,1250],{"class":753},[740,1380,1382,1384,1387,1389,1391,1394],{"class":742,"line":1381},24,[740,1383,1256],{"class":753},[740,1385,1386],{"class":761},"loading",[740,1388,768],{"class":753},[740,1390,771],{"class":753},[740,1392,1393],{"class":789},"busy",[740,1395,1250],{"class":753},[740,1397,1399,1402,1404,1406,1408,1411,1413,1415,1417,1419,1421,1424,1426],{"class":742,"line":1398},25,[740,1400,1401],{"class":753},"    @",[740,1403,1151],{"class":761},[740,1405,768],{"class":753},[740,1407,771],{"class":753},[740,1409,1410],{"class":795},"emit",[740,1412,883],{"class":753},[740,1414,886],{"class":753},[740,1416,1151],{"class":774},[740,1418,886],{"class":753},[740,1420,1283],{"class":753},[740,1422,664],{"class":1423},"sfNiH",[740,1425,1316],{"class":753},[740,1427,1250],{"class":753},[740,1429,1431],{"class":742,"line":1430},26,[740,1432,1433],{"class":753},"  >\n",[740,1435,1437,1440,1442,1445,1447,1449,1451,1453,1455,1458,1460,1462,1464,1466,1469,1471,1473,1476,1478,1481,1484,1486,1488,1491,1493],{"class":742,"line":1436},27,[740,1438,1439],{"class":753},"    \u003C",[740,1441,634],{"class":757},[740,1443,1444],{"class":761}," id",[740,1446,768],{"class":753},[740,1448,771],{"class":753},[740,1450,1247],{"class":774},[740,1452,771],{"class":753},[740,1454,1070],{"class":753},[740,1456,1457],{"class":761},"state",[740,1459,768],{"class":753},[740,1461,771],{"class":753},[740,1463,1457],{"class":789},[740,1465,771],{"class":753},[740,1467,1468],{"class":761}," class",[740,1470,768],{"class":753},[740,1472,771],{"class":753},[740,1474,1475],{"class":774},"flex flex-col gap-4",[740,1477,771],{"class":753},[740,1479,1480],{"class":753}," @",[740,1482,1483],{"class":761},"submit",[740,1485,768],{"class":753},[740,1487,771],{"class":753},[740,1489,1490],{"class":789},"save",[740,1492,771],{"class":753},[740,1494,780],{"class":753},[740,1496,1498,1501,1503,1506,1508,1510,1512,1514,1516,1519,1521,1523,1525,1527,1529,1532,1534,1536,1538,1541,1543,1545,1547,1549,1551,1553,1555,1557,1559,1561,1564,1566,1568,1570,1573,1575,1577,1579],{"class":742,"line":1497},28,[740,1499,1500],{"class":753},"      \u003C",[740,1502,684],{"class":757},[740,1504,1505],{"class":761}," name",[740,1507,768],{"class":753},[740,1509,771],{"class":753},[740,1511,1259],{"class":774},[740,1513,771],{"class":753},[740,1515,1070],{"class":753},[740,1517,1518],{"class":761},"label",[740,1520,768],{"class":753},[740,1522,771],{"class":753},[740,1524,1271],{"class":795},[740,1526,883],{"class":753},[740,1528,886],{"class":753},[740,1530,1531],{"class":774},"admin.title",[740,1533,886],{"class":753},[740,1535,1283],{"class":753},[740,1537,886],{"class":753},[740,1539,1540],{"class":774},"Title",[740,1542,886],{"class":753},[740,1544,1316],{"class":753},[740,1546,771],{"class":753},[740,1548,1070],{"class":753},[740,1550,688],{"class":761},[740,1552,768],{"class":753},[740,1554,771],{"class":753},[740,1556,1271],{"class":795},[740,1558,883],{"class":753},[740,1560,886],{"class":753},[740,1562,1563],{"class":774},"admin.titleHint",[740,1565,886],{"class":753},[740,1567,1283],{"class":753},[740,1569,886],{"class":753},[740,1571,1572],{"class":774},"Shown on the public page.",[740,1574,886],{"class":753},[740,1576,1316],{"class":753},[740,1578,771],{"class":753},[740,1580,780],{"class":753},[740,1582,1584,1587,1590,1593,1595,1597,1599,1601,1603,1605],{"class":742,"line":1583},29,[740,1585,1586],{"class":753},"        \u003C",[740,1588,1589],{"class":757},"UInput",[740,1591,1592],{"class":761}," v-model",[740,1594,768],{"class":753},[740,1596,771],{"class":753},[740,1598,1457],{"class":789},[740,1600,611],{"class":753},[740,1602,1259],{"class":789},[740,1604,771],{"class":753},[740,1606,1607],{"class":753}," \u002F>\n",[740,1609,1611,1614,1616],{"class":742,"line":1610},30,[740,1612,1613],{"class":753},"      \u003C\u002F",[740,1615,684],{"class":757},[740,1617,780],{"class":753},[740,1619,1621,1624,1626],{"class":742,"line":1620},31,[740,1622,1623],{"class":753},"    \u003C\u002F",[740,1625,634],{"class":757},[740,1627,780],{"class":753},[740,1629,1631,1634,1636],{"class":742,"line":1630},32,[740,1632,1633],{"class":753},"  \u003C\u002F",[740,1635,630],{"class":757},[740,1637,780],{"class":753},[740,1639,1641,1643,1645],{"class":742,"line":1640},33,[740,1642,1206],{"class":753},[740,1644,1223],{"class":757},[740,1646,780],{"class":753},[613,1648,1650],{"id":1649},"create-button","Create button",[593,1652,1653,1654,1657],{},"The primary create button has ",[628,1655,1656],{},"icon=\"i-lucide-plus\"",". Its label names the object, such as \"New event\" or \"Add user\".",[593,1659,1660,1661,1664],{},"The page only calls ",[628,1662,1663],{},"actions.create()",". The actions composable does the rest:",[1666,1667,1668,1673,1676],"ol",{},[621,1669,1670,1671,611],{},"It opens the ",[628,1672,630],{},[621,1674,1675],{},"It navigates to the detail page, when the entity has one.",[621,1677,1678,1679,1681],{},"It returns the record, or ",[628,1680,664],{}," when cancelled.",[593,1683,1684],{},"The page never navigates itself.",[613,1686,1688],{"id":1687},"one-actions-composable-per-entity","One actions composable per entity",[593,1690,1691,1692,1695,1696,1283,1699,1702,1703,1706],{},"Every entity has one actions composable, named ",[628,1693,1694],{},"use\u003CEntity>Actions()",", such as ",[628,1697,1698],{},"useUserActions",[628,1700,1701],{},"useEventActions","\nor ",[628,1704,1705],{},"useFormActions",". It keeps pages thin and every page consistent:",[618,1708,1709,1712,1719],{},[621,1710,1711],{},"It owns create, edit and remove, the toasts and the refresh afterwards.",[621,1713,1714,1715,1718],{},"It returns ",[628,1716,1717],{},"menu(record)"," for the row menu. So every list and detail page offers the same actions in the same order.",[621,1720,1721,1722,611],{},"It lives in the module that owns the entity, not in ",[609,1723,326],{"href":327},[593,1725,1726,1727,1730],{},"Sub-entities that have no page of their own, such as an event's ticket types and add-ons, get a composable of their\nown too. Its menus skip Open. ",[628,1728,1729],{},"useEventCatalogActions"," is the example.",[731,1732,1735],{"className":1733,"code":1734,"language":775,"meta":736,"style":736},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F composables\u002FuseEventActions.ts\nexport function useEventActions() {\n  const t = useModuleT('events')\n  const overlay = useOverlay()\n  const confirm = useConfirmDialog()\n  const toast = useToast()\n  const { localize } = useLocaleLink()\n\n  async function create() {\n    const saved = await overlay.create(EventFormSlideover).open()\n    if (saved) await navigateTo(localize(`\u002Fadmin\u002Fevents\u002F${saved.id}`))\n  }\n\n  async function remove(event: EventRow) {\n    const confirmed = await confirm({\n      title: t('admin.deleteTitle', 'Delete {name}?', { name: event.title }),\n      description: t('admin.deleteBody', 'Its tickets and attendees are deleted too. This cannot be undone.'),\n      confirmText: t('admin.delete', 'Delete event'),\n      destructive: true,\n    })\n    if (!confirmed) return\n    try {\n      await $fetch(`\u002Fapi\u002Fadmin\u002Fevents\u002F${event.id}`, { method: 'DELETE' })\n      toast.add({ title: t('admin.deleted', 'Event deleted'), description: event.title })\n      await refreshNuxtData('events')\n    }\n    catch (e) {\n      toast.add(errorToToast(e))\n    }\n  }\n\n  const menu = (event: EventRow) => [\n    [{ label: t('open', 'Open'), icon: 'i-lucide-arrow-right', to: localize(`\u002Fadmin\u002Fevents\u002F${event.id}`) }],\n    [{ label: t('admin.edit', 'Edit event'), icon: 'i-lucide-pencil', onSelect: () => overlay.create(EventFormSlideover).open({ event }) }],\n    [{ label: t('admin.delete', 'Delete event'), icon: 'i-lucide-trash-2', color: 'error' as const, onSelect: () => remove(event) }],\n  ]\n\n  return { create, remove, menu }\n}\n",[628,1736,1737,1742,1758,1778,1792,1806,1820,1838,1842,1856,1888,1932,1937,1941,1963,1981,2028,2059,2090,2102,2109,2126,2133,2176,2233,2250,2255,2269,2288,2292,2296,2300,2324,2405,2492,2580,2586,2591,2612],{"__ignoreMap":736},[740,1738,1739],{"class":742,"line":743},[740,1740,1741],{"class":746},"\u002F\u002F composables\u002FuseEventActions.ts\n",[740,1743,1744,1747,1750,1753,1756],{"class":742,"line":750},[740,1745,1746],{"class":1020},"export",[740,1748,1749],{"class":761}," function",[740,1751,1752],{"class":795}," useEventActions",[740,1754,1755],{"class":753},"()",[740,1757,1006],{"class":753},[740,1759,1760,1762,1764,1766,1768,1770,1772,1774,1776],{"class":742,"line":783},[740,1761,1012],{"class":761},[740,1763,1175],{"class":789},[740,1765,917],{"class":753},[740,1767,880],{"class":795},[740,1769,883],{"class":757},[740,1771,886],{"class":753},[740,1773,889],{"class":774},[740,1775,886],{"class":753},[740,1777,894],{"class":757},[740,1779,1780,1782,1785,1787,1790],{"class":742,"line":818},[740,1781,1012],{"class":761},[740,1783,1784],{"class":789}," overlay",[740,1786,917],{"class":753},[740,1788,1789],{"class":795}," useOverlay",[740,1791,815],{"class":757},[740,1793,1794,1796,1799,1801,1804],{"class":742,"line":863},[740,1795,1012],{"class":761},[740,1797,1798],{"class":789}," confirm",[740,1800,917],{"class":753},[740,1802,1803],{"class":795}," useConfirmDialog",[740,1805,815],{"class":757},[740,1807,1808,1810,1813,1815,1818],{"class":742,"line":870},[740,1809,1012],{"class":761},[740,1811,1812],{"class":789}," toast",[740,1814,917],{"class":753},[740,1816,1817],{"class":795}," useToast",[740,1819,815],{"class":757},[740,1821,1822,1824,1826,1829,1831,1833,1836],{"class":742,"line":897},[740,1823,1012],{"class":761},[740,1825,902],{"class":753},[740,1827,1828],{"class":789}," localize",[740,1830,968],{"class":753},[740,1832,917],{"class":753},[740,1834,1835],{"class":795}," useLocaleLink",[740,1837,815],{"class":757},[740,1839,1840],{"class":742,"line":925},[740,1841,867],{"emptyLinePlaceholder":866},[740,1843,1844,1847,1849,1852,1854],{"class":742,"line":973},[740,1845,1846],{"class":761},"  async",[740,1848,1749],{"class":761},[740,1850,1851],{"class":795}," create",[740,1853,1755],{"class":753},[740,1855,1006],{"class":753},[740,1857,1858,1861,1863,1865,1867,1869,1871,1874,1876,1879,1881,1883,1886],{"class":742,"line":978},[740,1859,1860],{"class":761},"    const",[740,1862,1015],{"class":789},[740,1864,917],{"class":753},[740,1866,1021],{"class":1020},[740,1868,1784],{"class":789},[740,1870,611],{"class":753},[740,1872,1873],{"class":795},"create",[740,1875,883],{"class":757},[740,1877,1878],{"class":789},"EventFormSlideover",[740,1880,1316],{"class":757},[740,1882,611],{"class":753},[740,1884,1885],{"class":795},"open",[740,1887,815],{"class":757},[740,1889,1890,1893,1896,1898,1900,1903,1906,1908,1911,1913,1916,1919,1921,1923,1925,1927,1929],{"class":742,"line":1009},[740,1891,1892],{"class":1020},"    if",[740,1894,1895],{"class":757}," (",[740,1897,842],{"class":789},[740,1899,1196],{"class":757},[740,1901,1902],{"class":1020},"await",[740,1904,1905],{"class":795}," navigateTo",[740,1907,883],{"class":757},[740,1909,1910],{"class":795},"localize",[740,1912,883],{"class":757},[740,1914,1915],{"class":753},"`",[740,1917,1918],{"class":774},"\u002Fadmin\u002Fevents\u002F",[740,1920,1053],{"class":753},[740,1922,842],{"class":789},[740,1924,611],{"class":753},[740,1926,1064],{"class":789},[740,1928,1067],{"class":753},[740,1930,1931],{"class":757},"))\n",[740,1933,1934],{"class":742,"line":1085},[740,1935,1936],{"class":753},"  }\n",[740,1938,1939],{"class":742,"line":1120},[740,1940,867],{"emptyLinePlaceholder":866},[740,1942,1943,1945,1947,1950,1952,1955,1957,1959,1961],{"class":742,"line":1133},[740,1944,1846],{"class":761},[740,1946,1749],{"class":761},[740,1948,1949],{"class":795}," remove",[740,1951,883],{"class":753},[740,1953,953],{"class":1954},"sHdIc",[740,1956,836],{"class":753},[740,1958,809],{"class":808},[740,1960,1316],{"class":753},[740,1962,1006],{"class":753},[740,1964,1965,1967,1970,1972,1974,1976,1978],{"class":742,"line":1141},[740,1966,1860],{"class":761},[740,1968,1969],{"class":789}," confirmed",[740,1971,917],{"class":753},[740,1973,1021],{"class":1020},[740,1975,1798],{"class":795},[740,1977,883],{"class":757},[740,1979,1980],{"class":753},"{\n",[740,1982,1983,1986,1988,1990,1992,1994,1997,1999,2001,2003,2006,2008,2010,2012,2014,2016,2018,2020,2022,2024,2026],{"class":742,"line":1162},[740,1984,1985],{"class":757},"      title",[740,1987,836],{"class":753},[740,1989,1175],{"class":795},[740,1991,883],{"class":757},[740,1993,886],{"class":753},[740,1995,1996],{"class":774},"admin.deleteTitle",[740,1998,886],{"class":753},[740,2000,908],{"class":753},[740,2002,1073],{"class":753},[740,2004,2005],{"class":774},"Delete {name}?",[740,2007,886],{"class":753},[740,2009,908],{"class":753},[740,2011,902],{"class":753},[740,2013,1505],{"class":757},[740,2015,836],{"class":753},[740,2017,802],{"class":789},[740,2019,611],{"class":753},[740,2021,1259],{"class":789},[740,2023,968],{"class":753},[740,2025,1316],{"class":757},[740,2027,1117],{"class":753},[740,2029,2030,2033,2035,2037,2039,2041,2044,2046,2048,2050,2053,2055,2057],{"class":742,"line":1203},[740,2031,2032],{"class":757},"      description",[740,2034,836],{"class":753},[740,2036,1175],{"class":795},[740,2038,883],{"class":757},[740,2040,886],{"class":753},[740,2042,2043],{"class":774},"admin.deleteBody",[740,2045,886],{"class":753},[740,2047,908],{"class":753},[740,2049,1073],{"class":753},[740,2051,2052],{"class":774},"Its tickets and attendees are deleted too. This cannot be undone.",[740,2054,886],{"class":753},[740,2056,1316],{"class":757},[740,2058,1117],{"class":753},[740,2060,2061,2064,2066,2068,2070,2072,2075,2077,2079,2081,2084,2086,2088],{"class":742,"line":1213},[740,2062,2063],{"class":757},"      confirmText",[740,2065,836],{"class":753},[740,2067,1175],{"class":795},[740,2069,883],{"class":757},[740,2071,886],{"class":753},[740,2073,2074],{"class":774},"admin.delete",[740,2076,886],{"class":753},[740,2078,908],{"class":753},[740,2080,1073],{"class":753},[740,2082,2083],{"class":774},"Delete event",[740,2085,886],{"class":753},[740,2087,1316],{"class":757},[740,2089,1117],{"class":753},[740,2091,2092,2095,2097,2100],{"class":742,"line":1218},[740,2093,2094],{"class":757},"      destructive",[740,2096,836],{"class":753},[740,2098,2099],{"class":1423}," true",[740,2101,1117],{"class":753},[740,2103,2104,2107],{"class":742,"line":1228},[740,2105,2106],{"class":753},"    }",[740,2108,894],{"class":757},[740,2110,2111,2113,2115,2118,2121,2123],{"class":742,"line":1237},[740,2112,1892],{"class":1020},[740,2114,1895],{"class":757},[740,2116,2117],{"class":753},"!",[740,2119,2120],{"class":789},"confirmed",[740,2122,1196],{"class":757},[740,2124,2125],{"class":1020},"return\n",[740,2127,2128,2131],{"class":742,"line":1253},[740,2129,2130],{"class":1020},"    try",[740,2132,1006],{"class":753},[740,2134,2135,2138,2140,2142,2144,2146,2148,2150,2152,2154,2156,2158,2160,2163,2165,2167,2170,2172,2174],{"class":742,"line":1321},[740,2136,2137],{"class":1020},"      await",[740,2139,1024],{"class":795},[740,2141,883],{"class":757},[740,2143,1915],{"class":753},[740,2145,1050],{"class":774},[740,2147,1053],{"class":753},[740,2149,953],{"class":789},[740,2151,611],{"class":753},[740,2153,1064],{"class":789},[740,2155,1067],{"class":753},[740,2157,908],{"class":753},[740,2159,902],{"class":753},[740,2161,2162],{"class":757}," method",[740,2164,836],{"class":753},[740,2166,1073],{"class":753},[740,2168,2169],{"class":774},"DELETE",[740,2171,886],{"class":753},[740,2173,968],{"class":753},[740,2175,894],{"class":757},[740,2177,2178,2181,2183,2186,2188,2190,2192,2194,2196,2198,2200,2203,2205,2207,2209,2212,2214,2216,2218,2221,2223,2225,2227,2229,2231],{"class":742,"line":1381},[740,2179,2180],{"class":789},"      toast",[740,2182,611],{"class":753},[740,2184,2185],{"class":795},"add",[740,2187,883],{"class":757},[740,2189,940],{"class":753},[740,2191,943],{"class":757},[740,2193,836],{"class":753},[740,2195,1175],{"class":795},[740,2197,883],{"class":757},[740,2199,886],{"class":753},[740,2201,2202],{"class":774},"admin.deleted",[740,2204,886],{"class":753},[740,2206,908],{"class":753},[740,2208,1073],{"class":753},[740,2210,2211],{"class":774},"Event deleted",[740,2213,886],{"class":753},[740,2215,1316],{"class":757},[740,2217,908],{"class":753},[740,2219,2220],{"class":757}," description",[740,2222,836],{"class":753},[740,2224,802],{"class":789},[740,2226,611],{"class":753},[740,2228,1259],{"class":789},[740,2230,968],{"class":753},[740,2232,894],{"class":757},[740,2234,2235,2237,2240,2242,2244,2246,2248],{"class":742,"line":1398},[740,2236,2137],{"class":1020},[740,2238,2239],{"class":795}," refreshNuxtData",[740,2241,883],{"class":757},[740,2243,886],{"class":753},[740,2245,889],{"class":774},[740,2247,886],{"class":753},[740,2249,894],{"class":757},[740,2251,2252],{"class":742,"line":1430},[740,2253,2254],{"class":753},"    }\n",[740,2256,2257,2260,2262,2265,2267],{"class":742,"line":1436},[740,2258,2259],{"class":1020},"    catch",[740,2261,1895],{"class":757},[740,2263,2264],{"class":789},"e",[740,2266,1196],{"class":757},[740,2268,1980],{"class":753},[740,2270,2271,2273,2275,2277,2279,2282,2284,2286],{"class":742,"line":1497},[740,2272,2180],{"class":789},[740,2274,611],{"class":753},[740,2276,2185],{"class":795},[740,2278,883],{"class":757},[740,2280,2281],{"class":795},"errorToToast",[740,2283,883],{"class":757},[740,2285,2264],{"class":789},[740,2287,1931],{"class":757},[740,2289,2290],{"class":742,"line":1583},[740,2291,2254],{"class":753},[740,2293,2294],{"class":742,"line":1610},[740,2295,1936],{"class":753},[740,2297,2298],{"class":742,"line":1620},[740,2299,867],{"emptyLinePlaceholder":866},[740,2301,2302,2304,2307,2309,2311,2313,2315,2317,2319,2321],{"class":742,"line":1630},[740,2303,1012],{"class":761},[740,2305,2306],{"class":789}," menu",[740,2308,917],{"class":753},[740,2310,1895],{"class":753},[740,2312,953],{"class":1954},[740,2314,836],{"class":753},[740,2316,809],{"class":808},[740,2318,1316],{"class":753},[740,2320,991],{"class":761},[740,2322,2323],{"class":757}," [\n",[740,2325,2326,2329,2331,2334,2336,2338,2340,2342,2344,2346,2348,2350,2353,2355,2357,2359,2362,2364,2366,2369,2371,2373,2376,2378,2380,2382,2384,2386,2388,2390,2392,2394,2396,2398,2400,2403],{"class":742,"line":1640},[740,2327,2328],{"class":757},"    [",[740,2330,940],{"class":753},[740,2332,2333],{"class":757}," label",[740,2335,836],{"class":753},[740,2337,1175],{"class":795},[740,2339,883],{"class":757},[740,2341,886],{"class":753},[740,2343,1885],{"class":774},[740,2345,886],{"class":753},[740,2347,908],{"class":753},[740,2349,1073],{"class":753},[740,2351,2352],{"class":774},"Open",[740,2354,886],{"class":753},[740,2356,1316],{"class":757},[740,2358,908],{"class":753},[740,2360,2361],{"class":757}," icon",[740,2363,836],{"class":753},[740,2365,1073],{"class":753},[740,2367,2368],{"class":774},"i-lucide-arrow-right",[740,2370,886],{"class":753},[740,2372,908],{"class":753},[740,2374,2375],{"class":757}," to",[740,2377,836],{"class":753},[740,2379,1828],{"class":795},[740,2381,883],{"class":757},[740,2383,1915],{"class":753},[740,2385,1918],{"class":774},[740,2387,1053],{"class":753},[740,2389,953],{"class":789},[740,2391,611],{"class":753},[740,2393,1064],{"class":789},[740,2395,1067],{"class":753},[740,2397,1196],{"class":757},[740,2399,914],{"class":753},[740,2401,2402],{"class":757},"]",[740,2404,1117],{"class":753},[740,2406,2408,2410,2412,2414,2416,2418,2420,2422,2424,2426,2428,2430,2432,2434,2436,2438,2440,2442,2444,2447,2449,2451,2454,2456,2458,2460,2462,2464,2466,2468,2470,2472,2474,2476,2478,2480,2482,2484,2486,2488,2490],{"class":742,"line":2407},34,[740,2409,2328],{"class":757},[740,2411,940],{"class":753},[740,2413,2333],{"class":757},[740,2415,836],{"class":753},[740,2417,1175],{"class":795},[740,2419,883],{"class":757},[740,2421,886],{"class":753},[740,2423,1278],{"class":774},[740,2425,886],{"class":753},[740,2427,908],{"class":753},[740,2429,1073],{"class":753},[740,2431,1288],{"class":774},[740,2433,886],{"class":753},[740,2435,1316],{"class":757},[740,2437,908],{"class":753},[740,2439,2361],{"class":757},[740,2441,836],{"class":753},[740,2443,1073],{"class":753},[740,2445,2446],{"class":774},"i-lucide-pencil",[740,2448,886],{"class":753},[740,2450,908],{"class":753},[740,2452,2453],{"class":795}," onSelect",[740,2455,836],{"class":753},[740,2457,988],{"class":753},[740,2459,991],{"class":761},[740,2461,1784],{"class":789},[740,2463,611],{"class":753},[740,2465,1873],{"class":795},[740,2467,883],{"class":757},[740,2469,1878],{"class":789},[740,2471,1316],{"class":757},[740,2473,611],{"class":753},[740,2475,1885],{"class":795},[740,2477,883],{"class":757},[740,2479,940],{"class":753},[740,2481,802],{"class":789},[740,2483,968],{"class":753},[740,2485,1196],{"class":757},[740,2487,914],{"class":753},[740,2489,2402],{"class":757},[740,2491,1117],{"class":753},[740,2493,2495,2497,2499,2501,2503,2505,2507,2509,2511,2513,2515,2517,2519,2521,2523,2525,2527,2529,2531,2534,2536,2538,2541,2543,2545,2548,2550,2553,2556,2558,2560,2562,2564,2566,2568,2570,2572,2574,2576,2578],{"class":742,"line":2494},35,[740,2496,2328],{"class":757},[740,2498,940],{"class":753},[740,2500,2333],{"class":757},[740,2502,836],{"class":753},[740,2504,1175],{"class":795},[740,2506,883],{"class":757},[740,2508,886],{"class":753},[740,2510,2074],{"class":774},[740,2512,886],{"class":753},[740,2514,908],{"class":753},[740,2516,1073],{"class":753},[740,2518,2083],{"class":774},[740,2520,886],{"class":753},[740,2522,1316],{"class":757},[740,2524,908],{"class":753},[740,2526,2361],{"class":757},[740,2528,836],{"class":753},[740,2530,1073],{"class":753},[740,2532,2533],{"class":774},"i-lucide-trash-2",[740,2535,886],{"class":753},[740,2537,908],{"class":753},[740,2539,2540],{"class":757}," color",[740,2542,836],{"class":753},[740,2544,1073],{"class":753},[740,2546,2547],{"class":774},"error",[740,2549,886],{"class":753},[740,2551,2552],{"class":1020}," as",[740,2554,2555],{"class":761}," const",[740,2557,908],{"class":753},[740,2559,2453],{"class":795},[740,2561,836],{"class":753},[740,2563,988],{"class":753},[740,2565,991],{"class":761},[740,2567,1949],{"class":795},[740,2569,883],{"class":757},[740,2571,953],{"class":789},[740,2573,1196],{"class":757},[740,2575,914],{"class":753},[740,2577,2402],{"class":757},[740,2579,1117],{"class":753},[740,2581,2583],{"class":742,"line":2582},36,[740,2584,2585],{"class":757},"  ]\n",[740,2587,2589],{"class":742,"line":2588},37,[740,2590,867],{"emptyLinePlaceholder":866},[740,2592,2594,2597,2599,2601,2603,2605,2607,2609],{"class":742,"line":2593},38,[740,2595,2596],{"class":1020},"  return",[740,2598,902],{"class":753},[740,2600,1851],{"class":789},[740,2602,908],{"class":753},[740,2604,1949],{"class":789},[740,2606,908],{"class":753},[740,2608,2306],{"class":789},[740,2610,2611],{"class":753}," }\n",[740,2613,2615],{"class":742,"line":2614},39,[740,2616,2617],{"class":753},"}\n",[613,2619,2621],{"id":2620},"row-actions","Row actions",[593,2623,2624,2625,2628,2629,2632],{},"Row actions go in a row menu (",[628,2626,2627],{},"RowMenu",", the ",[628,2630,2631],{},"⋯"," button) at the end of the row. There are no loose icon buttons in\nrows. The menu has its groups in this order:",[1666,2634,2635,2640,2643],{},[621,2636,2637,2639],{},[601,2638,2352],{}," first, with \"View public page\" when there is one.",[621,2641,2642],{},"The edits and extras.",[621,2644,2645],{},"The destructive action, in its own group, coloured red.",[2647,2648,2649,2662],"table",{},[2650,2651,2652],"thead",{},[2653,2654,2655,2659],"tr",{},[2656,2657,2658],"th",{},"Action",[2656,2660,2661],{},"Icon",[2663,2664,2665,2675,2685,2695,2705],"tbody",{},[2653,2666,2667,2670],{},[2668,2669,2352],"td",{},[2668,2671,2672],{},[628,2673,2674],{},"arrow-right",[2653,2676,2677,2680],{},[2668,2678,2679],{},"Edit",[2668,2681,2682],{},[628,2683,2684],{},"pencil",[2653,2686,2687,2690],{},[2668,2688,2689],{},"Duplicate",[2668,2691,2692],{},[628,2693,2694],{},"copy",[2653,2696,2697,2700],{},[2668,2698,2699],{},"Archive",[2668,2701,2702],{},[628,2703,2704],{},"archive",[2653,2706,2707,2710],{},[2668,2708,2709],{},"Delete",[2668,2711,2712],{},[628,2713,2714],{},"trash-2",[618,2716,2717,2724,2727],{},[621,2718,2719,2720,2723],{},"Detail pages build the menu with ",[628,2721,2722],{},"open: false",", because they are already there.",[621,2725,2726],{},"Sub-entities skip Open.",[621,2728,2729,2730,2733],{},"Pass ",[628,2731,2732],{},"subject",", so the button's accessible name reads \"Actions for Ada Lovelace\".",[613,2735,2737],{"id":2736},"destructive-actions","Destructive actions",[593,2739,2740,2741,2744,2745,2748],{},"A destructive action asks for confirmation with ",[628,2742,2743],{},"useConfirmDialog({ destructive: true })",", never with\n",[628,2746,2747],{},"window.confirm",". The dialog says three things:",[618,2750,2751,2754,2757],{},[621,2752,2753],{},"The title asks about the record by name: \"Delete Spring Gala?\"",[621,2755,2756],{},"The description says what else is affected: \"Its tickets and attendees are deleted too.\"",[621,2758,2759],{},"The confirm button names the verb and the object: \"Delete event\".",[593,2761,2762],{},[717,2763],{"alt":2764,"src":2765},"A confirm dialog titled \"Delete Board workshop?\" that says what else is deleted, with Cancel and a red Delete event button.","\u002Fimages\u002Fux-patterns\u002Fforms-and-actions-confirm.png",[613,2767,2769],{"id":2768},"feedback-and-errors","Feedback and errors",[618,2771,2772,2778,2792],{},[621,2773,2774,2777],{},[601,2775,2776],{},"Success."," A successful action is a toast with a title. When useful, the record's name is the description.",[621,2779,2780,2783,2784,2787,2788,2791],{},[601,2781,2782],{},"Failure."," A failed action is a toast built with ",[628,2785,2786],{},"errorToToast(e)",", or ",[628,2789,2790],{},"useErrorToast()"," for a ready-made\nfunction. Both read the server's message from the usual places and fall back to a translated generic message.",[621,2793,2794,2797,2798,2801],{},[601,2795,2796],{},"Blocking problems."," A problem that blocks the page, such as not found or forbidden, is a ",[628,2799,2800],{},"UEmpty",", not a toast.",[2803,2804,2805,2808],"tip",{},[628,2806,2807],{},"useAction()"," wraps the common \"busy, try, toast on error\" block. Use it instead of writing that block again.",[613,2810,2812],{"id":2811},"deep-links-instead-of-state-hand-offs","Deep links instead of state hand-offs",[593,2814,2815],{},"A page that needs context from another page reads it from the URL, or opens the right form directly. Two examples:",[618,2817,2818,2821],{},[621,2819,2820],{},"\"Add ticket type\" on an event opens the form with the event already selected.",[621,2822,2823,2824,611],{},"A ⌘K entry links to ",[628,2825,2826],{},"?application=\u003Cid>",[593,2828,2829,2830,611],{},"Do not pass state through stores or ",[628,2831,2832],{},"history.state",[613,2834,2836],{"id":2835},"next-steps","Next steps",[618,2838,2839,2844,2860],{},[621,2840,2841,2843],{},[609,2842,111],{"href":112}," – word the buttons, toasts and dialogs on this page.",[621,2845,2846,2849,2850,1283,2853,2856,2857,611],{},[609,2847,2848],{"href":345},"UI composables"," – look up ",[628,2851,2852],{},"useConfirmDialog",[628,2854,2855],{},"useAction"," and ",[628,2858,2859],{},"useErrorToast",[621,2861,2862,2864],{},[609,2863,101],{"href":102}," – place the row menu and the create button on a list or detail page.",[2866,2867,2868],"style",{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}",{"title":736,"searchDepth":750,"depth":750,"links":2870},[2871,2872,2873,2874,2875,2876,2877,2878],{"id":615,"depth":750,"text":616},{"id":1649,"depth":750,"text":1650},{"id":1687,"depth":750,"text":1688},{"id":2620,"depth":750,"text":2621},{"id":2736,"depth":750,"text":2737},{"id":2768,"depth":750,"text":2769},{"id":2811,"depth":750,"text":2812},{"id":2835,"depth":750,"text":2836},"How a screen creates, edits and deletes records, and how it tells the user what happened.","md",null,{},{"icon":109},{"title":106,"description":2879},"pxXhXS6wB6yyczn3TG1MpLaQ7PvethVCqeWlfM2d7tk",[2887,2889],{"title":101,"path":102,"stem":103,"description":2888,"icon":104,"children":-1},"The shape of each kind of app page, and the loading, empty and error states every page shows.",{"title":111,"path":112,"stem":113,"description":2890,"icon":114,"children":-1},"How a screen words its strings, formats dates and money and builds links, plus a checklist for a new page.",1794503151101]