@wix/design-system
Version:
@wix/design-system
361 lines (334 loc) • 11.4 kB
Markdown
## Feature Examples
### Structure
- description: <p>A form field consists of <code>label</code>, <code>suffix</code> and <code>children</code> areas. Children areas can include any kind of form element.</p>
- example:
```jsx
<FormField
label="Label"
suffix={
<StorybookComponents.Placeholder>
Suffix area
</StorybookComponents.Placeholder>
}
>
<StorybookComponents.Placeholder>
Any form element
</StorybookComponents.Placeholder>
</FormField>;
```
### Label placement
- description: <p>Control the label position with the <code>labelPlacement</code> prop. It supports 3 options:</p><li>Use <code>top</code> in all common cases.</li><li>Use <code>left</code> to save vertical space in less spacious layouts. This only works well with short labels. When using, be mindful of localization.</li><li>For <code><ToggleSwitch/></code>, use <code>right</code>.</li>
- example:
```jsx
<StorybookComponents.Stack flexDirection="column">
<FormField label="Top" labelPlacement="top">
<Input />
</FormField>
<FormField label="Left" labelPlacement="left">
<Input />
</FormField>
<FormField label="Right" labelPlacement="right" stretchContent={false}>
<ToggleSwitch checked />
</FormField>
</StorybookComponents.Stack>;
```
### Label alignment
- description: <p>When the field label is placed on the side, its vertical position can be controlled with the <code>labelAlignment</code> prop. It supports 2 options:</p><li>For larger form elements like <code><InputArea/></code> or <code><RadioGroup/></code>, use <code>top</code>.</li><li>Use <code>middle</code> for single line inputs.</li>
- example:
```jsx
<StorybookComponents.Stack>
<FormField label="Top" labelPlacement="left" labelAlignment="top">
<InputArea minHeight="90px" />
</FormField>
<FormField label="Middle" labelPlacement="left" labelAlignment="middle">
<Input />
</FormField>
</StorybookComponents.Stack>;
```
### Required
- description: <p>Mark mandatory fields with an asterisk by using <code>required</code>.</p>
- example:
```jsx
<StorybookComponents.Stack>
<FormField label="Mandatory field" required>
<Input />
</FormField>
<FormField label="Not mandatory field (optional)">
<Input />
</FormField>
</StorybookComponents.Stack>;
```
### Status and message
- description: <p>To change the status and display an inline message below any component, use the <code>status</code> and <code>statusMessage</code> props. </p><li>For error messages, set the <code>status</code> prop to <code>error</code>.</li><li>For warning messages, set the <code>status</code> prop to <code>warning</code>.</li><li>For loading messages, set the <code>status</code> prop to <code>loading</code>.</li><li>To show helper text, use the <code>statusMessage</code> prop with no <code>status</code>. </li>
- example:
```jsx
<StorybookComponents.Stack flexDirection="column">
<FormField
labelSize="small"
label="Label"
status="error"
statusMessage="This is an error message."
>
<Input />
</FormField>
<FormField
labelSize="small"
label="Label"
status="warning"
statusMessage="This is a warning message."
>
<Input />
</FormField>
<FormField
labelSize="small"
label="Label"
status="loading"
statusMessage="This is a loading message."
>
<Input />
</FormField>
<FormField
labelSize="small"
label="Label"
statusMessage="This is helper text."
>
<Input />
</FormField>
</StorybookComponents.Stack>;
```
### Additional info
- description: <p>Use a tooltip to provide users with more information about the field and what they need to input.</p>
- example:
```jsx
<FormField
label="Hover over info icon"
infoContent="This tooltip provides additional info about what the user needs to put in the input field."
>
<Input />
</FormField>;
```
### Suffix
- description: <p>Add a custom element on the top right of the input to provide more options or information. This area accepts any component as a child.</p><p></p><p><em>Note:</em> The suffix area replaces the character count; they can’t be used simultaneously.</p>
- example:
```jsx
<FormField
label="Label"
suffix={
<TextButton size="small" suffixIcon={<Icons.ExternalLinkSmall />}>
Go to External Site
</TextButton>
}
>
<InputArea />
</FormField>;
```
### Character count
- description: <p>Define the maximum length of the field value by using the <code>charCount</code> prop. Any value over the allowed character count will not be added.</p>
- example:
```jsx
() => {
const [charCount, setCharCount] = React.useState(0);
const [value, setValue] = React.useState('');
const handleOnChange = value => {
if (value.length <= 20) {
setValue(value);
setCharCount(value.length);
}
};
return (
<FormField label="Enter more than 20 characters" charCount={20 - charCount}>
<Input
value={value}
onChange={event => handleOnChange(event.target.value)}
/>
</FormField>
);
};
```
### Stretch content
- description: <p>Control the container width with <code>stretchContent</code>. This property is enabled by default and must be turned off when the form element has a fixed width, like when a <code><ToggleSwitch/></code> is used.</p>
- example:
```jsx
<FormField
label="Not stretched content"
labelPlacement="right"
stretchContent={false}
>
<ToggleSwitch checked />
</FormField>;
```
### Text overflow
- description: <p>Use the <code>ellipsis</code> prop for overflow text. The full text will be displayed in a <code><Tooltip/></code> when a user hovers over the button. Control the style of the tooltip using the <code>tooltipProps</code>. </p><p></p><p>To display label in multiple lines, use <code>maxLines</code> to define how many lines should be visible. <code>maxLines</code> can be used together with <code>ellipsis</code> to control after how many lines label would get truncated. </p><p></p><p>NOTE: it's not recommended to have labels longer than two lines, as the content would become too text heavy. </p>
- example:
```jsx
<StorybookComponents.Stack>
<SidePanel width="288px">
<SidePanel.Field>
<FormField label="This is an example text that overflows and is shown in tooltip">
<Input placeholder="Placeholder" />
</FormField>
</SidePanel.Field>
</SidePanel>
<SidePanel width="288px">
<SidePanel.Field>
<FormField ellipsis
maxLines="2" label="This is an example text that fits and is shown in two lines">
<Input placeholder="Placeholder" />
</FormField>
</SidePanel.Field>
</SidePanel>
</StorybookComponents.Stack>;
```
## Common Use Case Examples
### Regular form
- description: <p>Use a top label on forms whenever possible. This creates a clear hierarchy and is the most readable format. </p>
- example:
```jsx
<Card>
<Card.Header title="New dish" />
<Card.Divider />
<Card.Content>
<Layout>
<Cell span={4}>
<FormField label="Image">
<ImageViewer width="100%" height="176px" />
</FormField>
</Cell>
<Cell span={8}>
<Layout gap="24px">
<Cell span={8}>
<FormField label="Name">
<Input value="My New Dish" />
</FormField>
</Cell>
<Cell span={4}>
<FormField label="Price">
<Input value="0" prefix={<Input.Affix>$</Input.Affix>} />
</FormField>
</Cell>
<Cell>
<FormField label="Description">
<InputArea
placeholder="Describe your dish in a few sentences."
resizable
rows={3}
/>
</FormField>
</Cell>
</Layout>
</Cell>
<Cell span={6}>
<FormField label="Dietary preferences" infoContent="Choose which dietary preferences your dish is appropriate for.">
<Layout>
<Cell span={6}>
<Box direction="vertical" gap="12px">
<Checkbox>No salt</Checkbox>
<Checkbox>Vegan</Checkbox>
<Checkbox>Vegetarian</Checkbox>
</Box>
</Cell>
<Cell span={6}>
<Box direction="vertical" gap="12px">
<Checkbox>Gluten free</Checkbox>
<Checkbox>Organic</Checkbox>
<Checkbox>Spicy</Checkbox>
</Box>
</Cell>
</Layout>
</FormField>
</Cell>
<Cell span={3}>
<FormField label="Visibility">
<Checkbox checked>Visible on site</Checkbox>
</FormField>
</Cell>
<Cell span={3}>
<FormField label="Availability">
<Checkbox checked>In stock</Checkbox>
</FormField>
</Cell>
</Layout>
</Card.Content>
</Card>;
```
### Settings panel
- description: <p>Use a top label or a left label depending on the layout. For example, a left label works best with a single toggle button. </p>
- example:
```jsx
() => {
const [selectedOption, setSelectedOption] = React.useState(0);
const [value, setValue] = React.useState(2);
const [toggleChecked, setToggleChecked] = React.useState(true);
const options = [
{ id: 0, value: 'Image' },
{ id: 1, value: 'Video' },
{ id: 2, value: 'Image and video' },
{ id: 3, value: 'Document' },
{ id: 4, value: 'Audio' },
];
return (
<SidePanel maxHeight="576px" width="288px" skin="floating">
<SidePanel.Header title="Upload Settings" />
<SidePanel.Content noPadding>
<SidePanel.Field>
<FormField label="Supported file type">
<Dropdown
placeholder="Select"
size="small"
options={options}
onSelect={(option) => setSelectedOption(option.id)}
selectedId={selectedOption}
/>
</FormField>
</SidePanel.Field>
<SidePanel.Field>
<FieldSet
gap="small"
legend="Max number of files"
columns="auto 60px"
>
<Slider
onChange={setValue}
min={0}
max={10}
value={value}
displayMarks={false}
/>
<Input
size="small"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
</FieldSet>
</SidePanel.Field>
<SidePanel.Field>
<FormField
label="Is required"
labelPlacement="left"
labelWidth="1fr"
>
<ToggleSwitch
checked
size="small"
checked={toggleChecked}
onChange={() => setToggleChecked(!toggleChecked)}
/>
</FormField>
</SidePanel.Field>
<SidePanel.Section title="Display settings">
<SidePanel.Field>
<FormField label="Field title">
<Input size="small" placeholder="Enter field title" />
</FormField>
</SidePanel.Field>
<SidePanel.Field>
<FormField label="Button text">
<Input size="small" value="Choose file" />
</FormField>
</SidePanel.Field>
</SidePanel.Section>
</SidePanel.Content>
</SidePanel>
);
};
```