Skip to content

Commit

Permalink
feat(Forms): add variant="filled" and toolbarVariant="custom" to …
Browse files Browse the repository at this point in the history
…Iterate.EditContainer and Iterate.ViewContainer (#4329)
  • Loading branch information
tujoworker authored Nov 25, 2024
1 parent 9c18b51 commit b2b9eef
Show file tree
Hide file tree
Showing 28 changed files with 527 additions and 80 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import ComponentBox from '../../../../../../shared/tags/ComponentBox'
import { Flex, Table, Td, Th, Tr } from '@dnb/eufemia/src'
import { Avatar, Flex, Table, Td, Th, Tr } from '@dnb/eufemia/src'
import {
Iterate,
Field,
Expand Down Expand Up @@ -565,3 +565,135 @@ export const WithArrayValidator = () => {
</ComponentBox>
)
}

export const FilledViewAndEditContainer = () => {
return (
<ComponentBox
data-visual-test="filled-view-and-edit-container"
hideCode
>
{() => {
const MyEditItemForm = () => {
return (
<Flex.Stack>
<Field.Name.First itemPath="/firstName" required />
<Field.Name.Last itemPath="/lastName" required />
</Flex.Stack>
)
}

const EditItemToolbar = () => {
return (
<Iterate.Toolbar>
<Flex.Horizontal
justify="space-between"
style={{ width: '100%' }}
>
<Flex.Horizontal gap="large">
<Iterate.EditContainer.DoneButton />
<Iterate.EditContainer.CancelButton />
</Flex.Horizontal>
<Iterate.ViewContainer.RemoveButton left={false} />
</Flex.Horizontal>
</Iterate.Toolbar>
)
}

const MyEditItem = (props) => {
return (
<Iterate.EditContainer
variant="filled"
toolbarVariant="custom"
toolbar={<EditItemToolbar />}
{...props}
>
<ValueWithAvatar />
<MyEditItemForm />
</Iterate.EditContainer>
)
}

const CreateNewEntry = () => {
return (
<Iterate.PushContainer
path="/accounts"
title="New account holder"
variant="filled"
openButton={
<Iterate.PushContainer.OpenButton text="Add another account" />
}
showOpenButtonWhen={(list) => list.length > 0}
>
<MyEditItemForm />
</Iterate.PushContainer>
)
}

const ValueWithAvatar = () => {
const { value } = Iterate.useItem()
const firstName = String(value['firstName'] || '')
return (
<Flex.Horizontal align="center">
<Avatar.Group label={firstName}>
<Avatar>{firstName.substring(0, 1).toUpperCase()}</Avatar>
</Avatar.Group>
<Value.String itemPath="/firstName" />
</Flex.Horizontal>
)
}

const MyViewItem = () => {
return (
<Iterate.ViewContainer
variant="filled"
toolbarVariant="custom"
toolbar={<></>}
>
<Flex.Horizontal align="center" justify="space-between">
<ValueWithAvatar />

<Iterate.Toolbar>
<Iterate.ViewContainer.EditButton />
</Iterate.Toolbar>
</Flex.Horizontal>
</Iterate.ViewContainer>
)
}

return (
<Form.Handler
data={{
accounts: [
{
firstName:
'Tony with long name that maybe will wrap over to a new line',
lastName: 'Last',
},
{
firstName: 'Maria',
lastName: 'Last',
},
],
}}
onSubmit={(data) => console.log('onSubmit', data)}
onSubmitRequest={() => console.log('onSubmitRequest')}
>
<Flex.Vertical>
<Form.MainHeading>Accounts</Form.MainHeading>

<Form.Card>
<Iterate.Array path="/accounts" limit={2}>
<MyViewItem />
<MyEditItem />
</Iterate.Array>
<CreateNewEntry />
</Form.Card>

<Form.SubmitButton variant="send" />
</Flex.Vertical>
</Form.Handler>
)
}}
</ComponentBox>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ With an optional `title` and [Iterate.Toolbar](/uilib/extensions/forms/Iterate/T

<Examples.ViewAndEditContainer />

### Customize the view and edit containers

- Using `variant="filled"` will render the [ViewContainer](/uilib/extensions/forms/Iterate/ViewContainer) and [EditContainer](/uilib/extensions/forms/Iterate/EditContainer) with a background color.
- Using `toolbarVariant="custom"` will render the [Toolbar](/uilib/extensions/forms/Iterate/Toolbar/) without any spacing so you can customize it to your needs.

<Examples.FilledViewAndEditContainer />

### Initially open

<Examples.InitiallyOpen />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,9 @@ You can get the internal item object by using the `Iterate.useItem` hook.
import { Iterate, Field, Value } from '@dnb/eufemia/extensions/forms'

const MyItemForm = () => {
const item = Iterate.useItem()
console.log('index:', item.index)
// TypeScript type inference
const item = Iterate.useItem<{ foo: string }>()
console.log('My item:', item.index, item.value.foo)

return <Field.String itemPath="/" />
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const EditContainerProperties: PropertiesTableProps = {
status: 'optional',
},
variant: {
doc: 'Defines the variant of the container. Can be `outline` or `basic`. Defaults to `outline`.',
doc: 'Defines the variant of the container. Can be `outline`, `filled` or `basic`. Defaults to `outline`.',
type: 'string',
status: 'optional',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ describe('EditContainer and ViewContainer', () => {
)
})

it('should set variant to "basic" when variant is set to "basic"', async () => {
it('should set correct class for variant "basic"', () => {
render(
<Form.Section>
<Form.Section.ViewContainer variant="basic">
Expand All @@ -579,6 +579,30 @@ describe('EditContainer and ViewContainer', () => {
expect(editBlock).toHaveClass('dnb-forms-section-block--variant-basic')
})

it('should set correct class for variant "filled"', () => {
render(
<Form.Section>
<Form.Section.ViewContainer variant="filled">
View Content
</Form.Section.ViewContainer>

<Form.Section.EditContainer variant="filled">
Edit Content
</Form.Section.EditContainer>
</Form.Section>
)

const [viewBlock, editBlock] = Array.from(
document.querySelectorAll('.dnb-forms-section-block')
)
expect(viewBlock).toHaveClass(
'dnb-forms-section-block--variant-filled'
)
expect(editBlock).toHaveClass(
'dnb-forms-section-block--variant-filled'
)
})

it('should validate on done button click', async () => {
render(
<Form.Section>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const ViewContainerProperties: PropertiesTableProps = {
status: 'optional',
},
variant: {
doc: 'Defines the variant of the container. Can be `outline` or `basic`. Defaults to `outline`.',
doc: 'Defines the variant of the container. Can be `outline`, `filled` or `basic`. Defaults to `outline`.',
type: 'string',
status: 'optional',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export type SectionContainerProps = {
* Defines the variant of the ViewContainer or EditContainer. Can be `outline`.
* Defaults to `outline`.
*/
variant?: 'outline' | 'basic'
variant?: 'outline' | 'basic' | 'filled'
}

export type Props = {
Expand Down Expand Up @@ -126,6 +126,7 @@ function SectionContainer(props: Props & FlexContainerProps) {
<Card
stack
innerSpace={variant === 'basic' ? false : 'small'}
filled={variant === 'filled'}
className="dnb-forms-section-block__inner"
{...restProps}
aria-label={ariaLabel}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,6 @@
flex-direction: column;
}

&--variant-basic {
--border-color: transparent;
.dnb-card {
--card-outline-color: transparent;
}
}

&__inner {
flex: 1;
outline: none; // for JavaSCript focus
Expand All @@ -43,6 +36,18 @@
}
}

&--variant-basic {
--border-color: transparent;
.dnb-card {
--card-outline-color: transparent;
}
}

&--variant-filled &__inner {
--space: var(--spacing-small);
background-color: var(--color-lavender);
}

&--no-animation &__inner {
transform: translateY(0);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.dnb-forms-section {
&-block {
&--variant-filled &__inner {
--space: var(--spacing-small);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.dnb-forms-section {
&-block {
&--variant-filled &__inner {
--space: var(--spacing-small);
background-color: var(--color-lavender);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* Imports the default theme
*
*/

import './dnb-section-theme-ui.scss'
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ const useLayoutEffect =

export type ArrayItemAreaProps = {
/**
* Defines the variant of the ViewContainer, EditContainer or PushContainer. Can be `outline` or `basic`.
* Defines the variant of the ViewContainer, EditContainer or PushContainer. Can be `outline`, `filled` or `basic`.
* Defaults to `outline`.
*/
variant?: 'outline' | 'basic'
variant?: 'outline' | 'basic' | 'filled'
toolbarVariant?: 'minimumOneItem' | 'custom'
}

export type Props = {
Expand All @@ -40,6 +41,7 @@ function ArrayItemArea(props: Props & FlexContainerProps) {
children,
openDelay = 100,
variant = 'outline',
toolbarVariant,
...restProps
} = props

Expand Down Expand Up @@ -168,7 +170,9 @@ function ArrayItemArea(props: Props & FlexContainerProps) {
}, [handleRemove, index, setOpenState])

return (
<ArrayItemAreaContext.Provider value={{ handleRemoveItem }}>
<ArrayItemAreaContext.Provider
value={{ handleRemoveItem, variant, toolbarVariant }}
>
<HeightAnimation
className={classnames(
'dnb-forms-section-block',
Expand All @@ -184,7 +188,8 @@ function ArrayItemArea(props: Props & FlexContainerProps) {
>
<Card
stack
innerSpace="small"
filled={variant === 'filled'}
innerSpace={variant === 'basic' ? false : 'small'}
className="dnb-forms-section-block__inner"
{...restProps}
aria-label={ariaLabel}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { createContext } from 'react'
import { ArrayItemAreaProps } from './ArrayItemArea'

type ArrayItemAreaContext = {
handleRemoveItem?: () => void
variant?: ArrayItemAreaProps['variant']
toolbarVariant?: ArrayItemAreaProps['toolbarVariant']
}

const ArrayItemAreaContext = createContext<ArrayItemAreaContext>(null)
Expand Down
Loading

0 comments on commit b2b9eef

Please sign in to comment.