How to Customize the Side Menu Collapse Behavior and Width Adjustment Settings in Astro Big Doc

You can customize the side menu collapse behavior and width adjustment settings in Astro Big Doc by modifying the CSS transition properties in src/layout/ClientNavMenu.astro and the width logic in src/layout/client_nav_menu.js, allowing you to control animation speeds, disable transitions, or set custom widths like 250px instead of the default 20vw.

The Astro Big Doc theme from microwebstacks/astro-big-doc provides a responsive documentation layout with a collapsible side navigation. Understanding how to customize the side menu collapse behavior and width adjustment settings allows you to tailor the user experience to match your design requirements, whether you need faster animations, fixed pixel widths, or instant state changes.

Understanding the Side Menu Architecture

The side menu implementation separates concerns between two distinct mechanisms:

  • Submenu Collapse: Toggles the hidden class on nested <ul class="nested pages_menu"> elements, using CSS max-height transitions for smooth slide animations.
  • Global Menu Width: Controls the entire navigation container's width via the set_open_state function in src/layout/client_nav_menu.js, switching between 0vw (closed) and 20vw (open).

Both mechanisms rely on CSS transitions defined in src/layout/ClientNavMenu.astro for animation smoothing, while JavaScript handles state toggling and localStorage persistence.

Customizing Submenu Collapse Behavior

How the Collapse Logic Works

When a user clicks a parent menu item's arrow icon, the event handler in src/layout/client_nav_menu.js executes the following logic:

// In src/layout/client_nav_menu.js
toggler[i].addEventListener("click", function (e) {
  // Toggle the nested <ul> visibility
  this.parentElement.parentElement.querySelector("ul")?.classList.toggle("hidden");
  // Toggle the "expanded" state on the parent <div>
  this.parentElement.classList.toggle("expanded");
  // Persist the new state in localStorage
  const section_name = section_from_pathname(window.location.pathname);
  expand_toggle_save(section_name, toggler[i].getAttribute("data-url"));
  e.preventDefault();
});

The hidden class controls the max-height property through CSS, while the expanded class rotates the arrow icon 90 degrees.

Adjusting the CSS Transition Speed

The animation duration for submenu expansion is controlled by the transition-duration property in src/layout/ClientNavMenu.astro:

/* In src/layout/ClientNavMenu.astro global style block */
ul.nested.pages_menu{
    max-height: 200vh;
    transition-property: max-height;
    transition-duration: 0.4s;  /* Default speed */
}
ul.nested.hidden.pages_menu{
    max-height: 0px;
    transition-property: max-height;
    transition-duration: 0.4s;
}

To make the animation faster, override the duration values:

ul.nested.pages_menu,
ul.nested.hidden.pages_menu{
    transition-duration: 0.2s;  /* Faster collapse */
}

Disabling Animations Completely

For instant state changes without visual transitions, set the duration to zero:

ul.nested.pages_menu,
ul.nested.hidden.pages_menu{
    transition-duration: 0s;  /* Instant toggle */
}

Alternatively, you can remove the transition-property declarations entirely from the CSS rules.

Adjusting Side Menu Width Settings

The set_open_state Function

The global menu open/close state is managed by the set_open_state function in src/layout/client_nav_menu.js:

// In src/layout/client_nav_menu.js
function set_open_state(section_name){
  const left_open = menu.sections_open[section_name];
  const menu_nav = document.querySelector("nav.pages_menu");
  
  // Disable transition for initial state to prevent animation on page load
  menu_nav.style.transition = "width 0s";
  
  if (left_open){
    menu_nav.style.width = "20vw";          // Default open width
    menu_nav.setAttribute("data-width","20vw");
    menu_nav.classList.add("open");
    menu_nav.classList.remove("closed");
  } else {
    menu_nav.style.width = "0vw";           // Closed state
    menu_nav.classList.add("closed");
    menu_nav.classList.remove("open");
  }
  
  // Re-enable smooth transition after initial setup
  setTimeout(()=>{ menu_nav.style.transition = "width 0.5s"; }, 100);
}

The function checks menu.sections_open[section_name] to determine the initial state, then applies either 20vw (open) or 0vw (closed) to the navigation element.

Changing the Default Width Value

To use a fixed pixel width instead of the viewport-relative 20vw, modify the width assignments in set_open_state:

// Replace the width values in src/layout/client_nav_menu.js
menu_nav.style.width = "250px";          // Fixed width instead of 20vw
menu_nav.setAttribute("data-width","250px");

You must also update the CSS in src/layout/ClientNavMenu.astro to ensure the transition property accommodates the new unit:

nav{
    width: var(--data_width);
    transition: width 0.5s;  /* Works with both vw and px units */
}

Adding a Custom Width Prop to ClientNavMenu.astro

For a more flexible, component-based approach, extend the Astro component to accept a custom width prop:

---
// In src/layout/ClientNavMenu.astro
export interface Props {
  open: boolean;
  hash: string;
  openWidth?: string;   // New optional prop
}
const {hash, open, openWidth = "20vw"} = Astro.props;
const data_width = open ? openWidth : "0vw";
const open_class = open ? "open" : "closed";
---

<nav class={`${open_class} pages_menu client`} data-width={data_width} data-hash={hash}>
  <!-- Navigation content -->
</nav>

<style define:vars={{ data_width }}>
  nav{
    width: var(--data_width);
    transition: width 0.5s;
  }
</style>

<script src="./client_nav_menu.js" />

Now you can invoke the component with a custom width:

<ClientNavMenu open={true} openWidth="250px" hash={currentHash} />

Persisting User Preferences with localStorage

Both the submenu expand states and the global menu open state are persisted in the browser's localStorage under the key "menu". The relevant utility functions in src/layout/client_nav_menu.js include:

  • expand_toggle_save(section_name, href): Toggles the expanded state for a specific submenu item and saves the updated map.
  • set_open_state(section_name): Reads the open/closed state for the current section and applies it to the DOM.
  • save_menu(): Serializes the entire menu object to localStorage.

The storage schema follows this structure:

{
  sections_open: {
    "section-name": true,  // Whether the side menu is open for this section
    // ... other sections
  },
  expanded: {
    "section-name": ["url1", "url2"],  // Array of expanded submenu URLs
    // ... other sections
  }
}

To reset all user preferences during development or after structural changes, clear the storage:

localStorage.removeItem('menu');

Summary

  • Submenu collapse behavior is controlled by the hidden class toggle on <ul class="nested pages_menu"> elements, with animation speed determined by the transition-duration property in src/layout/ClientNavMenu.astro.

  • Side menu width adjustment relies on the set_open_state function in src/layout/client_nav_menu.js, which applies either 20vw (open) or 0vw (closed) by default, but can be modified to use fixed pixel values or dynamic props.

  • State persistence automatically saves user preferences to localStorage under the "menu" key, tracking both global open/closed states and individual submenu expansion states per section.

  • Customization entry points include the global CSS block in ClientNavMenu.astro for transition timing, the JavaScript width assignments for dimension changes, and optional Astro props for component-level flexibility.

Frequently Asked Questions

How do I change the animation speed for submenu expansion?

Modify the transition-duration value in the global CSS block of src/layout/ClientNavMenu.astro. The default is 0.4s for both the ul.nested.pages_menu and ul.nested.hidden.pages_menu selectors. Changing these to 0.2s makes the collapse faster, while 0s disables the animation entirely.

Can I use a fixed pixel width instead of the default 20vw for the side menu?

Yes. Edit the set_open_state function in src/layout/client_nav_menu.js and replace the 20vw string with a pixel value like "250px". Alternatively, extend ClientNavMenu.astro to accept an openWidth prop, then pass your desired pixel value when instantiating the component. Ensure the CSS transition property in the Astro component remains compatible with the new unit.

Where is the menu open/close state stored between page refreshes?

The state persists in the browser's localStorage under the key "menu". The save_menu() function in src/layout/client_nav_menu.js serializes the current configuration, including which sections are open and which submenus are expanded. This allows the documentation to remember user preferences across navigation and browser sessions.

How do I completely disable the width transition animation for the side menu?

To eliminate the sliding animation when opening or closing the entire side menu, set the transition duration to 0s in the set_open_state function of src/layout/client_nav_menu.js. Specifically, change menu_nav.style.transition = "width 0.5s" to menu_nav.style.transition = "width 0s", or remove the transition property entirely from the nav CSS rule in ClientNavMenu.astro.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →