mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-08-03 13:24:41 +00:00
* feat(web-shell): add git branch picker, commit dialog, and create PR flow Add an IntelliJ-style branch picker popover to the web shell git workspace, accessible from the branch chip in both the composer toolbar and sidebar. The picker provides search-filtered branch listing (local, remote, tags, recent), branch checkout, new branch creation, pull, push, and a commit view integrated into the existing GitDialog. The commit view reuses the diff panel (expandable file diffs with syntax highlighting, fullscreen support) and adds a commit message textarea with Commit / Commit and Push buttons. When a session is available (or one is auto-created), the commit message and PR title/body are generated via the model using session side-queries (btwSession), giving the agent full conversation context for accurate generation. The Create PR flow provides an inline form with auto-detected base branch and model-generated title/description, backed by a new daemon route that shells out to gh pr create. New daemon routes: - GET /workspaces/:workspace/git/branches - POST /workspaces/:workspace/git/checkout - POST /workspaces/:workspace/git/branch - POST /workspaces/:workspace/git/push - POST /workspaces/:workspace/git/pull - POST /workspaces/:workspace/git/commit - POST /workspaces/:workspace/github/prs/create - GET /workspaces/:workspace/github/default-branch * fix(web-shell): resolve correct workspace session for AI generation The commit message and PR title/body generation now resolves the most recent session for the target workspace via listWorkspaceSessions, rather than using the globally active connection.sessionId which may belong to a different workspace or session. Falls back to creating a new session only when no sessions exist for the workspace. Also improves the PR body editor with an Edit/Preview toggle using the existing Markdown component, and updates the generation prompt to follow the project PR template structure from AGENTS.md. * fix(web-shell): stabilize session resolver prop to prevent infinite re-generation Pass resolveSessionForWorkspace as a stable useCallback reference instead of an inline arrow function. The inline function created a new reference on every App render, causing the GitDialog useEffect to abort and restart generation in an infinite loop. * fix(web-shell): group remote branches by remote name and add PR target branch dropdown Remote branches in the branch picker are now grouped by remote (origin, upstream, etc.) with sub-headers, making fork workflows clear. The PR create form's base branch field is now a select dropdown populated from the workspace's branch list, grouped by remote with optgroup labels, instead of a free-text input. * fix(web-shell): use ref for session resolver to prevent effect re-run abort When resolveSessionForWorkspace creates a new session, it updates connection.sessionId in the provider, which changes the useCallback reference, which triggers the useEffect to re-run and abort the in-flight btwSession generation. Store the callback in a ref so the effect never depends on its identity. * fix(web-shell): resolve session per workspace, not from global active session The commit/PR generation effects used connection.sessionId directly without checking if it belongs to the target workspace. When opening the commit dialog from a sidebar workspace different from the active session's workspace, the wrong session was used for generation, producing incorrect content. Now always routes through resolveSessionForWorkspace(workspaceCwd) which checks workspace membership before reusing the active session. Also replaces 'PR' with 'Pull Request' / '合并请求' in all UI strings and adds error logging to the generation catch blocks. * fix(web-shell): retry btwSession with fresh session when stale session detected When listWorkspaceSessions returns a session that no longer exists in the daemon's memory (e.g. after daemon restart), btwSession fails with 'No session with id ...'. The generation effects now catch this error, force-create a new session via resolveSessionForWorkspace(cwd, true), and retry the btwSession call once. Both btwWithRetry and resolveSessionForWorkspace are stored in refs to avoid useEffect dependency chain aborts. * fix(web-shell): base PR generation on branch diff, not working tree PR title/body generation now fetches the commit log between the resolved base branch and HEAD (git log <base>..HEAD) plus any uncommitted changes, instead of only the working tree diff. The base branch is resolved inside the effect's promise chain (not from state) to avoid stale values and dependency warnings. Also adds range parameter support to fetchGitLog and workspaceGitLog. * feat(web-shell): replace PR base branch select with searchable popover The native <select> for the PR target branch is replaced with a custom searchable popover (BranchSelect) that shows a search input and a filtered branch list grouped by remote. The default selection is the target repository's main branch (resolved via getDefaultBranch). Supports filtering by typing in the search box. * fix(web-shell): show full remote ref in branch select (origin/main) Branch select now stores and displays full remote refs like origin/main instead of stripped names. getDefaultBranch returns the full ref (origin/main) instead of stripping the prefix. When creating the PR, the remote prefix is stripped for the gh pr create --base flag (origin/main → main). * fix(web-shell): stop pointer propagation in branch picker list to prevent popover dismiss Radix Popover's outside-click detection was incorrectly firing when clicking section headers (Recent/Local/Remote/Tags) inside the popover content, causing the popover to close immediately. Adding onPointerDown stopPropagation on the list container prevents pointer events from reaching Radix's document-level handlers. * fix(web-shell): use onPointerDownOutside guard for branch picker popover The previous stopPropagation approach failed because Radix Popover uses capture-phase document listeners for outside-click detection, which fire before bubble-phase stopPropagation. The correct fix is onPointerDownOutside on PopoverContent: when Radix incorrectly fires the outside handler for a click that is actually inside the content (can happen with portal containers), we check contentRef.contains() and preventDefault to keep the popover open. * fix(web-shell): stop click propagation on branch picker popover content Root cause: the ChatEditor composer container has onClick that calls core.focus(), stealing focus from the popover. React synthetic events bubble through the React tree (not DOM tree), so portaled popover clicks reach the container handler. Radix then detects focus-outside and dismisses the popover. Fix: onClick stopPropagation on PopoverContent, matching the existing pattern in GitModePopover and ToolbarPopover which already have this fix with an explanatory comment. * docs: add PR verification screenshots for branch picker feature * fix(web-shell): mock useWorkspace in tests for BranchPickerPopover BranchPickerPopover calls useWorkspace() which requires DaemonWorkspaceProvider context. The existing WorkspaceSection and ChatEditor tests didn't provide this context, causing 5 test failures. Added vi.mock with importActual to preserve other exports while providing a mock useWorkspace. Also updated the git chip click test to reflect that clicking now opens the branch picker popover instead of directly calling onOpenGitDiff. * fix: harden git write paths against argument injection Address review feedback on the web-shell git surface: - Reject option/pathspec injection in git checkout ref and branch start point (isValidCheckoutRef), and terminate `git checkout` argv with `--`. - Drop `git log` range values that start with `-` and terminate the argv with `--` so a range can never be reinterpreted as `--output=<file>`. - Fix getDefaultBranch always falling back to origin/main: the promisified exec lacked `encoding: 'utf8'`, so stdout was a Buffer and .trim() threw. - Parameterize ghErrorMessage so `gh pr create` timeouts name the right command and duration; sanitize workspace paths in PR-create errors. - GitDialog: guard doCommit against double-submit (button + keyboard), and strip only a known remote prefix from the PR base so local branches with "/" are not mangled; use theme tokens for commit button/success colors. - BranchPickerPopover: guard checkout/new-branch behind busyAction, reset inline-input text on reopen, and hide the commit action when unavailable. Adds regression tests for the checkout/branch validation and the git log range guard. * fix(web-shell): address review feedback on branch picker PR (#7731) - Fix Commit+Push error masking: split try/catch so push failure reports alongside the successful commit SHA - Replace hardcoded screenshot path with captureScreenshot harness - Replace silent if-isVisible skip with explicit assertion in visual test - Add focus-visible style for search input accessibility - Fix CSS specificity for active PR tab hover state - Add viewChanges to actionsVisible search filter - Wrap toggleSection in useCallback to avoid unnecessary re-renders - Add windowsHide: true to getDefaultBranch subprocess - Fix trailing slash handling in mockDaemon git action routing - Add git methods to top-level client mock in tests - Remove dead branchPicker.commitSuccess i18n key - Remove dead .actionShortcut CSS class - Show generation failure feedback in commit message placeholder * fix(web-shell): address review feedback on branch picker PR (#7731) - Add workspace trust checks to bound git branch routes - Use workspace-scoped client in BranchPickerPopover (fixes wrong-workspace mutation) - Add branch name validation and -- terminator to gitCreateBranch - Filter refs/remotes/*/HEAD from branch listings - Force LC_ALL=C for reflog parsing (non-English locale fix) - Narrow 'could not resolve' error regex to avoid DNS false positives - Add range validation to git log (reject path traversal) - Fix commit+push error i18n (dedicated key instead of concatenation) - Add i18n for BranchSelect component strings - Fix commit tab ARIA attributes - Add onBranchChanged callback to handlePush - Add btw to mockDaemon isDaemonPath regex - Add workspace_github_prs to visuals spec capabilities - Add -- terminator regression test - Remove docs/pr-assets/ from repo * fix(web-shell): address review feedback on branch picker PR (#7731) * fix(cli): reject dash-prefixed branch name with 400 in branch route (#7731) * fix(web-shell): address review feedback on git branch picker (#7731) Security: - Clear GIT_DIR/GIT_WORK_TREE/GIT_COMMON_DIR/GIT_INDEX_FILE from git subprocess env to prevent repository redirection - Add strict mutation gate to all POST git branch routes - Add generation guard to qualified write routes - Fail closed on invalid ?cwd= in mutation routes (resolveContainedCwdOrFail) - Reject wrong-typed startPoint, fetchOnly, rebase, and PR options with 400 Correctness: - Filter remote symbolic refs (origin/HEAD) by %(symref) instead of /HEAD name suffix, preserving valid branches like feature/HEAD - Add git rev-parse --git-dir probe so non-git dirs get 404 instead of empty available:true - Push preserves existing upstream; only adds --set-upstream when unset, resolving the remote from branch config or the sole configured remote - git commit -a replaced with git add -A + git commit so untracked files displayed in the UI are included - Always pass --body to gh pr create to prevent interactive prompts - getDefaultBranch returns null instead of fabricating origin/main - Memoize workspaceByCwd client in BranchPickerPopover to fix infinite render loop - Move sessionId to a ref in GitDialog effects to prevent self-abort - Bound commit-message prompt to fit /btw 4096-char limit - Mark all platforms as unverified in PR template (no fabricated ✅) - Guard PR auto-fill effect against wiping user edits on reconnect Accessibility: - Add tabIndex and onKeyDown to commit-mode tab span - Add aria-label to BranchSelect trigger and search input Cleanup: - Remove dead CSS (.prInputSmall, .prSelect) - Remove 9 unused i18n keys - Add ^ to git log range validation regex - Add busyAction guard to handlePush/handlePull - Add unit tests for gitCommit, gitPull, and route input validation * fix(web-shell): address review feedback on git branch picker PR (#7731) - Change commit tab from <span> to <button> for keyboard accessibility - Move setCommitMsg('') to success-only branches so the message is preserved when push fails after a successful commit - Add mutate middleware and generationGuard to PR creation route, matching all other POST mutation routes - Set genFailed when session resolution returns undefined so the user sees the failure indicator instead of a silent empty textarea - Make PR number nullable when URL regex does not match instead of returning a misleading 0 - Add LC_ALL=C and LANG=C to gitEnv() so for-each-ref upstream track parsing is locale-independent - Validate setUpstream and force as booleans in handlePush, matching the existing validation in handlePull - Add missing workspaceCwd and available fields to test mocks - Use stable data-web-shell-git-branch attribute in e2e selector * fix(web-shell): address R5 review feedback on git branch picker PR (#7731) - Classify git errors on stdout+stderr instead of err.message to fix false-positive no_upstream on every push failure and dead nothing_to_commit classifier - Sanitize workspace paths and cap error message length in sendGitError - Fix remote branch checkout to strip remote prefix so git DWIM creates a local tracking branch instead of detaching HEAD - Restore keyboard accessibility on composer branch chip (span → button) - Trim startPoint in handleCreateBranch before forwarding to git - Return bare branch name from getDefaultBranch (strip remote prefix) - Fix i18n shortcut hint to show ⌘/Ctrl+Enter for cross-platform - Update aria-label to reflect git management menu, not just changes - Add available: true to mockDaemon gitDiff default payload - Add regression tests: upstream preservation, sole remote resolution, strengthened fetch-only with divergent remote commit - Add aria-expanded assertion to sidebar picker test Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(web-shell): address R6 review feedback on git branch picker PR (#7731) * fix(web-shell): address R7 review feedback on git branch picker PR (#7731) * fix(web-shell): address R8 review feedback on git branch picker PR (#7731) * fix(web-shell): address R9 review feedback on git branch picker PR (#7731) * fix(web-shell): address R10 review feedback on git branch picker PR (#7731) * fix(web-shell): address R11 review feedback on git branch picker PR (#7731) * fix(web-shell): address R12 review feedback on git branch picker PR (#7731) * fix(web-shell): address R13 review feedback on git branch picker PR (#7731) * fix(web-shell): address R14 review feedback on git branch picker PR (#7731) * fix(web-shell): address R15 review feedback on git branch picker PR (#7731) - Validate localName derived from remote-tracking ref to prevent option injection (e.g. origin/-f → git checkout -f) - Add gitCwd prop to BranchPickerPopover and pass it to all git SDK calls so worktree sessions target the correct directory - Add symlink-escape and non-existent-path tests for resolveContainedCwdOrFail - Pin initial branch name in makeRepo() with git init -b master - Add gitPull merge and rebase integration tests * fix(web-shell): address git branch picker review feedback (#7731) * fix(web-shell): address R6 review feedback on git branch picker PR (#7731) * fix(web-shell): address review feedback on git branch picker PR (#7731) - Strip GIT_CONFIG_GLOBAL/SYSTEM/NOSYSTEM in gitEnv to prevent inherited config redirection (consistent with extension/github.ts) - Pass gitCwd to workspaceGitBranches in GitDialog loadPrBranches so worktree sessions fetch branches from the correct repository - Add aria-expanded to collapsible branch section headers - Add happy-path tests for PR create (201) and default-branch (200) routes, including the null fallback to origin/main * fix(cli): add sendGenerationClosedError to POST routes and cover untested branches (#7731) * fix(web-shell): address review feedback on branch picker and PR creation (#7731) - Refresh branch list after push/pull to avoid stale ahead/behind counts - Add pre-flight check for unpushed branches before PR creation - Fix base branch prefix stripping when branch list is unavailable - Cap PR body file list at MAX_SUMMARY_CHARS to bound model prompt size - Add qualified route tests: trust guard, input validation, cwd containment * fix(web-shell): hoist MAX_SUMMARY_CHARS to module scope for PR body generation (#7731) * fix(web-shell): address review feedback for git branch picker (#7731) - Hoist onOpenCommit to useCallback to fix App.test.tsx prop stability test - Keep commit tab visible after navigating away (startedInCommit ref) - Add onClick handler to commit tab for navigation back to commit view - Fix branch-prefix strip mangling local branch names containing '/' - Update sessionIdRef after force-creating a stale session replacement - Pin core.hooksPath in test makeRepo for reliable rollback tests - Add test asserting --force-with-lease is used for force pushes * fix(web-shell): target the worktree for sidebar commits and harden git actions (#7731) Scope the sidebar commit dialog to the active session's worktree checkout (matching the composer path) so linked-worktree sessions commit to the right checkout, guard PR creation against a double-click race, and surface an error when an invalid branch name is submitted. Adds focused coverage for the branch picker action wiring and the git branch route validation paths. * fix(web-shell): address review feedback for git branch picker (#7731) --------- Co-authored-by: qwen-code-ci-bot <qwen-code-ci-bot@users.noreply.github.com> Co-authored-by: qwen-code-dev-bot <qwen-code-dev@service.alibaba.com> Co-authored-by: Qwen Code Bot <qwen-code-bot@users.noreply.github.com> Co-authored-by: Qwen Code <qwen-code@users.noreply.github.com> Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Co-authored-by: Qwen Code Autofix <qwen-code-autofix@users.noreply.github.com>
387 lines
7 KiB
CSS
387 lines
7 KiB
CSS
.content {
|
|
display: flex;
|
|
min-height: 50vh;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.tabBar {
|
|
display: flex;
|
|
gap: 2px;
|
|
padding: 0 0 8px;
|
|
margin-bottom: 8px;
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
|
|
.tab {
|
|
padding: 4px 12px;
|
|
border: 0;
|
|
border-radius: 4px;
|
|
background: transparent;
|
|
color: var(--muted-foreground);
|
|
cursor: pointer;
|
|
font: inherit;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.tab:hover,
|
|
.tabActive {
|
|
background: var(--subtle-bg, rgba(128, 128, 128, 0.06));
|
|
}
|
|
|
|
.tabActive {
|
|
color: inherit;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.tabPanel {
|
|
display: flex;
|
|
min-height: 0;
|
|
flex: 1;
|
|
flex-direction: column;
|
|
}
|
|
|
|
/* ── commit panel ─────────────────────────── */
|
|
.commitPanel {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
padding: 10px 0 0;
|
|
border-top: 1px solid var(--border);
|
|
margin-top: 8px;
|
|
}
|
|
|
|
.commitMessage {
|
|
width: 100%;
|
|
min-height: 80px;
|
|
max-height: 180px;
|
|
resize: vertical;
|
|
border: 1px solid var(--border, rgba(128, 128, 128, 0.3));
|
|
border-radius: 6px;
|
|
background: var(--background, transparent);
|
|
color: var(--foreground, #e0e0e0);
|
|
font-size: 13px;
|
|
font-family: 'JetBrains Mono', monospace;
|
|
padding: 8px 10px;
|
|
outline: none;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.commitMessage:focus {
|
|
border-color: var(--primary, #3b82f6);
|
|
box-shadow: 0 0 0 2px
|
|
color-mix(in srgb, var(--primary, #3b82f6) 20%, transparent);
|
|
}
|
|
|
|
.commitMessage::placeholder {
|
|
color: var(--muted-foreground, #666);
|
|
}
|
|
|
|
.commitStatus {
|
|
font-size: 12px;
|
|
padding: 4px 0;
|
|
}
|
|
|
|
.commitStatusError {
|
|
color: var(--destructive, #ef4444);
|
|
}
|
|
|
|
.commitStatusSuccess {
|
|
color: var(--success-color);
|
|
}
|
|
|
|
.commitActions {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.commitBtn {
|
|
padding: 6px 16px;
|
|
border-radius: 6px;
|
|
border: none;
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
transition: opacity 0.15s;
|
|
}
|
|
|
|
.commitBtn:disabled {
|
|
opacity: 0.5;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
.commitBtnPrimary {
|
|
background: var(--primary, #3b82f6);
|
|
color: var(--background);
|
|
}
|
|
|
|
.commitBtnPrimary:hover:not(:disabled) {
|
|
opacity: 0.9;
|
|
}
|
|
|
|
.commitBtnSecondary {
|
|
background: var(--secondary, rgba(128, 128, 128, 0.15));
|
|
color: var(--foreground, #e0e0e0);
|
|
border: 1px solid var(--border, rgba(128, 128, 128, 0.3));
|
|
}
|
|
|
|
.commitBtnSecondary:hover:not(:disabled) {
|
|
background: var(--accent, rgba(128, 128, 128, 0.2));
|
|
}
|
|
|
|
.spin {
|
|
animation: spin 1s linear infinite;
|
|
}
|
|
|
|
@keyframes spin {
|
|
from {
|
|
transform: rotate(0deg);
|
|
}
|
|
to {
|
|
transform: rotate(360deg);
|
|
}
|
|
}
|
|
|
|
/* ── PR create form ─────────────────────────── */
|
|
.prForm {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
padding: 10px 0 0;
|
|
border-top: 1px solid var(--border);
|
|
margin-top: 8px;
|
|
}
|
|
|
|
.prInput {
|
|
width: 100%;
|
|
border: 1px solid var(--border, rgba(128, 128, 128, 0.3));
|
|
border-radius: 6px;
|
|
background: var(--background, transparent);
|
|
color: var(--foreground, #e0e0e0);
|
|
font-size: 13px;
|
|
padding: 6px 10px;
|
|
outline: none;
|
|
}
|
|
|
|
.prInput:focus {
|
|
border-color: var(--primary, #3b82f6);
|
|
}
|
|
|
|
.prInput::placeholder {
|
|
color: var(--muted-foreground, #666);
|
|
}
|
|
|
|
.prBody {
|
|
width: 100%;
|
|
min-height: 200px;
|
|
max-height: 400px;
|
|
resize: vertical;
|
|
border: 1px solid var(--border, rgba(128, 128, 128, 0.3));
|
|
border-radius: 0 0 6px 6px;
|
|
border-top: none;
|
|
background: var(--background, transparent);
|
|
color: var(--foreground, #e0e0e0);
|
|
font-size: 13px;
|
|
padding: 8px 10px;
|
|
outline: none;
|
|
line-height: 1.5;
|
|
font-family: 'JetBrains Mono', monospace;
|
|
}
|
|
|
|
.prBody:focus {
|
|
border-color: var(--primary, #3b82f6);
|
|
}
|
|
|
|
.prBody::placeholder {
|
|
color: var(--muted-foreground, #666);
|
|
}
|
|
|
|
.prBodyWrap {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.prBodyToolbar {
|
|
display: flex;
|
|
gap: 0;
|
|
border: 1px solid var(--border, rgba(128, 128, 128, 0.3));
|
|
border-bottom: none;
|
|
border-radius: 6px 6px 0 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.prBodyTab {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
padding: 4px 10px;
|
|
border: none;
|
|
background: transparent;
|
|
color: var(--muted-foreground, #888);
|
|
font-size: 11px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.prBodyTab:hover {
|
|
background: var(--subtle-bg, rgba(128, 128, 128, 0.06));
|
|
}
|
|
|
|
.prBodyTabActive:hover {
|
|
background: var(--subtle-bg, rgba(128, 128, 128, 0.1));
|
|
}
|
|
|
|
.prBodyTabActive {
|
|
color: var(--foreground, #e0e0e0);
|
|
background: var(--subtle-bg, rgba(128, 128, 128, 0.1));
|
|
font-weight: 500;
|
|
}
|
|
|
|
.prBodyPreview {
|
|
min-height: 200px;
|
|
max-height: 400px;
|
|
overflow-y: auto;
|
|
border: 1px solid var(--border, rgba(128, 128, 128, 0.3));
|
|
border-top: none;
|
|
border-radius: 0 0 6px 6px;
|
|
padding: 8px 10px;
|
|
font-size: 13px;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.prBodyEmpty {
|
|
color: var(--muted-foreground, #666);
|
|
font-style: italic;
|
|
}
|
|
|
|
.prFormRow {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ── branch select (searchable) ─────────────── */
|
|
.branchSelectTrigger {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
min-width: 120px;
|
|
max-width: 200px;
|
|
border: 1px solid var(--border, rgba(128, 128, 128, 0.3));
|
|
border-radius: 6px;
|
|
background: var(--background, transparent);
|
|
color: var(--foreground, #e0e0e0);
|
|
font-size: 12px;
|
|
padding: 5px 8px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.branchSelectTrigger:hover {
|
|
border-color: var(--primary, #3b82f6);
|
|
}
|
|
|
|
.branchSelectValue {
|
|
flex: 1;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
text-align: left;
|
|
}
|
|
|
|
.branchSelectPopover {
|
|
width: 240px;
|
|
max-height: 280px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
padding: 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.branchSelectSearch {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
padding: 6px 8px;
|
|
border-bottom: 1px solid var(--border, rgba(128, 128, 128, 0.2));
|
|
color: var(--muted-foreground, #888);
|
|
}
|
|
|
|
.branchSelectInput {
|
|
flex: 1;
|
|
border: none;
|
|
background: transparent;
|
|
color: var(--foreground, #e0e0e0);
|
|
font-size: 12px;
|
|
outline: none;
|
|
}
|
|
|
|
.branchSelectInput::placeholder {
|
|
color: var(--muted-foreground, #666);
|
|
}
|
|
|
|
.branchSelectList {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
padding: 4px 0;
|
|
}
|
|
|
|
.branchSelectGroup {
|
|
padding: 3px 10px 1px;
|
|
font-size: 10px;
|
|
font-weight: 600;
|
|
color: var(--muted-foreground, #666);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.3px;
|
|
}
|
|
|
|
.branchSelectItem {
|
|
display: block;
|
|
width: 100%;
|
|
padding: 4px 10px 4px 16px;
|
|
border: none;
|
|
background: none;
|
|
color: var(--foreground, #e0e0e0);
|
|
font-size: 12px;
|
|
text-align: left;
|
|
cursor: pointer;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.branchSelectItem:hover {
|
|
background: var(--accent, rgba(128, 128, 128, 0.12));
|
|
}
|
|
|
|
.branchSelectItemActive {
|
|
color: var(--primary, #60a5fa);
|
|
font-weight: 500;
|
|
}
|
|
|
|
.branchSelectEmpty {
|
|
padding: 12px 10px;
|
|
text-align: center;
|
|
font-size: 11px;
|
|
color: var(--muted-foreground, #888);
|
|
}
|
|
|
|
.branchSelectRetry {
|
|
margin-left: 6px;
|
|
padding: 0;
|
|
border: none;
|
|
background: none;
|
|
color: var(--primary, #60a5fa);
|
|
font-size: 11px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.branchSelectRetry:hover {
|
|
text-decoration: underline;
|
|
}
|