Skip to content

Commit

Permalink
Improve DrawerList, Autocomplete, Dropdown, props documentation. Add …
Browse files Browse the repository at this point in the history
…missing 'selectedKey'. Allow index 'value' if no matching 'selectedKey'
  • Loading branch information
snorrekim committed Oct 18, 2024
1 parent 2b2bad0 commit 16e614f
Show file tree
Hide file tree
Showing 11 changed files with 190 additions and 114 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import TranslationsTable from 'dnb-design-system-portal/src/shared/parts/Transla
import PropertiesTable from 'dnb-design-system-portal/src/shared/parts/PropertiesTable'
import { autocompleteProperties } from '@dnb/eufemia/src/components/autocomplete/AutocompleteDocs'
import { DrawerListProperties } from '@dnb/eufemia/src/fragments/drawer-list/DrawerListDocs'
import DrawerListDataDoc from '../fragments/drawer-list/_prop-data.mdx'

## Properties

Expand All @@ -17,59 +18,7 @@ You may check out the [DrawerList Properties](#drawerlist-properties) down below

<PropertiesTable props={DrawerListProperties} />

## Data structure

```js
// 1. as array
const data = [
// Every data item can, beside "content" - contain what ever
{
// (optional) can be what ever
selected_key: 'key_0',

// (optional) is show instead of "content", once selected
selected_value: 'Item 1 Value',
suffix_value: 'Addition 1',

// Item content as a string, array or React Element
content: 'Item 1 Content',
},

// more items ...
{
selected_key: 'key_1',
content: (
<>
<IconPrimary icon="bell" />
<span className="dnb-typo-bold">Searchable content</span>
</>
),
},
{
selected_key: 'key_2',
selected_value: 'Item 3 Value',
suffix_value: 'Addition 3',
content: (
<Autocomplete.HorizontalItem>
<IconPrimary icon="bell" />
<span className="dnb-typo-bold">Searchable content</span>
</Autocomplete.HorizontalItem>
),
},
{
selected_key: 'key_3',
selected_value: 'Item 4 Value',
suffix_value: 'Addition 4',
content: ['Item 4 Content A', <>Custom Component</>],
},
]

// 2. as object
const data = {
a: 'A',
b: 'B',
}
```
<DrawerListDataDoc />

## Translations

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ showTabs: true

## Events

| Events | Description |
| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `on_change` | _(optional)_ will be called on state changes made by the user. Returns an object with the new selected `data` item `{ data, event, attributes, value }`. |
| `on_select` | _(optional)_ will be called once the user selects an item by a click or keyboard navigation. Returns an object with the new selected `data` item `{ data, event, attributes, value, active_item }`. The **active_item** property is the currently selected item by keyboard navigation |
| `on_show` | _(optional)_ will be called once the user presses the dropdown. Returns the data item `{ data, attributes }`. |
| `on_hide` | _(optional)_ will be called once the user presses the dropdown again, or clicks somewhere else. Returns the data item `{ data, attributes }`. |
| Events | Description |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `on_change` | _(optional)_ will be called on state changes made by the user. Returns an object with the new selected `data` item `{ data, event, attributes, value }`. |
| `on_select` | _(optional)_ will be called once the user focuses or selects an item by a click or keyboard navigation. Returns an object with the new selected `data` item `{ data, event, attributes, value, active_item }`. The **active_item** property is the currently selected item by keyboard navigation |
| `on_show` | _(optional)_ will be called once the user presses the dropdown. Returns the data item `{ data, attributes }`. |
| `on_hide` | _(optional)_ will be called once the user presses the dropdown again, or clicks somewhere else. Returns the data item `{ data, attributes }`. |

### The `on_change` vs `on_select` difference

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ showTabs: true
import TranslationsTable from 'dnb-design-system-portal/src/shared/parts/TranslationsTable'
import PropertiesTable from 'dnb-design-system-portal/src/shared/parts/PropertiesTable'
import { DrawerListProperties } from '@dnb/eufemia/src/fragments/drawer-list/DrawerListDocs'
import DrawerListDataDoc from '../fragments/drawer-list/_prop-data.mdx'

## Properties

Expand Down Expand Up @@ -54,49 +55,7 @@ Should either be an index (integer) of the data array or a key – defined by `s

If `data` is an object, use the object key as the `value` to define the selected item. Can be a string or integer.

## Data structure

```js
// 1. as array
const data = [
// Every data item can, beside "content" - contain what ever
{
// (optional) can be what ever
selectedKey: 'key_0',

// (optional) is show instead of "content", once selected
selected_value: 'Item 1 Value',
suffix_value: 'Addition 1',

// Item content as a string or array
content: 'Item 1 Content',
},

// more items ...
{
selectedKey: 'key_1',
content: ['Item 2 Value', 'Item 2 Content'],
},
{
selectedKey: 'key_2',
selected_value: 'Item 3 Value',
suffix_value: 'Addition 3',
content: ['Item 3 Content A', 'Item 3 Content B'],
},
{
selectedKey: 'key_3',
selected_value: 'Item 4 Value',
suffix_value: 'Addition 4',
content: ['Item 4 Content A', <>Custom Component</>],
},
]

// 2. as object
const data = {
a: 'A',
b: 'B',
}
```
<DrawerListDataDoc />

## Translations

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import PropertiesTable from 'dnb-design-system-portal/src/shared/parts/PropertiesTable'
import { DrawerListItem } from '@dnb/eufemia/src/fragments/drawer-list/DrawerListDocs'

## Prop `data`

Note: even if we do not cover it here, the `data` prop can also accept a function that returns `data` or a JSON string of the `data`.

The `data` can be structured in two main ways: as an object, or as an array. An array is preferred as it gives you the most options.

### `data` as an array

```ts
// an array can contain complex items and offers the most control
const data = [
{
content: "Item 1",
},
{
content: <span>Item 2</span>
},
{
content: ["Item 3", "Line 2", <span>Line 3</span>]
},
{
content: ['Main account', '1234 12 12345'],
selected_value: 'Main account (605,22 kr)',
suffix_value: '605,22 kr',
},
{
content: ['Old account', <i>Closed</i>],
suffix_value: '0,00 kr',
},
]

// If you only use the `content` property, you can use it directly in the.
// This list is identical to the one above:
const data = [
"Item 1",
<span>Item 2</span>,
["Item 3", "Line 2", <span>Line 3</span>],
{
content: ['Main account', '1234 12 12345'],
selected_value: 'Main account (605,22 kr)',
suffix_value: '605,22 kr',
},
{
content: ['Old account', <i>Closed</i>],
suffix_value: '0,00 kr',
},
]

const onChange = ({ data, value }) => {
console.log(data) // returns the item as it appears in the array
console.log(value) // returns the array index of the item
}
```

Each object in the array have the following properties:

<PropertiesTable props={DrawerListItem} />

### `data` as an object

A simpler alternative, but with less options

```ts
// Each entry can contain the same type of value as the `content` property of an the array type
// property of an array item
const data = {
first: "Item 1",,
second: <span>Item 2</span>,
last: ["Item 3", "Line 2", <span>Line 3</span>],
}

const onChange = ({ data, value }) => {
console.log(data) // returns an object representing the item:
// {
// selectedKey: 'first',
// value: 'first',
// content: 'Item 1',
// type: 'object'
// }

console.log(value) // returns the key ("first", "second", or "last"), instead of an index

}

```

### `data` types overview

The following is an overview of all the types that the `data` prop accepts. (These are not actual names of actual types in the library.)

```ts
// The visual content that is shown in one DrawerList item.
// An array can be used to define multiple lines.
type CONTENT = string | React.Node | (string | React.Node)[]

// An array item
type ITEM = {
content: CONTENT
selectedKey?: string | number
selected_value?: CONTENT
suffix_value?: string | React.Node
}

// `data` as an array. A list of "ITEM" types is preferred,
// but the "CONTENT" type can be useful for simple lists.
type ARRAY = (CONTENT | ITEM)[]

// `data` as an object. Can only contain the "CONTENT" type.
// Each `key` behaves like the "ITEM"'s `selectedKey`.
type OBJECT = Record<string, CONTENT>

// An object or array that represents the entire DrawerList list.
type DATA = ARRAY | OBJECT

// A JSON stringified object/array of the "DATA" type
type JSON_DATA = string

// a dunction that returns an object/array of the "DATA" type
type FUNCTION_DATA = () => DATA

// The final type of the `data` prop.
type data = DATA | FUNCTION_DATA | JSON_DATA
```
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ showTabs: true

import PropertiesTable from 'dnb-design-system-portal/src/shared/parts/PropertiesTable'
import { DrawerListProperties } from '@dnb/eufemia/src/fragments/drawer-list/DrawerListDocs'
import DrawerListDataDoc from './_prop-data.mdx'

## Properties

<PropertiesTable props={DrawerListProperties} />

<DrawerListDataDoc />
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ function convertToCamelCase(doc: string, keys: string[]) {
}

export function formatName(name: string): React.ReactNode | string {
if (name.includes('/')) {
if (name.includes('[')) {
return <ReactMarkdown components={components}>{name}</ReactMarkdown>
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ export const AutocompleteEvents: PropertiesTableProps = {
status: 'optional',
},
on_select: {
doc: 'Will be called once the users selects an item by a click or keyboard navigation. Returns an object with the new selected `data` item `{ data, event, attributes, value, active_item }` including [these methods](/uilib/components/autocomplete/events#dynamically-change-data). The "active_item" property is the currently selected item by keyboard navigation',
doc: 'Will be called once the users focuses or selects an item by a click or keyboard navigation. Returns an object with the new selected `data` item `{ data, event, attributes, value, active_item }` including [these methods](/uilib/components/autocomplete/events#dynamically-change-data). The "active_item" property is the currently selected item by keyboard navigation',
type: 'function',
status: 'optional',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,7 @@ describe('Dropdown component', () => {
data: {
__id: 0,
content: 'English',
selectedKey: 'en-GB',
selected_key: 'en-GB',
type: 'object',
value: 'en-GB',
Expand All @@ -750,6 +751,7 @@ describe('Dropdown component', () => {
isTrusted: false,
data: {
content: 'Norsk',
selectedKey: 'nb-NO',
selected_key: 'nb-NO',
type: 'object',
value: 'nb-NO',
Expand Down
4 changes: 4 additions & 0 deletions packages/dnb-eufemia/src/fragments/drawer-list/DrawerList.js
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,10 @@ ItemContent.propTypes = {
hash: PropTypes.string,
children: PropTypes.oneOfType([PropTypes.node, PropTypes.object]),
}
ItemContent.defaultProps = {
hash: '',
children: undefined,
}

DrawerList.HorizontalItem = ({ className, ...props }) => (
<span
Expand Down
38 changes: 33 additions & 5 deletions packages/dnb-eufemia/src/fragments/drawer-list/DrawerListDocs.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { PropertiesTableProps } from '../../shared/types'

export const DrawerListProperties: PropertiesTableProps = {
data: {
doc: "The data we want to fill the list with. Provide the data as a JSON string, array, or object in the specified data structure. If you don't have to define a value, you can also send in a function which will be called once the user opens the DrawerList.",
type: 'string | object | function',
'[data](#prop-data)': {
doc: `The data we want to fill the list with. [Details on the type of data can be found below](#prop-data). The data can be provided as an array or object. Or as a function that returns the data (called when user opens the list), or a JSON stringified version of the data.`,
type: ['DATA', 'JSON.stringify(DATA)', '() => DATA'],
status: 'required',
},
value: {
doc: 'Define a preselected data entry (index) or key inside an array item. Can be a string or integer.',
doc: 'Define a preselected `data` entry. In order of priority, `value` can be set to: object key (if `data` is an object), `selectedKey` prop (if `data` is an array), array index (if no `selectedKey`) or content (if `value` is a non-integer string).',
type: ['string', 'number'],
status: 'optional',
},
Expand Down Expand Up @@ -165,7 +165,7 @@ export const DrawerListEvents: PropertiesTableProps = {
status: 'optional',
},
on_select: {
doc: 'Will be called once the user selects an item by a click or keyboard navigation.',
doc: 'Will be called once the user focuses or selects an item by a click or keyboard navigation.',
type: 'function',
status: 'optional',
},
Expand All @@ -180,3 +180,31 @@ export const DrawerListEvents: PropertiesTableProps = {
status: 'optional',
},
}

export const DrawerListItem: PropertiesTableProps = {
content: {
doc: 'Visual content in the list item',
type: ['string', 'React.node', '(string | React.Node)[]'],
status: 'optional',
},
selectedKey: {
doc: 'If set, can be used instead of list index to set the `value` prop',
type: ['string', 'number'],
status: 'optional',
},
selected_value: {
doc: 'Replaces the standard value output when selected. Only used in some implementations (Dropdown, Autocomplete).',
type: ['string', 'React.Node', '(string | React.Node)[]'],
status: 'optional',
},
suffix_value: {
doc: 'Content placed to the right in the list item.',
type: ['string', 'React.node'],
status: 'optional',
},
selected_key: {
doc: 'Use prop `selectedKey` instead',
type: ['string', 'number'],
status: 'deprecated',
},
}
Loading

0 comments on commit 16e614f

Please sign in to comment.