Merge fix/sw-viewer-strip-round: rounded viewer menu surface end and solid viewer background

This commit is contained in:
shkim4 committed 2026-10-21 19:02:13 +09:00
commit 6b6f17c1a9
3 files changed
+32 -3

No files matched your search

+1 -1
View File
@@ -141,7 +141,7 @@
| 영역 | 토큰 = 기본값 |
|---|---|
| Header | `--hm-sw-viewer-height` 52px, `--hm-sw-viewer-background` `linear-gradient(180deg, #266651 0%, #123328 45%, #0a221d 100%)`, `--hm-sw-viewer-border-color` #071e18, `--hm-sw-viewer-text` #fff, `--hm-sw-viewer-muted` #bddfd4, `--hm-sw-viewer-accent` #ffc600, `--hm-sw-viewer-hover` #266651 |
| Header | `--hm-sw-viewer-height` 52px, `--hm-sw-viewer-background` #0a0a0b(단색, 2026-10-21 — Storybook 뷰어 캔버스 바탕색), `--hm-sw-viewer-border-color` #071e18, `--hm-sw-viewer-text` #fff, `--hm-sw-viewer-muted` #bddfd4, `--hm-sw-viewer-accent` #ffc600, `--hm-sw-viewer-hover` #266651 |
| 로고 면 | `--hm-sw-viewer-brand-width` 72px, `--hm-sw-viewer-brand-empty-width` 24px(로고 없음), `--hm-sw-viewer-brand-top` #123328, `--hm-sw-viewer-brand-middle` #205241, `--hm-sw-viewer-brand-bottom` #071e18 |
| 크기·글자 | `--hm-sw-viewer-gap` 4px, `--hm-sw-viewer-radius` 4px, `--hm-sw-viewer-control-height` 40px, `--hm-sw-viewer-button-height` 34px, `--hm-sw-viewer-font-size` 14px, `--hm-sw-viewer-label-size` 11px, `--hm-sw-viewer-icon-size` 16px, `--hm-sw-viewer-disabled-opacity` 0.6 |
| Header 스위치·아이콘 | `--hm-sw-viewer-switch-off` #0a221d, `--hm-sw-viewer-switch-bevel` `inset 0 1px 0 rgba(255, 255, 255, 0.1), inset 0 -1px 1px rgba(0, 0, 0, 0.25)`, `--hm-sw-viewer-icon-outline-color` = `var(--hm-sw-header-text-outline-color)`, `--hm-sw-viewer-icon-outline-width` 1px |
+1 -1
View File
@@ -40,7 +40,7 @@
| `onDocumentOpen?()`, `documentOpenLabel?` | 로고 오른쪽 파일 열기 버튼(`SWHeader` `documentOpenPlacement="header"`와 같은 파일명 면 `SWToolButton appearance="document"` + 폴더 아이콘(다른 Header 아이콘과 같은 검정 외곽선 `SWViewerIcon`, 테두리·면 없음) + `documentOpenLabel`, 기본 `Open`). 공간이 부족하면 아이콘만(라벨은 Tooltip·접근성 이름) 표시하고 More로 옮기지 않습니다. 실행 후 `onCommand({ id: "open", itemId: "document" })` |
| `logoMenu?: { title?, items }` | (2026-10-21 이후 뷰어 화면에서 사용하지 않음, 호환용) 로고 클릭 메뉴. 파일 열기는 `onDocumentOpen` 버튼을 씁니다. 항목 `{ id, label, icon?, value?, checked?, disabled?, hidden?, onSelect? }` |
| `logo?`, `logoSrc?`, `logoAlt?`, `onHomeClick?` | `SWHeader`와 같은 로고 Props. **주지 않으면 아무것도 그리지 않습니다**(“HM” 문자·기본 아이콘 없음, 로고 면은 사선 끝 24px만). 주면 72px 면(로고가 더 넓으면 그만큼), 높이 최대 24px |
| `trailing?: ReactNode` | 오른쪽 끝 자유 영역: `SWViewerStatus`, `SWViewerHeaderButton`, 창 최소화·닫기 버전이면 맨 끝에 `SWHeaderWindowControls`(§2.1). 이 세 부품은 `SWHeader` 창 영역처럼 전체 높이(48px)의 칸이 이어진 띠로 그려집니다: 같은 면, 칸 앞 1px 구분선(라이선스 버튼 앞뒤에는 없음), 위·아래 경계는 객체 면 테두리 하나라 모든 칸의 위·아래가 같음, 칸 사이 여백 없음, 객체 면 오른쪽 끝까지(2026-10-21). 상태 칸은 표시 전용, 아이콘 버튼(정보·라이선스) 칸은 테두리·선 없음 |
| `trailing?: ReactNode` | 오른쪽 끝 자유 영역: `SWViewerStatus`, `SWViewerHeaderButton`, 창 최소화·닫기 버전이면 맨 끝에 `SWHeaderWindowControls`(§2.1). 이 세 부품은 `SWHeader` 창 영역처럼 전체 높이(48px)의 칸이 이어진 띠로 그려집니다: 같은 면, 칸 앞 1px 구분선(라이선스 버튼 앞뒤에는 없음), 위·아래 경계는 객체 면 테두리 하나라 모든 칸의 위·아래가 같음, 칸 사이 여백 없음, 객체 면 오른쪽 끝까지(2026-10-21). 메뉴 면은 띠 앞에서 `SWHeader` 객체 영역처럼 오른쪽 라운드(`--hm-sw-header-object-radius` 6px, 같은 면·테두리)로 끝나고 2px 간격 뒤에 띠가 옵니다. 상태 칸은 표시 전용, 아이콘 버튼(정보·라이선스) 칸은 테두리·선 없음 |
| `moreLabel?`, `toolbarLabel?`, `<header>` 속성, `ref` | |
- **반응형(2026-10-21, 실제 가용 폭 기준 3단계):** 고정 Breakpoint를 쓰지 않고 Header 행의 실제 남는 폭(로고·파일명·메뉴·Gap·Padding·More 버튼 포함)을 측정합니다. 파일명 면은 글자 수가 아니라 Header 폭으로 정한 기본 폭으로 계산하므로, 같은 폭에서는 짧은 파일명과 긴 파일명의 단계·파일 열기 버튼·파일명 면 너비가 같고 긴 이름은 `…`입니다(2026-10-21). ① 모두 들어가면 기본 형태(아이콘+텍스트), ② 부족하면 `icon`과 `iconOnlyBelow`가 있는 항목을 모두 아이콘만(라벨은 Tooltip·접근성 이름), ③ 그래도 부족하면 `collapseBelow` 항목을 하나씩 More(⋯, 베이지 260px Dropdown)로 옮깁니다(값이 큰 것부터, 같으면 오른쪽 먼저). 넓어지면 More → 아이콘 → 기본 순서로 복귀하고, 상단과 More에 같은 항목이 동시에 나오지 않습니다. `collapseBelow`·`iconOnlyBelow`의 숫자는 px Breakpoint가 아니며 순서만 정합니다(`iconOnlyBelow`는 지정 여부만, `collapseBelow`는 값이 큰 것부터; Props 형식 동일). 로고 옆 파일 열기 버튼(`onDocumentOpen`)은 ② 단계에서 아이콘만으로 줄고 More로 옮기지 않으며, 샘플은 `documents`. 레이어·설정·속성은 `collapseBelow` 없이 아이콘까지만. 1180px 미만 간격 2px, 560px 미만 상태 글자 숨김(CSS container)은 그대로입니다. 가로 스크롤은 만들지 않습니다.
+30 -1
View File
@@ -6,7 +6,8 @@
:is(.hm-sw-header, .hm-sw-theme):not(:where(.hm-sw-header, .hm-sw-theme) *) {
/* Header */
--hm-sw-viewer-height: 52px;
--hm-sw-viewer-background: linear-gradient(180deg, #266651 0%, #123328 45%, #0a221d 100%);
/* 2026-10-21 user request: the solid color of the Storybook viewer canvas (--sw-story-canvas base #0a0a0b), no gradient. */
--hm-sw-viewer-background: #0a0a0b;
--hm-sw-viewer-border-color: #071e18;
--hm-sw-viewer-brand-width: 72px;
/* No logo: no text or icon is drawn; the cap keeps only its slanted edge (no wide empty space). */
@@ -418,6 +419,33 @@ button.hm-sw-viewer-header__brand { text-align: left; }
/* No line at all on the button (2026-10-21 final): same 48px box and edges as minimize / close, the strip face only. */
box-shadow: none;
}
/* Rounded end of the menu surface before the strip (2026-10-21 user request, as SWHeader: object area radius 6px,
2px header gap, then the window area). The first strip segment paints, just left of itself and over the object
border band, the header background (gap + the corners outside the radius) and on top the surface end: the same
object face (a vertical gradient, so the copy lines up) and border with the right radius. The 8px it covers are
the empty group padding + gap; below 1180px (2px each) the segment keeps 4px more room. Heights are unchanged. */
.hm-sw-viewer-header .hm-sw-viewer-header__actions > :is(.hm-sw-viewer-status, .hm-sw-viewer-header__button, .hm-sw-header__window-buttons):not(:is(.hm-sw-viewer-status, .hm-sw-viewer-header__button, .hm-sw-header__window-buttons) + *) { position: relative; }
.hm-sw-viewer-header .hm-sw-viewer-header__actions > :is(.hm-sw-viewer-status, .hm-sw-viewer-header__button, .hm-sw-header__window-buttons):not(:is(.hm-sw-viewer-status, .hm-sw-viewer-header__button, .hm-sw-header__window-buttons) + *)::before,
.hm-sw-viewer-header .hm-sw-viewer-header__actions > :is(.hm-sw-viewer-status, .hm-sw-viewer-header__button, .hm-sw-header__window-buttons):not(:is(.hm-sw-viewer-status, .hm-sw-viewer-header__button, .hm-sw-header__window-buttons) + *)::after {
content: "";
position: absolute;
top: calc(-1 * var(--hm-sw-header-object-border-width, 1px));
bottom: calc(-1 * var(--hm-sw-header-object-border-width, 1px));
left: calc(-1 * (var(--hm-sw-header-object-radius) + 2px));
pointer-events: none;
}
.hm-sw-viewer-header .hm-sw-viewer-header__actions > :is(.hm-sw-viewer-status, .hm-sw-viewer-header__button, .hm-sw-header__window-buttons):not(:is(.hm-sw-viewer-status, .hm-sw-viewer-header__button, .hm-sw-header__window-buttons) + *)::before {
width: calc(var(--hm-sw-header-object-radius) + 2px);
background: var(--hm-sw-viewer-background);
}
.hm-sw-viewer-header .hm-sw-viewer-header__actions > :is(.hm-sw-viewer-status, .hm-sw-viewer-header__button, .hm-sw-header__window-buttons):not(:is(.hm-sw-viewer-status, .hm-sw-viewer-header__button, .hm-sw-header__window-buttons) + *)::after {
box-sizing: border-box;
width: var(--hm-sw-header-object-radius);
border: 1px solid var(--hm-sw-header-object-border-color);
border-left: 0;
border-radius: 0 var(--hm-sw-header-object-radius) var(--hm-sw-header-object-radius) 0;
background: var(--hm-sw-header-object-background);
}
/* No line around the license / info button: the window buttons right after it drop their line before it. */
.hm-sw-viewer-header .hm-sw-viewer-header__actions > .hm-sw-viewer-header__button + .hm-sw-header__window-buttons { box-shadow: none; }
@@ -428,6 +456,7 @@ button.hm-sw-viewer-header__brand { text-align: left; }
.hm-sw-viewer-header__actions { padding-left: 2px; gap: 2px; }
.hm-sw-viewer-status { padding-inline: 2px; }
.hm-sw-viewer-header__actions > .hm-sw-viewer-status { padding-inline: 8px; }
.hm-sw-viewer-header .hm-sw-viewer-header__actions > :is(.hm-sw-viewer-status, .hm-sw-viewer-header__button, .hm-sw-header__window-buttons):not(:is(.hm-sw-viewer-status, .hm-sw-viewer-header__button, .hm-sw-header__window-buttons) + *) { margin-left: 4px; }
.hm-sw-viewer-header__actions > :is(.hm-sw-viewer-status, .hm-sw-viewer-header__button, .hm-sw-header__window-buttons) + :is(.hm-sw-viewer-status, .hm-sw-viewer-header__button, .hm-sw-header__window-buttons) { margin-left: -2px; }
}
@container hm-sw-viewer (max-width: 559.98px) {