Skip to content

Commit

Permalink
Merge pull request #7160 from Sage/FE-7029
Browse files Browse the repository at this point in the history
feat(numeral-date, time): add support for labelAlign on non-inline labels
  • Loading branch information
nuria1110 authored Feb 3, 2025
2 parents f6c7ad4 + 7c2fb29 commit 06c838d
Show file tree
Hide file tree
Showing 16 changed files with 236 additions and 58 deletions.
14 changes: 12 additions & 2 deletions src/__internal__/fieldset/fieldset.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
StyledLegend,
StyledLegendContent,
StyledIconWrapper,
StyledLegendProps,
} from "./fieldset.style";
import ValidationIcon from "../validations/validation-icon.component";
import NewValidationContext from "../../components/carbon-provider/__internal__/new-validation.context";
Expand Down Expand Up @@ -67,7 +68,7 @@ const Fieldset = ({
children,
inline = false,
legendWidth,
legendAlign = "right",
legendAlign,
legendSpacing = 2,
error,
warning,
Expand Down Expand Up @@ -127,6 +128,15 @@ const Fieldset = ({
return null;
};

let legendAlignment: StyledLegendProps["align"];
if (inline && !legendAlign) {
legendAlignment = "right";
} else if (!legendAlign) {
legendAlignment = "left";
} else {
legendAlignment = legendAlign;
}

return (
<InputGroupBehaviour blockGroupBehaviour={blockGroupBehaviour}>
<StyledFieldset
Expand All @@ -143,7 +153,7 @@ const Fieldset = ({
onMouseLeave={onMouseLeave}
inline={inline}
width={legendWidth}
align={legendAlign}
align={legendAlignment}
rightPadding={legendSpacing}
{...legendMargin}
data-element="legend"
Expand Down
18 changes: 15 additions & 3 deletions src/__internal__/fieldset/fieldset.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const StyledLegendContent = styled.span<StyledLegendContentProps>`
`}
`;

type StyledLegendProps = {
export type StyledLegendProps = {
inline?: boolean;
width?: number;
align?: "left" | "right";
Expand All @@ -78,14 +78,26 @@ const StyledLegend = styled.legend<StyledLegendProps>`
padding: 0;
font-weight: var(--fontWeights500);
color: var(--colorsUtilityYin090);
${({ inline, width, align, rightPadding }) =>
${({ align, inline }) =>
align &&
css`
text-align: ${align};
justify-content: ${align === "right" ? "flex-end" : "flex-start"};
${!inline &&
css`
width: -moz-available;
`}
`};
${({ inline, width, rightPadding }) =>
inline &&
css`
float: left;
box-sizing: border-box;
margin: 0;
${width && `width: ${width}%`};
justify-content: ${align === "right" ? "flex-end" : "flex-start"};
padding-right: ${rightPadding === 1
? "var(--spacing100)"
: "var(--spacing200)"};
Expand Down
2 changes: 1 addition & 1 deletion src/__internal__/fieldset/fieldset.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ test("renders legend with provided `legendWidth` when `inline` is true", () => {
});

// coverage
test("renders with expected styles when `inline` is true and `align` is 'left'", () => {
test("renders with expected styles when `inline` is true and `legendAlign` is 'left'", () => {
render(
<Fieldset legend="Legend" inline legendAlign="left">
<input />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export const CheckboxGroup = (props: CheckboxGroupProps) => {
isOptional,
legendInline,
legendWidth,
legendAlign,
legendAlign = "left",
legendSpacing,
legendHelp,
tooltipPosition,
Expand Down
1 change: 1 addition & 0 deletions src/components/form/form.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,7 @@ export const FormAlignmentExample: Story = () => {
legendInline
legendWidth={10}
legendSpacing={2}
legendAlign="right"
>
<RadioButton
id="group-1-input-1"
Expand Down
70 changes: 64 additions & 6 deletions src/components/numeral-date/numeral-date-test.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -224,12 +224,6 @@ export const NewDesignValidations = (args: NumeralDateProps) => {

NewDesignValidations.storyName = "new design validations";

export const Required = () => {
return <NumeralDate label="Date of Birth" required />;
};

Required.storyName = "required";

export const TooltipPosition = () => {
return (
<>
Expand Down Expand Up @@ -263,3 +257,67 @@ export const InForm = () => {
};

InForm.storyName = "in form";

export const LabelAlign = ({ ...args }) => {
return (
<Box ml={2}>
<NumeralDate mb={2} label="labelAlign left" {...args} />
<NumeralDate
mb={2}
label="labelAlign right"
labelAlign="right"
{...args}
/>
<NumeralDate
mb={2}
label="labelAlign right and fieldLabelsAlign right"
labelAlign="right"
fieldLabelsAlign="right"
{...args}
/>
<NumeralDate
mb={2}
label="inline labelAlign left"
labelAlign="left"
labelInline
labelWidth={30}
{...args}
/>
<NumeralDate
label="inline labelAlign right"
labelInline
labelWidth={30}
{...args}
/>
</Box>
);
};

LabelAlign.storyName = "label align";
LabelAlign.args = {
dateFormat: ["dd", "mm", "yyyy"],
};
LabelAlign.parameters = {
chromatic: { disableSnapshot: false },
themeProvider: { chromatic: { theme: "sage" } },
};

export const InlineLabelsSizes = ({ ...args }) => {
return (
<Box ml={2}>
<NumeralDate mb={2} label="inline small" size="small" {...args} />
<NumeralDate mb={2} label="inline medium" size="medium" {...args} />
<NumeralDate mb={2} label="inline large" size="large" {...args} />
</Box>
);
};

InlineLabelsSizes.storyName = "inline labels sizes";
InlineLabelsSizes.args = {
dateFormat: ["dd", "mm", "yyyy"],
labelInline: true,
};
InlineLabelsSizes.parameters = {
chromatic: { disableSnapshot: false },
themeProvider: { chromatic: { theme: "sage" } },
};
15 changes: 11 additions & 4 deletions src/components/numeral-date/numeral-date.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,10 @@ export interface NumeralDateProps<DateType extends NumeralDateObject = FullDate>
name?: string;
/** Label */
label?: string;
/** [Legacy] Label alignment. Works only when labelInline is true */
/** Label alignment */
labelAlign?: "left" | "right";
/** Field labels alignment */
fieldLabelsAlign?: "left" | "right";
/**
* Text applied to label help tooltip, will be rendered as
* hint text when `validationRedesignOptIn` is true.
Expand Down Expand Up @@ -242,6 +244,7 @@ export const NumeralDate = <DateType extends NumeralDateObject = FullDate>({
labelInline,
labelWidth,
labelAlign,
fieldLabelsAlign,
labelHelp,
labelSpacing,
fieldHelp,
Expand Down Expand Up @@ -470,9 +473,9 @@ export const NumeralDate = <DateType extends NumeralDateObject = FullDate>({
}
>
<Textbox
maxWidth="fit-content"
id={inputIds.current[datePart]}
label={getDateLabel(datePart, locale)}
labelAlign={fieldLabelsAlign}
disabled={disabled}
readOnly={readOnly}
error={!!internalError}
Expand Down Expand Up @@ -512,6 +515,7 @@ export const NumeralDate = <DateType extends NumeralDateObject = FullDate>({
data-role={dataRole}
id={uniqueId}
legend={label}
legendMargin={{ mb: 0 }}
isRequired={required}
isOptional={isOptional}
isDisabled={disabled}
Expand All @@ -520,6 +524,7 @@ export const NumeralDate = <DateType extends NumeralDateObject = FullDate>({
warning={validationOnLabel && internalWarning}
info={validationOnLabel && info}
inline={inline}
size={size}
labelHelp={labelHelp}
legendAlign={labelAlign}
legendWidth={labelWidth}
Expand All @@ -528,7 +533,7 @@ export const NumeralDate = <DateType extends NumeralDateObject = FullDate>({
aria-describedby={ariaDescribedBy}
{...filterStyledSystemMarginProps(rest)}
>
<Box display="block" mt={1}>
<Box display="flex" flexDirection="column" mt={inline ? 0 : 1}>
{renderInputs()}
{fieldHelp && <FieldHelp id={fieldHelpId}>{fieldHelp}</FieldHelp>}
</Box>
Expand All @@ -544,6 +549,8 @@ export const NumeralDate = <DateType extends NumeralDateObject = FullDate>({
data-role={dataRole}
id={uniqueId}
legend={label}
legendMargin={{ mb: 0 }}
legendAlign={labelAlign}
isRequired={required}
isOptional={isOptional}
isDisabled={disabled}
Expand All @@ -555,7 +562,7 @@ export const NumeralDate = <DateType extends NumeralDateObject = FullDate>({
<StyledHintText id={inputHintId.current}>{labelHelp}</StyledHintText>
)}

<Box position="relative" mt={1}>
<Box position="relative" mt={labelHelp ? 0 : 1}>
{(internalError || internalWarning) && (
<>
<ValidationMessage
Expand Down
30 changes: 15 additions & 15 deletions src/components/numeral-date/numeral-date.pw.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,6 @@ test.describe("NumeralDate component", () => {
}) => {
await mount(<NumeralDateComponent labelInline />);

const fieldset = page.locator("fieldset");
await expect(fieldset).toHaveCSS("display", "flex");

const legend = getDataElementByValue(page, "legend");
await expect(legend).toHaveCSS("float", "left");
});
Expand Down Expand Up @@ -568,22 +565,25 @@ test.describe("NumeralDate component", () => {

(
[
["flex", 399],
["flex", 400],
["block", 401],
] as [string, NumeralDateProps["adaptiveLabelBreakpoint"]][]
).forEach(([displayValue, breakpoint]) => {
test(`should render NumeralDate with ${displayValue} label alignment when the adaptiveLabelBreakpoint prop is ${breakpoint} with a set viewport of 400`, async ({
[399, false],
[400, true],
[401, true],
] as [number, boolean][]
).forEach(([viewport, isInline]) => {
test(`should render NumeralDate with labelInline when the adaptiveLabelBreakpoint prop is 400 with a viewport of ${viewport}`, async ({
mount,
page,
}) => {
await page.setViewportSize({ width: 400, height: 300 });
await mount(
<NumeralDateComponent adaptiveLabelBreakpoint={breakpoint} />,
);
await page.setViewportSize({ width: viewport, height: 300 });
await mount(<NumeralDateComponent adaptiveLabelBreakpoint={400} />);

const legend = getDataElementByValue(page, "legend");

const fieldset = page.locator("fieldset");
await expect(fieldset).toHaveCSS("display", displayValue);
if (isInline) {
await expect(legend).toHaveCSS("float", "left");
} else {
await expect(legend).not.toHaveCSS("float", "left");
}
});
});

Expand Down
33 changes: 24 additions & 9 deletions src/components/numeral-date/numeral-date.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import styled, { css } from "styled-components";
import StyledIconSpan from "../../__internal__/input-icon-toggle/input-icon-toggle.style";
import StyledInputPresentation from "../../__internal__/input/input-presentation.style";
import StyledInput from "../../__internal__/input/input.style";
import Fieldset from "../../__internal__/fieldset";
import Fieldset, { FieldsetProps } from "../../__internal__/fieldset";
import { StyledLegend } from "../../__internal__/fieldset/fieldset.style";

interface StyledDateFieldProps {
Expand Down Expand Up @@ -56,16 +56,31 @@ export const StyledDateField = styled.div<StyledDateFieldProps>`
`}
`;

export const StyledFieldset = styled(Fieldset)`
${({ inline }) => css`
interface StyledFieldsetProps extends FieldsetProps {
inline?: boolean;
size?: "small" | "medium" | "large";
}

// We need to match height of the legend to the input container when it is inline to center it vertically,
// as Safari does not support display: flex on fieldset elements.
const sizeHeight = {
small: "57px",
medium: "65px",
large: "73px",
};

export const StyledFieldset = styled(Fieldset)<StyledFieldsetProps>`
${({ inline, size }) => css`
${inline &&
css`
display: flex;
align-items: center;
${StyledLegend} {
height: ${size && sizeHeight[size]};
}
`}
`}
${StyledLegend} {
margin-bottom: 0;
}
${!inline &&
css`
width: min-content;
`}
`}
`;
6 changes: 3 additions & 3 deletions src/components/numeral-date/numeral-date.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -767,9 +767,9 @@ test("should render with `labelInline` when `adaptiveLabelBreakpoint` set and sc
</CarbonProvider>,
);

expect(screen.getByRole("group")).toHaveStyle({
display: "flex",
alignItems: "center",
expect(screen.getByTestId("legend")).toHaveStyle({
float: "left",
height: "65px",
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export const RadioButtonGroup = (props: RadioButtonGroupProps) => {
inline = false,
legendInline = false,
legendWidth,
legendAlign,
legendAlign = "left",
legendSpacing,
labelSpacing = 1,
adaptiveLegendBreakpoint,
Expand Down
12 changes: 6 additions & 6 deletions src/components/textbox/textbox-test.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,13 @@ export const commonTextboxArgTypes = (isNewValidation?: boolean) => ({
type: "select",
},
},
...(!isNewValidation && {
labelAlign: {
options: ["left", "right"],
control: {
type: "select",
},
labelAlign: {
options: ["left", "right"],
control: {
type: "select",
},
},
...(!isNewValidation && {
labelWidth: {
control: {
type: "range",
Expand Down
Loading

0 comments on commit 06c838d

Please sign in to comment.