docs(storybook): preview-first Expanded OrgChart and leaner Tabs / Button pages
Deploy Storybook / deploy (push) Successful in 54s
Deploy Storybook / deploy (push) Successful in 54s
- Expanded OrgChart: the chart moves right under the page title; data, layout and interaction settings stay below it. Setting notes, section descriptions, hidden legends and the Drag & Drop ON/OFF text are removed; the example counts stay only as a hidden data hook for the OrgChart browser checks, and the pending note shows only while the employee count differs. - Tabs: drop the text-only Do / Don't section (rules live in tabs.md §16). - Button: the representative page hides the Brand / Standard state notes (story-only showNote); the hidden States Stories keep them. - Report: the follow-up simplification and its verification.
This commit is contained in:
1 parent
c5c6fed38e
commit
4a54cfbeb2
5 files changed
+48
-53
No files matched your search
@@ -35,3 +35,10 @@
|
||||
- `packages/sw/tests/storybook-simplification.browser.mjs` 9/9 PASS
|
||||
- `examples/org-chart/verify-p9.mjs`: 변경 전 빌드로 만든 로컬 기준에 대해 변경 후 67 PASS / 17 FAIL입니다. 변경 전 빌드도 같은 17건이 FAIL이므로 기존 이슈입니다.
|
||||
- `packages/sw/tests/integrated-visual.browser.mjs` capture/compare: 숨김 검증 Story 6종(detail-buttons 등)은 동일합니다. 표시 Story(overview, logo-slot, responsive-more, property-panel-compare)의 차이는 모두 분류 라벨 제거에 따른 세로 이동(24px, Overview는 12px)이며 그 외 픽셀 차이는 없습니다. 시각 기준 이미지는 갱신하지 않았습니다.
|
||||
|
||||
## 추가 간소화 (da0e647 이후)
|
||||
|
||||
- **Expanded OrgChart (Preview first)**: 조직도 미리보기를 제목 바로 아래로 옮겼습니다. 1440 × 900에서 미리보기 시작 위치가 1103 → 177px입니다. 데이터·레이아웃·인터랙션 설정은 미리보기 아래에 그대로 둡니다. 설정 안내 문구(회사 숨김 동작, Hybrid/TB 조건, Compact 미지원, Pan·클릭 안내)와 섹션 설명은 제거했습니다. Pan·Alt+M 안내는 조직도 툴바가 이미 표시합니다. `OrgChartExampleCounts` 집계 문구는 화면에서 제거하고, OrgChart 브라우저 검증(P8, P9-2/3/4)이 읽는 `hidden` 데이터 hook으로만 남겼습니다. 숨김 legend 3개(데이터·레이아웃·기능 설정)와 Drag & Drop ON/OFF 글자도 제거했습니다. 적용 예정 상태는 직원 수를 바꾼 동안에만 표시합니다. 초기 보기는 기존 100% center를 유지하며 Fit to View로 전체를 볼 수 있습니다.
|
||||
- **Tabs → Do / Don't**: UI 예시 없이 문단만 있던 섹션을 제거했습니다. 규칙은 [Tabs §16](../components/tabs.md)에 있습니다.
|
||||
- **Button → States**: 대표 화면에서만 Brand / Standard 상태 설명 문단을 숨깁니다(Story 전용 `showNote`). 숨김 Story `States`·`StandardStates`는 문단을 유지하고, 규칙은 [Button](../components/button.md)과 UI AI 가이드에 있습니다. 모든 상태 버튼과 `Activated` 출력은 유지합니다.
|
||||
- 검증: tsc PASS, `test:guard` 94/94, `check:ai-docs` PASS, Story 359개 렌더·ID 동일, SW simplification 9/9. Expanded 설정 조작(직원 수·데이터 적용·LR 전환·Drag & Drop·초기화) 9/9. OrgChart P9(67/17)와 P9-2(2/4)는 da0e647 빌드와 같은 FAIL 목록이므로 기존 이슈입니다.
|
||||
@@ -118,7 +118,8 @@ function SizesBoard() {
|
||||
)
|
||||
}
|
||||
|
||||
function BrandStates() {
|
||||
// `showNote={false}` keeps the representative page UI-only; the verification Stories keep the state notes.
|
||||
function BrandStates({ showNote = true }: { showNote?: boolean }) {
|
||||
const [count, setCount] = useState(0)
|
||||
return (
|
||||
<div className={stack}>
|
||||
@@ -132,9 +133,11 @@ function BrandStates() {
|
||||
</Button>
|
||||
</div>
|
||||
<output aria-live="polite">Activated: {count}</output>
|
||||
<p className={note}>
|
||||
Hover와 Pressed는 Storybook이 고정한 상태입니다. Interact 위에서 실제 Hover·Pressed·포인터 이탈을 확인합니다. Disabled는 실행되지 않습니다.
|
||||
</p>
|
||||
{showNote ? (
|
||||
<p className={note}>
|
||||
Hover와 Pressed는 Storybook이 고정한 상태입니다. Interact 위에서 실제 Hover·Pressed·포인터 이탈을 확인합니다. Disabled는 실행되지 않습니다.
|
||||
</p>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -182,14 +185,16 @@ function StandardStateTable({ appearance, title }: { appearance: "solid" | "outl
|
||||
)
|
||||
}
|
||||
|
||||
function StandardStatesBoard() {
|
||||
function StandardStatesBoard({ showNote = true }: { showNote?: boolean }) {
|
||||
return (
|
||||
<div className={stack}>
|
||||
<StandardStateTable appearance="solid" title="Standard Solid" />
|
||||
<StandardStateTable appearance="outline" title="Standard Outline" />
|
||||
<p className={note}>
|
||||
Standard Solid의 Hover·Pressed는 역할 면 위에 Black 20%를 합성합니다(Pressed = Hover). Green·Brown Outline은 Hover에서 역할색 면 + White 라벨, Pressed에서 White 면 + Black 20%입니다. Red Outline은 Hover·Pressed 모두 Red 8% 면이며 Red 라벨·보더를 유지합니다. Disabled는 Default 모양 그대로 opacity 60%이고 상태 면을 적용하지 않습니다. Default 열의 버튼으로 실제 포인터 상태도 확인할 수 있습니다. Brand 상태는 Brand States에서 확인합니다.
|
||||
</p>
|
||||
{showNote ? (
|
||||
<p className={note}>
|
||||
Standard Solid의 Hover·Pressed는 역할 면 위에 Black 20%를 합성합니다(Pressed = Hover). Green·Brown Outline은 Hover에서 역할색 면 + White 라벨, Pressed에서 White 면 + Black 20%입니다. Red Outline은 Hover·Pressed 모두 Red 8% 면이며 Red 라벨·보더를 유지합니다. Disabled는 Default 모양 그대로 opacity 60%이고 상태 면을 적용하지 않습니다. Default 열의 버튼으로 실제 포인터 상태도 확인할 수 있습니다. Brand 상태는 Brand States에서 확인합니다.
|
||||
</p>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -236,8 +241,8 @@ export const All: Story = {
|
||||
<StateBoard
|
||||
min={1200}
|
||||
states={[
|
||||
{ id: "brand-states", label: "Brand", children: <BrandStates /> },
|
||||
{ id: "standard-states", label: "Standard Solid · Standard Outline", children: <StandardStatesBoard /> },
|
||||
{ id: "brand-states", label: "Brand", children: <BrandStates showNote={false} /> },
|
||||
{ id: "standard-states", label: "Standard Solid · Standard Outline", children: <StandardStatesBoard showNote={false} /> },
|
||||
]}
|
||||
/>
|
||||
</StorySection>
|
||||
|
||||
@@ -185,9 +185,6 @@ export const All: Story = {
|
||||
{ id: "usage-page", label: "페이지 직접 배치 · Primary", noteAfter: true, note: "Layout content 배경 사용 · 추가 흰색 박스 없음", children: <SurfaceUsage /> },
|
||||
]} />
|
||||
</StorySection>
|
||||
<StorySection title="Do / Don't" description="Card Token을 화면 전체 간격에 쓰지 않음">
|
||||
<p className="text-sm text-muted-foreground">Do: Card 또는 Layout이 외곽 여백을 소유하고 내부 Input·Table·Alert의 고유 스타일을 유지합니다. Don't: 패널 박스 제거를 모든 border 제거로 해석하거나, 그라데이션 alpha 조정을 탭 전체 opacity 변경으로 구현하지 않습니다. 실제 패널 계산값·키보드 동작·모바일 넘침을 확인합니다.</p>
|
||||
</StorySection>
|
||||
</StoryPage>
|
||||
),
|
||||
}
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
--hm-orgchart-expanded-preview-radius: var(--sb-center-card-radius);
|
||||
padding: 0;
|
||||
}
|
||||
/* Preview first: the chart follows the page header with the header's own 24px rhythm. */
|
||||
.hm-orgchart-story-expanded .hm-orgchart-story-lead {
|
||||
display: grid;
|
||||
gap: 0.75rem;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.hm-orgchart-story-expanded .hm-orgchart-story-settings {
|
||||
display: grid;
|
||||
@@ -16,18 +22,6 @@
|
||||
border: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
/* StorySection supplies the visible heading; keep each fieldset named for assistive technology. */
|
||||
.hm-orgchart-story-expanded .hm-orgchart-story-section-legend {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
}
|
||||
.hm-orgchart-story-expanded .hm-orgchart-story-controls {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
@@ -116,9 +116,15 @@ function ExpandedPreview() {
|
||||
title="Expanded OrgChart"
|
||||
description="모든 직원은 가상 데이터"
|
||||
/>
|
||||
<StorySection title="데이터 설정" description="직원 수 변경은 데이터 적용으로 반영">
|
||||
{/* Preview first: the chart sits right under the page title; its own header already names it, so no section header. */}
|
||||
<div className="hm-orgchart-story hm-orgchart-story-lead">
|
||||
{error ? <p role="alert" className="hm-orgchart-story-note">{error}</p> : null}
|
||||
<div className="hm-orgchart-story-preview sb-center">
|
||||
<OrgChart dataSource={source} stylesheetUrls={compositionStylesheets} displayMode="readOnly" layoutMode="auto" autoLayout={layout} interactions={interactions} dragDropEnabled={dragDropEnabled} selectedCompanyIds={applied.companyIds} companyTopNodes={topNodes} employeePopup={popup} className="hm-orgchart-story-chart" onMove={result => { if (result.moved) setSession({ baseline: dataset, current: result.data }); }} onLifecycleError={cause => setError(cause instanceof Error ? cause.message : '조직도 설정을 적용할 수 없습니다.')} onStateChange={state => { if (state.status === 'error') setError(state.issues.map(issue => issue.message).join(' / ')); }} />
|
||||
</div>
|
||||
</div>
|
||||
<StorySection title="데이터 설정">
|
||||
<fieldset className="hm-orgchart-story-settings">
|
||||
<legend className="hm-orgchart-story-section-legend">데이터 설정</legend>
|
||||
<FilterBar layout="list-extended">
|
||||
<div className="hm-orgchart-story-instance">
|
||||
<Label id={`${id}-companies-label`} htmlFor={`${id}-companies`}>회사 선택</Label>
|
||||
@@ -160,15 +166,19 @@ function ExpandedPreview() {
|
||||
<Button variant="cancel" appearance="outline" onClick={() => { setError(null); setDraft(initialSettings); setApplied(initialSettings); setDataRevision(current => current + 1); }}>초기화</Button>
|
||||
</FilterBarActions>
|
||||
</FilterBar>
|
||||
{/* Not shown: kept only as the data hook that the OrgChart browser checks (P8, P9-2/3/4) read. */}
|
||||
<p hidden data-component="OrgChartExampleCounts">
|
||||
표시 중: {applied.companyIds.length}개 회사 · 현재 소속 기준 직원 합계 {displayedTotal.toLocaleString('ko-KR')}명 / 전체 {sessionTotal.toLocaleString('ko-KR')}명
|
||||
{companyCountSummary ? ` · ${companyCountSummary}` : ''}
|
||||
</p>
|
||||
{/* Live feedback only while the employee count differs from the applied data. */}
|
||||
<p className="hm-orgchart-story-note" role="status" aria-live="polite">
|
||||
{pending ? '적용 예정' : '예시 생성 기준'}: {draft.companyIds.length}개 회사 · 회사당 {draft.employeeCount}명 · 총 {predicted.toLocaleString('ko-KR')}명{pending ? ' · 데이터 적용을 눌러 반영하세요.' : ''}
|
||||
{pending ? `적용 예정: ${draft.companyIds.length}개 회사 · 회사당 ${draft.employeeCount}명 · 총 ${predicted.toLocaleString('ko-KR')}명 · 데이터 적용을 눌러 반영하세요.` : ''}
|
||||
</p>
|
||||
<p className="hm-orgchart-story-note">회사 숨김·다시 표시는 현재 소속 변경을 유지합니다. 데이터 적용은 선택한 조건의 예시를 새로 만들고, 초기화는 최초 데이터 설정과 소속으로 돌아갑니다.</p>
|
||||
</fieldset>
|
||||
</StorySection>
|
||||
<StorySection title="레이아웃 설정" description="표시 유형 · 초기 Depth">
|
||||
<StorySection title="레이아웃 설정">
|
||||
<fieldset className="hm-orgchart-story-settings">
|
||||
<legend className="hm-orgchart-story-section-legend">레이아웃 설정</legend>
|
||||
<div className="hm-orgchart-story-controls">
|
||||
<div className="hm-orgchart-story-instance">
|
||||
<Label id={`${id}-layout-label`} htmlFor={`${id}-layout`}>조직도 표시 유형</Label>
|
||||
@@ -180,18 +190,16 @@ function ExpandedPreview() {
|
||||
<div className="hm-orgchart-story-instance">
|
||||
<Label id={`${id}-hybrid-label`} htmlFor={`${id}-hybrid`}>혼합형 시작 Depth</Label>
|
||||
<Select value={String(layout.hybridStartDepth)} disabled={layout.type !== 'hybrid'} onValueChange={value => setLayout(current => ({ ...current, hybridStartDepth: Number(value) as 2 | 3 | 4 }))}>
|
||||
<SelectTrigger id={`${id}-hybrid`} aria-labelledby={`${id}-hybrid-label`} aria-describedby={`${id}-hybrid-help`} size="medium"><SelectValue /></SelectTrigger>
|
||||
<SelectTrigger id={`${id}-hybrid`} aria-labelledby={`${id}-hybrid-label`} size="medium"><SelectValue /></SelectTrigger>
|
||||
<SelectContent>{[2, 3, 4].map(depth => <SelectItem key={depth} value={String(depth)}>Depth {depth}부터 세로 배치</SelectItem>)}</SelectContent>
|
||||
</Select>
|
||||
<span id={`${id}-hybrid-help`} className="hm-orgchart-story-note">Hybrid에만 적용합니다.</span>
|
||||
</div>
|
||||
<div className="hm-orgchart-story-instance">
|
||||
<Label id={`${id}-group-hybrid-label`} htmlFor={`${id}-group-hybrid`}>특정 그룹 세로 배치</Label>
|
||||
<Select value={layout.hybridOrganizationIds?.[0] ?? 'none'} disabled={layout.type !== 'tb' || !applied.companyIds.length} onValueChange={value => setLayout(current => ({ ...current, hybridOrganizationIds: value === 'none' ? [] : [value] }))}>
|
||||
<SelectTrigger id={`${id}-group-hybrid`} aria-labelledby={`${id}-group-hybrid-label`} aria-describedby={`${id}-group-hybrid-help`} size="medium"><SelectValue /></SelectTrigger>
|
||||
<SelectTrigger id={`${id}-group-hybrid`} aria-labelledby={`${id}-group-hybrid-label`} size="medium"><SelectValue /></SelectTrigger>
|
||||
<SelectContent><SelectItem value="none">사용 안 함</SelectItem>{groupChoices.map(organization => <SelectItem key={organization.id} value={organization.id}>{organization.name}</SelectItem>)}</SelectContent>
|
||||
</Select>
|
||||
<span id={`${id}-group-hybrid-help`} className="hm-orgchart-story-note">TB에서 선택한 그룹 아래만 적용합니다. LR·Hybrid 전환 시 해제됩니다.</span>
|
||||
</div>
|
||||
<div className="hm-orgchart-story-instance">
|
||||
<Label id={`${id}-depth-label`} htmlFor={`${id}-depth`}>초기 표시 Depth</Label>
|
||||
@@ -201,17 +209,14 @@ function ExpandedPreview() {
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
<p className="hm-orgchart-story-note">Compact: 미지원. 기존 직원 카드 디자인을 보존하며, 압축 배치 선택은 제공하지 않습니다.</p>
|
||||
</fieldset>
|
||||
</StorySection>
|
||||
<StorySection title="인터랙션·직원 정보" description="Drag & Drop · 탐색 · 팝업 방식">
|
||||
<StorySection title="인터랙션·직원 정보">
|
||||
<div className="hm-orgchart-story-settings">
|
||||
<fieldset className="hm-orgchart-story-companies">
|
||||
<legend>독립 기능 설정 · 모든 표시 유형에서 개별 선택</legend>
|
||||
<div className="hm-orgchart-story-company">
|
||||
<Switch id={`${id}-drag-drop`} checked={dragDropEnabled} onCheckedChange={setDragDropEnabled} aria-describedby={`${id}-drag-drop-state`} />
|
||||
<Switch id={`${id}-drag-drop`} checked={dragDropEnabled} onCheckedChange={setDragDropEnabled} />
|
||||
<Label htmlFor={`${id}-drag-drop`}>Drag & Drop</Label>
|
||||
<span id={`${id}-drag-drop-state`}>{dragDropEnabled ? 'ON' : 'OFF'}</span>
|
||||
</div>
|
||||
{([
|
||||
['collapse', '접기·펼치기 사용'], ['zoom', 'Zoom 사용'], ['pan', 'Pan 사용'],
|
||||
@@ -231,19 +236,6 @@ function ExpandedPreview() {
|
||||
</div>
|
||||
</div>
|
||||
</StorySection>
|
||||
<StorySection title="조직도 미리보기" description="직원 카드를 눌러 정보 확인">
|
||||
<div className="hm-orgchart-story">
|
||||
<p className="hm-orgchart-story-note">빈 공간 드래그는 Pan입니다. {dragDropEnabled ? '직원 카드·그룹 타이틀 드래그로 회사 안팎의 소속을 변경합니다. 키보드: Alt+M → 방향키 → Enter / ESC 취소.' : '소속 변경은 Drag & Drop을 ON으로 설정하면 사용할 수 있습니다.'} 클릭은 직원 정보·그룹 접기입니다.</p>
|
||||
<p className="hm-orgchart-story-note" data-component="OrgChartExampleCounts" aria-live="polite">
|
||||
표시 중: {applied.companyIds.length}개 회사 · 현재 소속 기준 직원 합계 {displayedTotal.toLocaleString('ko-KR')}명 / 전체 {sessionTotal.toLocaleString('ko-KR')}명
|
||||
{companyCountSummary ? ` · ${companyCountSummary}` : ''}
|
||||
</p>
|
||||
{error ? <p role="alert" className="hm-orgchart-story-note">{error}</p> : null}
|
||||
<div className="hm-orgchart-story-preview sb-center">
|
||||
<OrgChart dataSource={source} stylesheetUrls={compositionStylesheets} displayMode="readOnly" layoutMode="auto" autoLayout={layout} interactions={interactions} dragDropEnabled={dragDropEnabled} selectedCompanyIds={applied.companyIds} companyTopNodes={topNodes} employeePopup={popup} className="hm-orgchart-story-chart" onMove={result => { if (result.moved) setSession({ baseline: dataset, current: result.data }); }} onLifecycleError={cause => setError(cause instanceof Error ? cause.message : '조직도 설정을 적용할 수 없습니다.')} onStateChange={state => { if (state.status === 'error') setError(state.issues.map(issue => issue.message).join(' / ')); }} />
|
||||
</div>
|
||||
</div>
|
||||
</StorySection>
|
||||
</StoryPage>;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user