Skip to content
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
179 changes: 106 additions & 73 deletions skills/carbon-react/components/fieldset.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ description: Carbon Fieldset component props and usage examples.
## Props
| Name | Type | Required | Literals | Description | Default |
| --- | --- | --- | --- | --- | --- |
| children | React.ReactNode | No | | Child elements | |
| legend | string \| undefined | No | | The text for the fieldset's legend element. | |
| children | React.ReactNode | No | | Inputs rendered within the fieldset. | |
| error | string \| undefined | No | | Error message to be displayed when validation fails. | |
| id | string \| undefined | No | | Set an id value on the fieldset. | |
| labelWeight | "bold" \| "regular" \| undefined | No | | Set the label weight of the children input's label. | "regular" |
| legend | string \| undefined | No | | The content for the fieldset legend. | |
| legendHint | string \| undefined | No | | Content for an additional hint text below the legend. | |
| m | ResponsiveValue<TVal, ThemeType> \| undefined | No | | Margin on top, left, bottom and right | |
| margin | ResponsiveValue<TVal, ThemeType> \| undefined | No | | Margin on top, left, bottom and right | |
| marginBottom | ResponsiveValue<TVal, ThemeType> \| undefined | No | | Margin on bottom | |
Expand All @@ -31,100 +35,129 @@ description: Carbon Fieldset component props and usage examples.
| mt | ResponsiveValue<TVal, ThemeType> \| undefined | No | | Margin on top | |
| mx | ResponsiveValue<TVal, ThemeType> \| undefined | No | | Margin on left and right | |
| my | ResponsiveValue<TVal, ThemeType> \| undefined | No | | Margin on top and bottom | |
| required | boolean \| undefined | No | | Flag to configure fields as mandatory. | |
| orientation | "horizontal" \| "vertical" \| undefined | No | | Set the orientation of the fieldset's children. | "vertical" |
| required | boolean \| undefined | No | | If true, an asterisk will be added to the legend and all inputs within the fieldset will be required. | |
| size | "small" \| "medium" \| "large" \| undefined | No | | Set the size of the component. | "medium" |
| validationMessagePositionTop | boolean \| undefined | No | | Specifies whether the validation message should be displayed above the input. | true |
| warning | string \| undefined | No | | Warning message to be displayed when validation warning occurs. | |
| data-element | string \| undefined | No | | Identifier used for testing purposes, applied to the root element of the component. | |
| data-role | string \| undefined | No | | Identifier used for testing purposes, applied to the root element of the component. | |

## Examples
### Default

**Args**

```tsx
{
legend: "Fieldset Legend",
}
```

**Render**

```tsx
() => (
<CarbonProvider validationRedesignOptIn>
<Form>
<Fieldset legend="Fieldset">
<Textbox label="Address Line 1" value={""} onChange={() => {}} />
<Textbox label="Address Line 2" value={""} onChange={() => {}} />
<Textbox label="City" value={""} onChange={() => {}} />
<Select label="Country" value={""} onChange={() => {}}>
<Option text="United Kingdom" value="uk" />
<Option text="Spain" value="sp" />
<Option text="France" value="fr" />
<Option text="Germany" value="ge" />
</Select>
<Textbox
label="Postcode"
maxWidth="100px"
value={""}
onChange={() => {}}
/>
</Fieldset>
</Form>
</CarbonProvider>
)
(args) => (
<Fieldset {...args}>
<Textbox label="Input 1" value="Input Text" onChange={() => {}} />
<Textbox label="Input 2" value="Input Text" onChange={() => {}} />
<Textbox label="Input 3" value="Input Text" onChange={() => {}} />
</Fieldset>
)
```


### With fieldSpacing
### WithLegendHint

**Args**

```tsx
{
...Default.args,
legendHint: "Fieldset LegendHint",
}
```


### HorizontalOrientation

**Args**

```tsx
{
...Default.args,
orientation: "horizontal",
}
```


### Sizes

**Args**

```tsx
{
mb: 4,
}
```

**Render**

```tsx
() => (
<CarbonProvider validationRedesignOptIn>
<Form fieldSpacing={1}>
<Fieldset legend="Fieldset">
<Textbox label="Address Line 1" value={""} onChange={() => {}} />
<Textbox label="Address Line 2" value={""} onChange={() => {}} />
<Textbox label="City" value={""} onChange={() => {}} />
<Select label="Country" value={""} onChange={() => {}}>
<Option text="United Kingdom" value="uk" />
<Option text="Spain" value="sp" />
<Option text="France" value="fr" />
<Option text="Germany" value="ge" />
</Select>
<Textbox
label="Postcode"
maxWidth="100px"
value={""}
onChange={() => {}}
/>
(args) => (
<>
<Fieldset legend="Small Fieldset" size="small" {...args}>
<Textbox label="Input 1" value="Input Text" onChange={() => {}} />
<Textbox label="Input 2" value="Input Text" onChange={() => {}} />
<Textbox label="Input 3" value="Input Text" onChange={() => {}} />
</Fieldset>
<Fieldset legend="Medium Fieldset" size="medium" {...args}>
<Textbox label="Input 1" value="Input Text" onChange={() => {}} />
<Textbox label="Input 2" value="Input Text" onChange={() => {}} />
<Textbox label="Input 3" value="Input Text" onChange={() => {}} />
</Fieldset>
</Form>
</CarbonProvider>
)
<Fieldset legend="Large Fieldset" size="large" {...args}>
<Textbox label="Input 1" value="Input Text" onChange={() => {}} />
<Textbox label="Input 2" value="Input Text" onChange={() => {}} />
<Textbox label="Input 3" value="Input Text" onChange={() => {}} />
</Fieldset>
</>
)
```


### HorizontalSizes

**Args**

```tsx
{
...Sizes.args,
orientation: "horizontal",
}
```


### LabelFontWeight

**Args**

```tsx
{
...Default.args,
labelWeight: "bold",
}
```


### Required

**Render**
**Args**

```tsx
() => (
<CarbonProvider validationRedesignOptIn>
<Form>
<Fieldset legend="Fieldset" required>
<Textbox label="Address Line 1" value={""} onChange={() => {}} />
<Textbox label="Address Line 2" value={""} onChange={() => {}} />
<Textbox label="City" value={""} onChange={() => {}} />
<Select label="Country" value={""} onChange={() => {}}>
<Option text="United Kingdom" value="uk" />
<Option text="Spain" value="sp" />
<Option text="France" value="fr" />
<Option text="Germany" value="ge" />
</Select>
<Textbox
label="Postcode"
maxWidth="100px"
value={""}
onChange={() => {}}
/>
</Fieldset>
</Form>
</CarbonProvider>
)
{
...Default.args,
required: true,
}
```

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useRef } from "react";
import React, { useRef, useContext } from "react";

import {
StyledCheckableInput,
Expand All @@ -12,6 +12,7 @@ import HiddenCheckableInput, {
import guid from "../utils/helpers/guid";
import useInputAccessibility from "../../hooks/__internal__/useInputAccessibility";
import { ValidationProps } from "../validations";
import FieldsetContext from "../../components/fieldset/__internal__/fieldset.context";

export interface CommonCheckableInputProps
extends ValidationProps,
Expand Down Expand Up @@ -101,6 +102,8 @@ const CheckableInput = React.forwardRef(
) => {
const { current: id } = useRef(inputId || guid());

const { required: fieldsetRequired } = useContext(FieldsetContext);

const { labelId, fieldHelpId, validationId, ariaDescribedBy } =
useInputAccessibility({
id,
Expand Down Expand Up @@ -149,7 +152,8 @@ const CheckableInput = React.forwardRef(
onBlur,
onChange,
onFocus,
required,
// set required if checkbox is rendered within Fieldset, but avoid rendering asterisk
required: required || fieldsetRequired,
ref,
validationIconId: validationId,
...props,
Expand Down
4 changes: 4 additions & 0 deletions src/__internal__/legacy-label/label.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ export const StyledLabelContainer = styled.div<StyledLabelContainerProps>`
align-items: center;
margin-bottom: 8px;

.fieldset-content & {
margin-bottom: var(--global-space-comp-xs);
}

${({ align }) => css`
justify-content: ${align !== "right" ? "flex-start" : "flex-end"};
`}
Expand Down
12 changes: 10 additions & 2 deletions src/components/checkbox/checkbox.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { TooltipProvider } from "../../__internal__/tooltip-provider";
import CheckboxGroupContext from "./checkbox-group/__internal__/checkbox-group.context";
import NewValidationContext from "../carbon-provider/__internal__/new-validation.context";
import { filterStyledSystemMarginProps } from "../../style/utils";
import FieldsetContext from "../fieldset/__internal__/fieldset.context";

export interface CheckboxProps
extends CommonCheckableInputProps,
Expand Down Expand Up @@ -87,6 +88,13 @@ export const Checkbox = React.forwardRef(
info: contextInfo,
} = checkboxGroupContext;

const { size: fieldsetSize, hasError: fieldsetError } =
useContext(FieldsetContext);
let actualSize = fieldsetSize || size;
if (actualSize === "medium") {
actualSize = "small";
}

const inputProps = {
ariaLabelledBy,
onClick,
Expand Down Expand Up @@ -116,7 +124,7 @@ export const Checkbox = React.forwardRef(
};

const validationProps = {
error: contextError || error,
error: contextError || error || fieldsetError,
warning: contextWarning || warning,
...(validationRedesignOptIn
? { validationOnLabel: false }
Expand All @@ -134,7 +142,7 @@ export const Checkbox = React.forwardRef(
{...validationProps}
fieldHelpInline={fieldHelpInline}
reverse={reverse}
size={size}
size={actualSize}
applyNewValidation={validationRedesignOptIn}
{...marginProps}
{...tagComponent("checkbox", {
Expand Down
10 changes: 7 additions & 3 deletions src/components/date/date.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import DateRangeContext, {
import useClickAwayListener from "../../hooks/__internal__/useClickAwayListener";
import guid from "../../__internal__/utils/helpers/guid";
import tagComponent from "../../__internal__/utils/helpers/tags/tags";
import FieldsetContext from "../fieldset/__internal__/fieldset.context";

interface CustomDateEvent {
type: string;
Expand Down Expand Up @@ -196,6 +197,9 @@ export const DateInput = React.forwardRef<HTMLInputElement, DateInputProps>(
const showValidationMessageOnTop =
validationMessagePositionTopContext ?? validationMessagePositionTop;

const { size: fieldsetSize } = useContext(FieldsetContext);
const actualSize = fieldsetSize || size;

const computeInvalidRawValue = (inputValue: string) =>
allowEmptyValue && !inputValue.length ? inputValue : null;

Expand Down Expand Up @@ -473,7 +477,7 @@ export const DateInput = React.forwardRef<HTMLInputElement, DateInputProps>(
<StyledDateInput
ref={wrapperRef}
role="presentation"
size={size}
size={actualSize}
labelInline={labelInline}
{...marginProps}
applyDateRangeStyling={!!inputRefMap}
Expand Down Expand Up @@ -505,12 +509,12 @@ export const DateInput = React.forwardRef<HTMLInputElement, DateInputProps>(
tooltipPosition={tooltipPosition}
helpAriaLabel={helpAriaLabel}
autoFocus={autoFocus}
size={size}
size={actualSize}
disabled={disabled}
readOnly={readOnly}
inputWidth={inputWidth}
labelWidth={labelWidth}
maxWidth={maxWidth ?? datePickerWidth[size]}
maxWidth={maxWidth ?? datePickerWidth[actualSize]}
m={0}
validationMessagePositionTop={showValidationMessageOnTop}
/>
Expand Down
9 changes: 9 additions & 0 deletions src/components/fieldset/__internal__/fieldset.context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from "react";

type FieldsetContextType = {
size?: "small" | "medium" | "large";
hasError?: boolean;
required?: boolean;
};

export default React.createContext<FieldsetContextType>({});
Loading
Loading