Skip to content

Commit

Permalink
feat(Forms): add variant to Iterate.Toolbar for hiding the buttons wh…
Browse files Browse the repository at this point in the history
…en there is only one item in the array
  • Loading branch information
tujoworker committed Sep 10, 2024
1 parent 8fdeecf commit 2dbea3f
Show file tree
Hide file tree
Showing 10 changed files with 215 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -379,21 +379,7 @@ export const InitialOpen = () => {
<Card align="stretch">
<Iterate.Array path="/countries" defaultValue={[null]}>
<Iterate.ViewContainer
toolbar={
<Iterate.Toolbar>
{({ EditButton, RemoveButton, items }) => {
if (items.length === 1) {
return <EditButton />
}
return (
<>
<EditButton />
<RemoveButton />
</>
)
}}
</Iterate.Toolbar>
}
toolbar={<Iterate.Toolbar variant="favorMinimumOneItem" />}
>
<Value.SelectCountry
label="Land du er statsborger i"
Expand All @@ -402,22 +388,7 @@ export const InitialOpen = () => {
</Iterate.ViewContainer>

<Iterate.EditContainer
toolbar={
<Iterate.Toolbar>
{({ DoneButton, CancelButton, items }) => {
if (items.length === 1) {
return null
}

return (
<>
<DoneButton />
<CancelButton />
</>
)
}}
</Iterate.Toolbar>
}
toolbar={<Iterate.Toolbar variant="favorMinimumOneItem" />}
>
<Field.SelectCountry
label="Land du er statsborger i"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ With an optional `title` and [Iterate.Toolbar](/uilib/extensions/forms/Iterate/T

### Initially open

This example uses a customized [Iterate.Toolbar](/uilib/extensions/forms/Iterate/Toolbar/).
This example uses the [Iterate.Toolbar](/uilib/extensions/forms/Iterate/Toolbar/) with the `variant="favorMinimumOneItem"` prop.

It hides the toolbar from the `EditContainer` when there is only one item in the array. And it hides the remove button from the `ViewContainer` when there is only one item in the array.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ tabs:
key: '/info'
- title: Demos
key: '/demos'
- title: Properties
key: '/properties'
breadcrumb:
- text: Forms
href: /uilib/extensions/forms/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ hideInMenu: true

Use `Iterate.Toolbar` to enhance each item in the array with additional functionality. It's particularly useful within components like [Iterate.AnimatedContainer](/uilib/extensions/forms/Iterate/AnimatedContainer) to incorporate a toolbar with extra tools.

The Toolbar is integrated into the containers [Iterate.ViewContainer](/uilib/extensions/forms/Iterate/ViewContainer/) and [Iterate.EditContainer](/uilib/extensions/forms/Iterate/EditContainer/).
The Toolbar is integrated into the [Iterate.ViewContainer](/uilib/extensions/forms/Iterate/ViewContainer/) and the [Iterate.EditContainer](/uilib/extensions/forms/Iterate/EditContainer/).

```tsx
import { Iterate } from '@dnb/eufemia/extensions/forms'
Expand All @@ -24,7 +24,7 @@ render(
)
```

## Cusomize the Toolbar
## Customize the Toolbar

You can customize the toolbar by passing a function as a child to `Iterate.Toolbar`. The function receives the following parameters as an object:

Expand Down Expand Up @@ -67,3 +67,31 @@ render(
</Iterate.Array>,
)
```

## Variants

### `favorMinimumOneItem`

This variant has the following behavior:

- When `EditContainer` is visible, and the number of items in the array is one, the entire toolbar will be hidden.
- When `ViewContainer` is visible, and the number of items in the array is one, the remove button will be hidden.

```tsx
import { Iterate } from '@dnb/eufemia/extensions/forms'

render(
<Iterate.Array>
<Iterate.ViewContainer
toolbar={<Iterate.Toolbar variant="favorMinimumOneItem" />}
>
Item Content
</Iterate.ViewContainer>
<Iterate.EditContainer
toolbar={<Iterate.Toolbar variant="favorMinimumOneItem" />}
>
Item Content
</Iterate.EditContainer>
</Iterate.Array>,
)
```
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Change log for the Eufemia Forms extension.
## v10.48

- Make [Iterate.Toolbar](/uilib/extensions/forms/Iterate/Toolbar/) customizable when used inside [Iterate.Array](/uilib/extensions/forms/Iterate/Array/).
- Add new `variant` to [Iterate.Toolbar](/uilib/extensions/forms/Iterate/Toolbar/) for hiding the buttons when there is only one item in the array.

## v10.46

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ function ElementBlock(props: Props & FlexContainerProps) {
}, [handleRemove, setOpenState])

return (
<ElementBlockContext.Provider value={{ handleRemoveBlock }}>
<ElementBlockContext.Provider value={{ mode, handleRemoveBlock }}>
<HeightAnimation
className={classnames(
'dnb-forms-section-block',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { createContext } from 'react'
import { ContainerMode } from '../Array/types'

type ElementBlockContext = {
mode?: ContainerMode
handleRemoveBlock?: () => void
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Hr } from '../../../../elements'
import { Flex, Space } from '../../../../components'
import { SpaceAllProps } from '../../../../components/Space'
import IterateItemContext from '../IterateItemContext'
import ElementBlockContext from '../AnimatedContainer/ElementBlockContext'
import EditButton from '../ViewContainer/EditButton'
import RemoveButton from '../ViewContainer/RemoveButton'
import CancelButton from '../EditContainer/CancelButton'
Expand All @@ -19,14 +20,20 @@ export type ToolbarParams = {
}
export type Props = Omit<SpaceAllProps, 'children'> & {
children?: React.ReactNode | ((params: ToolbarParams) => React.ReactNode)
variant?: /**
* Use this variant to hide the toolbar when there is only one item in the array.
*/
'favorMinimumOneItem'
}

export default function Toolbar({
variant,
children,
className,
...rest
}: Props = {}) {
const { index, arrayValue: items } = useContext(IterateItemContext)
const { index, arrayValue: items } = useContext(IterateItemContext) || {}
const { mode } = useContext(ElementBlockContext) || {}

if (typeof children === 'function') {
children = children?.({
Expand All @@ -39,6 +46,37 @@ export default function Toolbar({
})
}

if (variant === 'favorMinimumOneItem') {
switch (mode) {
case 'view': {
if ((items?.length || 0) <= 1) {
return <EditButton />
}
children = (
<>
<EditButton />
<RemoveButton />
</>
)
break
}

case 'edit': {
if ((items?.length || 0) <= 1) {
return null
}

children = (
<>
<DoneButton />
<CancelButton />
</>
)
break
}
}
}

if (React.Children.count(children) === 0) {
return <></>
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { PropertiesTableProps } from '../../../../shared/types'

export const ToolbarProperties: PropertiesTableProps = {}

export const ToolbarEvents: PropertiesTableProps = {}
export const ToolbarProperties: PropertiesTableProps = {
variant: {
doc: 'Use variants to render the toolbar differently. Currently there is only the `favorMinimumOneItem` variant. See the info section for more info.',
type: 'string',
status: 'optional',
},
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React from 'react'
import { render, fireEvent } from '@testing-library/react'
import IterateItemContext from '../../IterateItemContext'
import ElementBlockContext from '../../AnimatedContainer/ElementBlockContext'
import Toolbar from '../Toolbar'
import nbNO from '../../../constants/locales/nb-NO'
import RemoveButton from '../../RemoveButton'

const nb = nbNO['nb-NO'].RemoveButton
const nb = nbNO['nb-NO']

describe('Toolbar', () => {
it('supports spacing props', () => {
Expand Down Expand Up @@ -65,7 +66,7 @@ describe('Toolbar', () => {
const buttons = document.querySelectorAll('button')

expect(buttons).toHaveLength(1)
expect(buttons[0]).toHaveTextContent(nb.text)
expect(buttons[0]).toHaveTextContent(nb.RemoveButton.text)
})

it('and isNew is false', () => {
Expand All @@ -84,7 +85,133 @@ describe('Toolbar', () => {
const buttons = document.querySelectorAll('button')

expect(buttons).toHaveLength(1)
expect(buttons[0]).toHaveTextContent(nb.text)
expect(buttons[0]).toHaveTextContent(nb.RemoveButton.text)
})
})

describe('variant="favorMinimumOneItem"', () => {
it('should hide the toolbar when there is only one item in the array and the mode is edit', () => {
const { rerender } = render(
<ElementBlockContext.Provider value={{ mode: 'edit' }}>
<IterateItemContext.Provider
value={{
arrayValue: [],
}}
>
<Toolbar variant="favorMinimumOneItem" />
</IterateItemContext.Provider>
</ElementBlockContext.Provider>
)

{
const buttons = document.querySelectorAll('button')
expect(buttons).toHaveLength(0)
}

rerender(
<ElementBlockContext.Provider value={{ mode: 'edit' }}>
<IterateItemContext.Provider
value={{
arrayValue: ['foo'],
}}
>
<Toolbar variant="favorMinimumOneItem" />
</IterateItemContext.Provider>
</ElementBlockContext.Provider>
)

{
const buttons = document.querySelectorAll('button')
expect(buttons).toHaveLength(0)
}

rerender(
<ElementBlockContext.Provider value={{ mode: 'edit' }}>
<IterateItemContext.Provider
value={{
arrayValue: ['foo', 'bar'],
}}
>
<Toolbar variant="favorMinimumOneItem" />
</IterateItemContext.Provider>
</ElementBlockContext.Provider>
)

{
const buttons = document.querySelectorAll('button')
expect(buttons).toHaveLength(2)
expect(buttons[0]).toHaveTextContent(
nb.IterateEditContainer.doneButton
)
expect(buttons[1]).toHaveTextContent(
nb.IterateEditContainer.cancelButton
)
}
})

it('should hide the toolbar when there is only one item in the array and the mode is view', () => {
const { rerender } = render(
<ElementBlockContext.Provider value={{ mode: 'view' }}>
<IterateItemContext.Provider
value={{
arrayValue: [],
}}
>
<Toolbar variant="favorMinimumOneItem" />
</IterateItemContext.Provider>
</ElementBlockContext.Provider>
)

{
const buttons = document.querySelectorAll('button')
expect(buttons).toHaveLength(1)
expect(buttons[0]).toHaveTextContent(
nb.IterateViewContainer.editButton
)
}

rerender(
<ElementBlockContext.Provider value={{ mode: 'view' }}>
<IterateItemContext.Provider
value={{
arrayValue: ['foo'],
}}
>
<Toolbar variant="favorMinimumOneItem" />
</IterateItemContext.Provider>
</ElementBlockContext.Provider>
)

{
const buttons = document.querySelectorAll('button')
expect(buttons).toHaveLength(1)
expect(buttons[0]).toHaveTextContent(
nb.IterateViewContainer.editButton
)
}

rerender(
<ElementBlockContext.Provider value={{ mode: 'view' }}>
<IterateItemContext.Provider
value={{
arrayValue: ['foo', 'bar'],
}}
>
<Toolbar variant="favorMinimumOneItem" />
</IterateItemContext.Provider>
</ElementBlockContext.Provider>
)

{
const buttons = document.querySelectorAll('button')
expect(buttons).toHaveLength(2)
expect(buttons[0]).toHaveTextContent(
nb.IterateViewContainer.editButton
)
expect(buttons[1]).toHaveTextContent(
nb.IterateViewContainer.removeButton
)
}
})
})
})

0 comments on commit 2dbea3f

Please sign in to comment.