Skip to content

feat(template): replace folder-location toggles with a single dropdown (#1131)#1344

Merged
chhoumann merged 2 commits into
masterfrom
chhoumann/1131-folder-select-dropdown
Jun 14, 2026
Merged

feat(template): replace folder-location toggles with a single dropdown (#1131)#1344
chhoumann merged 2 commits into
masterfrom
chhoumann/1131-folder-select-dropdown

Conversation

@chhoumann

@chhoumann chhoumann commented Jun 13, 2026

Copy link
Copy Markdown
Owner

Closes #1131.

Problem

The Template choice builder's Location section used 4 interdependent toggles (Create in folder · Choose folder when creating a new note · Include subfolders · Create in same folder as active file) whose visibility depended on each other. New users found this confusing — and turning on the last toggle made the folder config above it vanish. Confirmed live in the dev vault (toggling Create in same folder as active file ON removes the folder input and two other toggles).

Solution

One "New note location" dropdown with four mutually-exclusive modes:

Mode Behaviour
Obsidian default Use Obsidian's "Default location for new notes"
In a specific folder Folder list (+ Include subfolders sub-checkbox)
Same folder as current file Create next to the active file
Ask for folder each time Prompt for any vault folder on create

It matches the form's existing pattern (the "If the target file already exists" row is already a dropdown) and is obsidian-native (<select>).

How it works — no schema change

The dropdown is a derived view over the existing four persisted booleans (folder.{enabled, folders, chooseWhenCreatingNote, createInSameFolderAsActiveFile, chooseFromSubfolders}):

  • A pure helper (src/gui/ChoiceBuilder/folderMode.ts) maps booleans → mode (deriveFolderMode) and mode → canonical booleans (applyFolderMode).
  • deriveFolderMode mirrors TemplateChoiceEngine.getFolderPath() precedence exactly — pinned by a 16-combination oracle test, so the dropdown always shows the mode that will actually run (legacy choices with multiple flags set open on their true mode).
  • Switching modes hides but never deletes the configured folder list (directly fixes the "my config disappeared" anxiety).
  • Include subfolders is scoped to the one mode where the engine honours it; chooseFromSubfolders is reset outside that mode so it stays inert in TemplateInsertEngine's move-offer.

Zero migration · forward/backward compatible · engines untouched · package export/import unaffected. Existing data.json works as-is; an older QuickAdd build still reads the booleans.

Empty-folder guard

"In a specific folder" with an empty list previously fell through to the active file's folder silently. A required inline warning now flags this.

Scope (maintainer-confirmed)

  • "Vault root" mode (the issue's 5th option) — deferred: there is no persisted representation independent of Obsidian's global setting, and adding one would break the zero-migration premise. Reachable today via "Obsidian default" when the global setting points at root.
  • Captureout of scope: it has no folder object (captureTo string + captureToActiveFile) and does not have this bug.

Verification

  • Full vitest suite green (incl. a new folderMode.test.ts: 16-combo precedence oracle, round-trip, residue-reset; rewritten TemplateChoiceForm.test.ts keeps the [FEATURE REQUEST] UX Improvement: Modal completely refreshes on button clicks, causing loss of edit position #1130 no-remount guard).
  • tsc + ESLint clean; production build OK.
  • Live dev-vault e2e: dropdown renders, all 4 modes show/hide the right fields, and end-to-end persistence writes the canonical booleans to data.json (active-file → prompt resets createInSameFolderAsActiveFile; prompt → specified + folder + subfolders persists).

Migration / release impact

None. User-facing UI only; feat → minor release.

Summary by CodeRabbit

  • Improvements
    • Template note location is now managed via a single dropdown (Obsidian default, specific folder(s), active file location, or prompt), with the relevant controls shown/hidden per selection.
    • “Include subfolders” is available for specific folder(s), and incomplete folder selections now show a warning.
    • Improved styling for the folder-mode guidance and warning display.
  • Documentation
    • Updated TemplateChoice documentation to reflect the new “New note location” dropdown and modes.
  • Tests
    • Expanded automated coverage for folder mode selection and configuration updates.

#1131)

Consolidate the Template choice builder's four interdependent folder
toggles (Create in folder / Choose folder when creating / Include
subfolders / Create in same folder as active file) into one "New note
location" dropdown over the existing persisted booleans — no schema
change, engines untouched, forward/backward compatible.

A pure helper (folderMode.ts) maps the four booleans to four
mutually-exclusive modes, mirroring TemplateChoiceEngine.getFolderPath()
precedence exactly (pinned by a 16-combo oracle test). Selecting a mode
writes the canonical flags; switching modes hides but never deletes the
configured folder list (fixes the "my config disappeared" complaint).
"Include subfolders" is scoped to the one mode where it has an effect,
and chooseFromSubfolders is reset outside that mode so it stays inert in
TemplateInsertEngine's move-offer.

Closes #1131
@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 51beb3bc-bdaf-435f-999e-cb6ef93b209d

📥 Commits

Reviewing files that changed from the base of the PR and between 977a22f and cbe3d6f.

📒 Files selected for processing (6)
  • docs/docs/Choices/TemplateChoice.md
  • src/engine/TemplateChoiceEngine.ts
  • src/gui/ChoiceBuilder/TemplateChoiceForm.svelte
  • src/gui/ChoiceBuilder/TemplateChoiceForm.test.ts
  • src/gui/ChoiceBuilder/folderMode.test.ts
  • src/gui/ChoiceBuilder/folderMode.ts
✅ Files skipped from review due to trivial changes (2)
  • docs/docs/Choices/TemplateChoice.md
  • src/engine/TemplateChoiceEngine.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/gui/ChoiceBuilder/folderMode.test.ts
  • src/gui/ChoiceBuilder/TemplateChoiceForm.svelte
  • src/gui/ChoiceBuilder/TemplateChoiceForm.test.ts

📝 Walkthrough

Walkthrough

Replaces the multi-boolean folder destination toggles in TemplateChoiceForm with a single FolderMode dropdown. Extracts TemplateFolderConfig as a shared type, introduces folderMode.ts with deriveFolderMode and applyFolderMode, updates the Svelte UI to use the new model, adds warning CSS, and provides exhaustive test coverage.

Changes

Folder Mode Dropdown Refactor

Layer / File(s) Summary
TemplateFolderConfig type extraction
src/types/choices/ITemplateChoice.ts, src/types/choices/TemplateChoice.ts
Extracts the inline folder object shape from ITemplateChoice.folder into a standalone exported TemplateFolderConfig type; TemplateChoice.ts imports and uses it in place of its own inline definition.
FolderMode derivation and application logic
src/gui/ChoiceBuilder/folderMode.ts
Adds FolderMode union type, deriveFolderMode (boolean precedence → canonical mode), applyFolderMode (mode → canonicalized config, preserving folders[]), plus folderModeOptions and folderModeDescriptions for dropdown wiring.
TemplateChoiceForm UI and warning CSS
src/gui/ChoiceBuilder/TemplateChoiceForm.svelte, src/styles.css
Replaces multi-boolean Location toggles with a single "New note location" dropdown driven by reactive folderMode; conditionally renders folder list, empty-folder warning, and subfolders toggle only in "specified" mode. Adds .qa-folder-mode-warning CSS rule.
FolderMode and form integration tests
src/gui/ChoiceBuilder/folderMode.test.ts, src/gui/ChoiceBuilder/TemplateChoiceForm.test.ts
folderMode.test.ts exhaustively covers all 16 boolean combinations against an independent oracle for deriveFolderMode and applyFolderMode round-trips, immutability, and options completeness. TemplateChoiceForm.test.ts adds granular dropdown option, legacy config mapping, mode-switch state preservation, and warning visibility tests.
Documentation and engine implementation sync
docs/docs/Choices/TemplateChoice.md, src/engine/TemplateChoiceEngine.ts
Updates user-facing documentation to describe the new "New note location" dropdown with four modes and field visibility behavior. Adds comments to engine code documenting that precedence order must stay synchronized with folderMode derivation tests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

released

Sequence Diagram

sequenceDiagram
  participant User as User (TemplateChoiceForm)
  participant Component as TemplateChoiceForm.svelte
  participant Derive as deriveFolderMode
  participant Apply as applyFolderMode
  participant Config as choice.folder
  User->>Component: opens form with existing config
  Component->>Derive: derive current FolderMode
  Derive-->>Component: return canonical mode
  Component->>Component: render dropdown with current mode
  User->>Component: selects new location mode
  Component->>Apply: apply selected mode to config
  Apply-->>Config: return updated TemplateFolderConfig
  Config-->>Component: update choice.folder
  Component->>Component: conditionally show/hide folder list, warning, subfolders toggle
Loading

🐇 Four old toggles, so tricky to tame,
Now one little dropdown plays their whole game!
deriveFolderMode sniffs the config with care,
applyFolderMode rewrites it—fair and square.
The folders stay safe, the warning glows bright,
This bunny hops happy—the UI feels right! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: replacing folder-location toggles with a single dropdown, directly addressing the primary objective.
Linked Issues check ✅ Passed The PR fully implements the requested feature: consolidates four toggles into a single dropdown with four mutually-exclusive modes (Obsidian default, specific folder, same as active file, prompt), preserves folder configuration across switches, and includes empty-folder warning.
Out of Scope Changes check ✅ Passed All changes directly support the dropdown implementation and feature objectives: new folderMode module, updated TemplateChoiceForm component, comprehensive tests, type refactoring, CSS styling, documentation, and explanatory comments.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chhoumann/1131-folder-select-dropdown

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install timed out. The project may have too many dependencies for the sandbox.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 13, 2026

Copy link
Copy Markdown

Deploying quickadd with  Cloudflare Pages  Cloudflare Pages

Latest commit: cbe3d6f
Status: ✅  Deploy successful!
Preview URL: https://e0a28843.quickadd.pages.dev
Branch Preview URL: https://chhoumann-1131-folder-select.quickadd.pages.dev

View logs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
src/gui/ChoiceBuilder/folderMode.ts (2)

87-102: ⚡ Quick win

Use camelCase for exported constants in this TypeScript module.

At Line 87 and Line 94, rename FOLDER_MODE_OPTIONS / FOLDER_MODE_DESCRIPTIONS to camelCase and update call sites.

Suggested rename diff
-export const FOLDER_MODE_OPTIONS: { value: FolderMode; label: string }[] = [
+export const folderModeOptions: { value: FolderMode; label: string }[] = [
@@
-export const FOLDER_MODE_DESCRIPTIONS: Record<FolderMode, string> = {
+export const folderModeDescriptions: Record<FolderMode, string> = {

As per coding guidelines: **/*.{ts,tsx}: Use camelCase for variables and functions.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gui/ChoiceBuilder/folderMode.ts` around lines 87 - 102, Rename the
exported constants FOLDER_MODE_OPTIONS and FOLDER_MODE_DESCRIPTIONS to camelCase
(folderModeOptions and folderModeDescriptions respectively) to comply with the
TypeScript coding guidelines for variables and constants. After renaming, locate
and update all call sites throughout the codebase that reference these constants
to use the new camelCase names.

Source: Coding guidelines


1-1: ⚡ Quick win

Rename this utility module to kebab-case.

src/gui/ChoiceBuilder/folderMode.ts should follow the repo utility naming rule; please rename it to folder-mode.ts and update imports accordingly.

As per coding guidelines: **/*: Use kebab-case for directories and utilities.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gui/ChoiceBuilder/folderMode.ts` at line 1, Rename the utility module
folderMode.ts to folder-mode.ts to comply with the kebab-case naming convention
for utilities in the repository. After renaming the file, search the codebase
for all import statements that reference the old filename and update them to
import from folder-mode.ts instead of folderMode.ts.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/gui/ChoiceBuilder/folderMode.ts`:
- Around line 87-102: Rename the exported constants FOLDER_MODE_OPTIONS and
FOLDER_MODE_DESCRIPTIONS to camelCase (folderModeOptions and
folderModeDescriptions respectively) to comply with the TypeScript coding
guidelines for variables and constants. After renaming, locate and update all
call sites throughout the codebase that reference these constants to use the new
camelCase names.
- Line 1: Rename the utility module folderMode.ts to folder-mode.ts to comply
with the kebab-case naming convention for utilities in the repository. After
renaming the file, search the codebase for all import statements that reference
the old filename and update them to import from folder-mode.ts instead of
folderMode.ts.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9ed951d1-c448-42cd-a184-1b7256e3fbac

📥 Commits

Reviewing files that changed from the base of the PR and between f111d45 and 977a22f.

📒 Files selected for processing (7)
  • src/gui/ChoiceBuilder/TemplateChoiceForm.svelte
  • src/gui/ChoiceBuilder/TemplateChoiceForm.test.ts
  • src/gui/ChoiceBuilder/folderMode.test.ts
  • src/gui/ChoiceBuilder/folderMode.ts
  • src/styles.css
  • src/types/choices/ITemplateChoice.ts
  • src/types/choices/TemplateChoice.ts

Adversarial review (3 Codex reviewers + CodeRabbit) findings:

- Preserve chooseFromSubfolders across mode switches instead of resetting it
  outside "specified". The reset caused a real regression vs the old form:
  switching specified -> other -> specified silently dropped the "Include
  subfolders" preference. applyFolderMode now only sets the mode-discriminant
  flags; folders[] and chooseFromSubfolders are always preserved (the old form
  hid but never cleared them). No new flag combination is produced, so the other
  consumers (TemplateInsertEngine, collectChoiceRequirements) see no regression.
- Reword the empty-"specific folder" warning: with no active file the engine
  prompts (or uses root), it does not always use the active file's folder.
- Add a back-reference comment in TemplateChoiceEngine.getFolderPath() pointing
  to folderMode.ts so the precedence mirror is kept in sync.
- camelCase the exported folderModeOptions/folderModeDescriptions (CodeRabbit).
- Update docs/docs/Choices/TemplateChoice.md to the dropdown model.

Skipped: CodeRabbit's kebab-case file-rename nit — folderMode.ts matches its
camelCase siblings (choiceBuilder.ts, captureChoiceBuilder.ts,
templateChoiceFormProps.svelte.ts); renaming would make it inconsistent.
@chhoumann chhoumann merged commit 3726cdb into master Jun 14, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE REQUEST] Simplify folder selection UI by replacing toggles with a dropdown menu

1 participant