✨(LabelledBox) add classic variant support
- Add variant prop to LabelledBox component - Ignore labelAsPlaceholder in classic mode - Add CSS styles for .labelled-box--classic - Add unit tests for both variants Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -77,4 +77,30 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&--classic {
|
||||||
|
label {
|
||||||
|
position: static;
|
||||||
|
margin-bottom: var(
|
||||||
|
--c--components--forms-labelledbox--classic-label-margin-bottom
|
||||||
|
);
|
||||||
|
font-size: var(
|
||||||
|
--c--components--forms-labelledbox--classic-label-font-size
|
||||||
|
);
|
||||||
|
color: var(--c--components--forms-labelledbox--label-color--small);
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.labelled-box__children {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.labelled-box--disabled {
|
||||||
|
label {
|
||||||
|
color: var(
|
||||||
|
--c--components--forms-labelledbox--label-color--small--disabled
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
124
packages/react/src/components/Forms/LabelledBox/index.spec.tsx
Normal file
124
packages/react/src/components/Forms/LabelledBox/index.spec.tsx
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
import { render, screen } from "@testing-library/react";
|
||||||
|
import React from "react";
|
||||||
|
import { expect } from "vitest";
|
||||||
|
import { LabelledBox } from "./index";
|
||||||
|
|
||||||
|
describe("<LabelledBox/>", () => {
|
||||||
|
describe("floating variant (default)", () => {
|
||||||
|
it("renders with floating variant by default", () => {
|
||||||
|
render(
|
||||||
|
<LabelledBox label="Test Label">
|
||||||
|
<input type="text" />
|
||||||
|
</LabelledBox>,
|
||||||
|
);
|
||||||
|
const container = document.querySelector(".labelled-box");
|
||||||
|
expect(container).not.toHaveClass("labelled-box--classic");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("applies placeholder class when labelAsPlaceholder is true", () => {
|
||||||
|
render(
|
||||||
|
<LabelledBox label="Test Label" labelAsPlaceholder={true}>
|
||||||
|
<input type="text" />
|
||||||
|
</LabelledBox>,
|
||||||
|
);
|
||||||
|
const label = screen.getByText("Test Label");
|
||||||
|
expect(label.closest("label")).toHaveClass("placeholder");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not apply placeholder class when labelAsPlaceholder is false", () => {
|
||||||
|
render(
|
||||||
|
<LabelledBox label="Test Label" labelAsPlaceholder={false}>
|
||||||
|
<input type="text" />
|
||||||
|
</LabelledBox>,
|
||||||
|
);
|
||||||
|
const label = screen.getByText("Test Label");
|
||||||
|
expect(label.closest("label")).not.toHaveClass("placeholder");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("classic variant", () => {
|
||||||
|
it("renders with classic variant class", () => {
|
||||||
|
render(
|
||||||
|
<LabelledBox label="Test Label" variant="classic">
|
||||||
|
<input type="text" />
|
||||||
|
</LabelledBox>,
|
||||||
|
);
|
||||||
|
const container = document.querySelector(".labelled-box");
|
||||||
|
expect(container).toHaveClass("labelled-box--classic");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("ignores labelAsPlaceholder in classic variant", () => {
|
||||||
|
render(
|
||||||
|
<LabelledBox
|
||||||
|
label="Test Label"
|
||||||
|
variant="classic"
|
||||||
|
labelAsPlaceholder={true}
|
||||||
|
>
|
||||||
|
<input type="text" />
|
||||||
|
</LabelledBox>,
|
||||||
|
);
|
||||||
|
const label = screen.getByText("Test Label");
|
||||||
|
// In classic variant, placeholder class should NOT be applied even if labelAsPlaceholder is true
|
||||||
|
expect(label.closest("label")).not.toHaveClass("placeholder");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("label is always static in classic variant regardless of labelAsPlaceholder", () => {
|
||||||
|
const { rerender } = render(
|
||||||
|
<LabelledBox
|
||||||
|
label="Test Label"
|
||||||
|
variant="classic"
|
||||||
|
labelAsPlaceholder={false}
|
||||||
|
>
|
||||||
|
<input type="text" />
|
||||||
|
</LabelledBox>,
|
||||||
|
);
|
||||||
|
let label = screen.getByText("Test Label");
|
||||||
|
expect(label.closest("label")).not.toHaveClass("placeholder");
|
||||||
|
|
||||||
|
rerender(
|
||||||
|
<LabelledBox
|
||||||
|
label="Test Label"
|
||||||
|
variant="classic"
|
||||||
|
labelAsPlaceholder={true}
|
||||||
|
>
|
||||||
|
<input type="text" />
|
||||||
|
</LabelledBox>,
|
||||||
|
);
|
||||||
|
label = screen.getByText("Test Label");
|
||||||
|
expect(label.closest("label")).not.toHaveClass("placeholder");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("other props work with both variants", () => {
|
||||||
|
it("applies disabled class in floating variant", () => {
|
||||||
|
render(
|
||||||
|
<LabelledBox label="Test Label" disabled>
|
||||||
|
<input type="text" />
|
||||||
|
</LabelledBox>,
|
||||||
|
);
|
||||||
|
const container = document.querySelector(".labelled-box");
|
||||||
|
expect(container).toHaveClass("labelled-box--disabled");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("applies disabled class in classic variant", () => {
|
||||||
|
render(
|
||||||
|
<LabelledBox label="Test Label" variant="classic" disabled>
|
||||||
|
<input type="text" />
|
||||||
|
</LabelledBox>,
|
||||||
|
);
|
||||||
|
const container = document.querySelector(".labelled-box");
|
||||||
|
expect(container).toHaveClass("labelled-box--classic");
|
||||||
|
expect(container).toHaveClass("labelled-box--disabled");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("applies hideLabel in classic variant", () => {
|
||||||
|
render(
|
||||||
|
<LabelledBox label="Test Label" variant="classic" hideLabel>
|
||||||
|
<input type="text" />
|
||||||
|
</LabelledBox>,
|
||||||
|
);
|
||||||
|
const label = screen.getByText("Test Label");
|
||||||
|
expect(label.closest("label")).toHaveClass("c__offscreen");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
import React, { PropsWithChildren } from "react";
|
import React, { PropsWithChildren } from "react";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
import type { FieldVariant } from ":/components/Forms/types";
|
||||||
|
|
||||||
export interface Props extends PropsWithChildren {
|
export interface Props extends PropsWithChildren {
|
||||||
label?: string;
|
label?: string;
|
||||||
|
variant?: FieldVariant;
|
||||||
labelAsPlaceholder?: boolean;
|
labelAsPlaceholder?: boolean;
|
||||||
htmlFor?: string;
|
htmlFor?: string;
|
||||||
labelId?: string;
|
labelId?: string;
|
||||||
@@ -14,6 +16,7 @@ export interface Props extends PropsWithChildren {
|
|||||||
export const LabelledBox = ({
|
export const LabelledBox = ({
|
||||||
children,
|
children,
|
||||||
label,
|
label,
|
||||||
|
variant = "floating",
|
||||||
labelAsPlaceholder,
|
labelAsPlaceholder,
|
||||||
htmlFor,
|
htmlFor,
|
||||||
labelId,
|
labelId,
|
||||||
@@ -21,9 +24,12 @@ export const LabelledBox = ({
|
|||||||
horizontal,
|
horizontal,
|
||||||
disabled,
|
disabled,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
|
const isClassic = variant === "classic";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classNames("labelled-box", {
|
className={classNames("labelled-box", {
|
||||||
|
"labelled-box--classic": isClassic,
|
||||||
"labelled-box--no-label": hideLabel,
|
"labelled-box--no-label": hideLabel,
|
||||||
"labelled-box--horizontal": horizontal,
|
"labelled-box--horizontal": horizontal,
|
||||||
"labelled-box--disabled": disabled,
|
"labelled-box--disabled": disabled,
|
||||||
@@ -32,7 +38,8 @@ export const LabelledBox = ({
|
|||||||
{label && (
|
{label && (
|
||||||
<label
|
<label
|
||||||
className={classNames("labelled-box__label", {
|
className={classNames("labelled-box__label", {
|
||||||
placeholder: labelAsPlaceholder,
|
// In classic variant, labelAsPlaceholder is ignored (label is always static)
|
||||||
|
placeholder: !isClassic && labelAsPlaceholder,
|
||||||
c__offscreen: hideLabel,
|
c__offscreen: hideLabel,
|
||||||
})}
|
})}
|
||||||
htmlFor={htmlFor}
|
htmlFor={htmlFor}
|
||||||
|
|||||||
Reference in New Issue
Block a user