fix(org-chart): complete department color previews and overview cleanup

This commit is contained in:
shkim4 committed 2026-10-13 14:50:26 +09:00
1 parent d0828a7ff4
commit 5acaf8a295
3 files changed
+45 -7

No files matched your search

+36 -5
View File
@@ -18,11 +18,11 @@ import { createDepartmentColors, updateDepartmentColorValues } from '../../packa
import fixture from '../../examples/org-chart/data-p1.json';
type PreviewKind = 'Logo' | 'DepartmentColors' | 'PositionSummary' | 'AffiliationSummary' | 'StatusSummary' | 'EmployeeCard' | 'OrganizationCards';
interface Props { kind: PreviewKind; data?: unknown; variant?: number; cardKind?: EmployeeCardOptions['kind']; presentation?: 'standalone' | 'workdesk' | 'design' }
interface Props { kind: PreviewKind; data?: unknown; variant?: number; cardKind?: EmployeeCardOptions['kind']; presentation?: 'standalone' | 'workdesk' | 'design'; hideLogoHeading?: boolean }
/** Story host only. Every pixel/card/count is rendered by the same Core modules
* used by Vanilla HTML and the production React Wrapper, not JSX copies. */
export function CoreComponentPreview({ kind, data = fixture, variant = 0, cardKind = 'employee', presentation = 'standalone' }: Props) {
export function CoreComponentPreview({ kind, data = fixture, variant = 0, cardKind = 'employee', presentation = 'standalone', hideLogoHeading = false }: Props) {
const ref = useRef<HTMLDivElement>(null);
useLayoutEffect(() => {
const validation = validateOrgChartDataset(data);
@@ -54,7 +54,11 @@ export function CoreComponentPreview({ kind, data = fixture, variant = 0, cardKi
// Share Fixed's passive presenters/styles without its stage coordinates.
shell.className = presentation === 'workdesk' ? 'hm-orgchart-shell hm-orgchart-summary-preview' : 'hm-orgchart-shell';
let component: HTMLElement;
if (kind === 'Logo') component = createLogoLegend(document, context, controller.signal);
if (kind === 'Logo') {
component = createLogoLegend(document, context, controller.signal);
// Overview already supplies the section heading; keep the shared logo list intact.
if (hideLogoHeading) component.querySelector(':scope > h2')?.remove();
}
else if (kind === 'DepartmentColors') component = createDepartmentColors(document, context, controller.signal);
else if (kind === 'PositionSummary') component = presentation === 'workdesk' ? createOrganizationTotals(document, context) : createPositionSummary(document, context);
else if (kind === 'AffiliationSummary') component = presentation === 'workdesk' ? createAffiliationBar(document, context, controller.signal) : createAffiliationSummary(document, context);
@@ -108,7 +112,34 @@ export function CoreComponentPreview({ kind, data = fixture, variant = 0, cardKi
row.classList.add('tunnel-reference__sample');
row.replaceChildren(header, stage);
}
component.replaceChildren(...(representative ? [representative] : []), ...rows);
// Reuse Fixed's compact status presenter, retaining its card ancestry/styles.
// One specimen per status is enough; the original fixture remains untouched.
const employees = ['dispatched', 'onLeave'].flatMap(status => {
const employee = dataset.employees.find(person => person.workStatus === status);
return employee ? [employee] : [];
});
const statusData = { ...dataset, employees };
const statuses = createStatusSummary(document, {
...context, data: statusData, summary: calculateSummary(statusData), readOnly: true,
}, controller.signal, { compact: true });
const statusPreviews = Array.from(statuses.querySelectorAll<HTMLElement>(':scope > .hm-orgchart-status-group')).map(group => {
const preview = document.createElement('section');
preview.className = 'hm-orgchart-status-preview tunnel-reference__sample';
const header = document.createElement('header');
const title = document.createElement('h2');
title.textContent = group.dataset.workStatus === 'dispatched' ? '파견자 카드' : '휴직자 카드';
header.append(title);
const stage = document.createElement('div');
stage.className = 'tunnel-reference__stage hm-orgchart-department-stage';
const composition = document.createElement('div');
composition.className = 'hm-orgchart-composition hm-orgchart-status-preview-composition';
composition.dataset.displayMode = 'readOnly';
const summary = statuses.cloneNode(false) as HTMLElement;
summary.append(group); composition.append(summary); stage.append(composition);
preview.append(header, stage);
return preview;
});
component.replaceChildren(...(representative ? [representative] : []), ...rows, ...statusPreviews);
component.classList.add('hm-orgchart-department-colors-design', 'tunnel-reference__variant-grid');
for (const name of component.querySelectorAll<HTMLElement>('.hm-orgchart-person-name')) name.setAttribute('aria-label', sampleName);
}
@@ -118,6 +149,6 @@ export function CoreComponentPreview({ kind, data = fixture, variant = 0, cardKi
const observer = kind === 'DepartmentColors' && !compactDepartmentPreview ? new ResizeObserver(() => updateDepartmentColorValues(shell)) : undefined;
observer?.observe(root);
return () => { observer?.disconnect(); controller.abort(); root.remove(); };
}, [kind, data, variant, cardKind, presentation]);
}, [kind, data, variant, cardKind, presentation, hideLogoHeading]);
return <div ref={ref} className="hm-orgchart-story-chart" />;
}
@@ -36,6 +36,13 @@
gap: var(--sb-center-column-gap);
}
/* Keep Fixed's status presenter inside the existing review surface, without
introducing the full canvas background or coordinates into the specimen. */
.hm-orgchart-department-preview .hm-orgchart-status-preview-composition {
width: max-content;
background: transparent;
}
@media (max-width: 760px) {
.hm-orgchart-department-preview .hm-orgchart-department-colors-design {
grid-template-columns: minmax(0, 1fr);
+2 -2
View File
@@ -40,8 +40,8 @@ export function DepartmentTypographyPreview() {
export function OverviewPreview() {
return <StoryPage className="hm-orgchart-story-page">
<StoryPageHeader kicker="HM DESIGN SYSTEM / ORGCHART" title="Overview" description="회사 로고와 조직·직위별, 관계사별 인원 현황입니다. 인원 현황은 고정형 조직도와 같은 Core 집계·표시 디자인을 사용하며 기존 가상 데이터를 표시합니다." />
<StorySection title="관계사·회사 로고" description="회사 로고와 기존 안내를 확인합니다.">
<div className="hm-orgchart-story-preview"><CoreComponentPreview kind="Logo" /></div>
<StorySection title="관계사·회사 로고" description="회사 로고와 기준 안내를 확인합니다.">
<div className="hm-orgchart-story-preview"><CoreComponentPreview kind="Logo" hideLogoHeading /></div>
</StorySection>
<StorySection title="조직·직위별 인원 현황" description="기존 가상 직원 데이터를 조직·직위별로 집계합니다.">
<div className="hm-orgchart-story-preview"><CoreComponentPreview kind="PositionSummary" presentation="workdesk" /></div>