Every screen accumulates options over time: a filter someone asked for once, an advanced field
that matters for one integration, a setting nine out of ten accounts never touch. Show all of
it and the page a new user opens looks nothing like the task they came to do. Hide too much of
it, or hide the wrong thing, and the interface has quietly removed a control people actually
need — which is worse than cluttering the page, because a hidden-but-needed setting reads as
“not supported” rather than “one click away.”Progressive disclosure is not a single control. It is a decision about scope — how much of the
page is affected by hiding something — made three different ways depending on that scope: a
text link revealing a few more rows of the same list, a collapsible section holding a
self-contained block of secondary content, or an entirely separate area reached by its own
navigation. Treating all three as interchangeable is how a setting that deserved its own tab
ends up buried one click inside an accordion, or a two-field toggle gets promoted to a whole
settings screen nobody needed.
The heuristic is testable, not a vibe. Before disclosing anything, name who uses it and how
often: “used by fewer than X% of accounts, in fewer than Y% of their sessions” is a claim
someone can check against real usage. “This feels advanced” is not.
The content is the reason the reader is on this page
Show it open, by default
Disclosure adds a click to the exact thing they came to do.
A majority of users need the option in a majority of sessions
Show it directly on the page
Hiding a widely-needed control behind an extra click is the failure this pattern exists to prevent, not to cause — see the overview’s Choosing a pattern table.
The section holds a validation error that needs to be seen
Open it regardless of the default
See Form validation for how an error should surface; this page only decides the collapsed/expanded default, not the validation rule itself.
Friction on a dangerous action is calibrated to its consequence, not to how often it’s used — hiding it behind disclosure is the wrong kind of friction entirely.
Disclosed content is the reason the reader is on this page
Starts expanded
Disclosed section contains a validation error
Starts expanded regardless of the default — see Form validation
Reader expands a section
Opens in place; the page does not scroll or jump
Reader collapses a section
Content and any input already entered are retained, not discarded
Reader reloads the page or returns in a later session
Undecided. No session-persistence rule exists yet for disclosure state — treat each load as collapsed-by-default until this is decided, rather than assuming either answer.
Disclose only content that’s genuinely secondary — used by a minority of users in a minority of sessions.
Disclosure is friction with a purpose. Applied to something most users need, it becomes the “hide a needed setting” failure this pattern exists to prevent, not cause.
TITAN-DISCLOSE-02
Match the scope of disclosure to the scope of the content: a few more rows or fields → “Show more” link; a self-contained section → Accordion; a whole secondary area → a separate settings tab.
The three controls cost the reader differently. Using Accordion for what should be a settings tab hides an entire area one click inside a page that isn’t advertised as containing it.
TITAN-DISCLOSE-03
A disclosed section starts collapsed unless it is the reason the reader is on the page, or it contains a validation error that must be visible.
Collapsed-by-default is the whole point for genuinely secondary content; the two exceptions are cases where the default would actively hide what the reader needs right now.
TITAN-DISCLOSE-04
The trigger’s label names what’s inside — never a bare icon or the word “More” alone.
A reader deciding whether to open something needs to know what’s behind it before committing the click.
TITAN-DISCLOSE-05
Each Accordion trigger carries its own id and aria-controls pointing at its content, wired by hand.
Accordion does not pair these automatically — the only published example does it manually. Omitting it ships a disclosure control with no programmatic link to what it discloses.
TITAN-DISCLOSE-06
Collapsing a section never discards content or input already entered inside it.
A reader who fills in an advanced field, collapses the section to check something else, and returns to find it empty has lost work to a UI action that should have been inert.
TITAN-DISCLOSE-07
A destructive or safety-relevant control is never the thing being hidden by this pattern.
Friction on a dangerous action follows Destructive confirmation’s tiers, which are calibrated to consequence — not to how rarely the control is used.
TITAN-DISCLOSE-08
Where several Accordions stack, nothing assumes shared “only one open” behavior unless the composition explicitly builds it.
Accordion carries no group state itself — each instance is independent. A caller expecting mutual exclusivity for free will not get it.
A collapsed section is not a hidden one — it is a keyboard- and screen-reader-operable
control that happens to be closed. The trigger must be reachable by keyboard and must state,
in its accessible name, what it reveals — not “toggle” or “expand,” which say nothing about the
content.Accordion’s own documentation does not confirm that aria-expanded is set automatically on
the trigger. Its accessibility section states only what the underlying elements provide
natively, with no test asserting specific ARIA attributes. Verify this at the call site rather
than assuming the component supplies it — the same caution that already applies to wiring
aria-controls and id by hand.A validation error inside a collapsed section must force it open, and must be announced.
A screen-reader user who submits a form and hears nothing, because the only invalid field is
inside a section that stayed collapsed, has no path to the problem — see
Form validation.
Disclosure as camouflage for a setting most people need. Burying a control the majority of
users touch in most sessions behind a collapsed accordion doesn’t simplify the page — it moves
the complexity from “visible” to “undiscoverable,” which is worse.A chevron with no label. An icon-only trigger asks the reader to open something before
telling them what it is. The label is what lets them decide whether opening it is worth the
click.A validation error hidden inside a collapsed section. A form that reports “something is
wrong” without opening the section containing the actual invalid field sends the reader hunting
through every collapsed area to find it.Reinventing “only one open at a time” per screen. Accordion ships with no group behavior,
so every list of mutually exclusive sections either gets this built fresh or gets left without
it — a smaller version of the same duplication already recorded for skeleton screens (see
Known issues).
Accordion carrying no group state of its own is a smaller version of the same per-application-rebuilding cost this gap already measures for skeleton screens — see Anti-patterns.
Whether disclosure state should persist across a page reload or a later session —
Behavior already flags this as undecided rather than guessing.
What the actual usage threshold is behind “a minority of users in a minority of sessions” —
the heuristic is stated as testable, but no specific percentage is set anywhere in Titan.
Whether a “Show more” link’s revealed rows should animate into place or simply appear, and
whether that differs from an Accordion’s own expand transition.
The three disclosure mechanisms are matched to scope, not to preference, because the cost of
getting the scope wrong is different in each direction. Using an Accordion for what should be
its own settings tab hides an entire area behind a control a reader might never notice was
there. Using a settings tab for two fields sends the reader on a navigation for something that
fit in the space of a single click.The heuristic is written to be checkable, because “this feels advanced” is exactly the kind of
claim that never gets revisited. A stated threshold — a percentage of accounts, a percentage
of sessions — is either true or it isn’t, and can be re-measured as usage changes; a feeling has
no such correction.
Accordion, the component this
pattern’s collapsible-section variant composes. Tabs,
for the settings-tab variant when the secondary area is large enough to be its own screen.
Form validation, for the validation-error
exception to the collapsed-by-default rule.
First-pass proposal, not established policy. No audited Invoca screen backs this page —
Titan’s design library was not available while writing it. It is built from general
interaction-design practice and from what Accordion
already establishes. Treat every threshold below as a starting point to check against real
product screens, not as a rule already enforced.
Last modified on September 17, 2026
Was this page helpful?
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Invoca","colors":{"primary":"#00A87F","light":"#00A87F","dark":"#0EEEB7"},"logo":{"light":"https://mintcdn.com/invoca-5bd45748/9Md68DqArcq3WD3L/logo/light.svg?fit=max\u0026auto=format\u0026n=9Md68DqArcq3WD3L\u0026q=85\u0026s=3ed629c5be28d08bd1a6580e72b6dbfa","dark":"https://mintcdn.com/invoca-5bd45748/9Md68DqArcq3WD3L/logo/dark.svg?fit=max\u0026auto=format\u0026n=9Md68DqArcq3WD3L\u0026q=85\u0026s=b64ce8e5cfa4f8c7893b2738e8131f45","href":"https://www.invoca.com/"},"favicon":"https://mintcdn.com/invoca-5bd45748/9Md68DqArcq3WD3L/favicon.png?fit=max\u0026auto=format\u0026n=9Md68DqArcq3WD3L\u0026q=85\u0026s=c846713bb1afdf274154a01d7e9abb8d","appearance":{"default":"light"},"background":{"decoration":"gradient"},"navbar":{"primary":{"type":"button","label":"Invoca Academy","href":"https://academy.invoca.com/"}},"footer":{"socials":{"linkedin":"https://www.linkedin.com/company/invoca-com","youtube":"https://www.youtube.com/channel/UCLQwNQFnN1OV1ACnlXICPKw"}},"fonts":{"body":{"family":"Gt America","source":"https://cdn.prod.website-files.com/5d82e225060d003d65ddae98/677d87009656fca63c0c7d8f_GT-America-Standard-Regular.woff2","format":"woff2"}},"contextual":{"options":["copy","download-pdf","view","assistant","chatgpt","claude","perplexity"],"display":"header"},"metadata":{"timestamp":true},"styling":{"latex":true},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"invoca-5bd45748","hasAudioNarration":false,"actualSubdomain":"invoca-5bd45748","customDomains":["docs.invoca.com"],"gitSource":{"type":"github","owner":"invoca","repo":"docs","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6ae8bdbaca78e468455a6b97","collectionId":"54b26950-9181-41ce-985a-32d474ce8dd0","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6ae8bdbaca78e468455a6b97"},"feedback":{"thumbs":true,"agentFeedback":true,"contextualFeedback":{"allowEmail":false}},"entitlements":{"AI_CHAT":{"status":"ENABLED"},"REMOVE_BRANDING":{"status":"ENABLED"},"CONTEXTUAL_FEEDBACK":{"status":"ENABLED","enabled":"ENABLED"},"CODE_SNIPPET_FEEDBACK":{"status":"ENABLED"},"WEB_MCP":{"status":"ENABLED"},"NARRATION":{"status":"ENABLED"}},"buildId":"6ae8bdbaca78e468455a6b97","clientVersion":"0.0.4045","searchFilterCounts":[{"language":"default","tag":"Invoca Docs","count":666},{"language":"default","tag":"Guide","count":665},{"language":"default","tag":"Developer","count":191},{"language":"default","tag":"Integrations","count":184},{"language":"default","tag":"Invoca Design System","count":163},{"language":"default","tag":"API Documentation","count":151},{"language":"default","tag":"Campaign \u0026 Call Handling","count":127},{"language":"default","tag":"Insights \u0026 Analytics","count":101},{"language":"default","tag":"Network Integration","count":99},{"language":"default","tag":"Components","count":75}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":true,"enableContextualStarterQuestions":true,"enableAskAiSearchBar":true,"deflection":{"enabled":true,"type":"link","url":"https://support.invoca.com/s/contactsupport"}},"basePath":"","hasChatPermissions":true,"hasWebMcpPermissions":true,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[{"filePath":"style.css","content":".custom-card .card img{width:60%;padding:1rem;margin:0 auto}a[href=\"https://academy.invoca.com/\"] span.absolute{background-color:#004030}#assistant-entry,#assistant-entry-mobile{background-color:#00a87f;border-color:#00a87f}#assistant-entry-mobile:hover,#assistant-entry:hover{background-color:#009973}#assistant-entry span,#assistant-entry svg,#assistant-entry-mobile span,#assistant-entry-mobile svg{color:#fff}.ivk-home{--ivk-forest:#0A231E;--ivk-footer-bg:#004030;--ivk-accent:#00A87F;--ivk-ink:#1F2121;--ivk-muted:#626464;--ivk-line:#E7E9E4;--ivk-bg:#FFFFFF;--ivk-sand:#F8FAF1;--ivk-banner:#D1FFD1;--ivk-card:#FFFFFF;--ivk-radius-btn:6px;--ivk-radius-card:16px;color:var(--ivk-ink);width:100%;max-width:1600px;margin:0 auto;padding:2rem clamp(1.25rem,4vw,4rem) 4rem}.dark .ivk-home,:root[data-theme=dark] .ivk-home{--ivk-bg:#10201B;--ivk-card:#16261F;--ivk-ink:#EAF1EC;--ivk-muted:#9BAAA1;--ivk-line:#223229;--ivk-sand:#16261F;--ivk-banner:#1C3A2C}.ivk-home a{color:inherit;text-decoration:none}.ivk-home footer a[href*=mintlify]{color:#9ea3a2}.dark .ivk-home footer a[href*=mintlify]{color:#6f7573}.ivk-home footer a[href*=mintlify]:hover{color:#4f5553}.dark .ivk-home footer a[href*=mintlify]:hover{color:#ced3d1}.ivk-home img,.ivk-home svg{display:block}.ivk-home-announce,.ivk-home-hero{border-radius:var(--ivk-radius-card)}.ivk-home-announce{background:var(--ivk-banner);color:var(--ivk-ink);font-size:13.5px;font-weight:500;text-align:center;padding:9px 16px;margin-bottom:20px}.ivk-home-announce a{color:var(--ivk-footer-bg);font-weight:600;text-decoration:underline;margin-left:6px}.ivk-home-hero{position:relative;overflow:hidden;background:var(--ivk-forest);color:#fff;padding:56px 32px}.ivk-home-hero-eyebrow{display:inline-flex;align-items:center;gap:8px;color:#fff;font-size:13px;font-weight:500;border:1px solid rgba(255,255,255,.28);border-radius:999px;padding:6px 14px;margin:0 0 22px}.ivk-home-hero h1{font-size:clamp(28px,4.2vw,44px);font-weight:700;line-height:1.1;letter-spacing:-.01em;max-width:17ch;margin:0 0 16px;color:#fff}.ivk-home-hero h1 .ivk-home-hl{color:#00b388}.ivk-home-hero-lede{font-size:16.5px;color:rgba(255,255,255,.78);max-width:48ch;margin:0 0 30px;line-height:1.55}.ivk-home-search-field{display:flex;align-items:center;gap:10px;background:#fff;border-radius:var(--ivk-radius-btn);padding:13px 16px;max-width:560px;box-shadow:0 14px 34px rgba(0,0,0,.28);cursor:pointer;border:0;width:100%;text-align:left;font-family:inherit}.ivk-home-search-field input{border:0;outline:0;flex:1;font-size:15px;font-family:inherit;color:#1f2121;background:0 0;pointer-events:none}.ivk-home-search-field input::placeholder{color:#626464}.ivk-home-search-field .ivk-home-icon{color:#626464;flex:none}.ivk-home-search-field kbd{font-size:11.5px;color:#626464;border:1px solid #e7e9e4;border-radius:5px;padding:2px 6px}.ivk-home-popular{margin-top:26px;display:flex;flex-wrap:wrap;gap:8px;align-items:center}.ivk-home-popular .ivk-home-label{color:rgba(255,255,255,.62);font-size:13px;margin-right:4px}.ivk-home-chip{display:inline-flex;align-items:center;gap:6px;background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.2);color:#fff;font-size:13px;padding:7px 12px;border-radius:999px}.ivk-home-chip:hover{background:rgba(255,255,255,.16)}.ivk-home-note-banner{background:var(--ivk-sand);border:1px solid var(--ivk-line);border-radius:var(--ivk-radius-card);padding:16px 20px;font-size:13.5px;color:var(--ivk-muted);line-height:1.55;margin-top:24px}.ivk-home-note-banner strong{color:var(--ivk-ink)}.ivk-home-band{padding:60px 0}.ivk-home-band-alt{background:var(--ivk-sand);border-radius:var(--ivk-radius-card)}.ivk-home-section-head{display:flex;align-items:baseline;justify-content:space-between;gap:16px;margin-bottom:26px;flex-wrap:wrap}.ivk-home-section-head h2,.ivk-home-topic-tile h3{font-size:23px;font-weight:700;letter-spacing:-.01em;margin:0;color:var(--ivk-ink)}.ivk-home-section-head .ivk-home-meta,.ivk-home-section-sub{color:var(--ivk-muted);font-size:13.5px}.ivk-home-section-sub{font-size:14.5px;max-width:62ch;margin:-14px 0 26px;line-height:1.55}.ivk-home-topic-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;align-items:start}@media (min-width:1400px){.ivk-home-topic-grid{grid-template-columns:repeat(4,1fr)}}@media (max-width:860px){.ivk-home-topic-grid{grid-template-columns:repeat(2,1fr)}}@media (max-width:600px){.ivk-home-topic-grid{grid-template-columns:1fr}}.ivk-home-topic-tile{background:var(--ivk-card);border:1px solid var(--ivk-line);border-radius:var(--ivk-radius-card);transition:border-color .15s ease}.ivk-home-topic-tile:hover{border-color:color-mix(in srgb,var(--ivk-accent) 40%,var(--ivk-line))}.ivk-home-t-head{display:block;width:100%;padding:22px 22px 18px;cursor:pointer;background:0 0;border:0;text-align:left;font-family:inherit;color:inherit}.ivk-home-row-top{display:flex;align-items:center;justify-content:space-between;gap:10px}.ivk-home-icon-wrap{width:36px;height:36px;border-radius:10px;background:rgba(0,168,127,.12);color:var(--ivk-accent);display:flex;align-items:center;justify-content:center}.ivk-home-count{font-size:12px;color:var(--ivk-muted);white-space:nowrap}.ivk-home-title-row{display:flex;align-items:flex-start;gap:6px;margin:12px 0 4px}.ivk-home-topic-tile h3{font-size:16.5px;font-weight:600;letter-spacing:-.005em;line-height:1.3;min-height:2.6em;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.ivk-home-tag-pill{flex:none;margin-top:2px;padding:2px 4px;border-radius:6px;font-size:.65rem;font-weight:700;line-height:13px;color:var(--ivk-accent);background:rgba(0,168,127,.1)}.dark .ivk-home-tag-pill,:root[data-theme=dark] .ivk-home-tag-pill{color:#1dc79a;background:rgba(29,199,154,.15)}.ivk-home-desc{font-size:13.5px;color:var(--ivk-muted);margin:0;line-height:1.5;min-height:3em;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.ivk-home-expand-cue{display:flex;align-items:center;gap:6px;margin-top:14px;font-size:12.5px;color:var(--ivk-accent);font-weight:600}.ivk-home-expand-cue svg{transition:transform .18s ease}.ivk-home-topic-tile.ivk-home-open .ivk-home-expand-cue svg{transform:rotate(180deg)}.ivk-home-t-panel{border-top:1px solid var(--ivk-line);margin-top:2px;padding:16px 22px 22px}.ivk-home-t-panel ul{list-style:none;margin:0 0 12px;padding:0;display:flex;flex-direction:column;gap:9px}.ivk-home-t-panel li a{font-size:13px;color:var(--ivk-ink);display:flex;align-items:center;gap:7px}.ivk-home-dev-card h3 a:hover,.ivk-home-t-panel li a:hover,.ivk-home-viewall{color:var(--ivk-accent)}.ivk-home-t-panel li a svg{flex:none;opacity:.5}.ivk-home-viewall{font-size:12.5px;font-weight:600}.ivk-home-dev-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}@media (max-width:700px){.ivk-home-dev-grid{grid-template-columns:1fr}}.ivk-home-dev-card{background:var(--ivk-card);border:1px solid var(--ivk-line);border-radius:var(--ivk-radius-card);padding:18px;display:flex;gap:12px;align-items:flex-start}.ivk-home-dev-card .ivk-home-icon-wrap{background:var(--ivk-forest);color:#fff;width:32px;height:32px;border-radius:9px}.ivk-home-dev-card h3{font-size:14.5px;font-weight:600;margin:0 0 3px;color:var(--ivk-ink)}.ivk-home-dev-card p{font-size:13px;color:var(--ivk-muted);margin:0;line-height:1.45}"}],"page":{"pagePath":"invoca-design-system/patterns/progressive-disclosure","slug":"/invoca-design-system/patterns/progressive-disclosure","pageMetadata":{"title":"Progressive disclosure","description":"Keeping a screen simple without hiding what people actually need.","icon":"chevrons-down-up","keywords":["progressive disclosure","accordion","show more","advanced options","settings","disclosure"],"href":"/invoca-design-system/patterns/progressive-disclosure"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Keeping a screen simple without hiding what people actually need.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,li:`li`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,ul:`ul`,..._provideComponents(),...props.components},{CodeBlock,Heading,Mermaid,Table,Tip}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Mermaid)_missingMdxReference(`Mermaid`,true);if(!Table)_missingMdxReference(`Table`,true);if(!Tip)_missingMdxReference(`Tip`,true);return _jsxs(_Fragment,{children:[_jsx(Heading,{level:`2`,id:`the-problem`,children:`The problem`}),`\n`,_jsx(_components.p,{children:`Every screen accumulates options over time: a filter someone asked for once, an advanced field\nthat matters for one integration, a setting nine out of ten accounts never touch. Show all of\nit and the page a new user opens looks nothing like the task they came to do. Hide too much of\nit, or hide the wrong thing, and the interface has quietly removed a control people actually\nneed — which is worse than cluttering the page, because a hidden-but-needed setting reads as\n“not supported” rather than “one click away.”`}),`\n`,_jsx(_components.p,{children:`Progressive disclosure is not a single control. It is a decision about scope — how much of the\npage is affected by hiding something — made three different ways depending on that scope: a\ntext link revealing a few more rows of the same list, a collapsible section holding a\nself-contained block of secondary content, or an entirely separate area reached by its own\nnavigation. Treating all three as interchangeable is how a setting that deserved its own tab\nends up buried one click inside an accordion, or a two-field toggle gets promoted to a whole\nsettings screen nobody needed.`}),`\n`,_jsx(Heading,{level:`2`,id:`decide-first-how-much-of-the-page-is-affected`,children:`Decide first: how much of the page is affected?`}),`\n`,_jsx(Mermaid,{chart:`flowchart TD\n A[Content is genuinely secondary —\u003cbr/>used by a minority of users\u003cbr/>in a minority of sessions] --> B{How much of the page does it affect?}\n B -->|A few more rows or fields\u003cbr/>within one section| C[Show more text link]\n B -->|A self-contained secondary\u003cbr/>section on this page| D[Accordion]\n B -->|A whole area most users\u003cbr/>never open, worth its own screen| E[Separate settings tab]`}),`\n`,_jsx(Tip,{children:_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`The heuristic is testable, not a vibe.`}),` Before disclosing anything, name who uses it and how\noften: “used by fewer than X% of accounts, in fewer than Y% of their sessions” is a claim\nsomeone can check against real usage. “This feels advanced” is not.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`vocabulary`,children:`Vocabulary`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Term`}),_jsx(_components.th,{children:`Also called`}),_jsx(_components.th,{children:`The system uses`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Disclosure`}),_jsx(_components.td,{children:`Show more, expand/collapse`}),_jsxs(_components.td,{children:[_jsx(_components.strong,{children:`Disclosure`}),` — deferring genuinely secondary content behind an action, scoped to how much of the page it affects`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Trigger`}),_jsx(_components.td,{children:`Toggle, expander`}),_jsxs(_components.td,{children:[_jsx(_components.strong,{children:`Trigger`}),` — the control that opens or closes the disclosed region; always labeled with what it reveals`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Secondary`}),_jsx(_components.td,{children:`Advanced, optional`}),_jsxs(_components.td,{children:[_jsx(_components.strong,{children:`Secondary`}),` — used by a minority of users in a minority of sessions, per the heuristic above, not “feels advanced”`]})]})]})]}),`\n`,_jsx(Heading,{level:`2`,id:`when-this-applies`,children:`When this applies`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`The content is genuinely secondary or advanced, by the heuristic above — not merely “would\nmake the page shorter.”`}),`\n`,_jsx(_components.li,{children:`Hiding it does not remove the only way to discover that the capability exists at all.`}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`when-it-doesn’t`,children:`When it doesn’t`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Situation`}),_jsx(_components.th,{children:`Do this instead`}),_jsx(_components.th,{children:`Why`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`The content is the reason the reader is on this page`}),_jsx(_components.td,{children:`Show it open, by default`}),_jsx(_components.td,{children:`Disclosure adds a click to the exact thing they came to do.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`A majority of users need the option in a majority of sessions`}),_jsx(_components.td,{children:`Show it directly on the page`}),_jsxs(_components.td,{children:[`Hiding a widely-needed control behind an extra click is the failure this pattern exists to prevent, not to cause — see the overview’s `,_jsx(_components.a,{href:`/invoca-design-system/patterns/overview#choosing-a-pattern`,children:`Choosing a pattern`}),` table.`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`The section holds a validation error that needs to be seen`}),_jsx(_components.td,{children:`Open it regardless of the default`}),_jsxs(_components.td,{children:[`See `,_jsx(_components.a,{href:`/invoca-design-system/patterns/form-validation`,children:`Form validation`}),` for how an error should surface; this page only decides the collapsed/expanded default, not the validation rule itself.`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`The option is destructive or safety-relevant`}),_jsx(_components.td,{children:_jsx(_components.a,{href:`/invoca-design-system/patterns/destructive-confirmation`,children:`Destructive confirmation`})}),_jsx(_components.td,{children:`Friction on a dangerous action is calibrated to its consequence, not to how often it’s used — hiding it behind disclosure is the wrong kind of friction entirely.`})]})]})]}),`\n`,_jsx(Heading,{level:`2`,id:`structure`,children:`Structure`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Order`}),_jsx(_components.th,{children:`Component`}),_jsx(_components.th,{children:`Role`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{\"data-numeric\":`true`,children:`1`}),_jsxs(_components.td,{children:[`Trigger — `,_jsx(_components.a,{href:`/invoca-design-system/components/containment/accordion`,children:`AccordionSummary`}),`, a text-styled `,_jsx(_components.a,{href:`/invoca-design-system/components/actions/button`,children:`Button`}),`, or a `,_jsx(_components.a,{href:`/invoca-design-system/components/navigation/tabs`,children:`Tab`})]}),_jsx(_components.td,{children:`Names what’s hidden and what opening it does. Never a bare chevron with no label.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{\"data-numeric\":`true`,children:`2`}),_jsxs(_components.td,{children:[`Disclosed region — `,_jsx(_components.a,{href:`/invoca-design-system/components/containment/accordion`,children:`AccordionDetails`}),`, the revealed rows, or the tab panel`]}),_jsx(_components.td,{children:`Holds the secondary content; collapsed by default unless an exception below applies`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{\"data-numeric\":`true`,children:`3`}),_jsx(_components.td,{children:`Expand indicator`}),_jsx(_components.td,{children:`Visual affordance that state can change — required on the Accordion and the text link; implicit on a tab`})]})]})]}),`\n`,_jsx(CodeBlock,{numberOfLines:`11`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`11`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`┌─────────────────────────────────────────┐`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`│ Routing rules │`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`│ ...primary fields... │`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`│ │`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`│ ▸ Advanced matching options │ ← Accordion, collapsed by default`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`├─────────────────────────────────────────┤`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`│ Recent calls (5 of 42) │`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`│ ...5 rows... │`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`│ Show 37 more ⌄ │ ← \"Show more\" text link, states the count`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`└─────────────────────────────────────────┘`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),`\n`,_jsx(Heading,{level:`2`,id:`behavior`,children:`Behavior`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`State`}),_jsx(_components.th,{children:`Behavior`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Page loads, no exception applies`}),_jsx(_components.td,{children:`Disclosed section starts collapsed`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Disclosed content is the reason the reader is on this page`}),_jsx(_components.td,{children:`Starts expanded`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Disclosed section contains a validation error`}),_jsxs(_components.td,{children:[`Starts expanded regardless of the default — see `,_jsx(_components.a,{href:`/invoca-design-system/patterns/form-validation`,children:`Form validation`})]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Reader expands a section`}),_jsx(_components.td,{children:`Opens in place; the page does not scroll or jump`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Reader collapses a section`}),_jsx(_components.td,{children:`Content and any input already entered are retained, not discarded`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Reader reloads the page or returns in a later session`}),_jsxs(_components.td,{children:[_jsx(_components.strong,{children:`Undecided.`}),` No session-persistence rule exists yet for disclosure state — treat each load as collapsed-by-default until this is decided, rather than assuming either answer.`]})]})]})]}),`\n`,_jsx(Heading,{level:`2`,id:`constraints`,children:`Constraints`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`ID`}),_jsx(_components.th,{children:`Constraint`}),_jsx(_components.th,{children:`Rationale`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.strong,{children:`TITAN-DISCLOSE-01`})}),_jsx(_components.td,{children:`Disclose only content that’s genuinely secondary — used by a minority of users in a minority of sessions.`}),_jsx(_components.td,{children:`Disclosure is friction with a purpose. Applied to something most users need, it becomes the “hide a needed setting” failure this pattern exists to prevent, not cause.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.strong,{children:`TITAN-DISCLOSE-02`})}),_jsx(_components.td,{children:`Match the scope of disclosure to the scope of the content: a few more rows or fields → “Show more” link; a self-contained section → Accordion; a whole secondary area → a separate settings tab.`}),_jsx(_components.td,{children:`The three controls cost the reader differently. Using Accordion for what should be a settings tab hides an entire area one click inside a page that isn’t advertised as containing it.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.strong,{children:`TITAN-DISCLOSE-03`})}),_jsx(_components.td,{children:`A disclosed section starts collapsed unless it is the reason the reader is on the page, or it contains a validation error that must be visible.`}),_jsx(_components.td,{children:`Collapsed-by-default is the whole point for genuinely secondary content; the two exceptions are cases where the default would actively hide what the reader needs right now.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.strong,{children:`TITAN-DISCLOSE-04`})}),_jsx(_components.td,{children:`The trigger’s label names what’s inside — never a bare icon or the word “More” alone.`}),_jsx(_components.td,{children:`A reader deciding whether to open something needs to know what’s behind it before committing the click.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.strong,{children:`TITAN-DISCLOSE-05`})}),_jsxs(_components.td,{children:[`Each Accordion trigger carries its own `,_jsx(_components.code,{children:`id`}),` and `,_jsx(_components.code,{children:`aria-controls`}),` pointing at its content, wired by hand.`]}),_jsx(_components.td,{children:`Accordion does not pair these automatically — the only published example does it manually. Omitting it ships a disclosure control with no programmatic link to what it discloses.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.strong,{children:`TITAN-DISCLOSE-06`})}),_jsx(_components.td,{children:`Collapsing a section never discards content or input already entered inside it.`}),_jsx(_components.td,{children:`A reader who fills in an advanced field, collapses the section to check something else, and returns to find it empty has lost work to a UI action that should have been inert.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.strong,{children:`TITAN-DISCLOSE-07`})}),_jsx(_components.td,{children:`A destructive or safety-relevant control is never the thing being hidden by this pattern.`}),_jsxs(_components.td,{children:[`Friction on a dangerous action follows `,_jsx(_components.a,{href:`/invoca-design-system/patterns/destructive-confirmation`,children:`Destructive confirmation`}),`’s tiers, which are calibrated to consequence — not to how rarely the control is used.`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.strong,{children:`TITAN-DISCLOSE-08`})}),_jsx(_components.td,{children:`Where several Accordions stack, nothing assumes shared “only one open” behavior unless the composition explicitly builds it.`}),_jsx(_components.td,{children:`Accordion carries no group state itself — each instance is independent. A caller expecting mutual exclusivity for free will not get it.`})]})]})]}),`\n`,_jsx(Heading,{level:`2`,id:`content`,children:`Content`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Element`}),_jsx(_components.th,{children:`✅`}),_jsx(_components.th,{children:`❌`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Accordion trigger`}),_jsx(_components.td,{children:`”Advanced matching options\"`}),_jsx(_components.td,{children:`\"More”`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Show-more link`}),_jsx(_components.td,{children:`”Show 37 more\"`}),_jsx(_components.td,{children:`\"Show more” with no count`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Collapsed section, no error`}),_jsx(_components.td,{children:`(nothing extra)`}),_jsx(_components.td,{children:`“Click here to expand this section” — narrating the obvious control`})]})]})]}),`\n`,_jsx(Heading,{level:`2`,id:`accessibility`,children:`Accessibility`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`A collapsed section is not a hidden one — it is a keyboard- and screen-reader-operable\ncontrol that happens to be closed.`}),` The trigger must be reachable by keyboard and must state,\nin its accessible name, what it reveals — not “toggle” or “expand,” which say nothing about the\ncontent.`]}),`\n`,_jsxs(_components.p,{children:[_jsxs(_components.strong,{children:[`Accordion’s own documentation does not confirm that `,_jsx(_components.code,{children:`aria-expanded`}),` is set automatically on\nthe trigger.`]}),` Its accessibility section states only what the underlying elements provide\nnatively, with no test asserting specific ARIA attributes. Verify this at the call site rather\nthan assuming the component supplies it — the same caution that already applies to wiring\n`,_jsx(_components.code,{children:`aria-controls`}),` and `,_jsx(_components.code,{children:`id`}),` by hand.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`A validation error inside a collapsed section must force it open, and must be announced.`}),`\nA screen-reader user who submits a form and hears nothing, because the only invalid field is\ninside a section that stayed collapsed, has no path to the problem — see\n`,_jsx(_components.a,{href:`/invoca-design-system/patterns/form-validation`,children:`Form validation`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`variations`,children:`Variations`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Variation`}),_jsx(_components.th,{children:`When`}),_jsx(_components.th,{children:`Change`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Accordion group, one open at a time`}),_jsx(_components.td,{children:`Sections are mutually exclusive alternatives, not independent reads`}),_jsx(_components.td,{children:`Caller manages shared state explicitly — Accordion provides no grouping behavior of its own`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`”Show more” over Accordion`}),_jsx(_components.td,{children:`The hidden content is more of the same list, not a different kind of information`}),_jsx(_components.td,{children:`A text link with a count, no header or border framing`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Settings tab over Accordion`}),_jsx(_components.td,{children:`The secondary area is large enough to be worth its own screen`}),_jsx(_components.td,{children:`A dedicated tab in the page’s tab bar, not a scroll-triggered reveal`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Disabled trigger`}),_jsx(_components.td,{children:`The disclosed content requires a prerequisite the reader hasn’t met yet`}),_jsxs(_components.td,{children:[`Accordion’s `,_jsx(_components.code,{children:`disabled`}),` prop; the trigger’s label states the prerequisite, not just that it’s unavailable`]})]})]})]}),`\n`,_jsx(Heading,{level:`2`,id:`anti-patterns`,children:`Anti-patterns`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Disclosure as camouflage for a setting most people need.`}),` Burying a control the majority of\nusers touch in most sessions behind a collapsed accordion doesn’t simplify the page — it moves\nthe complexity from “visible” to “undiscoverable,” which is worse.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`A chevron with no label.`}),` An icon-only trigger asks the reader to open something before\ntelling them what it is. The label is what lets them decide whether opening it is worth the\nclick.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`A validation error hidden inside a collapsed section.`}),` A form that reports “something is\nwrong” without opening the section containing the actual invalid field sends the reader hunting\nthrough every collapsed area to find it.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Reinventing “only one open at a time” per screen.`}),` Accordion ships with no group behavior,\nso every list of mutually exclusive sections either gets this built fresh or gets left without\nit — a smaller version of the same duplication already recorded for skeleton screens (see\n`,_jsx(_components.a,{href:`#known-issues`,children:`Known issues`}),`).`]}),`\n`,_jsx(Heading,{level:`2`,id:`known-issues`,children:`Known issues`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`ID`}),_jsx(_components.th,{children:`Kind`}),_jsx(_components.th,{children:`What`})]})}),_jsx(_components.tbody,{children:_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.a,{href:`/invoca-design-system/foundations/open-decisions#titan-gap-31`,children:`TITAN-GAP-31`})}),_jsx(_components.td,{children:`Open decision`}),_jsxs(_components.td,{children:[`Accordion carrying no group state of its own is a smaller version of the same per-application-rebuilding cost this gap already measures for skeleton screens — see `,_jsx(_components.a,{href:`#anti-patterns`,children:`Anti-patterns`}),`.`]})]})})]}),`\n`,_jsx(Heading,{level:`2`,id:`gaps-in-the-current-rules`,children:`Gaps in the current rules`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Whether disclosure state should persist across a page reload or a later session —\n`,_jsx(_components.a,{href:`#behavior`,children:`Behavior`}),` already flags this as undecided rather than guessing.`]}),`\n`,_jsx(_components.li,{children:`What the actual usage threshold is behind “a minority of users in a minority of sessions” —\nthe heuristic is stated as testable, but no specific percentage is set anywhere in Titan.`}),`\n`,_jsx(_components.li,{children:`Whether a “Show more” link’s revealed rows should animate into place or simply appear, and\nwhether that differs from an Accordion’s own expand transition.`}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`why-it-works-this-way`,children:`Why it works this way`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`The three disclosure mechanisms are matched to scope, not to preference, because the cost of\ngetting the scope wrong is different in each direction.`}),` Using an Accordion for what should be\nits own settings tab hides an entire area behind a control a reader might never notice was\nthere. Using a settings tab for two fields sends the reader on a navigation for something that\nfit in the space of a single click.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`The heuristic is written to be checkable, because “this feels advanced” is exactly the kind of\nclaim that never gets revisited.`}),` A stated threshold — a percentage of accounts, a percentage\nof sessions — is either true or it isn’t, and can be re-measured as usage changes; a feeling has\nno such correction.`]}),`\n`,_jsx(Heading,{level:`2`,id:`related`,children:`Related`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.a,{href:`/invoca-design-system/components/containment/accordion`,children:`Accordion`}),`, the component this\npattern’s collapsible-section variant composes. `,_jsx(_components.a,{href:`/invoca-design-system/components/navigation/tabs`,children:`Tabs`}),`,\nfor the settings-tab variant when the secondary area is large enough to be its own screen.\n`,_jsx(_components.a,{href:`/invoca-design-system/patterns/form-validation`,children:`Form validation`}),`, for the validation-error\nexception to the collapsed-by-default rule.`]}),`\n`,_jsx(Heading,{level:`2`,id:`status`,children:`Status`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`First-pass proposal, not established policy.`}),` No audited Invoca screen backs this page —\nTitan’s design library was not available while writing it. It is built from general\ninteraction-design practice and from what `,_jsx(_components.a,{href:`/invoca-design-system/components/containment/accordion`,children:`Accordion`}),`\nalready establishes. Treat every threshold below as a starting point to check against real\nproduct screens, not as a rule already enforced.`]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Progressive disclosure","description":"Keeping a screen simple without hiding what people actually need.","icon":"chevrons-down-up","keywords":["progressive disclosure","accordion","show more","advanced options","settings","disclosure"],"href":"/invoca-design-system/patterns/progressive-disclosure"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"The problem","slug":"the-problem","depth":2,"children":[]},{"title":"Decide first: how much of the page is affected?","slug":"decide-first-how-much-of-the-page-is-affected","depth":2,"children":[]},{"title":"Vocabulary","slug":"vocabulary","depth":2,"children":[]},{"title":"When this applies","slug":"when-this-applies","depth":2,"children":[]},{"title":"When it doesn’t","slug":"when-it-doesn’t","depth":2,"children":[]},{"title":"Structure","slug":"structure","depth":2,"children":[]},{"title":"Behavior","slug":"behavior","depth":2,"children":[]},{"title":"Constraints","slug":"constraints","depth":2,"children":[]},{"title":"Content","slug":"content","depth":2,"children":[]},{"title":"Accessibility","slug":"accessibility","depth":2,"children":[]},{"title":"Variations","slug":"variations","depth":2,"children":[]},{"title":"Anti-patterns","slug":"anti-patterns","depth":2,"children":[]},{"title":"Known issues","slug":"known-issues","depth":2,"children":[]},{"title":"Gaps in the current rules","slug":"gaps-in-the-current-rules","depth":2,"children":[]},{"title":"Why it works this way","slug":"why-it-works-this-way","depth":2,"children":[]},{"title":"Related","slug":"related","depth":2,"children":[]},{"title":"Status","slug":"status","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"invoca-5bd45748","siteName":"Invoca","title":"Progressive disclosure - Invoca","relatedPagesConfig":{"enabled":true,"limit":5,"mode":"automatic"},"contextualStarterQuestions":[{"_id":"6ab71c04fc74c9b83ba92d2c","deploymentId":"6a10d9fbb2a094386ec2a44e","questionText":"What makes content secondary?","status":"active","generatedBy":"contextual","path":"invoca-design-system/patterns/progressive-disclosure","createdAt":"2026-09-26T01:12:36.119Z","updatedAt":"2026-09-26T01:12:36.119Z","__v":0},{"_id":"6ab71c04fc74c9b83ba92d2b","deploymentId":"6a10d9fbb2a094386ec2a44e","questionText":"How do I choose a disclosure method?","status":"active","generatedBy":"contextual","path":"invoca-design-system/patterns/progressive-disclosure","createdAt":"2026-09-26T01:12:36.119Z","updatedAt":"2026-09-26T01:12:36.119Z","__v":0},{"_id":"6ab71c04fc74c9b83ba92d2a","deploymentId":"6a10d9fbb2a094386ec2a44e","questionText":"When should I hide content?","status":"active","generatedBy":"contextual","path":"invoca-design-system/patterns/progressive-disclosure","createdAt":"2026-09-26T01:12:36.119Z","updatedAt":"2026-09-26T01:12:36.119Z","__v":0}],"navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-09-17T18:53:35.848Z","gitLastModified":"2026-09-17T18:53:06.000Z","originalFileLocation":"invoca-design-system/patterns/progressive-disclosure.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"light\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Keeping a screen simple without hiding what people actually need.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Invoca\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/invoca-5bd45748/Q9AjSeskElHvFPzD/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/invoca-5bd45748/Q9AjSeskElHvFPzD/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/invoca-5bd45748/Q9AjSeskElHvFPzD/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/invoca-5bd45748/Q9AjSeskElHvFPzD/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/invoca-5bd45748/Q9AjSeskElHvFPzD/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/invoca-5bd45748/Q9AjSeskElHvFPzD/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/invoca-5bd45748/Q9AjSeskElHvFPzD/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/invoca-5bd45748/Q9AjSeskElHvFPzD/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/invoca-5bd45748/Q9AjSeskElHvFPzD/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Progressive disclosure - Invoca\">\u003cmeta data-mint-head property=\"og:description\" content=\"Keeping a screen simple without hiding what people actually need.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Invoca\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.invoca.com/invoca-design-system/patterns/progressive-disclosure\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://invoca-5bd45748.mintlify.app/_mintlify/api/og/v2?division=Patterns\u0026amp;title=Progressive+disclosure\u0026amp;description=Keeping+a+screen+simple+without+hiding+what+people+actually+need.\u0026amp;theme=1c2016f9c5ca3323f39e5905\u0026amp;signature=b374c3903b35d9ce86354fcf9929f3a2dc5f4dcbac5fefb52249b298754347ae\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Progressive disclosure - Invoca\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Keeping a screen simple without hiding what people actually need.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://invoca-5bd45748.mintlify.app/_mintlify/api/og/v2?division=Patterns\u0026amp;title=Progressive+disclosure\u0026amp;description=Keeping+a+screen+simple+without+hiding+what+people+actually+need.\u0026amp;theme=1c2016f9c5ca3323f39e5905\u0026amp;signature=b374c3903b35d9ce86354fcf9929f3a2dc5f4dcbac5fefb52249b298754347ae\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/invoca-5bd45748/Q9AjSeskElHvFPzD/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Invoca\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#00A87F\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.invoca.com/invoca-design-system/patterns/progressive-disclosure\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/invoca-design-system/patterns/progressive-disclosure.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.invoca.com/#organization\",\"name\":\"Invoca\",\"url\":\"https://docs.invoca.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/invoca-5bd45748/9Md68DqArcq3WD3L/logo/light.svg?fit=max\u0026auto=format\u0026n=9Md68DqArcq3WD3L\u0026q=85\u0026s=3ed629c5be28d08bd1a6580e72b6dbfa\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.invoca.com#website\",\"name\":\"Invoca\",\"url\":\"https://docs.invoca.com\",\"publisher\":{\"@id\":\"https://docs.invoca.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.invoca.com/invoca-design-system/patterns/progressive-disclosure#webpage\",\"url\":\"https://docs.invoca.com/invoca-design-system/patterns/progressive-disclosure\",\"name\":\"Progressive disclosure\",\"description\":\"Keeping a screen simple without hiding what people actually need.\",\"dateModified\":\"2026-09-17T18:53:06.000Z\",\"isPartOf\":{\"@id\":\"https://docs.invoca.com#website\"},\"breadcrumb\":{\"@id\":\"https://docs.invoca.com/invoca-design-system/patterns/progressive-disclosure#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.invoca.com/invoca-design-system/patterns/progressive-disclosure#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Patterns\",\"item\":\"https://docs.invoca.com/invoca-design-system/patterns/overview\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Progressive disclosure\",\"item\":\"https://docs.invoca.com/invoca-design-system/patterns/progressive-disclosure\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://docs.invoca.com/invoca-design-system/patterns/progressive-disclosure#article\",\"headline\":\"Progressive disclosure\",\"name\":\"Progressive disclosure\",\"description\":\"Keeping a screen simple without hiding what people actually need.\",\"url\":\"https://docs.invoca.com/invoca-design-system/patterns/progressive-disclosure\",\"mainEntityOfPage\":{\"@id\":\"https://docs.invoca.com/invoca-design-system/patterns/progressive-disclosure#webpage\"},\"dateModified\":\"2026-09-17T18:53:06.000Z\",\"keywords\":\"progressive disclosure, accordion, show more, advanced options, settings, disclosure\",\"publisher\":{\"@id\":\"https://docs.invoca.com/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.invoca.com#website\"}}]}\u003c/script>","siteName":"Invoca","nav":{"global":null,"products":[{"product":"Invoca Docs","pages":[{"title":"Invoca Docs","href":""}]},{"product":"Developer","pages":[{"title":"Developer","href":"/en/latest"}]},{"product":"Invoca Design System","icon":"palette","color":{"light":"#00b388","dark":"#00b388"},"description":"","tabs":[{"tab":"Get started","icon":"rocket","pages":[{"title":"Get started","href":"/invoca-design-system"}]},{"tab":"Foundations","icon":"palette","pages":[{"title":"Foundations","href":"/invoca-design-system/foundations/overview"}]},{"tab":"Content","icon":"font","pages":[{"title":"Content","href":"/invoca-design-system/content/voice-and-tone"}]},{"tab":"Components","icon":"shapes","pages":[{"title":"Components","href":"/invoca-design-system/components/overview"}]},{"tab":"Patterns","icon":"clipboard-list","groups":[{"group":"Patterns","root":{"title":"Patterns overview","icon":"layout-template","href":"/invoca-design-system/patterns/overview"},"directory":"card","pages":[{"title":"Destructive confirmation","icon":"trash-2","href":"/invoca-design-system/patterns/destructive-confirmation"},{"title":"Form validation","icon":"clipboard-check","href":"/invoca-design-system/patterns/form-validation"},{"title":"Empty \u0026 zero states","icon":"inbox","href":"/invoca-design-system/patterns/empty-and-zero-states"},{"title":"Loading \u0026 skeletons","icon":"loader","href":"/invoca-design-system/patterns/loading-and-skeletons"},{"title":"Error handling","icon":"octagon-alert","href":"/invoca-design-system/patterns/error-handling"},{"title":"Filtering and search","icon":"filter","href":"/invoca-design-system/patterns/filtering-and-search"},{"title":"Bulk selection","icon":"list-checks","href":"/invoca-design-system/patterns/bulk-selection"},{"title":"Inline editing","description":"Editing a value in place, and when that stops being the right idea.","icon":"pencil","href":"/invoca-design-system/patterns/inline-editing"},{"title":"Progressive disclosure","icon":"chevrons-down-up","href":"/invoca-design-system/patterns/progressive-disclosure"},{"title":"Notifications","description":"Toast, banner, or alert — and what decides which one tells the reader something happened.","icon":"bell","href":"/invoca-design-system/patterns/notifications"},{"title":"Footers","icon":"panel-bottom","href":"/invoca-design-system/patterns/footers"},{"group":"CRUD","root":{"title":"CRUD overview","icon":"database","href":"/invoca-design-system/patterns/crud/overview"},"pages":[{"title":"Create","icon":"circle-plus","href":"/invoca-design-system/patterns/crud/create"},{"title":"Read","icon":"eye","href":"/invoca-design-system/patterns/crud/read"},{"title":"Update","icon":"pencil-line","href":"/invoca-design-system/patterns/crud/update"}]}]}]},{"tab":"Views","icon":"table-columns","pages":[{"title":"Views","href":"/invoca-design-system/views/overview"}]},{"tab":"AI Experience","icon":"robot","pages":[{"title":"AI Experience","href":"/invoca-design-system/ai-experience/overview"}]},{"tab":"Contribute","icon":"code-pull-request","pages":[{"title":"Contribute","href":"/invoca-design-system/contribute/governance"}]},{"tab":"Open Issues","icon":"triangle-exclamation","pages":[{"title":"Open Issues","href":"/invoca-design-system/foundations/divergences"}]}]}]},"basePath":"","title":"Progressive disclosure - Invoca","buildId":"dpl_36EDyZCDfRuoUD9af5CH4M1bqY2h","deploymentId":"dpl_36EDyZCDfRuoUD9af5CH4M1bqY2h","dynamics":[],"chunks":[]}