Skip to content

Commit

Permalink
feat: add DefinitionList and HelpMark (#1731)
Browse files Browse the repository at this point in the history
  • Loading branch information
Raubzeug authored Oct 15, 2024
1 parent 21954db commit c587116
Show file tree
Hide file tree
Showing 24 changed files with 923 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
/src/components/ClipboardIcon @Raubzeug
/src/components/ControlLabel @korvin89
/src/components/CopyToClipboard @SeqviriouM
/src/components/DefinitionList @Raubzeug
#/src/components/Dialog
/src/components/Disclosure @Raubzeug
/src/components/Divider @v4dyar4
/src/components/DropdownMenu @axtk
/src/components/HelpMark @Raubzeug
/src/components/Hotkey @d3m1d0v
/src/components/Icon @amje
/src/components/Label @goshander
Expand Down Expand Up @@ -68,5 +70,6 @@
/src/hooks/useUniqId @ValeraS

# Allow everyone to update dependencies

/package.json
/package-lock.json
93 changes: 93 additions & 0 deletions src/components/DefinitionList/DefinitionList.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
@use '../../../styles/mixins.scss';
@use '../variables';

$block: '.#{variables.$ns}definition-list';

#{$block} {
--_--item-block-start: var(--g-spacing-4);
--_--term-width: 300px;
margin: 0;

&__item {
display: flex;
align-items: baseline;
gap: var(--g-spacing-1);

& + & {
margin-block-start: var(--g-definition-list-item-gap, var(--_--item-block-start));
}
}

&__term-container {
display: flex;
flex: 0 0 auto;
width: var(--_--term-width);
max-width: var(--_--term-width);
align-items: baseline;

overflow: hidden;
position: relative;
}

&__term-wrapper {
color: var(--g-color-text-secondary);
}

&__dots {
box-sizing: border-box;
flex: 1 0 auto;
min-width: 25px;
margin: 0 2px;
border-block-end: 1px dotted var(--g-color-line-generic-active);
}

&__definition {
flex: 0 1 auto;
margin: 0;
}

&_responsive {
#{$block}__term-container {
--_--term-width: auto;
flex: 1 0 50%;
}
}
&_vertical {
--_--item-block-start: var(--g-spacing-3);
--_--term-width: auto;

#{$block}__term-container {
flex: 1 0 auto;
}
#{$block}__item {
flex-direction: column;
gap: var(--g-spacing-half);
}
}

&__copy-container {
position: relative;
display: inline-flex;
align-items: center;
padding-inline-end: var(--g-spacing-7);

margin-inline-end: calc(-1 * var(--g-spacing-7));

&:hover {
#{$block}__copy-button {
opacity: 1;
}
}
}

&__copy-button {
position: absolute;
display: inline-block;
inset-inline-end: 0;
margin-inline-start: 10px;
opacity: 0;
&:focus-visible {
opacity: 1;
}
}
}
59 changes: 59 additions & 0 deletions src/components/DefinitionList/DefinitionList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React from 'react';

import {isOfType} from '../utils/isOfType';
import {warnOnce} from '../utils/warn';

import {DefinitionListProvider} from './components/DefinitionListContext';
import {DefinitionListItem} from './components/DefinitionListItem';
import {b} from './constants';
import type {DefinitionListProps} from './types';

import './DefinitionList.scss';

export function DefinitionList({
responsive,
direction = 'horizontal',
nameMaxWidth,
contentMaxWidth,
className,
children,
qa,
}: DefinitionListProps) {
const normalizedChildren = prepareChildren(children);
return (
<DefinitionListProvider
direction={direction}
nameMaxWidth={nameMaxWidth}
contentMaxWidth={contentMaxWidth}
>
<dl
className={b({responsive, vertical: direction === 'vertical'}, className)}
data-qa={qa}
>
{normalizedChildren}
</dl>
</DefinitionListProvider>
);
}

const isDefinitionListItem = isOfType(DefinitionListItem);

function prepareChildren(children: React.ReactNode) {
const items = React.Children.toArray(children);

const normalizedItems = [];
for (const item of items) {
const isItem = isDefinitionListItem(item);
if (isItem) {
normalizedItems.push(item);
} else {
warnOnce(
'[DefinitionList] Only <DefinitionList.Item> components is allowed as children',
);
}
}
return normalizedItems;
}

DefinitionList.Item = DefinitionListItem;
DefinitionList.displayName = 'DefinitionList';
72 changes: 72 additions & 0 deletions src/components/DefinitionList/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<!--GITHUB_BLOCK-->

# DefinitionList

<!--/GITHUB_BLOCK-->

The component to display definition list with term and definition separated by dots.

## Examples

<!--LANDING_BLOCK
<ExampleBlock
code={`
<DefinitionList nameMaxWidth={100} contentMaxWidth={100}>
<DefinitionList.Item name="Node value with copy" copyText="value">
<strong>value with copy</strong>
</DefinitionList.Item>
<DefinitionList.Item name="Empty value with copy" copyText="nothing to copy" />
</DefinitionList>
`}
>
<UIKit.DefinitionList nameMaxWidth={100} contentMaxWidth={100}>
<UIKit.DefinitionListItem name="Node value with copy" copyText="value">
<strong>value with copy</strong>
</UIKit.DefinitionListItem>
<UIKit.DefinitionListItem name="Empty value with copy" copyText="nothing to copy" />
</UIKit.DefinitionList>;
</ExampleBlock>
LANDING_BLOCK-->

<!--GITHUB_BLOCK-->

```tsx
<DefinitionList nameMaxWidth={100} contentMaxWidth={100}>
<DefinitionList.Item name="Node value with copy" copyText="value">
<strong>value with copy</strong>
</DefinitionList.Item>
<DefinitionList.Item name="Empty value with copy" copyText="nothing to copy" />
</DefinitionList>
```

<!--/GITHUB_BLOCK-->

## Properties

| Name | Description | Type | Default |
| :----------------- | :-------------------------------------------------------------------------------------------------- | :----------------------------: | :----------: |
| [children](#items) | Items of the list | `React.ReactNode` | |
| responsive | If set to `true` list will take 100% width of its parent | `boolean` | |
| direction | If set to `vertical` content will be located under name and list will take 100% width of its parent | `'horizontal'` \| `'vertical'` | 'horizontal' |
| nameMaxWidth | Maximum width of term | `number` | |
| contentMaxWidth | Maximum width of definition | `number` | |
| className | Class name for the definition list | `string` | |

### Items

DefinitionList children should be components of type `DefinitionList.Item` with following properties:

| Name | Description | Type | Default |
| -------- | ------------------------------------------------ | :-----------------------: | :-----: |
| name | Term | `ReactNode` | |
| children | Definition | `ReactNode` | |
| copyText | If set, it will be shown icon for copy this text | `string` | |
| note | If set, HelpMark will be shown next to term | `string \| HelpMarkProps` | |

## CSS API

| Name | Description |
| :----------------------------- | :---------------------------------- |
| `--g-definition-list-item-gap` | Space between definition list items |
Loading

0 comments on commit c587116

Please sign in to comment.