Files
HMDesign/packages/ui/src/theme/gnb.css
T

596 lines
25 KiB
CSS

/* GNB pattern (layout visual reference: D:\컴포넌트\ui-viz Patterns/GNB, implementation: current @hm-design/ui primitives).
The bar is the ui-viz green top header: 70px, vertical brand gradient, brand left, menu centered on the whole bar, text-only profile
right, Beige "current" item joined to the content by two concave corners, White 2-depth panel. The Navigation Menu, Dropdown Menu,
Sheet, Button and Avatar keep their own markup, Radix behavior and tokens; here they are only re-colored INSIDE the GNB scope
(`[data-slot="gnb"] …`), so their own Stories do not change. Spacing values are pattern-local (no global spacing scale exists).
Navigation must use `<NavigationMenu viewport={false}>` so each panel opens under its own trigger at the trigger's width. */
:root, [data-hm-theme] {
/* Exposed for GNB Mode content layouts: the bar height and the content join below it. Mobile uses a shorter bar. */
--hm-gnb-height: 70px;
--hm-gnb-join: 12px;
/* Same stops as the shared Semantic action surface gradient family (tone 1-4); painted over bar + join as one gradient. */
--hm-gnb-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%);
--hm-gnb-padding-x: 28px;
--hm-gnb-column-gap: 24px;
/* Below the z-50 of Popover / Dropdown / Sheet / Dialog (portaled). Applies when `sticky`. */
--hm-gnb-z-index: 40;
--hm-gnb-text: var(--hm-sem-on-action-primary);
--hm-gnb-text-secondary: var(--hm-sem-palette-green-tint);
--hm-gnb-text-stroke-color: color-mix(in srgb, var(--hm-sem-palette-black) 30%, transparent);
--hm-gnb-text-stroke-width: 1px;
--hm-gnb-hover-background: color-mix(in srgb, var(--hm-sem-palette-black) 10%, transparent);
--hm-gnb-focus-outline: 2px solid var(--hm-sem-on-action-primary);
--hm-gnb-brand-gap: 12px;
--hm-gnb-brand-padding-end: 28px;
--hm-gnb-brand-eyebrow-size: 11px;
--hm-gnb-brand-eyebrow-spacing: 0.12em;
--hm-gnb-brand-name-size: 16px;
--hm-gnb-brand-text-gap: 5px;
--hm-gnb-logo-max-height: 100%;
/* Primary menu: 4px above the item, item face 66px = bar 70; first/last item keeps room for the current join curves. */
--hm-gnb-menu-inset-top: 4px;
--hm-gnb-menu-join: 12px;
--hm-gnb-menu-min-width: 112px;
--hm-gnb-menu-padding-x: 16px;
--hm-gnb-menu-gap: 12px;
--hm-gnb-menu-radius: 4px 4px 0 0;
--hm-gnb-menu-font-size: 16px;
--hm-gnb-menu-font-weight: 700;
--hm-gnb-current-background: var(--hm-sem-bg-content);
--hm-gnb-current-text: var(--hm-sem-action-primary);
--hm-gnb-open-background: var(--hm-sem-bg-surface);
--hm-gnb-open-text: var(--hm-sem-action-primary);
/* 2-depth panel: parent width, White, items centered. Radius and shadow are review values in ui-viz. */
--hm-gnb-panel-background: var(--hm-sem-bg-surface);
--hm-gnb-panel-radius: 0 0 8px 8px;
--hm-gnb-panel-shadow: 0 6px 16px color-mix(in srgb, var(--hm-sem-palette-black) 10%, transparent);
--hm-gnb-panel-item-min-height: 56px;
--hm-gnb-panel-item-padding: 16px;
--hm-gnb-panel-item-font-size: 16px;
--hm-gnb-panel-item-line-height: 24px;
--hm-gnb-panel-item-text: var(--hm-sem-fg-primary);
--hm-gnb-panel-item-hover-background: var(--hm-sem-bg-content);
--hm-gnb-panel-item-hover-text: var(--hm-sem-action-primary);
/* Profile (Avatar default size + name and role; the text is hidden on the mobile bar, the Avatar stays). */
--hm-gnb-user-gap: 3px;
--hm-gnb-user-radius: var(--hm-radius-control-md);
--hm-gnb-user-name-size: 16px;
--hm-gnb-user-description-size: 12px;
--hm-gnb-user-text-max-width: 220px;
/* Mobile menu content (inside the HM Sheet, white face). */
--hm-gnb-mobile-link-height: 44px;
--hm-gnb-mobile-link-padding-x: 12px;
--hm-gnb-mobile-link-radius: var(--hm-radius-control-md);
--hm-gnb-mobile-link-font-size: 14px;
--hm-gnb-mobile-link-line-height: 20px;
--hm-gnb-mobile-link-font-weight: 500;
--hm-gnb-mobile-link-text: var(--hm-sem-fg-primary);
--hm-gnb-mobile-link-hover-background: var(--accent);
--hm-gnb-mobile-link-hover-text: var(--accent-foreground);
--hm-gnb-mobile-link-current-background: var(--hm-sem-bg-content);
--hm-gnb-mobile-link-current-text: var(--hm-sem-action-primary);
--hm-gnb-mobile-link-current-font-weight: 700;
--hm-gnb-mobile-group-label-color: var(--hm-sem-fg-secondary);
--hm-gnb-mobile-group-gap: 16px;
--hm-gnb-mobile-nested-gap: 8px;
--hm-gnb-mobile-nested-indent: var(--hm-gnb-mobile-link-padding-x);
--hm-gnb-mobile-focus-ring: 0 0 0 3px color-mix(in srgb, var(--ring) 50%, transparent);
}
/* ── Bar ─────────────────────────────────────────────────────────────────────────────────────── */
[data-slot="gnb"] {
position: relative;
box-sizing: border-box;
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, auto) minmax(0, 1fr);
column-gap: var(--hm-gnb-column-gap);
align-items: start;
width: 100%;
height: var(--hm-gnb-height);
padding: 0 var(--hm-gnb-padding-x);
background: var(--hm-gnb-background) left top / 100% calc(var(--hm-gnb-height) + var(--hm-gnb-join)) no-repeat;
color: var(--hm-gnb-text);
font-size: 16px;
}
/* Continue the gradient only outside the content's rounded top corners. A full strip would cover the content when the sticky
header creates a higher stacking context. Static and sticky share this geometry (Dashboard Layout contract). */
[data-slot="gnb"]::after {
content: "";
position: absolute;
top: 100%;
left: 0;
right: 0;
height: var(--hm-gnb-join);
background: var(--hm-gnb-background) 0 calc(-1 * var(--hm-gnb-height)) / 100% calc(var(--hm-gnb-height) + var(--hm-gnb-join)) no-repeat;
mask:
radial-gradient(circle at bottom right, transparent var(--hm-gnb-join), #000 var(--hm-gnb-join)) left top / var(--hm-gnb-join) 100% no-repeat,
radial-gradient(circle at bottom left, transparent var(--hm-gnb-join), #000 var(--hm-gnb-join)) right top / var(--hm-gnb-join) 100% no-repeat;
pointer-events: none;
}
[data-slot="gnb"][data-sticky] {
position: sticky;
top: 0;
z-index: var(--hm-gnb-z-index);
}
/* ── Brand: horizontal; logo (img / svg) only when supplied, then the name. Eyebrow + name are optional. ───────── */
[data-slot="gnb-brand"] {
grid-column: 1;
justify-self: start;
box-sizing: border-box;
min-width: 0;
max-width: 100%;
height: calc(var(--hm-gnb-height) - 2px);
padding-right: var(--hm-gnb-brand-padding-end);
gap: var(--hm-gnb-brand-gap);
color: var(--hm-gnb-text);
text-decoration: none;
outline: none;
}
[data-slot="gnb-brand"]:focus-visible {
outline: var(--hm-gnb-focus-outline);
outline-offset: -2px;
}
[data-slot="gnb-brand"] > :is(img, svg) {
flex: 0 1 auto;
min-width: 0;
width: auto;
height: auto;
max-width: 100%;
max-height: var(--hm-gnb-logo-max-height);
}
[data-slot="gnb-brand"] > span {
display: grid;
gap: var(--hm-gnb-brand-text-gap);
flex: 0 1 auto;
min-width: 0;
-webkit-text-stroke: var(--hm-gnb-text-stroke-width) var(--hm-gnb-text-stroke-color);
paint-order: stroke fill;
}
[data-slot="gnb-brand"] :is(small, strong) {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
[data-slot="gnb-brand"] small {
color: var(--hm-gnb-text-secondary);
font-size: var(--hm-gnb-brand-eyebrow-size);
font-weight: 700;
letter-spacing: var(--hm-gnb-brand-eyebrow-spacing);
line-height: 1.2;
}
[data-slot="gnb-brand"] strong {
font-size: var(--hm-gnb-brand-name-size);
font-weight: 700;
}
/* ── Primary navigation: centered on the whole bar by the equal side columns ────────────────────────────────── */
[data-slot="gnb"] [data-slot="gnb-nav"] {
grid-column: 2;
align-items: flex-start;
min-width: 0;
height: var(--hm-gnb-height);
/* `clip` (unlike `hidden`) leaves the vertical axis visible so the open panel below the bar is not cut; too-long labels are cut here. */
overflow-x: clip;
}
[data-slot="gnb"] [data-slot="gnb-nav"] [data-slot="navigation-menu"] {
flex: 0 1 auto;
align-items: flex-start;
height: 100%;
justify-content: center;
}
[data-slot="gnb"] [data-slot="gnb-nav"] [data-slot="navigation-menu-list"] {
align-items: flex-start;
justify-content: center;
gap: 0;
height: 100%;
padding-inline: var(--hm-gnb-menu-join);
}
[data-slot="gnb"] [data-slot="gnb-nav"] [data-slot="navigation-menu-item"] {
height: 100%;
}
[data-slot="gnb"] [data-slot="gnb-nav"] :is([data-slot="navigation-menu-trigger"], [data-slot="navigation-menu-link"]) {
position: relative;
justify-content: center;
gap: var(--hm-gnb-menu-gap);
min-width: var(--hm-gnb-menu-min-width);
height: calc(var(--hm-gnb-height) - var(--hm-gnb-menu-inset-top));
margin-top: var(--hm-gnb-menu-inset-top);
padding: 0 var(--hm-gnb-menu-padding-x);
border-radius: var(--hm-gnb-menu-radius);
background: transparent;
color: var(--hm-gnb-text);
font-size: var(--hm-gnb-menu-font-size);
font-weight: var(--hm-gnb-menu-font-weight);
white-space: nowrap;
box-shadow: none;
}
/* Arrow optical correction: (12px SVG box - 7px painted width) / 4 = 1.25px.
Keep the total padding, intrinsic trigger width, gap and icon margin unchanged. */
[data-slot="gnb"] [data-slot="gnb-nav"] [data-slot="navigation-menu-trigger"]:has(> [data-slot="navigation-menu-trigger-icon"]) {
padding-left: calc(var(--hm-gnb-menu-padding-x) + 1.25px);
padding-right: calc(var(--hm-gnb-menu-padding-x) - 1.25px);
}
/* Hover / focus (not the current item, not an open parent): Black 10% over the green. */
[data-slot="gnb"] [data-slot="gnb-nav"] :is([data-slot="navigation-menu-trigger"], [data-slot="navigation-menu-link"]):is(:hover, :focus-visible):not([data-active], [aria-current="page"], [data-state="open"]) {
background: var(--hm-gnb-hover-background);
color: var(--hm-gnb-text);
}
[data-slot="gnb"] [data-slot="gnb-nav"] :is([data-slot="navigation-menu-trigger"], [data-slot="navigation-menu-link"]):focus-visible {
outline: var(--hm-gnb-focus-outline);
outline-offset: -2px;
}
/* Current location: Beige face joined to the content below by two concave corners. Hover does not repaint it. Radix `active` on a
Link (`data-active`, `aria-current="page"`); a Trigger carries `aria-current="page"` from the consumer. */
[data-slot="gnb"] [data-slot="gnb-nav"] :is([data-slot="navigation-menu-trigger"], [data-slot="navigation-menu-link"]):is([data-active], [aria-current="page"]) {
z-index: 1;
background: var(--hm-gnb-current-background);
color: var(--hm-gnb-current-text);
}
[data-slot="gnb"] [data-slot="gnb-nav"] :is([data-slot="navigation-menu-trigger"], [data-slot="navigation-menu-link"]):is([data-active], [aria-current="page"]):focus-visible {
outline-color: var(--hm-gnb-current-text);
}
[data-slot="gnb"] [data-slot="gnb-nav"] :is([data-slot="navigation-menu-trigger"], [data-slot="navigation-menu-link"]):is([data-active], [aria-current="page"])::before,
[data-slot="gnb"] [data-slot="gnb-nav"] :is([data-slot="navigation-menu-trigger"], [data-slot="navigation-menu-link"]):is([data-active], [aria-current="page"])::after {
content: "";
position: absolute;
bottom: 0;
width: var(--hm-gnb-menu-join);
height: var(--hm-gnb-menu-join);
pointer-events: none;
}
[data-slot="gnb"] [data-slot="gnb-nav"] :is([data-slot="navigation-menu-trigger"], [data-slot="navigation-menu-link"]):is([data-active], [aria-current="page"])::before {
right: 100%;
background: radial-gradient(circle at top left, transparent calc(var(--hm-gnb-menu-join) - 0.5px), var(--hm-gnb-current-background) var(--hm-gnb-menu-join));
}
[data-slot="gnb"] [data-slot="gnb-nav"] :is([data-slot="navigation-menu-trigger"], [data-slot="navigation-menu-link"]):is([data-active], [aria-current="page"])::after {
left: 100%;
background: radial-gradient(circle at top right, transparent calc(var(--hm-gnb-menu-join) - 0.5px), var(--hm-gnb-current-background) var(--hm-gnb-menu-join));
}
/* Open parent: reuse the current concave joins with the panel's surface.
alignPanels supplies each side independently after viewport clamping. */
[data-slot="gnb"] [data-slot="gnb-nav"] [data-slot="navigation-menu-trigger"][data-state="open"] {
z-index: 3;
background: var(--hm-gnb-open-background);
color: var(--hm-gnb-open-text);
}
[data-slot="gnb"] [data-slot="gnb-nav"] [data-slot="navigation-menu-trigger"][data-state="open"]::before,
[data-slot="gnb"] [data-slot="gnb-nav"] [data-slot="navigation-menu-trigger"][data-state="open"]::after {
content: "";
display: block;
position: absolute;
bottom: 0;
height: var(--hm-gnb-menu-join);
pointer-events: none;
}
[data-slot="gnb"] [data-slot="gnb-nav"] [data-slot="navigation-menu-trigger"][data-state="open"]::before {
right: 100%;
width: min(var(--hm-gnb-panel-left-extension, 0px), var(--hm-gnb-menu-join));
background: radial-gradient(circle at top left, transparent calc(var(--hm-gnb-menu-join) - 0.5px), var(--hm-gnb-panel-background) var(--hm-gnb-menu-join)) right bottom / var(--hm-gnb-menu-join) var(--hm-gnb-menu-join) no-repeat;
}
[data-slot="gnb"] [data-slot="gnb-nav"] [data-slot="navigation-menu-trigger"][data-state="open"]::after {
left: 100%;
width: min(var(--hm-gnb-panel-right-extension, 0px), var(--hm-gnb-menu-join));
background: radial-gradient(circle at top right, transparent calc(var(--hm-gnb-menu-join) - 0.5px), var(--hm-gnb-panel-background) var(--hm-gnb-menu-join)) left bottom / var(--hm-gnb-menu-join) var(--hm-gnb-menu-join) no-repeat;
}
[data-slot="gnb"] [data-slot="gnb-nav"] [data-slot="navigation-menu-trigger"][data-state="open"]:focus-visible {
outline-color: var(--hm-gnb-open-text);
}
/* ── 2-depth panel (viewport={false}): under its own trigger, same width, White, centered items ─────────────── */
[data-slot="gnb"] [data-slot="gnb-nav"] [data-slot="navigation-menu-content"] {
position: absolute;
z-index: 2;
top: 100%;
left: 0;
box-sizing: border-box;
width: 100%;
min-width: 0;
margin: 0;
padding: 0;
border: 0;
border-radius: var(--hm-gnb-panel-radius);
background: var(--hm-gnb-panel-background);
color: var(--hm-gnb-panel-item-text);
box-shadow: var(--hm-gnb-panel-shadow);
}
[data-slot="gnb"] [data-slot="gnb-nav"] [data-slot="navigation-menu-content"] > ul {
display: grid;
width: auto;
margin: 0;
padding: 0;
gap: 0;
list-style: none;
}
[data-slot="gnb"] [data-slot="gnb-nav"] [data-slot="navigation-menu-content"] [data-slot="navigation-menu-link"] {
flex-direction: row;
justify-content: center;
align-items: center;
box-sizing: border-box;
width: 100%;
height: auto;
min-height: var(--hm-gnb-panel-item-min-height);
margin: 0;
padding: var(--hm-gnb-panel-item-padding);
border-radius: 0;
background: transparent;
color: var(--hm-gnb-panel-item-text);
font-size: var(--hm-gnb-panel-item-font-size);
line-height: var(--hm-gnb-panel-item-line-height);
font-weight: 700;
text-align: center;
white-space: normal;
word-break: keep-all;
overflow-wrap: anywhere;
}
[data-slot="gnb"] [data-slot="gnb-nav"] [data-slot="navigation-menu-content"] [data-slot="navigation-menu-link"]:is(:hover, :focus-visible, [data-active]) {
background: var(--hm-gnb-panel-item-hover-background);
color: var(--hm-gnb-panel-item-hover-text);
outline: none;
}
[data-slot="gnb"] [data-slot="gnb-nav"] [data-slot="navigation-menu-content"] [data-slot="navigation-menu-link"]:focus-visible {
outline: 2px solid var(--hm-gnb-panel-item-hover-text);
outline-offset: -2px;
}
/* ── Utilities and profile ──────────────────────────────────────────────────────────────────────────────── */
[data-slot="gnb-utilities"] {
grid-column: 3;
justify-self: end;
min-width: 0;
height: calc(var(--hm-gnb-height) - 2px);
gap: 4px;
}
/* Optional icon actions (search, notification...) are HM ghost Buttons; on the green bar they are white with the Black 10% hover. */
[data-slot="gnb-utilities"] [data-slot="button"][data-variant="ghost"] {
color: var(--hm-gnb-text);
}
[data-slot="gnb-utilities"] [data-slot="button"][data-variant="ghost"]:is(:hover, [aria-expanded="true"]) {
background: var(--hm-gnb-hover-background);
color: var(--hm-gnb-text);
}
[data-slot="gnb-utilities"] [data-slot="button"][data-variant="ghost"]:focus-visible {
border-color: transparent;
outline: var(--hm-gnb-focus-outline);
outline-offset: -2px;
box-shadow: none;
}
[data-slot="gnb-user"] {
box-sizing: border-box;
min-width: 0;
max-width: 100%;
padding: 0 8px;
gap: 10px;
border: 0;
border-radius: var(--hm-gnb-user-radius);
background: transparent;
color: var(--hm-gnb-text);
text-align: left;
cursor: pointer;
outline: none;
}
[data-slot="gnb-user"]:is(:hover, [data-state="open"]) {
background: var(--hm-gnb-hover-background);
}
[data-slot="gnb-user"]:focus-visible {
outline: var(--hm-gnb-focus-outline);
outline-offset: -2px;
}
[data-slot="gnb-user-text"] {
display: grid;
gap: var(--hm-gnb-user-gap);
min-width: 0;
max-width: var(--hm-gnb-user-text-max-width);
padding-block: 4px;
}
[data-slot="gnb-user-name"],
[data-slot="gnb-user-description"] {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
-webkit-text-stroke: var(--hm-gnb-text-stroke-width) var(--hm-gnb-text-stroke-color);
paint-order: stroke fill;
}
[data-slot="gnb-user-name"] {
font-size: var(--hm-gnb-user-name-size);
font-weight: 700;
}
[data-slot="gnb-user-description"] {
color: var(--hm-gnb-text-secondary);
font-size: var(--hm-gnb-user-description-size);
}
/* ── Mobile menu content (inside the HM Sheet): destinations as a plain link list ─────────────────────────── */
[data-slot="gnb-mobile-nav"] {
display: grid;
gap: var(--hm-gnb-mobile-group-gap);
padding-bottom: 16px;
}
[data-slot="gnb-mobile-group-label"] {
margin: 0;
padding: 0 var(--hm-gnb-mobile-link-padding-x) 4px;
color: var(--hm-gnb-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="gnb-mobile-group"] [data-slot="gnb-mobile-group"] {
margin-top: var(--hm-gnb-mobile-nested-gap);
padding-left: var(--hm-gnb-mobile-nested-indent);
}
[data-slot="gnb-mobile-link"] {
box-sizing: border-box;
min-height: var(--hm-gnb-mobile-link-height);
padding: 0 var(--hm-gnb-mobile-link-padding-x);
border-radius: var(--hm-gnb-mobile-link-radius);
color: var(--hm-gnb-mobile-link-text);
font-size: var(--hm-gnb-mobile-link-font-size);
line-height: var(--hm-gnb-mobile-link-line-height);
font-weight: var(--hm-gnb-mobile-link-font-weight);
text-decoration: none;
overflow-wrap: anywhere;
outline: none;
}
[data-slot="gnb-mobile-link"]:is(:hover, :focus-visible) {
background: var(--hm-gnb-mobile-link-hover-background);
color: var(--hm-gnb-mobile-link-hover-text);
}
[data-slot="gnb-mobile-link"]:focus-visible {
box-shadow: var(--hm-gnb-mobile-focus-ring);
}
[data-slot="gnb-mobile-link"][aria-current="page"] {
background: var(--hm-gnb-mobile-link-current-background);
color: var(--hm-gnb-mobile-link-current-text);
font-weight: var(--hm-gnb-mobile-link-current-font-weight);
}
/* Desktop panels grow to their longest label. The GNB region measures only the
viewport-edge correction; extreme labels scroll within the bounded panel. */
@media (min-width: 1024px) {
[data-slot="gnb"] [data-slot="gnb-nav"] {
overflow-x: visible;
}
[data-slot="gnb"] [data-slot="gnb-nav"] [data-slot="navigation-menu-content"] {
left: var(--hm-gnb-panel-offset-x, 0px);
width: max-content;
min-width: 100%;
max-width: calc(100vw - 2 * var(--hm-gnb-padding-x));
overflow-x: auto;
}
[data-slot="gnb"] [data-slot="gnb-nav"] [data-slot="navigation-menu-content"] > ul {
min-width: max-content;
}
[data-slot="gnb"] [data-slot="gnb-nav"] [data-slot="navigation-menu-content"] [data-slot="navigation-menu-link"] {
white-space: nowrap;
overflow-wrap: normal;
}
/* The concave current-page joins belong to 1Depth only, not panel rows. */
[data-slot="gnb"] [data-slot="gnb-nav"] [data-slot="navigation-menu-content"] [data-slot="navigation-menu-link"]::before,
[data-slot="gnb"] [data-slot="gnb-nav"] [data-slot="navigation-menu-content"] [data-slot="navigation-menu-link"]::after {
display: none;
}
}
/* ── Mobile bar: below 1024px (Tailwind `lg`). Menu → hamburger + Sheet; profile → Avatar only. Keep this block last. ──────── */
@media (max-width: 1023px) {
:root, [data-hm-theme] {
--hm-gnb-height: 56px;
--hm-gnb-padding-x: 16px;
}
[data-slot="gnb"] {
display: flex;
align-items: center;
gap: 8px;
}
[data-slot="gnb"] [data-slot="gnb-nav"] {
display: none;
}
[data-slot="gnb-brand"] {
flex: 0 1 auto;
height: auto;
padding-right: 0;
}
[data-slot="gnb-brand"] small {
display: none;
}
[data-slot="gnb-utilities"] {
flex: none;
height: auto;
margin-left: auto;
}
[data-slot="gnb-user"] {
padding: 0 4px;
}
[data-slot="gnb-user-text"] {
display: none;
}
/* The hamburger is a ghost Button: white on the green bar. */
[data-slot="gnb"] > [data-slot="button"][data-variant="ghost"] {
color: var(--hm-gnb-text);
}
[data-slot="gnb"] > [data-slot="button"][data-variant="ghost"]:is(:hover, [aria-expanded="true"]) {
background: var(--hm-gnb-hover-background);
color: var(--hm-gnb-text);
}
[data-slot="gnb"] > [data-slot="button"][data-variant="ghost"]:focus-visible {
border-color: transparent;
outline: var(--hm-gnb-focus-outline);
outline-offset: -2px;
box-shadow: none;
}
}
/* Opt-in GNB ONLY composition. Reuse LNB's DOM, tokens and responsive menu unchanged.
These layout hooks ship with @hm-design/ui/theme.css; no Story-only stylesheet is required.
The consumer provides the frame height and content padding. */
[data-hm-gnb-layout="sidebar"] {
display: grid;
grid-template-rows: auto minmax(0, 1fr);
min-width: 0;
min-height: 0;
}
[data-hm-gnb-layout="sidebar"] > [data-slot="gnb"] {
z-index: var(--hm-gnb-z-index);
}
[data-hm-gnb-layout="sidebar"] > [data-hm-gnb-body] {
position: relative;
display: grid;
grid-template-columns: var(--hm-lnb-width) minmax(0, 1fr);
min-width: 0;
min-height: 0;
background: var(--hm-sem-bg-content);
border-radius: var(--hm-gnb-join) var(--hm-gnb-join) 0 0;
}
[data-hm-gnb-layout="sidebar"] > [data-hm-gnb-body] > [data-slot="lnb"][data-hm-gnb-sidebar] {
--hm-gnb-content-menu-color: var(--hm-sem-action-primary);
--hm-lnb-background: var(--hm-sem-bg-content);
--hm-lnb-background-end: var(--hm-sem-bg-content);
--hm-lnb-text: var(--hm-gnb-content-menu-color);
--hm-lnb-text-secondary: var(--hm-gnb-content-menu-color);
--hm-lnb-item-text-stroke-width: 0px;
--hm-lnb-item-text-shadow: none;
--hm-lnb-hover-background: color-mix(in srgb, var(--hm-gnb-content-menu-color) 8%, transparent);
--hm-lnb-current-background: color-mix(in srgb, var(--hm-gnb-content-menu-color) 20%, transparent);
--hm-lnb-current-text: var(--hm-gnb-content-menu-color);
--hm-lnb-current-depth: none;
--hm-lnb-group-current-text: var(--hm-gnb-content-menu-color);
--hm-lnb-group-open-background: transparent;
--hm-lnb-group-open-line: 0;
--hm-lnb-focus-outline: 2px solid var(--hm-gnb-content-menu-color);
border-right: 1px solid var(--hm-sem-stroke-input-default);
}
[data-hm-gnb-layout="sidebar"][data-hm-color="brown"] > [data-hm-gnb-body] > [data-hm-gnb-sidebar] {
--hm-gnb-content-menu-color: var(--hm-sem-palette-brown-default);
}
/* Content navigation uses one straight divider, without the green LNB join. */
[data-hm-gnb-layout="sidebar"] [data-hm-gnb-sidebar]::after,
[data-hm-gnb-layout="sidebar"] [data-hm-gnb-sidebar] [data-slot="lnb-item"][aria-current="page"]::before,
[data-hm-gnb-layout="sidebar"] [data-hm-gnb-sidebar] [data-slot="lnb-item"][aria-current="page"]::after { content: none; }
[data-hm-gnb-layout="sidebar"] > [data-hm-gnb-body] > [data-hm-gnb-main] {
position: relative;
grid-column: 2;
min-width: 0;
min-height: 0;
overflow: auto;
background: var(--hm-sem-bg-content);
border-radius: 0 var(--hm-gnb-join) 0 0;
}
@media (max-width: 1023px) {
[data-hm-gnb-layout="sidebar"] > [data-hm-gnb-body] {
grid-template-columns: minmax(0, 1fr);
}
[data-hm-gnb-layout="sidebar"] > [data-hm-gnb-body] > [data-hm-gnb-main] {
grid-column: 1;
border-radius: var(--hm-gnb-join) var(--hm-gnb-join) 0 0;
}
}