Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(DefinitionList): add mobile view #205

Merged
merged 2 commits into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/components/DefinitionList/DefinitionList.scss
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,22 @@ $block: '.#{variables.$ns}definition-list';
}
}
}

#{$block}_vertical {
#{$block}__term-container {
flex: 1 0 auto;
}
#{$block}__item {
flex-direction: column;
gap: var(--g-spacing-half);
}
#{$block}__item + #{$block}__item {
margin-block-start: var(--g-spacing-3);
}
#{$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) {
margin-block-start: var(--g-spacing-8);
Comment on lines +137 to +140
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These margins looks too big imo. Have been they approved by design team?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Designers have been approved this.

}
}
28 changes: 14 additions & 14 deletions src/components/DefinitionList/DefinitionList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,39 @@ import {Definition} from './components/Definition';
import {GroupLabel} from './components/GroupLabel';
import {Term} from './components/Term';
import {DefinitionListProps} from './types';
import {b, getFlattenItems, getTitle, isGroup, isUnbreakableOver} from './utils';
import {
b,
getFlattenItems,
getKeyStyles,
getTitle,
getValueStyles,
isGroup,
isUnbreakableOver,
} from './utils';

import './DefinitionList.scss';

export function DefinitionList({
items,
responsive,
direction = 'horizontal',
nameMaxWidth,
contentMaxWidth = 'auto',
className,
itemClassName,
copyPosition = 'outside',
qa,
}: DefinitionListProps) {
const keyStyle = nameMaxWidth
? {
flexBasis: nameMaxWidth,
}
: {};
const keyStyle = getKeyStyles({nameMaxWidth, direction});

const valueStyle =
typeof contentMaxWidth === 'number'
? {
flexBasis: contentMaxWidth,
maxWidth: contentMaxWidth,
}
: {};
const valueStyle = getValueStyles({contentMaxWidth, direction});

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

return (
<dl className={b({responsive}, className)} data-qa={qa}>
<dl className={b({responsive, vertical: direction === 'vertical'}, className)} data-qa={qa}>
{normalizedItems.map((item) => {
if (isGroup(item)) {
const {key, label} = item;
Expand All @@ -62,6 +61,7 @@ export function DefinitionList({
style={keyStyle}
>
<Term
direction={direction}
name={name}
nameTitle={nameTitle}
note={note}
Expand Down
19 changes: 10 additions & 9 deletions src/components/DefinitionList/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ The component to display definition list with term and definition separated by d

### PropTypes

| Property | Type | Required | Default | Description |
| :-------------- | :---------------------- | :-------: | :------ | :----------------------------------------------------------- |
| [items](#items) | `DefinitionListItem[]` | yes | | Items of the list |
| responsive | `boolean` | | | If set to `true` list will take 100% width of its parent |
| nameMaxWidth | `number` | | | Maximum width of term |
| contentMaxWidth | `number \| 'auto'` | | 'auto' | Maximum width of definition |
| className | `string` | | | Class name for the list container |
| itemClassName | `string` | | | Class name for the list item |
| copyPosition | `'inside' \| 'outside'` | 'outside' | | If set to `inside`, copy icon will be placed over definition |
| Property | Type | Required | Default | Description |
| :-------------- | :----------------------------- | :-------: | :----------- | :-------------------------------------------------------------------------------------------------- |
| [items](#items) | `DefinitionListItem[]` | yes | | Items of the list |
| responsive | `boolean` | | | If set to `true` list will take 100% width of its parent |
| direction | `'horizontal'` \| `'vertical'` | | 'horizontal' | If set to `vertical` content will be located under name and list will take 100% width of its parent |
| nameMaxWidth | `number` | | | Maximum width of term |
| contentMaxWidth | `number \| 'auto'` | | 'auto' | Maximum width of definition |
| className | `string` | | | Class name for the list container |
| itemClassName | `string` | | | Class name for the list item |
| copyPosition | `'inside' \| 'outside'` | 'outside' | | If set to `inside`, copy icon will be placed over definition |

#### Items

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,11 +167,11 @@ export const ListWithIconInside = TemplateWithIconInside.bind({});

const groupedItems = [
{
label: 'Compute',
label: 'Group 1',
items: [{name: 'Link', content: 'value'}],
},
{
label: 'VPC',
label: 'Group 2',
items: [
{name: 'Number value', content: 2},
{name: 'Node value', content: <strong>value</strong>},
Expand All @@ -181,7 +181,27 @@ const groupedItems = [
{name: 'Simple value', content: 2},
{name: 'Something else', content: <strong>value</strong>},
{name: 'Foo bar', content: 'value'},
{label: 'Test', items: [{name: 'Node value', content: <strong>value</strong>}]},
{
label: 'Group 3',
items: [
{
name: 'String long value with copy',
content:
'The HTML <dl> element represents a description list. The element encloses a list of groups of terms (specified using the <dt> element) and descriptions (provided by <dd> elements). Common uses for this element are to implement a glossary or to display metadata (a list of key-value pairs)',
copyText:
'The HTML <dl> element represents a description list. The element encloses a list of groups of terms (specified using the <dt> element) and descriptions (provided by <dd> elements). Common uses for this element are to implement a glossary or to display metadata (a list of key-value pairs)',
},
{
name: 'String long looooooooooooooong looooooooooooooong looooooooooooooong looooooooooooooong value',
multilineName: true,
note: 'This is multiline value',
content:
'https://example.com/long-long/like/beyond/the/farthest/lands/long/path/to/handle?and=some&list=of&query=parameters&that=is&overcomplicated=maybe&with=some&token=inside&not=really&readable=but&sometimes=useful',
copyText:
'https://example.com/long-long/like/beyond/the/farthest/lands/long/path/to/handle?and=some&list=of&query=parameters&that=is&overcomplicated=maybe&with=some&token=inside&not=really&readable=but&sometimes=useful',
},
],
},
];

export const GroupedItems = DefaultTemplate.bind({});
Expand All @@ -190,3 +210,14 @@ GroupedItems.args = {
responsive: false,
contentMaxWidth: 480,
};

const TemplateVertical: StoryFn<DefinitionListProps> = (args) => {
return <DefinitionList {...args} />;
};
export const VerticalList = TemplateVertical.bind({});
VerticalList.args = {
items: groupedItems,
direction: 'vertical',
contentMaxWidth: 'auto',
copyPosition: 'inside',
};
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,9 @@ describe('components: DefinitionList', () => {
expect(component).toBeVisible();
expect(component).toHaveClass(b('definition'));
});
it('should render vertical view', () => {
getComponent({direction: 'vertical'});
const component = screen.getByTestId(qaAttribute);
expect(component).toHaveClass(b({vertical: true}));
});
});
12 changes: 8 additions & 4 deletions src/components/DefinitionList/components/Term.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';

import {HelpPopover} from '../../HelpPopover';
import {DefinitionListItemNote, DefinitionListSingleItem} from '../types';
import {DefinitionListDirection, DefinitionListItemNote, DefinitionListSingleItem} from '../types';
import {b, getTitle} from '../utils';

interface NoteElementsProps {
Expand Down Expand Up @@ -30,9 +30,11 @@ function NoteElement({note}: NoteElementsProps) {
}

export interface TermProps
extends Pick<DefinitionListSingleItem, 'note' | 'name' | 'nameTitle' | 'multilineName'> {}
extends Pick<DefinitionListSingleItem, 'note' | 'name' | 'nameTitle' | 'multilineName'> {
direction?: DefinitionListDirection;
}

export function Term({note, name, nameTitle, multilineName}: TermProps) {
export function Term({note, name, nameTitle, multilineName, direction}: TermProps) {
const noteElement = (
<React.Fragment>
&nbsp;
Expand All @@ -46,7 +48,9 @@ export function Term({note, name, nameTitle, multilineName}: TermProps) {
{multilineName && noteElement}
</div>
{!multilineName && noteElement}
<div className={b('dots', {'with-note': Boolean(note)})} />
{direction === 'horizontal' && (
<div className={b('dots', {'with-note': Boolean(note)})} />
)}
</React.Fragment>
);
}
2 changes: 1 addition & 1 deletion src/components/DefinitionList/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export {DefinitionList} from './DefinitionList';
export type {DefinitionListProps, DefinitionListItem} from './types';
export type {DefinitionListProps, DefinitionListItem, DefinitionListSingleItem} from './types';
3 changes: 3 additions & 0 deletions src/components/DefinitionList/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,13 @@ export interface DefinitionListItemGrouped extends DefinitionListSingleItem {

export type DefinitionListItem = DefinitionListSingleItem | DefinitionListGroup;

export type DefinitionListDirection = 'vertical' | 'horizontal';

export interface DefinitionListProps extends QAProps {
items: DefinitionListItem[];
copyPosition?: 'inside' | 'outside';
responsive?: boolean;
direction?: DefinitionListDirection;
nameMaxWidth?: number;
contentMaxWidth?: number | 'auto';
className?: string;
Expand Down
27 changes: 27 additions & 0 deletions src/components/DefinitionList/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type {
DefinitionListGroup,
DefinitionListItem,
DefinitionListItemGrouped,
DefinitionListProps,
DefinitionListSingleItem,
} from './types';

Expand Down Expand Up @@ -48,3 +49,29 @@ export function getTitle(title?: string, content?: React.ReactNode) {

return undefined;
}

export function getKeyStyles({
nameMaxWidth,
direction,
}: Pick<DefinitionListProps, 'nameMaxWidth' | 'direction'>) {
if (!nameMaxWidth) {
return {};
}
if (direction === 'vertical') {
return {maxWidth: nameMaxWidth};
}
return {flexBasis: nameMaxWidth};
}

export function getValueStyles({
contentMaxWidth,
direction,
}: Pick<DefinitionListProps, 'contentMaxWidth' | 'direction'>) {
if (!(typeof contentMaxWidth === 'number')) {
return {};
}
if (direction === 'vertical') {
return {maxWidth: contentMaxWidth};
}
return {flexBasis: contentMaxWidth, maxWidth: contentMaxWidth};
}
Loading