Skip to content

Commit

Permalink
fix(DefinitionList): should be semantic correct
Browse files Browse the repository at this point in the history
  • Loading branch information
Raubzeug committed Jul 20, 2024
1 parent c740204 commit 9619194
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 42 deletions.
15 changes: 9 additions & 6 deletions src/components/DefinitionList/DefinitionList.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ $block: '.#{variables.$ns}definition-list';
}
}

#{$block}__item:is(#{$block}__item_grouped) + #{$block}__item:not(#{$block}__item_grouped) {
margin-block-start: var(--g-spacing-5);
}

&__item {
display: flex;
align-items: baseline;
Expand All @@ -34,8 +30,15 @@ $block: '.#{variables.$ns}definition-list';
}
}

&__group_margin {
&:not(:first-of-type) {
margin-block-start: var(--g-spacing-5);
}
}

&__term-container {
flex: 0 0 300px;
flex: 0 0 auto;
min-width: 300px;
display: flex;
align-items: baseline;

Expand Down Expand Up @@ -136,7 +139,7 @@ $block: '.#{variables.$ns}definition-list';
#{$block}__title:not(:first-of-type) {
margin-block-start: var(--g-spacing-8);
}
#{$block}__item:is(#{$block}__item_grouped) + #{$block}__item:not(#{$block}__item_grouped) {
#{$block}__group_margin:not(:first-of-type) {
margin-block-start: var(--g-spacing-8);
}
}
78 changes: 56 additions & 22 deletions src/components/DefinitionList/DefinitionList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,24 @@ import React from 'react';
import {Definition} from './components/Definition';
import {GroupLabel} from './components/GroupLabel';
import {Term} from './components/Term';
import {DefinitionListProps} from './types';
import {
DefinitionListGranularProps,
DefinitionListGroupedProps,
DefinitionListProps,
} from './types';
import {
b,
getFlattenItems,
getAllItemsAsGroups,
getKeyStyles,
getTitle,
getValueStyles,
isGroup,
isUnbreakableOver,
onlySingleItems,
} from './utils';

import './DefinitionList.scss';

export function DefinitionList({
function DefinitionListGranular({
items,
responsive,
direction = 'horizontal',
Expand All @@ -26,36 +30,23 @@ export function DefinitionList({
itemClassName,
copyPosition = 'outside',
qa,
}: DefinitionListProps) {
}: DefinitionListGranularProps) {
const keyStyle = getKeyStyles({nameMaxWidth, direction});

const valueStyle = getValueStyles({contentMaxWidth, direction});

const normalizedItems = React.useMemo(() => {
return getFlattenItems(items).map((value, index) => ({...value, key: index}));
return items.map((value, index) => ({...value, key: index}));
}, [items]);

return (
<dl className={b({responsive, vertical: direction === 'vertical'}, className)} data-qa={qa}>
{normalizedItems.map((item) => {
if (isGroup(item)) {
const {key, label} = item;
return <GroupLabel key={key} label={label} />;
}
const {
name,
key,
content,
contentTitle,
nameTitle,
copyText,
note,
multilineName,
isGrouped,
} = item;
const {name, key, content, contentTitle, nameTitle, copyText, note, multilineName} =
item;

return (
<div key={key} className={b('item', {grouped: isGrouped}, itemClassName)}>
<div key={key} className={b('item', itemClassName)}>
<dt
className={b('term-container', {multiline: multilineName})}
style={keyStyle}
Expand Down Expand Up @@ -91,3 +82,46 @@ export function DefinitionList({
</dl>
);
}

function DefinitionListGrouped({
items,
className,
itemClassName,
...rest
}: DefinitionListGroupedProps) {
const normalizedItems = React.useMemo(() => {
return items.map((value, index) => ({...value, key: index}));
}, [items]);

return (
<div className={b({vertical: rest.direction === 'vertical'}, className)}>
{normalizedItems.map((item) => {
const {key, label} = item;

return (
<React.Fragment key={key}>
{label && <GroupLabel label={label} />}
{item.items && (
<DefinitionListGranular
{...rest}
className={b('group', {margin: !label})}
items={item.items}
itemClassName={b('item', {grouped: Boolean(label)}, itemClassName)}
/>
)}
</React.Fragment>
);
})}
</div>
);
}

export function DefinitionList({items, ...rest}: DefinitionListProps) {
if (onlySingleItems(items)) {
return <DefinitionListGranular {...rest} items={items} />;
}

const preparedItems = getAllItemsAsGroups(items);

return <DefinitionListGrouped {...rest} items={preparedItems} />;
}
11 changes: 7 additions & 4 deletions src/components/DefinitionList/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ export interface DefinitionListSingleItem {
multilineName?: boolean;
}

export interface DefinitionListItemGrouped extends DefinitionListSingleItem {
isGrouped?: boolean;
}

export type DefinitionListItem = DefinitionListSingleItem | DefinitionListGroup;

export type DefinitionListDirection = 'vertical' | 'horizontal';
Expand All @@ -38,3 +34,10 @@ export interface DefinitionListProps extends QAProps {
className?: string;
itemClassName?: string;
}

export interface DefinitionListGranularProps extends Omit<DefinitionListProps, 'items'> {
items: DefinitionListSingleItem[];
}
export interface DefinitionListGroupedProps extends Omit<DefinitionListProps, 'items'> {
items: DefinitionListGroup[];
}
31 changes: 21 additions & 10 deletions src/components/DefinitionList/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {block} from '../utils/cn';
import type {
DefinitionListGroup,
DefinitionListItem,
DefinitionListItemGrouped,
DefinitionListProps,
DefinitionListSingleItem,
} from './types';
Expand All @@ -23,19 +22,31 @@ export function isUnbreakableOver(limit: number) {
export const isGroup = (item: DefinitionListItem): item is DefinitionListGroup =>
'label' in item && !('name' in item);

export function getFlattenItems(
export const onlySingleItems = (items: DefinitionListItem[]): items is DefinitionListSingleItem[] =>
!items.some((el) => isGroup(el));

export function getAllItemsAsGroups(
items: (DefinitionListSingleItem | DefinitionListGroup)[],
): (DefinitionListItemGrouped | DefinitionListGroup)[] {
return items.reduce<(DefinitionListSingleItem | DefinitionListGroup)[]>((acc, item) => {
): DefinitionListGroup[] {
const result: DefinitionListGroup[] = [];
let temporaryList: DefinitionListSingleItem[] = [];
for (const item of items) {
if (isGroup(item)) {
acc.push({label: item.label});
const items = [...(item.items ?? [])].map((el) => ({...el, isGrouped: true}));
acc.push(...items);
if (temporaryList.length) {
result.push({items: temporaryList, label: null});
temporaryList = [];
}

result.push(item);
} else {
acc.push(item);
temporaryList.push(item);
}
return acc;
}, []);
}
if (temporaryList.length) {
result.push({items: temporaryList, label: null});
temporaryList = [];
}
return result;
}

export function getTitle(title?: string, content?: React.ReactNode) {
Expand Down

0 comments on commit 9619194

Please sign in to comment.