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(Forms): add Value.Provider to propagate value props down to Value.* components (e.g. inheritVisibility) #4005

Merged
merged 2 commits into from
Sep 27, 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
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react'
import ComponentBox from '../../../../../../shared/tags/ComponentBox'
import { Card, Flex, P, Section } from '@dnb/eufemia/src'
import { Card, Flex, HeightAnimation, P, Section } from '@dnb/eufemia/src'
import {
Field,
Form,
Expand Down Expand Up @@ -280,3 +280,33 @@ export const FilterData = () => {
</ComponentBox>
)
}

export function InheritVisibility() {
return (
<ComponentBox>
<Form.Handler>
<Card stack>
<Field.Boolean
variant="button"
path="/isVisible"
defaultValue={true}
/>

<Form.Visibility pathTrue="/isVisible" animate>
<Field.Name.First path="/foo" defaultValue="foo" />
<Field.Name.Last path="/bar" defaultValue="bar" />
</Form.Visibility>

<Value.Provider inheritVisibility>
<HeightAnimation>
<Value.SummaryList>
<Value.Name.First path="/foo" />
<Value.Name.First path="/bar" />
</Value.SummaryList>
</HeightAnimation>
</Value.Provider>
</Card>
</Form.Handler>
</ComponentBox>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,7 @@ In this example we filter out all fields that have the `data-exclude-field` attr
**Note:** This example uses `filterData` with `pathDefined` on a Visibility component along, which is a declarative way to describe the data to be shown.

<Examples.FilterData />

### Inherit visibility

<Examples.InheritVisibility />
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,20 @@ Check out the [Nested visibility example](#nested-visibility-example) to see how
### Why is this useful?

In some cases, you want to keep the content in the DOM, even if it's not visible. This can be useful for fields that still needs to run validation.

## Inherit visibility

By using the provider component `Value.Provider`, you can propagate the visibility (with the `inheritVisibility` property) of the parent to all nested values.

```tsx
import { Form, Value } from '@dnb/eufemia/extensions/forms'

render(
<Form.Handler>
<Value.Provider inheritVisibility>
<Value.String path="/foo" />
<Value.String path="/bar" />
</Value.Provider>
</Form.Handler>,
)
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
title: 'Provider'
description: 'The `Value.Provider` lets you pass generic properties to all nested Value.* components.'
componentType: 'base-value'
hideInMenu: true
showTabs: true
tabs:
- title: Info
key: '/info'
- title: Demos
key: '/demos'
- title: Properties
key: '/properties'
breadcrumb:
- text: Forms
href: /uilib/extensions/forms/
- text: Value
href: /uilib/extensions/forms/Value/
- text: Provider
href: /uilib/extensions/forms/Value/Provider/
---

import Info from 'Docs/uilib/extensions/forms/Value/Provider/info'
import Demos from 'Docs/uilib/extensions/forms/Value/Provider/demos'

<Info />
<Demos />
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react'
import ComponentBox from '../../../../../../shared/tags/ComponentBox'
import { Card } from '@dnb/eufemia/src'
import { Field, Form, Value } from '@dnb/eufemia/src/extensions/forms'

export function InheritVisibility() {
return (
<ComponentBox>
<Form.Handler>
<Card stack>
<Field.Boolean
variant="button"
path="/isVisible"
defaultValue={true}
/>

<Form.Visibility pathTrue="/isVisible" animate>
<Field.Name.First path="/foo" defaultValue="foo" />
<Field.Name.Last path="/bar" defaultValue="bar" />
</Form.Visibility>

<Value.Provider inheritVisibility>
<Value.SummaryList>
<Value.Name.First path="/foo" />
<Value.Name.First path="/bar" />
</Value.SummaryList>
</Value.Provider>
</Card>
</Form.Handler>
</ComponentBox>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
showTabs: true
---

import * as Examples from './Examples'

## Demos

### Inherit visibility

<Examples.InheritVisibility />
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
showTabs: true
---

## Description

The `Value.Provider` lets you pass generic properties to all nested Value.\* components.

```tsx
import { Field, Value } from '@dnb/eufemia/extensions/forms'
render(
<>
<Field.Boolean path="/myPath" label="My label" />

<Value.Provider inheritLabel>
<Value.Boolean path="/myPath" />
</Value.Provider>
</>,
)
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
showTabs: true
---

import PropertiesTable from 'dnb-design-system-portal/src/shared/parts/PropertiesTable'
import { ValueProviderProperties } from '@dnb/eufemia/src/extensions/forms/Value/Provider/ValueProviderDocs'

## Properties

<PropertiesTable props={ValueProviderProperties} />
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ const MyForm = () => {

It's recommended to use [Form.Visibility](/uilib/extensions/forms/Form/Visibility/) because it can animate and describes the UI in a clear, declarative way. However, `inheritVisibility` will also work with other methods, such as React's `useState` hook.

You can also propagate the `inheritVisibility` property down to all nested values with the [Value.Provider](/uilib/extensions/forms/Form/Visibility/).

## Inherit labels from fields to values

You can use `inheritLabel={true}` to inherit the label from the field with the same path.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { createContext } from 'react'

type VisibilityContext = {
inheritVisibility?: boolean
isVisible?: boolean
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react'
import ValueProviderContext from './ValueProviderContext'
import type { Path, ValueProps } from '../../types'
import useValueProvider from './useValueProvider'

export type ValueProviderProps = {
children: React.ReactNode
overwriteProps?: {
[key: Path]: ValueProps
}
} & ValueProps

function ValueProviderProvider(props: ValueProviderProps) {
const { children, ...restProps } = props
const providerValue = useValueProvider(restProps)

return (
<ValueProviderContext.Provider value={providerValue}>
{children}
</ValueProviderContext.Provider>
)
}

ValueProviderProvider._supportsSpacingProps = 'children'
export default ValueProviderProvider
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react'
import { ValueProps } from '../../types'

export type ValueProviderContextProps = {
extend: <T = ValueProps>(props: T) => T
inheritedProps?: ValueProps
inheritedContext?: ValueProps
}

const extend: ValueProviderContextProps['extend'] = (props) => props
const ValueProviderContext =
React.createContext<ValueProviderContextProps>({
extend,
})

export default ValueProviderContext
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { PropertiesTableProps } from '../../../../shared/types'
import { ValueProperties } from '../ValueDocs'

export const ValueProviderProperties: PropertiesTableProps = {
...ValueProperties,
children: {
doc: 'Contents.',
type: 'React.Node',
status: 'required',
},
}

export const StepEvents: PropertiesTableProps = {}
Loading
Loading