Files
deepseek-harness/packages/client/ui-primitives/src/Menu.module.css
_Kerman 62dd2ab38e Merge remote-tracking branch 'github/master' into xtr/trajectory-inspection-ui
# Conflicts:
#	packages/client/runtime/src/client/sessions/fold-adapter.ts
#	packages/compact/compact-basic/src/summarizer.ts
2026-07-28 21:56:02 +08:00

234 lines
5.3 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
.root {
position: relative;
display: inline-flex;
}
/* Dropdown card (figma MenuDropdown 122:9481 / 419:16920): menu surface,
* r12, inverted hairline border, shadow-lv3, 4px inset padding. */
.list,
.submenu {
/* min-widths below are the design's outer card widths — include the pad. */
box-sizing: border-box;
padding: 4px;
display: flex;
flex-direction: column;
gap: 0;
border: 1px solid var(--dsw-alias-border-inverted);
border-radius: 12px;
background: var(--dsw-specific-menu);
box-shadow: var(--dsw-shadow-lv3);
/* Elevated surface: the scrollbar thumb takes the l2 elevation tokens. The
declaration sits on the card rather than on `.scrollable .viewport`
because the elevation is a property of this surface, and the custom
properties inherit down to whichever descendant actually scrolls (see
ui-theme styles/scrollbar.css for the rebinding contract). */
--dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2);
--dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2);
}
/* Primary card is 218 wide in the design across both hosts. */
.list {
position: absolute;
top: calc(100% + 4px);
left: 0;
z-index: 100;
min-width: 218px;
max-width: 360px;
}
/* Portal mode: fixed in the viewport, coordinates supplied inline from the
* anchor rect (side/align resolved in JS, the in-place offset rules above
* don't apply). Portaled lists must layer above modal overlays (z 1000) —
* an anchor inside a dialog still expects its menu on top. */
.portal {
position: fixed;
top: auto;
left: auto;
z-index: 1100;
}
/* Open above the anchor (empty-state workspace chip: figma 122:9481). */
.sideTop {
top: auto;
bottom: calc(100% + 4px);
}
.alignEnd {
left: auto;
right: 0;
}
/* Viewport fit: the card stops 12px short of the viewport's top/bottom edges
* (24 = 2 × the portal MARGIN in Menu.tsx) and taller content scrolls inside
* .viewport, so a pinned .footer stays visible. Menus with submenu rows skip
* this class — the overflow clip would crop the side card, so they rely on
* staying short. */
.scrollable {
max-height: calc(100vh - 24px);
}
.viewport {
display: flex;
flex-direction: column;
min-height: 0;
}
.scrollable .viewport {
overflow-y: auto;
}
/* Pinned rows below the scroll region; l2 hairline (l1 is near-invisible on
* the menu surface) mirrors the .separator spacing. */
.footer {
flex: none;
display: flex;
flex-direction: column;
margin-top: 4px;
padding-top: 4px;
border-top: 1px solid var(--dsw-alias-border-l2);
}
.itemWrap {
position: relative;
}
/* Menu cell (figma .Menu_cell): min-h 40, r10, pad 10/8, 14/22 primary,
* gap 8 between leading icon / label / trailing check. */
.item {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
min-height: 40px;
padding: 8px 10px;
border: none;
border-radius: 10px;
background: transparent;
cursor: pointer;
font-size: 14px;
line-height: 22px;
color: var(--dsw-alias-label-primary);
text-align: left;
}
.item:hover:not(:disabled) {
background: var(--dsw-alias-interactive-bg-hover);
}
.list.compactList,
.submenu.compactList {
min-width: 164px;
padding: 2px;
border-radius: 7px;
}
.compactList .item {
min-height: 26px;
gap: 6px;
padding: 3px 7px;
border-radius: 5px;
font-size: 12px;
line-height: 18px;
}
.compactList .itemIcon {
width: 14px;
height: 14px;
}
.compactList .separator {
margin: 2px;
}
.compactList .label {
padding: 4px 7px;
font-size: 11px;
line-height: 16px;
}
.item:disabled {
opacity: 0.4;
cursor: not-allowed;
}
.itemIcon {
display: inline-flex;
flex: none;
width: 16px;
height: 16px;
align-items: center;
justify-content: center;
color: var(--dsw-alias-label-tertiary);
}
.itemLabel {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.check {
flex: none;
color: var(--dsw-alias-label-primary);
}
/* Selected cell keeps the plain fill (marker is the trailing check); the
* class remains as a hook for owner-side emphasis. */
.selected {
background: transparent;
}
/* Destructive row: error text/icon, danger hover fill. */
.danger {
color: var(--dsw-alias-state-error-primary);
}
.danger .itemIcon {
color: var(--dsw-alias-state-error-primary);
}
.danger:hover:not(:disabled) {
background: var(--dsw-alias-interactive-bg-hover-danger);
}
/* Heading row: non-interactive small grey text, padding aligned with items. */
.label {
padding: 8px 10px;
font-size: 12px;
line-height: 16px;
color: var(--dsw-alias-label-tertiary);
}
/* Separator cell (figma 122:9481): py 4 / px 2 around the hairline. */
.separator {
height: 1px;
margin: 4px 2px;
background: var(--dsw-alias-border-l1);
}
/* Nested card to the right of the parent row (figma 419:16920).
* Bottom-aligned with the parent menu card (grows upward): itemWrap sits in
* .list's 4px pad, so bottom: -4px matches the list's outer bottom edge.
* Horizontal: list pad (4px) + 6px card gap = 10px past itemWrap — plain
* `100% + 6px` collapses to ~2px between outer card edges.
* ::before bridges the full gap so the pointer can cross without mouseLeave. */
.submenu {
position: absolute;
top: auto;
bottom: -4px;
left: calc(100% + 10px);
z-index: 101;
min-width: 163px;
}
.submenu::before {
content: '';
position: absolute;
top: 0;
bottom: 0;
left: -10px;
width: 10px;
}