- Adopt the official LNB desktop spec as package defaults: 240px column, 14px menu text, 48px 1-depth rows and 42px 2/3-depth rows, with new item/subitem padding-block and profile min-height tokens. - Match --hm-lnb-current-depth to the Storybook Manager selected item: sampled soft inset falloff (left/top/bottom) and a fade over the last quarter, keeping the concave corners and content join. - Drop the size overrides from the LNB Story CSS and update the LNB, GNB and Dashboard docs, AI guides and the theme verification baseline.
572 lines
26 KiB
CSS
572 lines
26 KiB
CSS
/* LNB pattern (layout visual reference: D:\컴포넌트\ui-viz Patterns/LNB, implementation: HM Collapsible + plain elements).
|
|
A 272px green column: horizontal 5-stop surface, brand on top, menu in the middle, text-only profile at the bottom. The current
|
|
item is a Beige face (left corners rounded) that runs to the content edge and joins it through two concave corners; hover is
|
|
Black 10% to the same edge; an open group is a Black 8% face with a 1px green line. Spacing values are pattern-local. */
|
|
:root, [data-hm-theme] {
|
|
/* Exposed for the layout: grid column width and the surface that continues behind the content's rounded corners. */
|
|
--hm-lnb-width: 240px;
|
|
--hm-lnb-join: 18px;
|
|
--hm-lnb-background: linear-gradient(90deg, var(--hm-sem-action-primary) 0%, var(--hm-sem-palette-green-light-1) 30%, var(--hm-sem-palette-green-light-2) 50%, var(--hm-sem-palette-green-light-3) 90%, var(--hm-sem-palette-green-light-2) 100%);
|
|
--hm-lnb-background-end: var(--hm-sem-palette-green-light-2);
|
|
--hm-lnb-padding-top: 28px;
|
|
--hm-lnb-padding-bottom: 22px;
|
|
--hm-lnb-inset-start: 20px;
|
|
--hm-lnb-inset-end: 20px;
|
|
/* Menu top (ui-viz 20 under the brand). Padding inside the scroll region, so the scroll starts right under the brand; keep it at
|
|
least `--hm-lnb-join` so the curve above a current first item is not clipped (the bottom padding is the join for the same reason). */
|
|
--hm-lnb-nav-padding-top: 20px;
|
|
|
|
--hm-lnb-text: var(--hm-sem-on-action-primary);
|
|
--hm-lnb-text-secondary: var(--hm-sem-palette-green-tint);
|
|
--hm-lnb-text-stroke-color: color-mix(in srgb, var(--hm-sem-palette-black) 30%, transparent);
|
|
--hm-lnb-focus-outline: 2px solid var(--hm-sem-on-action-primary);
|
|
|
|
--hm-lnb-brand-padding-x: 30px;
|
|
--hm-lnb-brand-padding-bottom: 22px;
|
|
--hm-lnb-brand-gap: 12px;
|
|
--hm-lnb-brand-eyebrow-size: 11px;
|
|
--hm-lnb-brand-eyebrow-spacing: 0.12em;
|
|
--hm-lnb-brand-name-size: 17px;
|
|
--hm-lnb-brand-text-gap: 5px;
|
|
|
|
--hm-lnb-item-min-height: 48px;
|
|
/* 1-depth row: 28px line + 2 x 10px = 48px. */
|
|
--hm-lnb-item-padding-block: 10px;
|
|
--hm-lnb-item-padding-start: 18px;
|
|
--hm-lnb-item-gap: 12px;
|
|
--hm-lnb-item-font-size: 14px;
|
|
--hm-lnb-item-line-height: 28px;
|
|
--hm-lnb-item-font-weight: 700;
|
|
--hm-lnb-item-radius: 4px 0 0 4px;
|
|
--hm-lnb-item-icon-size: 20px;
|
|
--hm-lnb-item-icon-opacity: 0.5;
|
|
--hm-lnb-item-icon-stroke: 1.7;
|
|
--hm-lnb-item-text-stroke-width: 1.5px;
|
|
--hm-lnb-item-text-shadow: 1px 2px 1px var(--hm-lnb-text-stroke-color);
|
|
--hm-lnb-hover-background: color-mix(in srgb, var(--hm-sem-palette-black) 10%, transparent);
|
|
|
|
--hm-lnb-current-background: var(--hm-sem-bg-content);
|
|
--hm-lnb-current-text: var(--hm-sem-action-primary);
|
|
--hm-lnb-current-radius: 8px 0 0 8px;
|
|
/* Inset depth of the current face (left, top, bottom), matched to the Storybook Manager's selected item: inset box-shadows
|
|
6px 0 8px -5px Black 30%, 0 3px 5px -3px Black 20% and 0 -2px 4px -3px Black 20%, faded out over the last quarter. A background
|
|
cannot hold a box-shadow and ::before / ::after already draw the concave corners, so the blurred falloff is sampled as gradient
|
|
stops (left 10px, top 5px, bottom 4px), and the first layer repaints the face color from 75% to 100% so the depth fades toward
|
|
the content side. */
|
|
--hm-lnb-current-depth:
|
|
linear-gradient(to right, transparent, var(--hm-lnb-current-background)) 100% 0 / 25% 100% no-repeat,
|
|
linear-gradient(to right,
|
|
color-mix(in srgb, var(--hm-sem-palette-black) 20%, transparent) 0,
|
|
color-mix(in srgb, var(--hm-sem-palette-black) 15.7%, transparent) 1px,
|
|
color-mix(in srgb, var(--hm-sem-palette-black) 12.2%, transparent) 2px,
|
|
color-mix(in srgb, var(--hm-sem-palette-black) 9.5%, transparent) 3px,
|
|
color-mix(in srgb, var(--hm-sem-palette-black) 7.1%, transparent) 4px,
|
|
color-mix(in srgb, var(--hm-sem-palette-black) 5%, transparent) 5px,
|
|
color-mix(in srgb, var(--hm-sem-palette-black) 3.3%, transparent) 6px,
|
|
color-mix(in srgb, var(--hm-sem-palette-black) 2.2%, transparent) 7px,
|
|
color-mix(in srgb, var(--hm-sem-palette-black) 1.4%, transparent) 8px,
|
|
color-mix(in srgb, var(--hm-sem-palette-black) 0.8%, transparent) 9px,
|
|
transparent 10px),
|
|
linear-gradient(to bottom,
|
|
color-mix(in srgb, var(--hm-sem-palette-black) 12%, transparent) 0,
|
|
color-mix(in srgb, var(--hm-sem-palette-black) 8.5%, transparent) 1px,
|
|
color-mix(in srgb, var(--hm-sem-palette-black) 5%, transparent) 2px,
|
|
color-mix(in srgb, var(--hm-sem-palette-black) 2.3%, transparent) 3px,
|
|
color-mix(in srgb, var(--hm-sem-palette-black) 0.8%, transparent) 4px,
|
|
transparent 5px),
|
|
linear-gradient(to top,
|
|
color-mix(in srgb, var(--hm-sem-palette-black) 9%, transparent) 0,
|
|
color-mix(in srgb, var(--hm-sem-palette-black) 5.1%, transparent) 1px,
|
|
color-mix(in srgb, var(--hm-sem-palette-black) 2.4%, transparent) 2px,
|
|
color-mix(in srgb, var(--hm-sem-palette-black) 0.7%, transparent) 3px,
|
|
transparent 4px);
|
|
|
|
--hm-lnb-group-open-background: color-mix(in srgb, var(--hm-sem-palette-black) 8%, transparent);
|
|
--hm-lnb-group-open-line: 1px solid var(--hm-sem-palette-green-light-2);
|
|
--hm-lnb-group-radius: 8px 0 0 8px;
|
|
--hm-lnb-group-current-text: var(--hm-sem-palette-yellow-accent);
|
|
--hm-lnb-group-arrow-size: 18px;
|
|
--hm-lnb-subitem-padding-start: 68px;
|
|
/* 2-depth row (links directly in a group, nested group triggers): 28px line + 2 x 7px = 42px. */
|
|
--hm-lnb-subitem-min-height: 42px;
|
|
--hm-lnb-subitem-padding-block: 7px;
|
|
/* Align the 2-depth link surface with the 1-depth group text; retain its existing text inset. */
|
|
--hm-lnb-subitem-surface-inset: calc(var(--hm-lnb-item-padding-start) + var(--hm-lnb-group-arrow-size) + var(--hm-lnb-item-gap));
|
|
--hm-lnb-group-padding-bottom: 8px;
|
|
|
|
/* 3-depth: the items of an `LNBGroup` nested in a group. Same font size as the other depths; the hierarchy is the extra 20px indent and the connector
|
|
(a vertical line at the 2-depth text start, a 12px branch to each row's middle, 8px to the text; it ends at the last row). 42px = 24px line + 9px padding x2. */
|
|
--hm-lnb-third-min-height: 42px;
|
|
--hm-lnb-third-padding-block: 9px;
|
|
--hm-lnb-third-padding-start: 88px;
|
|
--hm-lnb-third-line-height: 24px;
|
|
--hm-lnb-third-font-weight: 500;
|
|
--hm-lnb-third-current-font-weight: 700;
|
|
--hm-lnb-third-connector-x: var(--hm-lnb-subitem-padding-start);
|
|
--hm-lnb-third-connector-length: 12px;
|
|
--hm-lnb-third-connector-width: 1px;
|
|
--hm-lnb-third-connector-color: color-mix(in srgb, var(--hm-sem-palette-green-tint) 40%, transparent);
|
|
--hm-lnb-third-connector-current-color: color-mix(in srgb, var(--hm-sem-palette-green-light-2) 40%, transparent);
|
|
|
|
--hm-lnb-profile-padding-x: 30px;
|
|
--hm-lnb-profile-padding-top: 22px;
|
|
--hm-lnb-profile-gap: 12px;
|
|
--hm-lnb-profile-min-height: 48px;
|
|
--hm-lnb-profile-name-size: 16px;
|
|
--hm-lnb-profile-description-size: 12px;
|
|
}
|
|
|
|
[data-slot="lnb"] {
|
|
position: relative;
|
|
box-sizing: border-box;
|
|
width: var(--hm-lnb-width);
|
|
min-height: 100%;
|
|
padding: var(--hm-lnb-padding-top) 0 var(--hm-lnb-padding-bottom);
|
|
background: var(--hm-lnb-background);
|
|
color: var(--hm-lnb-text);
|
|
}
|
|
/* The surface keeps going for `--hm-lnb-join` behind the rounded left corners of the content next to the column. */
|
|
[data-slot="lnb"]::after {
|
|
content: "";
|
|
position: absolute;
|
|
top: 0;
|
|
bottom: 0;
|
|
left: 100%;
|
|
width: var(--hm-lnb-join);
|
|
background: var(--hm-lnb-background-end);
|
|
pointer-events: none;
|
|
}
|
|
|
|
/* Brand (vertical) and profile: text with the dark text border. */
|
|
[data-slot="lnb-brand"] {
|
|
flex: none;
|
|
gap: var(--hm-lnb-brand-gap);
|
|
align-items: flex-start;
|
|
padding: 0 var(--hm-lnb-brand-padding-x) var(--hm-lnb-brand-padding-bottom);
|
|
}
|
|
[data-slot="lnb-brand"] > :is(img, svg) {
|
|
flex: 0 0 auto;
|
|
max-width: 100%;
|
|
height: auto;
|
|
}
|
|
[data-slot="lnb-brand"] > span {
|
|
display: grid;
|
|
gap: var(--hm-lnb-brand-text-gap);
|
|
min-width: 0;
|
|
max-width: 100%;
|
|
}
|
|
[data-slot="lnb-brand"] :is(small, strong),
|
|
[data-slot="lnb-profile"] :is(strong, p) {
|
|
-webkit-text-stroke: 1px var(--hm-lnb-text-stroke-color);
|
|
paint-order: stroke fill;
|
|
}
|
|
[data-slot="lnb-brand"] small {
|
|
color: var(--hm-lnb-text-secondary);
|
|
font-size: var(--hm-lnb-brand-eyebrow-size);
|
|
font-weight: 700;
|
|
letter-spacing: var(--hm-lnb-brand-eyebrow-spacing);
|
|
line-height: 1.2;
|
|
}
|
|
[data-slot="lnb-brand"] strong {
|
|
font-size: var(--hm-lnb-brand-name-size);
|
|
font-weight: 700;
|
|
overflow-wrap: anywhere;
|
|
}
|
|
[data-slot="lnb"] > [data-slot="lnb-profile"] {
|
|
display: flex;
|
|
flex: none;
|
|
align-items: center;
|
|
gap: var(--hm-lnb-profile-gap);
|
|
align-self: flex-start;
|
|
width: fit-content;
|
|
/* GNB profile's 8px inner hit padding; the existing 30px inset still places the Avatar. */
|
|
max-width: calc(100% - 2 * (var(--hm-lnb-profile-padding-x) - 8px));
|
|
margin-top: auto;
|
|
margin-inline: calc(var(--hm-lnb-profile-padding-x) - 8px);
|
|
min-height: var(--hm-lnb-profile-min-height);
|
|
padding: 0 8px;
|
|
border: 0;
|
|
background: transparent;
|
|
color: inherit;
|
|
font: inherit;
|
|
text-align: left;
|
|
cursor: pointer;
|
|
}
|
|
[data-slot="lnb"] > [data-slot="lnb-profile"]:is(:hover, [data-state="open"]) {
|
|
background: var(--hm-lnb-hover-background);
|
|
}
|
|
[data-slot="lnb"] > [data-slot="lnb-profile"]:focus-visible {
|
|
outline: var(--hm-lnb-focus-outline);
|
|
outline-offset: -2px;
|
|
}
|
|
[data-slot="lnb-profile-text"] {
|
|
min-width: 0;
|
|
}
|
|
[data-slot="lnb-profile"] strong {
|
|
display: block;
|
|
font-size: var(--hm-lnb-profile-name-size);
|
|
overflow-wrap: anywhere;
|
|
}
|
|
[data-slot="lnb-profile"] p {
|
|
margin: 4px 0 0;
|
|
color: var(--hm-lnb-text-secondary);
|
|
font-size: var(--hm-lnb-profile-description-size);
|
|
overflow-wrap: anywhere;
|
|
}
|
|
|
|
/* Menu region and the only scroll container of the column (brand and profile are `flex: none`; the column itself never scrolls). In a
|
|
column of fixed height it fills the space between them (`min-height: 0` lets it shrink below the menu height), so it starts at the
|
|
brand bottom and ends at the profile top. It is `inset-end + 1px` wider than the column's inner area so a current item can overlap
|
|
the content by 1px; vertical padding keeps the join curves of the first / last item from being clipped. `direction: rtl` only moves
|
|
the native scrollbar to the left edge, so it never takes width from the right side where the current item joins the content; the
|
|
menu itself is LTR again (direct children, see "Menu rows" below). */
|
|
[data-slot="lnb-nav"] {
|
|
flex: 1 1 auto;
|
|
min-height: 0;
|
|
direction: rtl;
|
|
margin: 0 -1px 0 0;
|
|
padding: var(--hm-lnb-nav-padding-top) 0 var(--hm-lnb-join) var(--hm-lnb-inset-start);
|
|
overflow-x: clip;
|
|
overflow-y: auto;
|
|
scrollbar-width: thin;
|
|
scrollbar-color: color-mix(in srgb, var(--hm-sem-palette-white) 35%, transparent) transparent;
|
|
}
|
|
/* Layout owns the old top spacing only when this column owns a Profile. */
|
|
[data-slot="lnb"]:has(> [data-slot="lnb-profile"]) > [data-slot="lnb-nav"] {
|
|
margin-bottom: var(--hm-lnb-profile-padding-top);
|
|
}
|
|
|
|
/* ── Item ───────────────────────────────────────────────────────────────────────────────────────────── */
|
|
[data-slot="lnb-item"],
|
|
[data-slot="lnb-group-trigger"] {
|
|
position: relative;
|
|
box-sizing: border-box;
|
|
gap: var(--hm-lnb-item-gap);
|
|
width: calc(100% - 1px);
|
|
min-height: var(--hm-lnb-item-min-height);
|
|
padding: var(--hm-lnb-item-padding-block) calc(var(--hm-lnb-inset-end) + 12px) var(--hm-lnb-item-padding-block) var(--hm-lnb-item-padding-start);
|
|
border: 0;
|
|
border-radius: var(--hm-lnb-item-radius);
|
|
background: transparent;
|
|
color: var(--hm-lnb-text);
|
|
font-family: inherit;
|
|
font-size: var(--hm-lnb-item-font-size);
|
|
line-height: var(--hm-lnb-item-line-height);
|
|
font-weight: var(--hm-lnb-item-font-weight);
|
|
text-align: left;
|
|
text-decoration: none;
|
|
word-break: keep-all;
|
|
overflow-wrap: anywhere;
|
|
cursor: pointer;
|
|
outline: none;
|
|
-webkit-text-stroke: var(--hm-lnb-item-text-stroke-width) var(--hm-lnb-text-stroke-color);
|
|
paint-order: stroke fill;
|
|
text-shadow: var(--hm-lnb-item-text-shadow);
|
|
}
|
|
[data-slot="lnb-item"] > svg:not([data-slot]) {
|
|
flex: 0 0 auto;
|
|
width: var(--hm-lnb-item-icon-size);
|
|
height: var(--hm-lnb-item-icon-size);
|
|
opacity: var(--hm-lnb-item-icon-opacity);
|
|
stroke-width: var(--hm-lnb-item-icon-stroke);
|
|
}
|
|
[data-slot="lnb-item"]:not([aria-current="page"]):hover,
|
|
[data-slot="lnb-group-trigger"]:hover {
|
|
background: var(--hm-lnb-hover-background);
|
|
}
|
|
[data-slot="lnb-item"]:focus-visible,
|
|
[data-slot="lnb-group-trigger"]:focus-visible {
|
|
outline: var(--hm-lnb-focus-outline);
|
|
outline-offset: -2px;
|
|
}
|
|
|
|
/* Current: Beige face, left corners 8, runs 1px into the content, concave corners above and below, inset depth. No text effects. */
|
|
[data-slot="lnb-item"][aria-current="page"] {
|
|
z-index: 1;
|
|
width: 100%;
|
|
background: var(--hm-lnb-current-depth), var(--hm-lnb-current-background);
|
|
border-radius: var(--hm-lnb-current-radius);
|
|
color: var(--hm-lnb-current-text);
|
|
-webkit-text-stroke: 0;
|
|
text-shadow: none;
|
|
}
|
|
[data-slot="lnb-item"][aria-current="page"]:focus-visible {
|
|
outline-color: var(--hm-lnb-current-text);
|
|
}
|
|
[data-slot="lnb-item"][aria-current="page"]::before,
|
|
[data-slot="lnb-item"][aria-current="page"]::after {
|
|
content: "";
|
|
position: absolute;
|
|
right: 1px;
|
|
width: var(--hm-lnb-join);
|
|
height: var(--hm-lnb-join);
|
|
pointer-events: none;
|
|
}
|
|
[data-slot="lnb-item"][aria-current="page"]::before {
|
|
bottom: 100%;
|
|
background: radial-gradient(circle at top left, transparent calc(var(--hm-lnb-join) - 0.5px), var(--hm-lnb-current-background) var(--hm-lnb-join));
|
|
}
|
|
[data-slot="lnb-item"][aria-current="page"]::after {
|
|
top: 100%;
|
|
background: radial-gradient(circle at bottom left, transparent calc(var(--hm-lnb-join) - 0.5px), var(--hm-lnb-current-background) var(--hm-lnb-join));
|
|
}
|
|
|
|
/* ── Group (HM Collapsible) ─────────────────────────────────────────────────────────────────────────── */
|
|
[data-slot="lnb-group"] {
|
|
position: relative;
|
|
width: calc(100% - 1px);
|
|
border-radius: var(--hm-lnb-group-radius);
|
|
}
|
|
[data-slot="lnb-group"][data-state="open"] {
|
|
background: var(--hm-lnb-group-open-background);
|
|
}
|
|
[data-slot="lnb-group"][data-state="open"]::before {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0;
|
|
border: var(--hm-lnb-group-open-line);
|
|
border-right: 0;
|
|
border-radius: inherit;
|
|
pointer-events: none;
|
|
}
|
|
[data-slot="lnb-group-trigger"] {
|
|
width: 100%;
|
|
border-radius: var(--hm-lnb-group-radius);
|
|
}
|
|
[data-slot="lnb-group"][data-state="open"] > [data-slot="lnb-group-trigger"]:hover {
|
|
border-radius: 8px 0 0 0;
|
|
}
|
|
[data-slot="lnb-group"][data-current] > [data-slot="lnb-group-trigger"] {
|
|
color: var(--hm-lnb-group-current-text);
|
|
}
|
|
[data-slot="lnb-group-arrow"] {
|
|
flex: 0 0 auto;
|
|
width: var(--hm-lnb-group-arrow-size);
|
|
height: var(--hm-lnb-group-arrow-size);
|
|
stroke-width: 2;
|
|
filter: drop-shadow(var(--hm-lnb-item-text-shadow));
|
|
transition: transform 0.15s ease;
|
|
}
|
|
[data-slot="lnb-group-trigger"][data-state="open"] > [data-slot="lnb-group-arrow"] {
|
|
transform: rotate(90deg);
|
|
}
|
|
[data-slot="lnb-group-content"][data-state="open"] {
|
|
display: grid;
|
|
padding-bottom: var(--hm-lnb-group-padding-bottom);
|
|
}
|
|
[data-slot="lnb-group-content"] [data-slot="lnb-item"] {
|
|
width: 100%;
|
|
padding-left: var(--hm-lnb-subitem-padding-start);
|
|
border-radius: 0;
|
|
}
|
|
[data-slot="lnb-group-content"] [data-slot="lnb-item"]:not([aria-current="page"]):hover {
|
|
border-radius: var(--hm-lnb-item-radius);
|
|
}
|
|
/* 2-depth rows (links directly in a group, nested group triggers): 42px = 28px line + 2 x 7px. */
|
|
[data-slot="lnb-group-content"] > [data-slot="lnb-item"],
|
|
[data-slot="lnb-group-content"] [data-slot="lnb-group-trigger"] {
|
|
min-height: var(--hm-lnb-subitem-min-height);
|
|
padding-top: var(--hm-lnb-subitem-padding-block);
|
|
padding-bottom: var(--hm-lnb-subitem-padding-block);
|
|
}
|
|
[data-slot="lnb-group-content"] [data-slot="lnb-item"][aria-current="page"] {
|
|
width: calc(100% + 1px);
|
|
margin-right: -1px;
|
|
border-radius: var(--hm-lnb-current-radius);
|
|
}
|
|
/* Only 2-depth destination links: the group keeps its full layout width, while hover, current, focus and click belong to the
|
|
inset link. Subtract the same inset from text padding and width to preserve text wrapping and the right content join. */
|
|
[data-slot="lnb-nav"] > [data-slot="lnb-group"] > [data-slot="lnb-group-content"] > [data-slot="lnb-item"] {
|
|
width: calc(100% - var(--hm-lnb-subitem-surface-inset));
|
|
margin-left: var(--hm-lnb-subitem-surface-inset);
|
|
padding-left: calc(var(--hm-lnb-subitem-padding-start) - var(--hm-lnb-subitem-surface-inset));
|
|
}
|
|
[data-slot="lnb-nav"] > [data-slot="lnb-group"] > [data-slot="lnb-group-content"] > [data-slot="lnb-item"][aria-current="page"] {
|
|
width: calc(100% + 1px - var(--hm-lnb-subitem-surface-inset));
|
|
}
|
|
|
|
/* ── Menu rows (direct children of the menu region) ─────────────────────────────────────────────────── */
|
|
/* Back to LTR. A left scrollbar narrows the content box from the left, so each row starts that much (the scrollbar width, 0 without
|
|
one) to the left again: `100%` is the content box, the region is `--hm-lnb-width + 1px` wide with `--hm-lnb-inset-start` padding. The
|
|
scrollbar sits in that padding and the rows keep x 20 → 272 (current 273) with or without it. */
|
|
[data-slot="lnb-nav"] > * {
|
|
direction: ltr;
|
|
margin-left: calc(100% + var(--hm-lnb-inset-start) - var(--hm-lnb-width) - 1px);
|
|
}
|
|
[data-slot="lnb-nav"] > :is([data-slot="lnb-item"], [data-slot="lnb-group"]) {
|
|
width: auto;
|
|
margin-right: 1px;
|
|
}
|
|
[data-slot="lnb-nav"] > [data-slot="lnb-item"][aria-current="page"] {
|
|
margin-right: 0;
|
|
}
|
|
|
|
/* ── Nested group (2-depth group inside a group) ────────────────────────────────────────────────────── */
|
|
/* The outer group already draws the open face and line, so a nested group adds no face, line, padding or width loss; its name
|
|
lines up with the 2-depth item text. */
|
|
[data-slot="lnb-group-content"] [data-slot="lnb-group"] {
|
|
width: 100%;
|
|
border-radius: 0;
|
|
}
|
|
[data-slot="lnb-group-content"] [data-slot="lnb-group"][data-state="open"] {
|
|
background: none;
|
|
}
|
|
[data-slot="lnb-group-content"] [data-slot="lnb-group"][data-state="open"]::before {
|
|
content: none;
|
|
}
|
|
[data-slot="lnb-group-content"] [data-slot="lnb-group-trigger"] {
|
|
padding-left: calc(var(--hm-lnb-subitem-padding-start) - var(--hm-lnb-group-arrow-size) - var(--hm-lnb-item-gap));
|
|
border-radius: 0;
|
|
}
|
|
[data-slot="lnb-group-content"] [data-slot="lnb-group"] > [data-slot="lnb-group-trigger"]:hover {
|
|
border-radius: var(--hm-lnb-item-radius);
|
|
}
|
|
[data-slot="lnb-group-content"] [data-slot="lnb-group-content"][data-state="open"] {
|
|
padding-bottom: 0;
|
|
}
|
|
|
|
/* 3-depth only: the row owns the existing connector gradients; the link begins at the branch end.
|
|
Decoration follows the row's real middle when text wraps and never owns pointer interaction. */
|
|
[data-slot="lnb-third-row"] {
|
|
--hm-lnb-third-line: var(--hm-lnb-third-connector-color);
|
|
--hm-lnb-third-line-end: 100%;
|
|
--hm-lnb-third-connector:
|
|
linear-gradient(var(--hm-lnb-third-line), var(--hm-lnb-third-line)) var(--hm-lnb-third-connector-x) 0 / var(--hm-lnb-third-connector-width) var(--hm-lnb-third-line-end) no-repeat,
|
|
linear-gradient(var(--hm-lnb-third-line), var(--hm-lnb-third-line)) var(--hm-lnb-third-connector-x) calc(50% - var(--hm-lnb-third-connector-width) / 2) / var(--hm-lnb-third-connector-length) var(--hm-lnb-third-connector-width) no-repeat;
|
|
position: relative;
|
|
padding-left: calc(var(--hm-lnb-third-connector-x) + var(--hm-lnb-third-connector-length));
|
|
}
|
|
[data-slot="lnb-third-row"]::before {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0;
|
|
background: var(--hm-lnb-third-connector);
|
|
pointer-events: none;
|
|
}
|
|
[data-slot="lnb-group-content"] [data-slot="lnb-third-row"] > [data-slot="lnb-item"] {
|
|
min-height: var(--hm-lnb-third-min-height);
|
|
padding-top: var(--hm-lnb-third-padding-block);
|
|
padding-bottom: var(--hm-lnb-third-padding-block);
|
|
padding-left: calc(var(--hm-lnb-third-padding-start) - var(--hm-lnb-third-connector-x) - var(--hm-lnb-third-connector-length));
|
|
line-height: var(--hm-lnb-third-line-height);
|
|
font-weight: var(--hm-lnb-third-font-weight);
|
|
-webkit-text-stroke: 0;
|
|
text-shadow: none;
|
|
}
|
|
/* The vertical line ends at the middle of the last row. */
|
|
[data-slot="lnb-third-row"]:last-child {
|
|
--hm-lnb-third-line-end: 50%;
|
|
}
|
|
[data-slot="lnb-group-content"] [data-slot="lnb-third-row"] > [data-slot="lnb-item"][aria-current="page"] {
|
|
font-weight: var(--hm-lnb-third-current-font-weight);
|
|
}
|
|
|
|
/* Desktop only: below 1024px the column is gone and the layout column collapses with it. */
|
|
@media (max-width: 1023px) {
|
|
:root, [data-hm-theme] {
|
|
--hm-lnb-width: 0px;
|
|
}
|
|
[data-slot="lnb"] {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
/* LNB Mobile Header is the mobile representation of LNB Mode, independent of GNB/Dashboard. */
|
|
:root, [data-hm-theme] {
|
|
--hm-lnb-mobile-height: 56px;
|
|
--hm-lnb-mobile-join: 12px;
|
|
--hm-lnb-mobile-background: linear-gradient(180deg, var(--hm-sem-action-surface-stop-0) 0%, var(--hm-sem-action-surface-stop-30) 30%, var(--hm-sem-action-surface-stop-65) 65%, var(--hm-sem-action-surface-stop-100) 100%);
|
|
/* Mobile menu content (inside the HM Sheet, white face). */
|
|
--hm-lnb-mobile-link-height: 44px;
|
|
--hm-lnb-mobile-link-padding-x: 12px;
|
|
--hm-lnb-mobile-link-radius: var(--hm-radius-control-md);
|
|
--hm-lnb-mobile-link-font-size: 14px;
|
|
--hm-lnb-mobile-link-line-height: 20px;
|
|
--hm-lnb-mobile-link-font-weight: 500;
|
|
--hm-lnb-mobile-link-text: var(--hm-sem-fg-primary);
|
|
--hm-lnb-mobile-link-hover-background: var(--accent);
|
|
--hm-lnb-mobile-link-hover-text: var(--accent-foreground);
|
|
--hm-lnb-mobile-link-current-background: var(--hm-sem-bg-content);
|
|
--hm-lnb-mobile-link-current-text: var(--hm-sem-action-primary);
|
|
--hm-lnb-mobile-link-current-font-weight: 700;
|
|
--hm-lnb-mobile-group-label-color: var(--hm-sem-fg-secondary);
|
|
--hm-lnb-mobile-group-gap: 16px;
|
|
--hm-lnb-mobile-nested-gap: 8px;
|
|
--hm-lnb-mobile-nested-indent: var(--hm-lnb-mobile-link-padding-x);
|
|
--hm-lnb-mobile-focus-ring: 0 0 0 3px color-mix(in srgb, var(--ring) 50%, transparent);
|
|
}
|
|
[data-slot="lnb-mobile-header"] { display: none; }
|
|
[data-slot="lnb-mobile-nav"] {
|
|
display: grid;
|
|
gap: var(--hm-lnb-mobile-group-gap);
|
|
padding-bottom: 16px;
|
|
}
|
|
[data-slot="lnb-mobile-group-label"] {
|
|
margin: 0;
|
|
padding: 0 var(--hm-lnb-mobile-link-padding-x) 4px;
|
|
color: var(--hm-lnb-mobile-group-label-color);
|
|
font-size: 12px;
|
|
line-height: 18px;
|
|
font-weight: 500;
|
|
}
|
|
/* A group inside a group (a deeper local level, e.g. the LNB 3-depth): one link padding further in, with room above its title. */
|
|
[data-slot="lnb-mobile-group"] [data-slot="lnb-mobile-group"] {
|
|
margin-top: var(--hm-lnb-mobile-nested-gap);
|
|
padding-left: var(--hm-lnb-mobile-nested-indent);
|
|
}
|
|
[data-slot="lnb-mobile-link"] {
|
|
box-sizing: border-box;
|
|
min-height: var(--hm-lnb-mobile-link-height);
|
|
padding: 0 var(--hm-lnb-mobile-link-padding-x);
|
|
border-radius: var(--hm-lnb-mobile-link-radius);
|
|
color: var(--hm-lnb-mobile-link-text);
|
|
font-size: var(--hm-lnb-mobile-link-font-size);
|
|
line-height: var(--hm-lnb-mobile-link-line-height);
|
|
font-weight: var(--hm-lnb-mobile-link-font-weight);
|
|
text-decoration: none;
|
|
overflow-wrap: anywhere;
|
|
outline: none;
|
|
}
|
|
[data-slot="lnb-mobile-link"]:is(:hover, :focus-visible) {
|
|
background: var(--hm-lnb-mobile-link-hover-background);
|
|
color: var(--hm-lnb-mobile-link-hover-text);
|
|
}
|
|
[data-slot="lnb-mobile-link"]:focus-visible {
|
|
box-shadow: var(--hm-lnb-mobile-focus-ring);
|
|
}
|
|
[data-slot="lnb-mobile-link"][aria-current="page"] {
|
|
background: var(--hm-lnb-mobile-link-current-background);
|
|
color: var(--hm-lnb-mobile-link-current-text);
|
|
font-weight: var(--hm-lnb-mobile-link-current-font-weight);
|
|
}
|
|
|
|
|
|
[data-slot="lnb-mobile-nav"] [data-slot="lnb-profile"] {
|
|
display: flex; align-items: center; gap: 12px; width: 100%; padding: 8px;
|
|
border-radius: var(--hm-radius-control-md); color: var(--hm-sem-fg-primary); text-align: left; cursor: pointer;
|
|
}
|
|
[data-slot="lnb-mobile-nav"] [data-slot="lnb-profile"]:hover { background: var(--accent); }
|
|
[data-slot="lnb-mobile-nav"] [data-slot="lnb-profile"]:focus-visible { outline: 2px solid var(--ring); }
|
|
[data-slot="lnb-mobile-nav"] [data-slot="lnb-profile"] p { color: var(--hm-sem-fg-secondary); }
|
|
@media (max-width: 1023px) {
|
|
[data-slot="lnb-mobile-header"] {
|
|
position: relative; display: flex; flex: none; align-items: center; gap: 8px;
|
|
height: var(--hm-lnb-mobile-height); padding: 0 16px;
|
|
background: var(--hm-lnb-mobile-background) left top / 100% calc(var(--hm-lnb-mobile-height) + var(--hm-lnb-mobile-join)) no-repeat;
|
|
color: var(--hm-sem-on-action-primary);
|
|
}
|
|
[data-slot="lnb-mobile-header"]::after {
|
|
content: ""; position: absolute; inset: 100% 0 auto; height: var(--hm-lnb-mobile-join);
|
|
background: var(--hm-lnb-mobile-background) left bottom / 100% calc(var(--hm-lnb-mobile-height) + var(--hm-lnb-mobile-join)) no-repeat;
|
|
pointer-events: none;
|
|
}
|
|
[data-slot="lnb-mobile-brand"] { min-width: 0; gap: 12px; text-decoration: none; }
|
|
[data-slot="lnb-mobile-brand"] :is(span, strong) { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
[data-slot="lnb-mobile-brand"] strong { font-size: 16px; font-weight: 700; }
|
|
[data-slot="lnb-mobile-brand"] small { display: none; }
|
|
[data-slot="lnb-mobile-brand"] > :is(img, svg) { max-height: 32px; width: auto; }
|
|
[data-slot="lnb-mobile-header"] > [data-slot="button"] { color: var(--hm-sem-on-action-primary); }
|
|
[data-slot="lnb-mobile-header"] > [data-slot="button"]:hover { background: var(--hm-lnb-hover-background); }
|
|
[data-slot="lnb-mobile-header"] > [data-slot="button"]:focus-visible { outline: var(--hm-lnb-focus-outline); outline-offset: -2px; box-shadow: none; }
|
|
}
|