## Feature Examples

### Structure
- description: A field set consists of `legend`, `suffix` and `children` areas. Children and suffix areas can include any actions or form components.
- example:
```jsx
<FieldSet
  legend="Legend"
  suffix={
    <StorybookComponents.Placeholder>Suffix</StorybookComponents.Placeholder>
  }
>
  <StorybookComponents.Placeholder height="36px">
    Children
  </StorybookComponents.Placeholder>
</FieldSet>;
```

### Legend placement
- description: Control the legend position with the `legendPlacement`. It supports 4 options: - For all common cases use `top` (default). - Use `left` or `right` to save vertical space in less spacious layouts. This only works well with short legends. When using, be mindful of localization. - Use `none` to visually hide the legend. It will still be available for screen readers.
- example:
```jsx
<StorybookComponents.Stack flexDirection="column">
  <FieldSet legend="Top (default)">
    <StorybookComponents.Placeholder height="36px" />
    <StorybookComponents.Placeholder />
  </FieldSet>
  <FieldSet legend="Left" legendPlacement="left">
    <StorybookComponents.Placeholder height="36px" />
    <StorybookComponents.Placeholder />
  </FieldSet>
  <FieldSet legend="Right" legendPlacement="right">
    <StorybookComponents.Placeholder height="36px" />
    <StorybookComponents.Placeholder />
  </FieldSet>
  <FieldSet legend="Hidden legend" legendPlacement="none">
    <StorybookComponents.Placeholder height="36px" />
    <StorybookComponents.Placeholder />
  </FieldSet>
</StorybookComponents.Stack>;
```

### Legend alignment
- description: When legend is placed on the side, its vertical position can be controlled with `legendAlignment`. It supports 2 options: - For all common cases use `top` (default). - Use `middle` for single line inputs.
- example:
```jsx
<StorybookComponents.Stack flexDirection="column">
  <FieldSet legend="Top" legendAlignment="top" legendPlacement="left">
    <StorybookComponents.Placeholder height="60px" />
    <StorybookComponents.Placeholder />
  </FieldSet>
  <FieldSet legend="Middle" legendAlignment="middle" legendPlacement="left">
    <StorybookComponents.Placeholder height="60px" />
    <StorybookComponents.Placeholder />
  </FieldSet>
</StorybookComponents.Stack>;
```

### Required
- description: Mark mandatory field sets with an asterisk by using `required`.
- example:
```jsx
<FieldSet legend="Required" required>
  <StorybookComponents.Placeholder height="36px" />
  <StorybookComponents.Placeholder />
</FieldSet>;
```

### Status and message
- description: To change the status and display a message below the field set, use `status` and `statusMessage`. - For an error message, set the `status` to `error`. - For a warning message, set the `status` to `warning`. - To show helper text, use the `statusMessage` with no `status`. _Note_: to set the status and message for individual child components, use the same props within that component's `FormField`.
- example:
```jsx
<StorybookComponents.Stack flexDirection="column">
  <FieldSet
    legend="Field set in error state"
    status="error"
    statusMessage="This is an error message."
  >
    <StorybookComponents.Placeholder height="36px" />
    <StorybookComponents.Placeholder />
  </FieldSet>

  <FieldSet
    legend="Field set in warning state"
    status="warning"
    statusMessage="This is a warning message."
  >
    <StorybookComponents.Placeholder height="36px" />
    <StorybookComponents.Placeholder />
  </FieldSet>

  <FieldSet
    legend="Field set in default state"
    statusMessage="This is helper text."
  >
    <StorybookComponents.Placeholder height="36px" />
    <StorybookComponents.Placeholder />
  </FieldSet>
</StorybookComponents.Stack>;
```

### Additional info
- description: Use a tooltip to provide users with more information about the field set and what they need to input. To add info icon content use `infoContent`.
- example:
```jsx
<FieldSet
  legend="Hover over info icon"
  infoContent="This tooltip provides additional info about what the user needs to put in the field set elements."
>
  <StorybookComponents.Placeholder height="36px" />
  <StorybookComponents.Placeholder />
</FieldSet>;
```

### Suffix
- description: Add a custom element in the top-right corner of the field set to add extra actions or information. Any component can be used in this area. Or use `charCount` to show how many characters are left in a text input. _Note:_ Choose either `charCount` or a custom element inside suffix; using both together is not possible.
- example:
```jsx
<StorybookComponents.Stack flexDirection="column">
  <FieldSet
    legend="Custom suffix"
    suffix={
      <TextButton size="small" suffixIcon={<Icons.ExternalLinkSmall />}>
        Go to External Site
      </TextButton>
    }
  >
    <StorybookComponents.Placeholder height="36px" />
    <StorybookComponents.Placeholder />
  </FieldSet>
  <FieldSet legend="Character count in suffix" charCount={20}>
    <StorybookComponents.Placeholder height="36px" />
    <StorybookComponents.Placeholder />
  </FieldSet>
</StorybookComponents.Stack>;
```

### Content direction
- description: Choose how child components are arranged in the field set: - `horizontal` (default) arranges them in a row. - `vertical` arranges them in a column.
- example:
```jsx
<StorybookComponents.Stack flexDirection="column">
  <FieldSet legend="Horizontal" columns="auto 120px">
    <StorybookComponents.Placeholder height="36px" />
    <StorybookComponents.Placeholder />
  </FieldSet>
  <FieldSet legend="Vertical" direction="vertical">
    <StorybookComponents.Placeholder height="36px" />
    <StorybookComponents.Placeholder height="36px" width="120px" />
  </FieldSet>
</StorybookComponents.Stack>;
```

### Content alignment
- description: Choose how child components are aligned using `alignment`. In `horizontal`: - `start` (default) aligns to the top. - `center` aligns to the middle. - `end` to aligns to the bottom. In `vertical`: - `start` (default) aligns to the left. - `center` aligns to the center. - `end` to aligns to the right.
- example:
```jsx
<Layout>
  <Cell span={6}>
    <Text secondary weight="normal">
      Horizontal direction
    </Text>
  </Cell>
  <Cell span={6}>
    <Text secondary weight="normal">
      Vertical direction
    </Text>
  </Cell>
  <Cell span={6}>
    <FieldSet legend="Start" columns="auto 120px">
      <StorybookComponents.Placeholder height="36px" />
      <StorybookComponents.Placeholder height="18px" />
    </FieldSet>
  </Cell>
  <Cell span={6}>
    <FieldSet legend="Start" direction="vertical">
      <StorybookComponents.Placeholder height="36px" />
      <StorybookComponents.Placeholder height="18px" width="120px" />
    </FieldSet>
  </Cell>
  <Cell span={6}>
    <FieldSet legend="Center" columns="auto 120px" alignment="center">
      <StorybookComponents.Placeholder height="36px" />
      <StorybookComponents.Placeholder height="18px" />
    </FieldSet>
  </Cell>
  <Cell span={6}>
    <FieldSet legend="Center" direction="vertical" alignment="center">
      <StorybookComponents.Placeholder height="36px" />
      <StorybookComponents.Placeholder height="18px" width="120px" />
    </FieldSet>
  </Cell>{' '}
  <Cell span={6}>
    <FieldSet legend="End" columns="auto 120px" alignment="end">
      <StorybookComponents.Placeholder height="36px" />
      <StorybookComponents.Placeholder height="18px" />
    </FieldSet>
  </Cell>
  <Cell span={6}>
    <FieldSet legend="End" direction="vertical" alignment="end">
      <StorybookComponents.Placeholder height="36px" />
      <StorybookComponents.Placeholder height="18px" width="120px" />
    </FieldSet>
  </Cell>
</Layout>;
```

### Content width
- description: Use `columns` to control the width of each field set child component. Check developer examples for more guidelines. _Note_: `columns` only works with `horizontal` direction.
- example:
```jsx
<FieldSet legend="Custom content width" columns="auto 120px 60px">
  <StorybookComponents.Placeholder height="36px" />
  <StorybookComponents.Placeholder />
  <StorybookComponents.Placeholder />
</FieldSet>;
```

### Gap
- description: Control the space between field set child components with `gap`: - For all common cases use `small` (default). - Use `medium` in more spacious layouts. - Use `large` for extra space between components.
- example:
```jsx
<StorybookComponents.Stack flexDirection="column">
  <FieldSet legend="Small gap" gap="small">
    <StorybookComponents.Placeholder height="36px" />
    <StorybookComponents.Placeholder />
    <StorybookComponents.Placeholder />
  </FieldSet>
  <FieldSet legend="Medium gap" gap="medium">
    <StorybookComponents.Placeholder height="36px" />
    <StorybookComponents.Placeholder />
    <StorybookComponents.Placeholder />
  </FieldSet>
  <FieldSet legend="Large gap" gap="large">
    <StorybookComponents.Placeholder height="36px" />
    <StorybookComponents.Placeholder />
    <StorybookComponents.Placeholder />
  </FieldSet>
</StorybookComponents.Stack>;
```

## Developer Examples

### Custom content width
- description: Set the width of each child component using `columns`. - Use `min-content` to make the child component as narrow as possible. - Use `auto` to make the child component fill in all available space. - Use `px` to set the component's width. - Use `fr` to set the column proportions. For example, use `1fr 1fr` for equal width child components and `1fr 3fr` to make the first child fill 25% and second to fill 75% of available width. - Use a combination of all 4 values to create custom content layouts. _Note_: Do not use percentage values as they will cause child components to exceed the field set width.
- example:
```jsx
<StorybookComponents.Stack flexDirection="column">
  <FieldSet
    legend="Opacity and color"
    columns="auto 90px min-content"
    alignment="center"
  >
    <Slider
      displayMarks={false}
      gradientColor="purple"
      min={0}
      max={100}
      value={50}
    />
    <Input value="50" suffix={<Input.Affix>%</Input.Affix>} />
    <FillButton fill="purple" tooltipContent="Pick a color" />
  </FieldSet>
  <FieldSet
    legend="Assign color to a team"
    columns="auto min-content"
    alignment="center"
  >
    <Dropdown placeholder="Select a team" />
    <FillButton fill="purple" tooltipContent="Pick a color" />
  </FieldSet>
  <FieldSet
    legend="Select a time range"
    alignment="end"
    columns="1fr 1fr min-content"
  >
    <FormField label="From">
      <TimeInput value={new Date()} />
    </FormField>
    <FormField label="To">
      <TimeInput value={new Date()} />
    </FormField>
    <IconButton priority="secondary">
      <Icons.Edit />
    </IconButton>
  </FieldSet>
</StorybookComponents.Stack>;
```

## Common Use Case Examples

### In setting panels
- description: Use field sets to group related form components together and give them a title. When individual component labels are descriptive enough, set field set `legendPlacement` to `none`.
- example:
```jsx
() => {
  const [backgroundOpacity, setBackgroundOpacity] = React.useState(100);
  const [textOpacity, setTextOpacity] = React.useState(100);
  const [hasPublishPeriod, setHasPublishPeriod] = React.useState(true);

  const changeBackgroundOpacity = (value) => {
    setBackgroundOpacity(value);
  };

  const changeTextOpacity = (value) => {
    setTextOpacity(value);
  };

  const items = [
    {
      id: 0,
      label: 'Crop & Rotate',
      icon: <Icons.Crop />,
    },
    {
      id: 1,
      label: 'Enhance',
      icon: <Icons.MagicWand />,
    },
    {
      id: 2,
      label: 'Settings',
      icon: <Icons.Settings />,
    },
  ];

  const renderBackgroundSidePanel = () => {
    return (
      <SidePanel width="480px" onCloseButtonClick={() => {}}>
        <SidePanel.Header title="Settings" showDivider={true} />
        <SidePanel.Content noPadding>
          <SidePanel.Field>
            <FieldSet
              legend="Background color"
              columns="30px auto 72px"
              alignment="center"
            >
              <Box>
                <FillPreview fill="#B7EEFF" />
              </Box>
              <Box marginRight="12px">
                <Slider
                  displayMarks={false}
                  gradientColor="#B7EEFF"
                  min={0}
                  max={100}
                  value={backgroundOpacity}
                  onChange={changeBackgroundOpacity}
                />
              </Box>
              <Input
                value={backgroundOpacity}
                suffix={<Input.Affix>%</Input.Affix>}
                size="small"
                onChange={(e) => changeBackgroundOpacity(e.target.value)}
              />
            </FieldSet>
          </SidePanel.Field>
          <SidePanel.Field>
            <FieldSet
              legend="Text color"
              columns="30px auto 72px"
              alignment="center"
            >
              <Box>
                <FillPreview fill="#454B46" />
              </Box>
              <Box marginRight="12px">
                <Slider
                  displayMarks={false}
                  gradientColor="#454B46"
                  min={0}
                  max={100}
                  value={textOpacity}
                  onChange={changeTextOpacity}
                />
              </Box>
              <Input
                value={textOpacity}
                suffix={<Input.Affix>%</Input.Affix>}
                size="small"
                onChange={(e) => changeTextOpacity(e.target.value)}
              />
            </FieldSet>
          </SidePanel.Field>
          <SidePanel.Field>
            <FieldSet
              legend="Background photo"
              columns="auto min-content min-content"
              alignment="center"
            >
              <Box marginRight="12px">
                <Image src="running_man.png" />
              </Box>
              <Button priority="secondary" size="small">
                Replace
              </Button>
              <Tooltip content="Delete image">
                <IconButton priority="secondary" size="small">
                  <Icons.DeleteSmall />
                </IconButton>
              </Tooltip>
            </FieldSet>
          </SidePanel.Field>
          <SidePanel.Section title="Publish period">
            <SidePanel.Field divider={false}>
              <FormField labelPlacement="left" label="Set publish period">
                <ToggleSwitch
                  checked={hasPublishPeriod}
                  onChange={() => setHasPublishPeriod(!hasPublishPeriod)}
                  size="small"
                />
              </FormField>
            </SidePanel.Field>
            <SidePanel.Field>
              {hasPublishPeriod && (
                <FieldSet
                  legend="Publish period"
                  legendPlacement="none"
                  columns="1fr 1fr"
                >
                  <FormField label="From">
                    <DatePicker
                      width="100%"
                      value={new Date()}
                      size="small"
                      onChange={() => {}}
                      popoverProps={{ appendTo: 'window' }}
                    />
                  </FormField>
                  <FormField label="To">
                    <DatePicker
                      width="100%"
                      value={new Date()}
                      size="small"
                      onChange={() => {}}
                      popoverProps={{ appendTo: 'window' }}
                    />
                  </FormField>
                </FieldSet>
              )}
            </SidePanel.Field>
          </SidePanel.Section>
        </SidePanel.Content>
      </SidePanel>
    );
  };

  const renderCreateStep = () => (
    <>
      <ComposerSidebar labelPlacement="bottom" items={items} selectedId={2} />
      {renderBackgroundSidePanel()}

      <Box backgroundColor="D70" width="100%">
        <Box width="100%" padding={4}>
          <StorybookComponents.Placeholder>
            <Box verticalAlign="middle" align="center" height="100%">
              <Text>Composer content area</Text>
            </Box>
          </StorybookComponents.Placeholder>
        </Box>
      </Box>
    </>
  );

  return (
    <Layout gap={0}>
      <Cell>
        <ComposerHeader backButtonValue="Manage Album">
          <ComposerHeader.Actions justifyContent="end">
            <Button priority="secondary">Preview</Button>
            <Button>Publish</Button>
          </ComposerHeader.Actions>
        </ComposerHeader>
      </Cell>
      <Cell>
        <Box direction="vertical">
          <Box gap="0" height="800px">
            {renderCreateStep()}
          </Box>
        </Box>
      </Cell>
    </Layout>
  );
};
```

## Accessibility Examples

### Using hidden legends
- description: Provide extra information within the `legend` for screen reader users. To hide this information on screen, set the `legendPlacement` to `none`.
- example:
```jsx
<StorybookComponents.Stack flexDirection="column">
  <FieldSet legend="Select a date range" columns="1fr 1fr">
    <FormField label="From">
      <DatePicker width="100%" value={new Date()} onChange={() => {}} />
    </FormField>
    <FormField label="To">
      <DatePicker width="100%" value={new Date()} onChange={() => {}} />
    </FormField>
  </FieldSet>
  <FieldSet
    legend="Select a date range"
    columns="1fr 1fr"
    legendPlacement="none"
  >
    <FormField label="Start date">
      <DatePicker width="100%" value={new Date()} onChange={() => {}} />
    </FormField>
    <FormField label="End date">
      <DatePicker width="100%" value={new Date()} onChange={() => {}} />
    </FormField>
  </FieldSet>
</StorybookComponents.Stack>;
```

### Status messages
- description: When using FieldSet with FormField, the status message is connected to Input element automatically. If it's a FieldSet message without status, it applies to all Inputs under that FieldSet and if message has a status, it only applies the message to the FormField of matching status. If more control is required over status message linking, set FieldSet `statusId` and Input `aria-describedby` to the same value. This disables the automatic linking.
- example:
```jsx
() => {
  return (
    <StorybookComponents.Stack flexDirection="column">
      <FieldSet
        legend="User contacts (Auto linked status message)"
        status="error"
        columns="1fr 1fr"
        statusMessage="Insert your phone number starting with +3706."
      >
        <FormField label="Phone number" status="error">
          <Input value="00000" />
        </FormField>
        <FormField label="Email">
          <Input value="user@email.com" />
        </FormField>
      </FieldSet>

      {/* Manually linked status message */}
      <FieldSet
        legend="User contacts (Manually linked status message)"
        status="error"
        columns="1fr 1fr"
        statusMessage="Insert your phone number starting with +3706."
        statusId="number-status"
      >
        <FormField label="Phone number" status="error">
          <Input value="00000" ariaDescribedby="number-status" />
        </FormField>
        <FormField label="Email">
          <Input value="user@email.com" />
        </FormField>
      </FieldSet>
    </StorybookComponents.Stack>
  );
};
```
