Skip to content

feat: collapsible sidebar with icon-only mode - #797

Merged
KnifeLemon merged 22 commits into
KnifeLemon:mainfrom
adnan-bhaldar:feat/collapsible-sidebar
Oct 30, 2026
Merged

KnifeLemon merged 22 commits into
KnifeLemon:mainfrom
adnan-bhaldar:feat/collapsible-sidebar

Conversation

@adnan-bhaldar

@adnan-bhaldar adnan-bhaldar commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Tip

Start the title with a prefix so the PR is labeled automatically: feat: fix: docs: ci: build: i18n:
Example: fix(hwp): keep tables when converting to DOCX

What does this change?

Adds a button to the main window's sidebar, just above the update, GitHub and Sponsor icons, that collapses it to an icon-only rail and expands it again. The logo and app name stay at the top.

  • Collapsed: titles, tagline and version are hidden. The nav items, Update, GitHub and Sponsor show only their icon, each with a tooltip.
  • The width animates, and doesn't animate when reduced motion is on.
  • The state is saved in settings.json (AppSettings.NavCollapsed), so it survives the window going to the tray and coming back. Settings from before this change start expanded, so no schema step is needed.
  • Accessibility: while collapsed, each nav row keeps its title as its screen-reader name (AutomationProperties.Name), because the visible text is hidden.
  • While in here: hovering a nav item now nudges only the icon, so the highlighted background no longer slides with it.
  • MainWindowViewModel now takes a UserDataStore, so the existing tests that construct it were updated to pass one.

Type of change

  • Bug fix
  • New feature or improvement
  • New format or engine
  • Translation
  • Documentation
  • Build, CI or dependencies

How was it tested?

  • dotnet format --verify-no-changes
  • dotnet test
  • Tried it in the app (what you converted or clicked, and on which OS):
    • OS: Windows 11
    • Collapsed and expanded the sidebar, hovered every item and the bottom icons, switched pages while collapsed, closed to the tray and reopened (state is kept), switched language (tooltips follow), tried with an update available.

New tests in Filee.App.Tests:

  • NavCollapseTests (new file):
    • Collapsing saves NavCollapsed, and a new view model starts collapsed.
    • Expanding saves it too.
    • Settings from before this change start expanded.
  • AutomationNameTests: while collapsed, every nav item has its title as both its tooltip and its automation name. Expanded, there is no tooltip.
  • 14 existing test files were updated for the new MainWindowViewModel constructor argument.

Screenshots (UI changes)

State Screenshots
Expanded sidebar image
Collapsed sidebar image
Collapsed, tooltip on a nav item image
Collapsed, update available image
Hovering a nav item (expanded) image
Dark theme image

Checklist

  • New UI strings are in all src/Filee.App/Assets/i18n/*.json files (including Indonesian, rebased onto i18n: add Indonesian language support (UI translation and platform resources)Β #790), and each file ends as it does on main
  • New third-party code or binaries are listed in THIRD-PARTY-NOTICES.md (none added)
  • Tests added for the new behavior, and existing tests updated so the test project builds
  • The PR does one thing (the sidebar; the hover tweak, translations and tests are separate commits)

Add a button at the top of the main window's navigation that collapses it
to an icon rail and expands it again.

- Collapsed: titles, tagline and version are hidden; nav items, Update,
  GitHub and Sponsor show only their icon, with a tooltip
- The width animates (no animation when reduced motion is on)
- The state is saved in settings.json (AppSettings.NavCollapsed), so it
  survives the window being closed to the tray
- Nav item padding moved into the item template so the tooltip covers the
  whole row
- Adds nav.collapse and nav.expand (English; other languages follow)
The whole row (including its background) slid 3px to the right on hover.
Now only the icon moves and the highlighted background stays put.
Add nav.collapse and nav.expand to ar, de, es, fr, hi, it, ja, ko, ne, pl,
pt-BR, pt-PT, ru, th, tr, zh-CN and zh-TW.
The collapse/expand button sat at the top of the sidebar, above the logo
and app name. Put it at the bottom, just above the update, GitHub and
Sponsor group, so the logo and name stay at the top.
@github-actions github-actions Bot added the feature New features label Oct 30, 2026
@adnan-bhaldar
adnan-bhaldar marked this pull request as draft October 30, 2026 06:48

@KnifeLemon KnifeLemon left a comment •

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @adnan-bhaldar! The rail looks tidy in both themes, and it's good that it keeps its state, uses tooltips and respects reduced motion. A few things before it can go in:

Must fix

  1. The tests don't build. MainWindowViewModel now needs a UserDataStore, but about a dozen test files still construct it with three arguments (AutomationNameTests, BrowserDropTests, CloseActionTests, WhatsNewTests, WhatsNewMedia, DonutFlipTests, DonutOpacityTests, …), so CI fails at compile time. Please update them and run dotnet test. The template's dotnet test box is unchecked.
  2. Indonesian: id.json reached main just now (#790). Please rebase and add nav.collapse / nav.expand there too.
  3. File endings: every i18n/*.json loses its final newline. Please keep the files ending as they do on main.

Tests for the feature

Please add a test or two in Filee.App.Tests:

  • collapsing saves NavCollapsed and a new view model starts collapsed;
  • while collapsed, every nav item has its title as a tooltip and an automation name.

AutomationNameTests is a good place to start.

Next time

For a change to the main window like this one, please open an issue first, so the design can be agreed before the code is written and nobody spends time on a version that changes.

adnan-bhaldar and others added 16 commits October 30, 2026 14:49
Copy a video-only and audio-only M4S pair to one MP4 through the
existing merge videos preset.

Addresses KnifeLemon#659.
A preset's picture size limit gets a minimum next to the maximum, and
both can be entered in KB or MB. The preset keeps megabytes
(ImageOptions.MinSizeMb is new, default 0), so the schema is unchanged
and older versions ignore the minimum.

- The editor shows one "File size" row with a shared KB/MB unit; a limit
  under 1 MB opens in KB, and switching units keeps the values.
- A lossy picture under the minimum is saved again at a higher quality,
  never enlarged or padded, and never over the maximum.
- The final pictures of each file are measured where the maximum is
  checked (inside a ZIP, merged images and multi-page TIFF too). One
  under the minimum is saved with a notice, kept as its own flag next
  to any other note, in the app and the CLI.
- Minimum bytes are rounded; maximum bytes are cut as before.
- An image refusal under 1 MB reads in KB; videos keep MB.
- CLI text prints a file whose first step only fed a merge or a
  multi-page TIFF once, at the end, with its result.
- A minimum over the maximum can't be saved while the boxes show.

Closes KnifeLemon#662
A_program_that_keeps_reporting_runs_well_past_the_stall_limit still failed
on CI after KnifeLemon#768 (KnifeLemon#790's run): its fake output was a Task.Delay loop, which
waits for the thread pool, and the other test classes running in parallel
can hold that up for over a second, so the watch saw a stall. The output
now comes from a dedicated thread, like the real output reader, and the
test's continuation runs asynchronously so it never joins its own thread.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
"Could not get dispatch ID for HWND (error: 0x8000FFFF)" (KnifeLemon#606) is the
.NET COM binder's MissingMemberException: reading HWND or Document of a
Shell.Application window through `dynamic` failed with E_UNEXPECTED. Only
COMException and RuntimeBinderException were caught, so it escaped the
hold / shortcut gesture and showed as an error dialog. Such a window is now
skipped like an Internet Explorer one, and the desktop path catches it too.

Refs KnifeLemon#606

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
KnifeLemon#791 added eight strings to main after this branch started (minimum file
size, the KB/MB unit and the notice), so id.json was missing them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MainWindowViewModel now takes a UserDataStore, so the 40 test call
sites across 14 files pass AppHost.Get<UserDataStore>() as well.

- add NavCollapseTests: collapsing saves NavCollapsed, a new view model
  starts collapsed, and settings from before the rail start expanded
- add an AutomationNameTests case: while collapsed, every nav item has
  its title as the tooltip and as its automation name
- name each nav row for screen readers (AutomationProperties.Name),
  since the title text is hidden when collapsed
- drop the trailing newline from it.json to match main
@adnan-bhaldar
adnan-bhaldar marked this pull request as ready for review October 30, 2026 10:18
@adnan-bhaldar

Copy link
Copy Markdown
Contributor Author

Thanks for the review, @KnifeLemon! I've pushed the changes:

  1. Tests build again. All the MainWindowViewModel call sites in the tests now pass a UserDataStore. dotnet test passes locally.
  2. Indonesian. Rebased onto main and added nav.collapse / nav.expand to id.json.
  3. File endings. The i18n files now end the same way as on main (it.json had gained a final newline, which I removed).

New tests:

  • NavCollapseTests: collapsing saves NavCollapsed, a new view model starts collapsed, and settings from before this change start expanded.
  • AutomationNameTests: while collapsed, every nav item has its title as its tooltip and its automation name.

Writing the second test showed that the collapsed items had no accessible name, because the title text is hidden. I added AutomationProperties.Name to the nav row to fix that.

And noted on opening an issue first for main-window changes. I'll do that next time so the design can be agreed before I write the code.

I also updated the PR description with the tests and the changes above.

@KnifeLemon KnifeLemon left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @adnan-bhaldar! Everything from the review is in:

  • the tests build again;
  • id.json has the two strings;
  • the file endings match main.

The new tests caught a real gap: collapsed items had no accessible name, and you fixed it. CI is green on all platforms.

@KnifeLemon
KnifeLemon merged commit d592789 into KnifeLemon:main Oct 30, 2026
10 checks passed
@adnan-bhaldar
adnan-bhaldar deleted the feat/collapsible-sidebar branch November 1, 2026 04:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants