import type { SxProps, Theme } from '@mui/material' export const styles = { // Padding lives on header/content/footer (not the root) so the sticky // header is opaque and full-bleed while pinned. row: { display: 'flex', flexDirection: 'column', position: 'relative', '& + &': { borderTop: '1px solid', borderColor: 'divider', }, // Hover-fade actions (widgets-v2 Wrapper parity). Direct children of // `.PsLegend-rowFade` are hidden on fine-pointer devices and fade in when // the row is hovered or holds focus; a control carrying `.active` (dirty // state — hidden layer, open menu, opacity ≠ 1) stays visible. Coarse- // pointer (touch) devices always show them. Each non-active child also // collapses to zero width on its own (not just the whole actions slot — // see `PsLegend-rowActions` below) so a sibling's `.active` pin (e.g. the // eye while hidden) doesn't leave a same-sized invisible hole where the // still-faded ⋮ menu would've been; the title grows into that space. The // collapse chevron sits outside the fade group and never fades. '& .PsLegend-rowFade > *': { opacity: 1, transition: ({ transitions }: Theme) => transitions.create(['opacity', 'width'], { duration: transitions.duration.standard, easing: transitions.easing.easeInOut, }), '@media (hover: hover)': { opacity: 0, }, '&.active': { opacity: 1, }, }, // Faded actions don't reserve flex space on fine-pointer devices — the // title grows to the trailing edge. Hover/focus-within restores the slot // so the title reflows with the buttons; a dirty `.active` child keeps // the slot open even outside hover. '@media (hover: hover)': { '& .PsLegend-rowFade > *:not(.active)': { width: 0, minWidth: 0, // border-box IconButtons keep their padding inside `width` — zero it // too, otherwise the fixed 2px+2px padding survives as a tiny but // needless residual gap. padding: 0, overflow: 'hidden', pointerEvents: 'none', }, '& .PsLegend-rowActions:not(:has(.active))': { width: 0, minWidth: 0, overflow: 'hidden', // Cancel the header gap so nothing is left behind the title. marginInlineStart: ({ spacing }: Theme) => `calc(-1 * ${spacing(0.5)})`, pointerEvents: 'none', }, }, '&:hover .PsLegend-rowFade > *, &:focus-within .PsLegend-rowFade > *': { opacity: 1, width: 'auto', minWidth: 0, padding: '2px', overflow: 'visible', pointerEvents: 'auto', }, '&:hover .PsLegend-rowActions, &:focus-within .PsLegend-rowActions': { width: 'auto', minWidth: 0, overflow: 'visible', marginInlineStart: 0, pointerEvents: 'auto', }, // Hovering anywhere in the row also reveals the category/icon values // (the renderers keep their own list-scoped rule for standalone usage). '&:hover .PsLegend-value, &:focus-within .PsLegend-value': { opacity: 1, }, // Drag handle (Legend.Sortable): absolutely positioned (no reserved flex // slot, so it never shifts the title/icon); the button inside fades in // on hover/focus and is always visible on touch devices. '& .PsLegend-dragHandle-layer > *': { opacity: 0, transition: ({ transitions }: Theme) => transitions.create('opacity', { duration: transitions.duration.standard, easing: transitions.easing.easeInOut, }), '@media (hover: none)': { opacity: 1, }, }, '&:hover .PsLegend-dragHandle-layer > *, &:focus-within .PsLegend-dragHandle-layer > *': { opacity: 1, }, }, // The original stays in place, dimmed, while its overlay clone is dragged. rowDragging: { opacity: 0.4, }, // Figma `_Legend header`: 16px top/left inset (title glyphs start at // y≈17, x=16 in the 68px-tall header), actions share the title's vertical // band (subtitle flows below them) — hence `flex-start` with the title // optically centered against the 30px icon-button row. Sticky: pins inside // the panel's scroll container; `top` is applied inline per row (0, or the // group-header height for grouped rows). Grouped rows get an extra 20px // left inset (36px total) so member layers read as nested under the group // and line up with the group's own icon+label text start. header: { display: 'flex', alignItems: 'flex-start', gap: 0.5, minHeight: 32, padding: ({ spacing }) => spacing(1.5, 2, 1.5, 2), position: 'sticky', // Above MUI's z-index-1 form internals (e.g. InputLabel) in row content, // below the group header (3). zIndex: 2, backgroundColor: 'background.paper', }, headerGrouped: { paddingLeft: 4.5, }, titleBox: { flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column', }, // Accordion click target (whole title block + spare space). Non-native // button, so it carries its own focus ring. titleBoxInteractive: { cursor: 'pointer', userSelect: 'none', '&:focus-visible': { outline: '2px solid', outlineColor: 'primary.main', outlineOffset: -2, }, }, // The title line and the actions box share the same 24px band, centered, // so the title and the action icons stay aligned under the header's // `flex-start` — no padding magic. The subtitle flows below. titleLine: { minHeight: 24, display: 'flex', alignItems: 'center', gap: 0.5, }, // No `flex:1` here — the title sizes to its own text (shrinking to // ellipsis when too long) so the chevron sits right after it, instead of // being dragged to the trailing edge of `titleLine` (which spans the full // width of `titleBox`, itself `flex:1` to fill the header up to actions). title: { minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', }, // Informative collapse indicator beside the title (the title area is the // button). Points down when expanded, right when collapsed; not shown on // touch devices — there the title row itself is the affordance. chevron: { fontSize: 16, color: 'text.secondary', flexShrink: 0, transition: ({ transitions }: Theme) => transitions.create('transform', { duration: transitions.duration.shorter, }), '@media (hover: none)': { display: 'none', }, }, chevronCollapsed: { transform: 'rotate(-90deg)', }, // Same 24px band as the title line, so both sides of the header stay // aligned even when the composed actions are shorter (or fade out). // Icon buttons (actions + collapse chevron) are squeezed to 24×24: // 2px padding around the 20px small icon. actions: { minHeight: 24, display: 'flex', alignItems: 'center', gap: 0.25, flexShrink: 0, '& .MuiIconButton-root': { padding: '2px', }, }, // Figma rhythm: ~16px from the subtitle to the select (8px header bottom // padding + 4px here + line leading), 8px between body blocks, 8px bottom // inset before the next row's divider. content: { display: 'flex', flexDirection: 'column', gap: 1, padding: ({ spacing }) => spacing(0.5, 2, 1, 2), }, contentGrouped: { paddingLeft: 4.5, }, // ~16px above the note (content's 8px bottom inset + 8px here), per design. footer: { padding: ({ spacing }) => spacing(1, 2, 1, 2), }, footerGrouped: { paddingLeft: 4.5, }, dimmed: { opacity: 0.5, }, } satisfies Record>