Skip to content

feat: rework add-choice UX (explained types, Multi-as-folder, add-into-folder) + fix AI-disabled layout#1257

Open
chhoumann wants to merge 5 commits into
masterfrom
1256-rework-add-choice-ux-clearer-types-multi-as-folder-+-fix-bottom-bar-layout-when-ai-disabled
Open

feat: rework add-choice UX (explained types, Multi-as-folder, add-into-folder) + fix AI-disabled layout#1257
chhoumann wants to merge 5 commits into
masterfrom
1256-rework-add-choice-ux-clearer-types-multi-as-folder-+-fix-bottom-bar-layout-when-ai-disabled

Conversation

@chhoumann
Copy link
Copy Markdown
Owner

@chhoumann chhoumann commented May 30, 2026

Closes #1256.

Reworks how users add a choice in the settings Choices view, and fixes the reported layout bug. Built on top of #1255 (Obsidian 1.13 declarative settings).

The problem

The old add row — [Name] [Template/Capture/Macro/Multi ▾] [Add Choice] — presented the four types as an unexplained dropdown, and "Multi" (really a folder) masqueraded as a peer type. And when AI/online features were disabled, the add box collapsed hard to the left (.choiceViewBottomBar used justify-content: space-between, so the lone add box had nothing to balance against).

What changed

  • Top action bar: + New choice ▾ — an Obsidian menu of the three doer types, each with a one-line description — plus a separate + New folder button. Multi is no longer a peer "type"; it reads as a folder. Renamed Multi → "folder" in user-facing copy (stored ChoiceType value unchanged — no migration).
  • First-class add-into-folder: a per-folder add affordance inside each expanded folder, rendered outside the dndzone (so svelte-dnd never treats it as a draggable item / shadow placeholder). Adds route through the top-level handler via the exported insertIntoMulti/addChoiceToTree, so nested adds persist correctly at any depth (the rootReorder invariant).
  • Builder handoff: after adding a doer, its builder opens automatically (Alt-click skips for batch scaffolding); folders skip it. Auto-named, so the flow never gates on typing a name first.
  • Empty/first-run state with a single hero CTA (no duplicate controls).
  • Layout fix: the add controls are now a left-anchored, content-width cluster (margin-right: auto) with the AI button pinned right — the add cluster's position is independent of the AI button, so it can't collapse when AI is disabled.
  • a11y: WCAG 2.5.3 label-in-name on the add buttons; aria-haspopup/aria-expanded on the menu trigger.
  • Deletes AddChoiceBox.svelte; MultiChoice now initializes collapsed = false.

Verification

CI-equivalent locally: tsc, svelte-check (0 errors), lint, 1470 tests — including new addChoiceToTree/insertIntoMulti unit tests and a ChoiceView add-into-folder integration test that drives the per-folder affordance through the real DOM (asserts the new choice lands nested and the folder stays expanded).

Real Obsidian 1.13.0 dev vault (eval + data.json assertions): top bar renders flex; add cluster left at content-width while the AI button pins far right when on and the cluster doesn't move when off (bug fixed in both states); New folder and per-folder add persist (nested at depth 1); zero runtime errors.

Adversarial review (4 agents) ran on the diff and verified the load-bearing invariants hold (dndzone isolation, top-level insertIntoMulti persistence with no depth≥2 corruption, snapshot plainness, no ./main value-import). Its recommended items are all addressed in this PR: the add-into-folder test, the empty-state double-render, WCAG labels, and dropping the eager double-save.

Scope notes

  • Deferred the context-menu "New choice here" entry — the per-folder affordance already covers add-into-folder and is keyboard-accessible.
  • The + New choice menu → pick-type → builder flow and the empty state can't be synthetically driven (Obsidian menus don't open via programmatic clicks — verified the existing context menu behaves identically), so those are covered by unit tests + parity rather than a scripted end-to-end.

Open in Devin Review

Summary by CodeRabbit

  • New Features

    • New add-controls: “New choice” menu and “New folder” action, Alt/⌥ to skip configuration, autogenerated default names, responsive placement, and improved empty-state CTA; supports adding into folders.
  • Refactor

    • Consolidated and relocated add UI into unified controls; add-row exposed for multi-folder lists.
  • Bug Fixes & Stability

    • More reliable add/save flow, auto-expands target folders and scrolls new items into view.
  • Tests

    • Expanded unit, lifecycle and accessibility tests covering add controls and tree insertion.

Review Change Stack

… AI-disabled layout

Replace the cramped [Name] [type] [Add Choice] row with a clearer flow:

- Top action bar: "New choice" (an Obsidian menu of the three doer types —
  Template/Capture/Macro — each with a one-line description) plus a separate
  "New folder" button. Multi is no longer a confusing peer "type"; it reads as a
  folder. Renamed Multi -> "folder" in user-facing copy (stored ChoiceType value
  unchanged, no migration).
- First-class add-into-folder: a per-folder add affordance inside each expanded
  folder (rendered OUTSIDE the dndzone). Adds route through the top-level handler
  via the exported insertIntoMulti/addChoiceToTree, so nested adds persist
  correctly at any depth (the rootReorder invariant).
- After adding a doer its builder opens automatically (Alt-click skips); folders
  skip it. Auto-named so the flow never gates on typing a name first.
- Empty/first-run state with a single hero CTA.
- Fix the layout bug: the old .choiceViewBottomBar used space-between, so the add
  box collapsed left when the AI Assistant button was hidden. The add controls
  are now a left-anchored, content-width cluster (margin-right:auto) with the AI
  button pinned right — the add cluster's position is independent of the AI button.

Tests: addChoiceToTree + insertIntoMulti unit tests; a ChoiceView add-into-folder
integration test (drives the per-folder affordance through the real DOM);
rewritten add-flow test. a11y: WCAG 2.5.3 label-in-name on the add buttons,
aria-haspopup/aria-expanded on the menu trigger. MultiChoice initializes
collapsed=false. Deletes AddChoiceBox.svelte.

Validated end-to-end in a real Obsidian 1.13.0 dev vault: layout fixed in both AI
states; New folder + add-into-folder persist (nested at depth); the "New choice"
menu is parity-identical to the existing context menu.

Closes #1256
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 30, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

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: eb86c14e-ca46-4068-82d4-0877d6cf8c87

📥 Commits

Reviewing files that changed from the base of the PR and between 6223f6a and 8f4284e.

📒 Files selected for processing (2)
  • src/gui/choiceList/AddChoiceControls.svelte
  • src/gui/choiceList/ChoiceView.svelte
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/gui/choiceList/AddChoiceControls.svelte

📝 Walkthrough

<review_stack_artifact>

</review_stack_artifact>

🚥 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 clearly summarizes the main changes: reworking the add-choice UX with explained types, Multi-as-folder support, add-into-folder functionality, and fixing the AI-disabled layout bug.
Linked Issues check ✅ Passed All objectives from issue #1256 are met: layout bug fixed by decoupling add controls from AI button, add-choice UX clarified with menu of three doer types plus separate folder button, per-folder add affordances implemented, auto-builder opening added, and empty state introduced.
Out of Scope Changes check ✅ Passed All changes align with objectives from #1256; no out-of-scope modifications detected. Updates to QuickAddSettingsTab styling are minor UI refinements consistent with the overall layout improvements.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 1256-rework-add-choice-ux-clearer-types-multi-as-folder-+-fix-bottom-bar-layout-when-ai-disabled

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
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented May 30, 2026

Deploying quickadd with  Cloudflare Pages  Cloudflare Pages

Latest commit: 8f4284e
Status: ✅  Deploy successful!
Preview URL: https://49187967.quickadd.pages.dev
Branch Preview URL: https://1256-rework-add-choice-ux-cl.quickadd.pages.dev

View logs

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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.

Inline comments:
In `@src/gui/choiceList/ChoiceView.svelte`:
- Around line 110-135: The code in ChoiceView.svelte currently uses
console.error when a builder throws in the block around createChoice/type
handling; replace that console.error call with the project logger (use
log.logError from src/logger/logManager.ts), making sure to import the logger
(e.g., import { log } from "src/logger/logManager") and pass both a descriptive
message and the caught error (e.g., "QuickAdd: failed to configure new choice",
err) to log.logError; leave the existing save() call intact so behavior is
unchanged.
- Line 129: Replace the console.error call in ChoiceView.svelte ("QuickAdd:
failed to configure new choice", err) with the repo logger: import { log,
toError } from the logger module and call log.logError(toError(err)) (or
log.logError("QuickAdd: failed to configure new choice", toError(err))) so
errors use the centralized logging utilities; update the import block to include
log and toError and remove the console.error usage.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6da11c46-8f6a-4470-b1b1-129dd0240db1

📥 Commits

Reviewing files that changed from the base of the PR and between fcb22f6 and 469e733.

📒 Files selected for processing (13)
  • src/gui/choiceList/AddChoiceBox.svelte
  • src/gui/choiceList/AddChoiceControls.svelte
  • src/gui/choiceList/ChoiceList.a11y.test.ts
  • src/gui/choiceList/ChoiceList.callbacks.test.ts
  • src/gui/choiceList/ChoiceView.svelte
  • src/gui/choiceList/ChoiceView.test.ts
  • src/gui/choiceList/MultiChoiceListItem.svelte
  • src/gui/choiceList/choiceListActions.ts
  • src/gui/choiceList/choiceTypeMeta.ts
  • src/gui/choiceList/cmpLifecycle.test.ts
  • src/services/choiceService.insertIntoMulti.test.ts
  • src/services/choiceService.ts
  • src/types/choices/MultiChoice.ts
💤 Files with no reviewable changes (1)
  • src/gui/choiceList/AddChoiceBox.svelte

Comment on lines 110 to 135
const newChoice = createChoice(type, name);
choices = [...choices, newChoice];
save();
choices = addChoiceToTree(choices, newChoice, targetFolderId);

// A root-level add while a filter is active would otherwise look like
// nothing happened (the auto-named choice may not match the filter).
if (!targetFolderId && filterQuery.trim().length > 0) {
filterQuery = "";
}

// Doers (Template/Capture/Macro) hand off to their builder so the user
// isn't stranded on an unconfigured row; handleConfigureChoice persists
// the result, so there's no eager save here (avoids a double write).
// Folders and Alt-click skip the builder and are committed immediately.
if (type !== "Multi" && !skipConfigure) {
try {
await handleConfigureChoice(newChoice);
} catch (err) {
// Builders resolve rather than reject, but don't let a stray throw
// become an unhandled rejection or lose the new choice.
console.error("QuickAdd: failed to configure new choice", err);
save();
}
} else {
save();
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect waitForClose resolution / onClose / cancel handling in the builders
fd -e ts -e svelte | rg -l 'waitForClose' | sort -u
ast-grep --pattern 'waitForClose = $_'
rg -nP -C4 '\bwaitForClose\b' --type=ts
rg -nP -C4 '(resolvePromise|this\.resolve|reject)\s*\(' --type=ts -g '*Builder*'

Repository: chhoumann/quickadd

Length of output: 45929


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Inspect ChoiceView.svelte around handleConfigureChoice
rg -n "handleConfigureChoice" src/gui/choiceList/ChoiceView.svelte
rg -n "configureChoice|waitForClose" src/gui/choiceList/ChoiceView.svelte
sed -n '1,220p' src/gui/choiceList/ChoiceView.svelte | sed -n '90,190p'

# 2) Locate concrete builders (template/capture) and inspect their close/cancel handling
fd -t f "template*ChoiceBuilder*" src/gui | sort
fd -t f "capture*ChoiceBuilder*" src/gui | sort
fd -t f "*ChoiceBuilder*" src/gui/ChoiceBuilder src/gui/MacroGUIs 2>/dev/null | sort

# show key parts of the base ChoiceBuilder and concrete builders
sed -n '1,260p' src/gui/ChoiceBuilder/choiceBuilder.ts
for f in $(fd -t f "*template*ChoiceBuilder*" src/gui | sort); do
  echo "---- $f"; sed -n '1,260p' "$f"; done
for f in $(fd -t f "*capture*ChoiceBuilder*" src/gui | sort); do
  echo "---- $f"; sed -n '1,260p' "$f"; done

# 3) Inspect MacroBuilder close behavior (since it was found)
sed -n '1,220p' src/gui/MacroGUIs/MacroBuilder.ts

Repository: chhoumann/quickadd

Length of output: 3535


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect configureChoice + builder cancel semantics
rg -n "async function configureChoice|function configureChoice|configureChoice\\(" src/services/choiceService.ts
sed -n '1,260p' src/services/choiceService.ts
sed -n '120,220p' src/services/choiceService.ts

# Inspect base ChoiceBuilder close/resolve behavior
sed -n '1,280p' src/gui/ChoiceBuilder/choiceBuilder.ts

# Inspect Template/Capture builders close/cancel
sed -n '1,260p' src/gui/ChoiceBuilder/templateChoiceBuilder.ts
sed -n '1,320p' src/gui/ChoiceBuilder/captureChoiceBuilder.ts

# Also locate any "cancel" handlers in these builders
rg -n "cancel|onCancel|close\\(|onClose\\(|destroy\\(" src/gui/ChoiceBuilder/templateChoiceBuilder.ts src/gui/ChoiceBuilder/captureChoiceBuilder.ts src/gui/ChoiceBuilder/choiceBuilder.ts

Repository: chhoumann/quickadd

Length of output: 36241


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) show ChoiceBuilder.onClose fully (around where it resolves waitForClose)
sed -n '200,280p' src/gui/ChoiceBuilder/choiceBuilder.ts

# 2) inspect the ChoiceView catch block region for context
sed -n '90,180p' src/gui/choiceList/ChoiceView.svelte

# 3) inspect logger utilities (look for logManager methods)
rg -n "class .*logManager|function log|export const log|logger" src/logger/logManager.ts src/logger -S || true
ls -R src/logger || true
sed -n '1,220p' src/logger/logManager.ts

# 4) find how other code logs errors (console.error vs logger.log/error)
rg -n "console\.error\(" src/gui/choiceList/ChoiceView.svelte src/gui/ChoiceBuilder src/gui -S || true
rg -n "log\\.(error|warn|info)|logger\\." src/logger src/gui -S | head -n 50

Repository: chhoumann/quickadd

Length of output: 8161


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n "log\\.logError\\(|log\\.logWarning\\(|log\\.logMessage\\(" src | head -n 50
rg -n "quickAddLogger|guiLogger|consoleErrorLogger" src/logger src/gui -S
sed -n '1,220p' src/logger/quickAddLogger.ts
sed -n '1,220p' src/logger/consoleErrorLogger.ts

Repository: chhoumann/quickadd

Length of output: 8702


🏁 Script executed:

#!/bin/bash
set -euo pipefail
sed -n '1,120p' src/gui/choiceList/ChoiceView.svelte
rg -n "console\\.error\\(" src/gui/choiceList/ChoiceView.svelte
rg -n "\\blog\\b|logManager|log\\.logError" src/gui/choiceList/ChoiceView.svelte

Repository: chhoumann/quickadd

Length of output: 4246


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n "import .*log|from \"src/logger|log\\b" src/gui/choiceList/ChoiceView.svelte
sed -n '1,80p' src/gui/choiceList/ChoiceView.svelte

Repository: chhoumann/quickadd

Length of output: 44


Replace console.error with the project logger

The “builder cancel leaves an unsaved phantom choice” concern doesn’t match current behavior: ChoiceBuilder.onClose() resolves waitForClose with this.choice (so configureChoice() returns an IChoice, not undefined, for Template/Capture/Macro), and handleConfigureChoice() will call save().

src/gui/choiceList/ChoiceView.svelte still logs via console.error(...); switch to log.logError(...) (from src/logger/logManager.ts) to follow the logger 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/choiceList/ChoiceView.svelte` around lines 110 - 135, The code in
ChoiceView.svelte currently uses console.error when a builder throws in the
block around createChoice/type handling; replace that console.error call with
the project logger (use log.logError from src/logger/logManager.ts), making sure
to import the logger (e.g., import { log } from "src/logger/logManager") and
pass both a descriptive message and the caught error (e.g., "QuickAdd: failed to
configure new choice", err) to log.logError; leave the existing save() call
intact so behavior is unchanged.

} catch (err) {
// Builders resolve rather than reject, but don't let a stray throw
// become an unhandled rejection or lose the new choice.
console.error("QuickAdd: failed to configure new choice", err);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm the logger utility location and its public API
fd -i logger -e ts
rg -nP -C2 '(export (const|class|function)\s+\w*[Ll]og|logError|logMessage)' --type=ts -g '*[Ll]og*'

Repository: chhoumann/quickadd

Length of output: 5446


Use the repo logging utilities (log) instead of console.error in ChoiceView.svelte

Replace console.error("QuickAdd: failed to configure new choice", err); with log.logError(...) (e.g., log.logError(toError(err))), importing { log, toError } from src/logger/logManager.ts.

🤖 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/choiceList/ChoiceView.svelte` at line 129, Replace the console.error
call in ChoiceView.svelte ("QuickAdd: failed to configure new choice", err) with
the repo logger: import { log, toError } from the logger module and call
log.logError(toError(err)) (or log.logError("QuickAdd: failed to configure new
choice", toError(err))) so errors use the centralized logging utilities; update
the import block to include log and toError and remove the console.error usage.

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 5 additional findings.

Open in Devin Review

chhoumann added 2 commits May 30, 2026 21:20
Addresses hands-on QA findings on the redesign:

- New folder now auto-opens rename immediately (clear feedback; the click no
  longer "looks like nothing happened", and it avoids duplicate "New folder"
  confusion). Cancelling rename keeps the default name.
- Every add scrolls the new row into view (rows now carry data-choice-id) so a
  new root choice doesn't land unseen at the bottom of a long list.
- Quieter per-folder ("compact") controls: ghost styling, no mod-cta accent, so
  nested add buttons don't compete with the top-bar primary CTA.
…add as text links

Per maintainer QA:
- New choice / New folder move back to the bottom of the view, pinned right via
  margin-left:auto (not the old justify-content:space-between), so they stay put
  when the AI Assistant button is hidden — no return of the collapse bug.
- Per-folder ("compact") add affordances now render as quiet, clickable text —
  "Add choice" / "Add folder" — with a folder-named tooltip + aria-label
  ("Add choice to {folder}") instead of filled buttons. WCAG 2.5.3 still holds
  (the visible text is a substring of the accessible name). The type-menu chevron
  shows only on the global control.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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.

Inline comments:
In `@src/gui/choiceList/ChoiceView.svelte`:
- Around line 322-351: The add-controls cluster (.choiceAddGroup /
AddChoiceControls) is currently pinned to the right via margin-left:auto, which
causes CTAs to shift right when the AI button is hidden; change the CSS to pin
the add cluster to the left by replacing margin-left:auto with margin-right:auto
in the .choiceAddGroup rule so the add controls stay left-anchored and the AI
button sits to their right; apply the same change to the other occurrence
mentioned (lines 411-417) to keep both blocks consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5df49ba1-b78f-4f56-8425-3a9371d0eed7

📥 Commits

Reviewing files that changed from the base of the PR and between c8acb9c and f68e599.

📒 Files selected for processing (4)
  • src/gui/choiceList/AddChoiceControls.svelte
  • src/gui/choiceList/ChoiceView.svelte
  • src/gui/choiceList/ChoiceView.test.ts
  • src/gui/choiceList/MultiChoiceListItem.svelte
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/gui/choiceList/MultiChoiceListItem.svelte
  • src/gui/choiceList/AddChoiceControls.svelte
  • src/gui/choiceList/ChoiceView.test.ts

Comment thread src/gui/choiceList/ChoiceView.svelte Outdated
chhoumann added 2 commits May 30, 2026 21:40
Per the one-primary-button-per-page rule (/ui Buttons guideline): "New choice" is
the view's single primary action, so the competing purple CTAs near it are demoted
to secondary:
- "Export package…" no longer calls .setCta() (both package actions are secondary
  utilities), removing the purple-over-purple with "New choice".
- The "AI Assistant" button drops mod-cta (it's a configure-AI utility), so AI
  being enabled doesn't reintroduce a second purple in the bottom bar.

Only "New choice" remains a filled primary; New folder / Export / Import / AI are
secondary. ("Add variable" stays primary within its own Global Variables section.)
… no hairline)

From design iteration in the dev vault:
- Right-pack the add cluster (justify-content:flex-end) — no margin-left:auto
  gutter, so the bar stays put when the AI button toggles without needing a
  grounding hairline (the line read as too heavy next to the Packages divider).
- AI Assistant becomes a quiet icon button (sparkles / clickable-icon) leading the
  cluster, so the bar's width barely changes when AI/online features toggle.
- Order is AI | New folder | New choice — the primary "New choice" is the terminal
  (rightmost) action. Reordered in AddChoiceControls so it's consistent everywhere
  (including the per-folder "Add folder | Add choice" text links).
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.

Rework add-choice UX (clearer types, Multi-as-folder) + fix bottom-bar layout when AI disabled

1 participant