Files
deepseek-harness/packages/client/ui-workspace/src/client/WorkspaceBrowser.module.css
T
2026-08-04 14:11:54 +08:00

299 lines
6.6 KiB
CSS

/* Workspace browsing region (fills the sidebar shell's hole): section
header, search capsule, and the scrolling session list. Wide/rail
variants ride the shell's fold state through the `wide` owner prop —
rail state renders only the two 36x36 icon controls. */
.root {
--dsh-session-list-edge-inset: var(--dsh-sidebar-inline-padding);
--dsh-session-list-scrollbar-width: 8px;
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
box-sizing: border-box;
padding-right: var(--dsh-session-list-edge-inset);
}
.root.rail {
padding-right: 0;
}
.iconButton {
flex: none;
display: inline-flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
border: none;
border-radius: 50%;
padding: 0;
background: transparent;
cursor: pointer;
color: var(--dsw-alias-label-secondary);
}
.iconButton:hover {
background: var(--dsw-alias-interactive-bg-hover);
}
/* Section header: 36px, "Workspaces/Sessions" label + group-by /
new-workspace buttons; the right-anchored new-workspace button is the
row's rail survivor. */
.sectionHeader {
flex: none;
display: flex;
align-items: center;
justify-content: flex-end;
gap: 4px;
height: 36px;
padding-left: 12px;
margin-bottom: 4px;
box-sizing: border-box;
border-radius: 12px;
overflow: hidden;
color: var(--dsw-alias-label-tertiary);
}
.sectionLabel {
flex: 1;
min-width: 0;
overflow: hidden;
white-space: nowrap;
line-height: 20px;
}
/* Search input: 38px capsule (figma 133:7649); rail state renders it as the
region's search control. Upstream binds a dedicated design-system variable
(light #F1F3F5 / dark #1B1B1C) matching no shipped alias — a component
token pinned to the static scale mirrors it. */
.search {
--dsh-search-input-fill: var(--dsw-static-neutral-bluish-75);
flex: none;
display: flex;
align-items: center;
gap: 8px;
height: 38px;
margin: 0 2px 12px;
padding: 0 14px;
box-sizing: border-box;
border: 1px solid var(--dsw-alias-border-l2);
border-radius: 24px;
background: var(--dsh-search-input-fill);
color: var(--dsw-alias-label-caption);
overflow: hidden;
}
:global(body[data-ds-dark-theme]) .search {
--dsh-search-input-fill: var(--dsw-static-neutral-bluish-900);
}
/* The capsule's leading icon: decorative while wide (pointer-events off so
clicks reach the input), the hit target in rail state. */
.searchButton {
flex: none;
display: inline-flex;
align-items: center;
justify-content: center;
border: none;
border-radius: 50%;
padding: 0;
background: transparent;
pointer-events: none;
color: inherit;
}
.searchInput {
flex: 1;
min-width: 0;
border: none;
outline: none;
background: transparent;
font-size: 14px;
line-height: 20px;
color: var(--dsw-alias-label-primary);
}
.searchInput::placeholder {
color: var(--dsw-alias-label-tertiary);
}
.clearButton {
flex: none;
display: inline-flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
border: none;
border-radius: 50%;
padding: 0;
background: transparent;
cursor: pointer;
color: var(--dsw-alias-label-secondary);
}
/* Rail variant (own .rail class from the wide owner prop — the region never
reads the shell's class names): the two icon controls stack as 36x36
circles matching the shell's rail rhythm. */
.rail .sectionHeader {
gap: 0;
padding-left: 0;
margin-bottom: 12px;
}
.rail .iconButton {
width: 36px;
height: 36px;
color: var(--dsw-alias-label-primary);
}
.rail .search {
height: 36px;
padding: 0;
margin: 0 0 12px;
gap: 0;
border-color: transparent;
background: transparent;
}
.rail .searchButton {
width: 36px;
height: 36px;
pointer-events: auto;
cursor: pointer;
color: var(--dsw-alias-label-primary);
}
.rail .searchButton:hover {
background: var(--dsw-alias-interactive-bg-hover);
}
/* List seat: always mounted so the shell foot never moves. */
.listArea {
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
margin-right: calc(-1 * var(--dsh-session-list-edge-inset));
overflow: hidden;
}
.rail .listArea {
margin-right: 0;
}
/* Relative for the bottom fade overlay. */
.treeBody {
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
position: relative;
}
/* Bottom fade (figma 133:7666): 72px overlay pinned to the visible bottom,
transparent -> sidebar fill so it tracks the theme. */
.fade {
position: absolute;
left: 0;
right: var(--dsh-session-list-edge-inset);
bottom: 0;
height: 72px;
background: linear-gradient(to bottom, transparent, var(--dsw-specific-sidebar-fill));
pointer-events: none;
}
/* Wide-only content fades back in on expand remount (mirrors the shell). */
.wide {
animation: wide-in 200ms var(--ds-ease-in-out);
}
@keyframes wide-in {
from { opacity: 0; }
}
/* List: the only scrolling region. Block children keep their design heights
under content overflow. The stable 8px themed scrollbar and the remaining
padding together equal the shell's right inset, with or without overflow. */
.list {
flex: 1;
min-height: 0;
overflow-y: auto;
padding-right: calc(var(--dsh-session-list-edge-inset) - var(--dsh-session-list-scrollbar-width));
padding-bottom: 12px;
scrollbar-gutter: stable;
}
.flatList > * + *,
.searchTree > [role='treeitem'] + [role='treeitem'],
.groupSection > * + * {
margin-top: 2px;
}
.searchStatus,
.searchWarning {
padding: 10px 12px;
font-size: 12px;
line-height: 18px;
color: var(--dsw-alias-label-tertiary);
}
.searchWarning {
color: var(--dsw-alias-label-secondary);
}
/* One workspace section: header row + a compact expanded session run. */
.groupSection + .groupSection {
margin-top: 4px;
}
.empty {
padding: 16px 12px;
color: var(--dsw-alias-label-tertiary);
font-size: 13px;
}
/* Rename dialog form (same figma dialog family as the create modals). */
.renameInput {
box-sizing: border-box;
width: 100%;
height: 44px;
padding: 7px 14px;
border: 1px solid var(--dsw-alias-border-l2);
border-radius: 22px;
outline: none;
background: transparent;
font-size: 14px;
font-weight: 400;
line-height: 22px;
color: var(--dsw-alias-label-primary);
}
.renameInput:disabled {
color: var(--dsw-alias-label-dimmed);
}
.renameError {
margin-top: 8px;
font-size: 12px;
line-height: 18px;
color: var(--dsw-alias-state-error-primary);
}
.deleteAction:not(:disabled) {
color: var(--dsw-alias-state-error-primary);
}
.deleteStatus {
font-size: 12px;
line-height: 18px;
color: var(--dsw-alias-label-secondary);
}
@media (prefers-reduced-motion: reduce) {
.wide {
animation: none;
}
}