Skip to content

Conversation

@mrmees
Copy link

@mrmees mrmees commented Feb 10, 2026

Summary

  • Extract theme preset icons from inline SVG path data to separate .svg files using CSS variables for dynamic theming
  • Migrate theme preset config from single url to links[] array for multi-link support
  • Add user-configurable custom navigation links to the sidebar with add/edit/delete via a settings dialog
  • Add drag-to-reorder for both system navigation links and custom links
  • Add collapsible links with "More" menu (system) and "Bookmarks" popup (custom) for hidden items
  • Add expandable sidebar with persistent toggle and hover-to-expand
  • Add import/export for custom link configuration backup and sharing
  • Add context menus for all link types with appropriate actions per type

Note: This PR was evaluated for splitting (theme icon extraction vs. navigation features) but the two share types, rendering infrastructure, and the icon fallback chain, making separation impractical without duplicating significant code.

Details

Custom Navigation Links

Users can add external links to the sidebar via Settings > Navigation. Each link supports:

  • Icon types: Built-in Material Design icons, custom SVG upload, or custom image (PNG/JPEG)
  • Color options: Theme color, custom hex color, or original file colors (SVG only)
  • URL validation: Protocol safety checks, warning for URLs missing https://

Theme Icon Extraction

Each theme preset now has a dedicated icon_*.svg file (23 total) that uses CSS custom properties (--v-primary-base, --v-primary-offset-base) for dynamic color theming via vue-inline-svg DOM injection. This replaces the previous inline SVG path arrays in config.json.

Sidebar Enhancements

  • Drag-to-reorder: System links (excluding Home and Settings which are pinned) and custom links can be reordered by dragging
  • Collapsible links: Right-click any link to collapse it into the More menu (system) or Bookmarks popup (custom)
  • Expandable sidebar: Click the logo to expand/collapse, or hover over dashboard layout to temporarily expand
  • Context menus: Right-click system links to collapse/show, custom links to edit/delete/collapse, theme links to hide

Import/Export

Custom links can be exported as JSON and imported with merge or replace modes, enabling backup and sharing across instances.

Storage

All navigation config is stored in Moonraker's database via the existing uiSettings.navigation path — no new storage mechanisms or API endpoints.

New Dependencies

  • vue-inline-svg — DOM-injected SVG rendering for theme icons with CSS variable support

Screenshots

Sidebar with custom links

Expanded Minimized Fully collapsed
sidebar_w_links_expanded sidebar_w_links_minimized sidebar_fully_minimized_collapsed

Navigation Links settings

settings_card

Add/Edit link dialog

Built-in icon Icon type selector Custom SVG with color options
add_nav_link_built_in add_nav_link_icon_type add_nav_link_svg_colors

Context menus

Custom link context menu Collapsed links submenu
sidebar_mainmenu_context sidebar_submenu_context

Backwards Compatibility

  • Existing users with no navigation settings will see default behavior (no custom links, standard sidebar order)
  • All new config fields use optional chaining with sensible defaults
  • Theme presets maintain backwards compatibility via fallback chain: links[] -> legacy url field
  • Icon rendering falls back through: per-link SVG filename -> preset-level icon -> legacy inline path array -> logo filename

Test Plan

  • Verify sidebar renders correctly with default settings (no stored navigation config)
  • Add a custom link via Settings > Navigation, verify it appears in sidebar
  • Edit and delete custom links
  • Test all icon types: built-in icon, custom SVG upload, custom image upload
  • Test color options: theme color, custom color, file colors (SVG)
  • Drag-to-reorder system links, verify order persists across refresh
  • Drag-to-reorder custom links, verify order persists across refresh
  • Collapse system links to More menu via context menu
  • Collapse custom links to Bookmarks popup via context menu
  • Right-click More/Bookmarks icon to "Show all in sidebar"
  • Export links, import with merge mode, import with replace mode
  • Switch themes and verify theme link updates correctly
  • Hide theme links via context menu and settings panel
  • Test expandable sidebar: click logo to toggle, hover to expand
  • Verify keyboard shortcuts still work for system navigation
  • Test on mobile viewport (sidebar behavior)

… separation

Add user-configurable custom navigation links to the sidebar with
add/edit/delete, icon selection (Material Design, Klipper, URL favicon,
emoji), drag-to-reorder for system and custom links, collapsible links
with popup menus, context menus, import/export, and expandable sidebar
with hover-to-expand.

Extract inline theme SVG icon data from config.json into individual
icon_*.svg files using CSS variables for dynamic theming via
vue-inline-svg. Add multi-link support per theme preset with icon
fallback chain.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@mrmees mrmees marked this pull request as ready for review February 10, 2026 04:39
@pedrolamas
Copy link
Member

Hi @mrmees thank you for your work on this feature - this looks very interesting indeed! 🙂

I haven't tested this yet but I will do it ASAP.

I do have a few questions though:

  • Why do we need the new brand icons SVG? Can't we just use the already existing logo SVG files instead?
  • I have my reservations that you actually need those changes on the AppDraggable... I would argue that something else is probably failing there as I have found it works fine on every scenario I tested it (even with external order updates)

@pedrolamas pedrolamas added the FR - Enhancement New feature or request label Feb 11, 2026
@pedrolamas pedrolamas added this to the 1.36.2 milestone Feb 11, 2026
@mrmees
Copy link
Author

mrmees commented Feb 12, 2026

* I have my reservations that you actually need those changes on the `AppDraggable`... I would argue that something else is probably failing there as I have found it works fine on every scenario I tested it (even with external order updates)

Yup, you were right, it was something that worked when I was having issues getting the ordering to save after refresh, but looks like that was a DOM element issue that was able to be worked around. Got it working without any changes to AppDraggable.vue. Will amend later this weekend when I'm in front of my real machine.

* Why do we need the new brand icons SVG? Can't we just use the already existing logo SVG files instead?

Ahhh, I never explained the changes to the built-in-theme configuration in the commit, my mistake, I kinda backed into those changes for a few reasons :

  • Frustration during testing due to a few logos/themes not working the same way as the others as far as color overrides worked. EG: The Z-bolt theme is always black and just doesn't work in the dark theme that it defaults to. The RatRig SVG was hard coded green and didn't respond to theme color adjustments.
  • I figured better sponsorship perks (namely, a Patreon/Coffee/Donation link) would be something that Fluidd might be interested in, and therefore might raise the chance of getting this pulled in.
  • I just absolutely could not get that CocoaPress icon to look good in the sidebar.

So, the configuration schema was modified to allow a theme to have a couple of additional sections:

  • In addition to the main logo, a separate settings page background image - because why not.
  • A theoretically unlimited number of links, with an individual href and SVG file for each. The idea was to allow a sponsor to provide easy access to documentation/project pages, and also a quick link for donations to people who obviously enjoy the project. (Quick note - sponsor links are hide-able but can't be deleted, so they'll always show up within the settings menu - which seems like a good tradeoff between user and sponsor preferences.)
  • Considering the potential for config file bloat, I thought it made more sense to just let the SVG path information live in an SVG file and theoretically allow easier updating/maintenance in the future.
  • Everything should fall back gracefully to the original inline config SVG storage if it exists. I have not extensively tested this.

This is a little janky, and if you wanted to strip it out I wouldn't be opposed. There are two major things to be aware of:

  • To get the SVG files to properly respond to theme color and dark/light mode changes, they need to have CSS classes embedded within them that aren't standard (eg: var(--v-primary-base, #fallback))
  • Using those internal tags with inline-svg technically allows for a DOM injection, though that would require either Fluidd officially adding an SVG with an attack embedded or a user manually changing an SVG for an infected one.

@pedrolamas pedrolamas modified the milestones: 1.36.2, 1.36.3 Feb 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

FR - Enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants