react-declarative-docs / documents /docs_components_scaffold.html
tripolskypetr's picture
patch
9375fc1
<!DOCTYPE html><html class="default" lang="en" data-base=".."><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>docs/components/scaffold | react-declarative</title><meta name="description" content="Documentation for react-declarative"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script><script async src="../assets/hierarchy.js" id="tsd-hierarchy-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><div class="table-cell" id="tsd-search"><div class="field"><label for="tsd-search-field" class="tsd-widget tsd-toolbar-icon search no-caption"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></label><input type="text" id="tsd-search-field" aria-label="Search"/></div><div class="field"><div id="tsd-toolbar-links"></div></div><ul class="results"><li class="state loading">Preparing search index...</li><li class="state failure">The search index is not available</li></ul><a href="../index.html" class="title">react-declarative</a></div><div class="table-cell" id="tsd-widgets"><a href="#" class="tsd-widget tsd-toolbar-icon menu no-caption" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb"><li><a href="../modules.html">react-declarative</a></li><li><a href="docs_components_scaffold.html">docs/components/scaffold</a></li></ul></div><div class="tsd-panel tsd-typography"><a id="scaffold2-config-driven-material-design-app-shell" class="tsd-anchor"></a><h1 class="tsd-anchor-link">Scaffold2: config-driven Material Design app shell<a href="#scaffold2-config-driven-material-design-app-shell" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h1><p><code>&lt;Scaffold2 /&gt;</code> implements the Material Design app shell pattern — the top app bar, collapsible side navigation drawer, and content area — entirely from a configuration array. You declare groups and menu items as plain objects, attach async visibility and disabled guards, and let the component wire up the chrome. Your page content goes in as <code>children</code>. <code>Scaffold3</code> is a newer variant with an updated visual style; the configuration API is identical.</p>
<a id="installation" class="tsd-anchor"></a><h2 class="tsd-anchor-link">Installation<a href="#installation" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><pre><code class="bash"><span class="hl-5">npm</span><span class="hl-1"> </span><span class="hl-3">install</span><span class="hl-1"> </span><span class="hl-4">--save</span><span class="hl-1"> </span><span class="hl-3">react-declarative</span><span class="hl-1"> </span><span class="hl-3">tss-react</span><span class="hl-1"> </span><span class="hl-3">@mui/material</span><span class="hl-1"> </span><span class="hl-3">@emotion/react</span><span class="hl-1"> </span><span class="hl-3">@emotion/styled</span>
</code><button type="button">Copy</button></pre>
<a id="basic-setup" class="tsd-anchor"></a><h2 class="tsd-anchor-link">Basic setup<a href="#basic-setup" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><a id="step-1-define-your-navigation-groups" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Step 1: Define your navigation groups<a href="#step-1-define-your-navigation-groups" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Create an <code>IScaffold2Group[]</code> array. Each group has an <code>id</code>, an optional <code>label</code>, and a <code>children</code> array of <code>IScaffold2Option</code> items.</p>
<pre><code class="tsx"><span class="hl-0">import</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">IScaffold2Group</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">IScaffold2Option</span><span class="hl-1">,</span><br/><span class="hl-1">} </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&#39;react-declarative&#39;</span><span class="hl-1">;</span><br/><span class="hl-0">import</span><span class="hl-1"> </span><span class="hl-2">PeopleIcon</span><span class="hl-1"> </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&#39;@mui/icons-material/People&#39;</span><span class="hl-1">;</span><br/><span class="hl-0">import</span><span class="hl-1"> </span><span class="hl-2">DnsIcon</span><span class="hl-1"> </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&#39;@mui/icons-material/Dns&#39;</span><span class="hl-1">;</span><br/><span class="hl-0">import</span><span class="hl-1"> </span><span class="hl-2">PublicIcon</span><span class="hl-1"> </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&#39;@mui/icons-material/Public&#39;</span><span class="hl-1">;</span><br/><br/><span class="hl-0">export</span><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-10">options</span><span class="hl-1">: </span><span class="hl-7">IScaffold2Group</span><span class="hl-1">[] = [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">id:</span><span class="hl-1"> </span><span class="hl-3">&#39;build&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">label:</span><span class="hl-1"> </span><span class="hl-3">&#39;Build&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">children:</span><span class="hl-1"> [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">id:</span><span class="hl-1"> </span><span class="hl-3">&#39;authentication&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">label:</span><span class="hl-1"> </span><span class="hl-3">&#39;Authentication&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">icon:</span><span class="hl-1"> </span><span class="hl-2">PeopleIcon</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">isVisible</span><span class="hl-2">:</span><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> () </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-2">authService</span><span class="hl-1">.</span><span class="hl-5">hasRole</span><span class="hl-1">(</span><span class="hl-3">&#39;admin&#39;</span><span class="hl-1">),</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">id:</span><span class="hl-1"> </span><span class="hl-3">&#39;database&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">label:</span><span class="hl-1"> </span><span class="hl-3">&#39;Database&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">icon:</span><span class="hl-1"> </span><span class="hl-2">DnsIcon</span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">id:</span><span class="hl-1"> </span><span class="hl-3">&#39;hosting&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">label:</span><span class="hl-1"> </span><span class="hl-3">&#39;Hosting&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">icon:</span><span class="hl-1"> </span><span class="hl-2">PublicIcon</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">isDisabled</span><span class="hl-2">:</span><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> () </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-5">maintenanceGuard</span><span class="hl-1">(),</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> ],</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">id:</span><span class="hl-1"> </span><span class="hl-3">&#39;release&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">label:</span><span class="hl-1"> </span><span class="hl-3">&#39;Release&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">children:</span><span class="hl-1"> [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">id:</span><span class="hl-1"> </span><span class="hl-3">&#39;analytics&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">label:</span><span class="hl-1"> </span><span class="hl-3">&#39;Analytics&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> ],</span><br/><span class="hl-1"> },</span><br/><span class="hl-1">];</span>
</code><button type="button">Copy</button></pre>
<a id="step-2-render-scaffold2-with-your-options" class="tsd-anchor"></a><h3 class="tsd-anchor-link">Step 2: Render Scaffold2 with your options<a href="#step-2-render-scaffold2-with-your-options" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Pass <code>options</code>, <code>activeOptionPath</code> (the currently selected item id chain), and your page content as <code>children</code>.</p>
<pre><code class="tsx"><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">Scaffold2</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&#39;react-declarative&#39;</span><span class="hl-1">;</span><br/><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">options</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&#39;./navigation&#39;</span><span class="hl-1">;</span><br/><br/><span class="hl-0">export</span><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-5">App</span><span class="hl-1"> = () </span><span class="hl-4">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> [</span><span class="hl-10">activePath</span><span class="hl-1">, </span><span class="hl-10">setActivePath</span><span class="hl-1">] = </span><span class="hl-2">React</span><span class="hl-1">.</span><span class="hl-5">useState</span><span class="hl-1">(</span><span class="hl-3">&#39;build.authentication&#39;</span><span class="hl-1">);</span><br/><br/><span class="hl-1"> </span><span class="hl-0">return</span><span class="hl-1"> (</span><br/><span class="hl-1"> </span><span class="hl-6">&lt;</span><span class="hl-7">Scaffold2</span><br/><span class="hl-1"> </span><span class="hl-8">appName</span><span class="hl-1">=</span><span class="hl-3">&quot;My App&quot;</span><br/><span class="hl-1"> </span><span class="hl-8">options</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-2">options</span><span class="hl-4">}</span><br/><span class="hl-1"> </span><span class="hl-8">activeOptionPath</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-2">activePath</span><span class="hl-4">}</span><br/><span class="hl-1"> </span><span class="hl-8">onOptionClick</span><span class="hl-1">=</span><span class="hl-4">{</span><span class="hl-9">(</span><span class="hl-2">path</span><span class="hl-9">, </span><span class="hl-2">id</span><span class="hl-9">) </span><span class="hl-4">=&gt;</span><span class="hl-9"> {</span><br/><span class="hl-9"> </span><span class="hl-5">setActivePath</span><span class="hl-9">(</span><span class="hl-2">path</span><span class="hl-9">);</span><br/><span class="hl-9"> </span><span class="hl-2">router</span><span class="hl-9">.</span><span class="hl-5">navigate</span><span class="hl-9">(</span><span class="hl-3">`/</span><span class="hl-4">${</span><span class="hl-2">id</span><span class="hl-4">}</span><span class="hl-3">`</span><span class="hl-9">);</span><br/><span class="hl-9"> }</span><span class="hl-4">}</span><br/><span class="hl-1"> </span><span class="hl-6">&gt;</span><br/><span class="hl-1"> </span><span class="hl-4">{</span><span class="hl-17">/* your routed page content */</span><span class="hl-4">}</span><br/><span class="hl-1"> </span><span class="hl-6">&lt;</span><span class="hl-7">Outlet</span><span class="hl-1"> </span><span class="hl-6">/&gt;</span><br/><span class="hl-1"> </span><span class="hl-6">&lt;/</span><span class="hl-7">Scaffold2</span><span class="hl-6">&gt;</span><br/><span class="hl-1"> );</span><br/><span class="hl-1">};</span>
</code><button type="button">Copy</button></pre>
<a id="key-props" class="tsd-anchor"></a><h2 class="tsd-anchor-link">Key props<a href="#key-props" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><p><strong><code>options</code></strong> <code>IScaffold2Group[]</code> (required)</p>
<p>The full navigation tree. Groups contain options; options can nest further options and declare tabs.</p>
<hr>
<p><strong><code>activeOptionPath</code></strong> <code>string</code> (required)</p>
<p>A dot-separated path that identifies the currently highlighted menu item, e.g. <code>&quot;build.authentication&quot;</code>. The Scaffold highlights the matching item in the side drawer.</p>
<hr>
<p><strong><code>activeTabPath</code></strong> <code>string</code></p>
<p>Identifies the active tab within the current option, e.g. <code>&quot;tab1&quot;</code>. Tabs are rendered in the top app bar.</p>
<hr>
<p><strong><code>appName</code></strong> <code>string</code></p>
<p>The application name shown in the top app bar. Defaults to <code>&quot;Scaffold2&quot;</code>.</p>
<hr>
<p><strong><code>noSearch</code></strong> <code>boolean</code></p>
<p>Hides the search box in the side drawer when <code>true</code>.</p>
<hr>
<p><strong><code>noAppName</code></strong> <code>boolean</code></p>
<p>Hides the app name from the top bar.</p>
<hr>
<p><strong><code>payload</code></strong> <code>T</code></p>
<p>An arbitrary object forwarded to every <code>isVisible</code> and <code>isDisabled</code> callback on options and tabs. Use it to pass the current user session.</p>
<hr>
<p><strong><code>onOptionClick</code></strong> <code>(path: string, id: string) =&gt; void | boolean</code></p>
<p>Called when the user clicks a menu item. <code>path</code> is the dot-joined ancestor chain; <code>id</code> is the clicked option's own <code>id</code>. Return <code>false</code> to prevent the default highlight update.</p>
<hr>
<p><strong><code>onTabChange</code></strong> <code>(path: string, tab: string, id: string) =&gt; void</code></p>
<p>Called when the user switches between tabs in the top bar.</p>
<hr>
<p><strong><code>onInit</code></strong> <code>() =&gt; void | Promise&lt;void&gt;</code></p>
<p>Called once after mount. Use it to trigger async operations such as loading the user profile before computing visibility.</p>
<a id="async-visibility-and-disabled-guards" class="tsd-anchor"></a><h2 class="tsd-anchor-link">Async visibility and disabled guards<a href="#async-visibility-and-disabled-guards" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><p>Both <code>IScaffold2Group</code> and <code>IScaffold2Option</code> accept async functions for <code>isVisible</code> and <code>isDisabled</code>. The Scaffold evaluates all guards on mount (and whenever <code>deps</code> changes) and hides or disables items accordingly.</p>
<pre><code class="tsx"><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">IScaffold2Group</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&#39;react-declarative&#39;</span><span class="hl-1">;</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-10">options</span><span class="hl-1">: </span><span class="hl-7">IScaffold2Group</span><span class="hl-1">[] = [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">id:</span><span class="hl-1"> </span><span class="hl-3">&#39;admin&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">label:</span><span class="hl-1"> </span><span class="hl-3">&#39;Admin&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">isVisible</span><span class="hl-2">:</span><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> () </span><span class="hl-4">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-17">// hide this entire group for non-admins</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-10">role</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-2">authService</span><span class="hl-1">.</span><span class="hl-5">getCurrentRole</span><span class="hl-1">();</span><br/><span class="hl-1"> </span><span class="hl-0">return</span><span class="hl-1"> </span><span class="hl-2">role</span><span class="hl-1"> === </span><span class="hl-3">&#39;admin&#39;</span><span class="hl-1">;</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-2">children:</span><span class="hl-1"> [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">id:</span><span class="hl-1"> </span><span class="hl-3">&#39;users&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">label:</span><span class="hl-1"> </span><span class="hl-3">&#39;Users&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-5">isDisabled</span><span class="hl-2">:</span><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> (</span><span class="hl-2">payload</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-0">return</span><span class="hl-1"> !</span><span class="hl-2">payload</span><span class="hl-1">.</span><span class="hl-2">hasUsersPermission</span><span class="hl-1">;</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> ],</span><br/><span class="hl-1"> },</span><br/><span class="hl-1">];</span>
</code><button type="button">Copy</button></pre>
<blockquote>
<p><strong>Warning:</strong> Guards run asynchronously. Items are visible and enabled by default until the guard resolves. If you need to block access immediately, set <code>loading</code> on the <code>Scaffold2</code> while guards are pending.</p>
</blockquote>
<a id="tabs-and-nested-options" class="tsd-anchor"></a><h2 class="tsd-anchor-link">Tabs and nested options<a href="#tabs-and-nested-options" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><p>An <code>IScaffold2Option</code> can have both <code>tabs</code> (rendered in the top app bar) and <code>options</code> (nested sub-items in the side menu):</p>
<pre><code class="tsx"><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">IScaffold2Group</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&#39;react-declarative&#39;</span><span class="hl-1">;</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-10">options</span><span class="hl-1">: </span><span class="hl-7">IScaffold2Group</span><span class="hl-1">[] = [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">id:</span><span class="hl-1"> </span><span class="hl-3">&#39;build&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">label:</span><span class="hl-1"> </span><span class="hl-3">&#39;Build&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">children:</span><span class="hl-1"> [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">id:</span><span class="hl-1"> </span><span class="hl-3">&#39;authentication&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">label:</span><span class="hl-1"> </span><span class="hl-3">&#39;Authentication&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-17">// tabs appear in the top bar when this option is active</span><br/><span class="hl-1"> </span><span class="hl-2">tabs:</span><span class="hl-1"> [</span><br/><span class="hl-1"> { </span><span class="hl-2">id:</span><span class="hl-1"> </span><span class="hl-3">&#39;users&#39;</span><span class="hl-1">, </span><span class="hl-2">label:</span><span class="hl-1"> </span><span class="hl-3">&#39;Users&#39;</span><span class="hl-1"> },</span><br/><span class="hl-1"> { </span><span class="hl-2">id:</span><span class="hl-1"> </span><span class="hl-3">&#39;sessions&#39;</span><span class="hl-1">, </span><span class="hl-2">label:</span><span class="hl-1"> </span><span class="hl-3">&#39;Sessions&#39;</span><span class="hl-1"> },</span><br/><span class="hl-1"> ],</span><br/><span class="hl-1"> </span><span class="hl-17">// options appear as sub-items in the side menu</span><br/><span class="hl-1"> </span><span class="hl-2">options:</span><span class="hl-1"> [</span><br/><span class="hl-1"> { </span><span class="hl-2">id:</span><span class="hl-1"> </span><span class="hl-3">&#39;users&#39;</span><span class="hl-1">, </span><span class="hl-2">label:</span><span class="hl-1"> </span><span class="hl-3">&#39;Users list&#39;</span><span class="hl-1"> },</span><br/><span class="hl-1"> { </span><span class="hl-2">id:</span><span class="hl-1"> </span><span class="hl-3">&#39;sessions&#39;</span><span class="hl-1">, </span><span class="hl-2">label:</span><span class="hl-1"> </span><span class="hl-3">&#39;Active sessions&#39;</span><span class="hl-1"> },</span><br/><span class="hl-1"> ],</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> ],</span><br/><span class="hl-1"> },</span><br/><span class="hl-1">];</span>
</code><button type="button">Copy</button></pre>
<a id="scaffold2-vs-scaffold3-vs-scaffold-v1" class="tsd-anchor"></a><h2 class="tsd-anchor-link">Scaffold2 vs Scaffold3 vs Scaffold (v1)<a href="#scaffold2-vs-scaffold3-vs-scaffold-v1" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><p><strong>Scaffold (v1)</strong></p>
<p>The original app shell. Minimal API but limited customisation. Consider migrating to Scaffold2.</p>
<p><strong>Scaffold2</strong></p>
<p>Recommended for most apps. Full async guard support, tabs, nested options, payload forwarding, and slot components.</p>
<p><strong>Scaffold3</strong></p>
<p>Updated visual style with the same configuration API as Scaffold2. Drop-in replacement when you want a refreshed look.</p>
<blockquote>
<p><strong>Tip:</strong> All three variants accept the same <code>IScaffold2Group[]</code> array for <code>options</code>. You can switch between Scaffold2 and Scaffold3 by changing the import without touching your navigation config.</p>
</blockquote>
<a id="slot-components" class="tsd-anchor"></a><h2 class="tsd-anchor-link">Slot components<a href="#slot-components" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><p><code>Scaffold2</code> exposes named slot props for inserting custom React components at specific positions in the layout:</p>
<table>
<thead>
<tr>
<th>Prop</th>
<th>Position</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>AfterAppName</code></td>
<td>After the app name in the top bar</td>
</tr>
<tr>
<td><code>BeforeActionMenu</code></td>
<td>Before the action icon row</td>
</tr>
<tr>
<td><code>BeforeSearch</code> / <code>AfterSearch</code></td>
<td>Around the search box in the drawer</td>
</tr>
<tr>
<td><code>BeforeMenuContent</code> / <code>AfterMenuContent</code></td>
<td>Around the menu item list</td>
</tr>
<tr>
<td><code>BeforeContent</code> / <code>AfterContent</code></td>
<td>Around the main content area</td>
</tr>
<tr>
<td><code>Copyright</code></td>
<td>Footer of the side drawer</td>
</tr>
</tbody>
</table>
</div></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div><details open class="tsd-accordion tsd-page-navigation"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>On This Page</h3></summary><div class="tsd-accordion-details"><a href="#scaffold2-config-driven-material-design-app-shell"><span>Scaffold2: config-<wbr/>driven <wbr/>Material <wbr/>Design app shell</span></a><ul><li><a href="#installation"><span>Installation</span></a></li><li><a href="#basic-setup"><span>Basic setup</span></a></li><li><ul><li><a href="#step-1-define-your-navigation-groups"><span>Step 1: <wbr/>Define your navigation groups</span></a></li><li><a href="#step-2-render-scaffold2-with-your-options"><span>Step 2: <wbr/>Render <wbr/>Scaffold2 with your options</span></a></li></ul></li><li><a href="#key-props"><span>Key props</span></a></li><li><a href="#async-visibility-and-disabled-guards"><span>Async visibility and disabled guards</span></a></li><li><a href="#tabs-and-nested-options"><span>Tabs and nested options</span></a></li><li><a href="#scaffold2-vs-scaffold3-vs-scaffold-v1"><span>Scaffold2 vs <wbr/>Scaffold3 vs <wbr/>Scaffold (v1)</span></a></li><li><a href="#slot-components"><span>Slot components</span></a></li></ul></div></details></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">react-declarative</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>