fix(org-chart): complete department color previews and overview cleanup
This commit is contained in:
1 parent
d0828a7ff4
commit
5acaf8a295
3 files changed
+45
-7
No files matched your search
@@ -18,11 +18,11 @@ import { createDepartmentColors, updateDepartmentColorValues } from '../../packa
|
|||||||
import fixture from '../../examples/org-chart/data-p1.json';
|
import fixture from '../../examples/org-chart/data-p1.json';
|
||||||
|
|
||||||
type PreviewKind = 'Logo' | 'DepartmentColors' | 'PositionSummary' | 'AffiliationSummary' | 'StatusSummary' | 'EmployeeCard' | 'OrganizationCards';
|
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
|
/** 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. */
|
* 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);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
const validation = validateOrgChartDataset(data);
|
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.
|
// Share Fixed's passive presenters/styles without its stage coordinates.
|
||||||
shell.className = presentation === 'workdesk' ? 'hm-orgchart-shell hm-orgchart-summary-preview' : 'hm-orgchart-shell';
|
shell.className = presentation === 'workdesk' ? 'hm-orgchart-shell hm-orgchart-summary-preview' : 'hm-orgchart-shell';
|
||||||
let component: HTMLElement;
|
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 === 'DepartmentColors') component = createDepartmentColors(document, context, controller.signal);
|
||||||
else if (kind === 'PositionSummary') component = presentation === 'workdesk' ? createOrganizationTotals(document, context) : createPositionSummary(document, context);
|
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);
|
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.classList.add('tunnel-reference__sample');
|
||||||
row.replaceChildren(header, stage);
|
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');
|
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);
|
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;
|
const observer = kind === 'DepartmentColors' && !compactDepartmentPreview ? new ResizeObserver(() => updateDepartmentColorValues(shell)) : undefined;
|
||||||
observer?.observe(root);
|
observer?.observe(root);
|
||||||
return () => { observer?.disconnect(); controller.abort(); root.remove(); };
|
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" />;
|
return <div ref={ref} className="hm-orgchart-story-chart" />;
|
||||||
}
|
}
|
||||||
@@ -36,6 +36,13 @@
|
|||||||
gap: var(--sb-center-column-gap);
|
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) {
|
@media (max-width: 760px) {
|
||||||
.hm-orgchart-department-preview .hm-orgchart-department-colors-design {
|
.hm-orgchart-department-preview .hm-orgchart-department-colors-design {
|
||||||
grid-template-columns: minmax(0, 1fr);
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ export function DepartmentTypographyPreview() {
|
|||||||
export function OverviewPreview() {
|
export function OverviewPreview() {
|
||||||
return <StoryPage className="hm-orgchart-story-page">
|
return <StoryPage className="hm-orgchart-story-page">
|
||||||
<StoryPageHeader kicker="HM DESIGN SYSTEM / ORGCHART" title="Overview" description="회사 로고와 조직·직위별, 관계사별 인원 현황입니다. 인원 현황은 고정형 조직도와 같은 Core 집계·표시 디자인을 사용하며 기존 가상 데이터를 표시합니다." />
|
<StoryPageHeader kicker="HM DESIGN SYSTEM / ORGCHART" title="Overview" description="회사 로고와 조직·직위별, 관계사별 인원 현황입니다. 인원 현황은 고정형 조직도와 같은 Core 집계·표시 디자인을 사용하며 기존 가상 데이터를 표시합니다." />
|
||||||
<StorySection title="관계사·회사 로고" description="회사 로고와 기존 안내를 확인합니다.">
|
<StorySection title="관계사·회사 로고" description="회사 로고와 기준 안내를 확인합니다.">
|
||||||
<div className="hm-orgchart-story-preview"><CoreComponentPreview kind="Logo" /></div>
|
<div className="hm-orgchart-story-preview"><CoreComponentPreview kind="Logo" hideLogoHeading /></div>
|
||||||
</StorySection>
|
</StorySection>
|
||||||
<StorySection title="조직·직위별 인원 현황" description="기존 가상 직원 데이터를 조직·직위별로 집계합니다.">
|
<StorySection title="조직·직위별 인원 현황" description="기존 가상 직원 데이터를 조직·직위별로 집계합니다.">
|
||||||
<div className="hm-orgchart-story-preview"><CoreComponentPreview kind="PositionSummary" presentation="workdesk" /></div>
|
<div className="hm-orgchart-story-preview"><CoreComponentPreview kind="PositionSummary" presentation="workdesk" /></div>
|
||||||
|
|||||||
Reference in new issue
Block a user