♻️(react) make className standard across components
The className prop was sometimes set onto the nested element and sometimes on the container element, which was not consistent. Now we always set the className onto the upmost element.
This commit is contained in:
@@ -249,4 +249,11 @@ describe("<Alert/>", () => {
|
||||
screen.queryByText("Additional information"),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders with className", async () => {
|
||||
render(<Alert className="my-custom-class" />);
|
||||
expect(
|
||||
document.querySelector(".c__alert.my-custom-class"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -87,4 +87,11 @@ describe("<Button/>", () => {
|
||||
tokens.themes.default.components.button["border-radius"],
|
||||
).toBeDefined();
|
||||
});
|
||||
|
||||
it("renders with className", async () => {
|
||||
render(<Button className="my-custom-class" />);
|
||||
expect(
|
||||
document.querySelector(".c__button.my-custom-class"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -382,6 +382,26 @@ describe("<DataGrid/>", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("renders with className", async () => {
|
||||
render(
|
||||
<CunninghamProvider>
|
||||
<DataGrid
|
||||
columns={[
|
||||
{
|
||||
field: "name",
|
||||
headerName: "Name",
|
||||
},
|
||||
]}
|
||||
rows={[]}
|
||||
className="my-custom-class"
|
||||
/>
|
||||
</CunninghamProvider>,
|
||||
);
|
||||
expect(
|
||||
document.querySelector(".c__datagrid.my-custom-class"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should render column with specific width", async () => {
|
||||
const database = Array.from(Array(10)).map(() => ({
|
||||
id: faker.string.uuid(),
|
||||
|
||||
@@ -64,6 +64,7 @@ export interface BaseProps<T extends Row = Row> {
|
||||
emptyCta?: ReactNode;
|
||||
hideEmptyPlaceholderImage?: boolean;
|
||||
enableSorting?: boolean;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export interface DataGridProps<T extends Row = Row> extends BaseProps<T> {
|
||||
@@ -86,6 +87,7 @@ export const DataGrid = <T extends Row>({
|
||||
onRowSelectionChange,
|
||||
rowSelection,
|
||||
tableOptions,
|
||||
className,
|
||||
emptyPlaceholderLabel,
|
||||
emptyCta,
|
||||
hideEmptyPlaceholderImage,
|
||||
@@ -297,7 +299,7 @@ export const DataGrid = <T extends Row>({
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames("c__datagrid", {
|
||||
className={classNames("c__datagrid", className, {
|
||||
"c__datagrid--empty": isEmpty,
|
||||
"c__datagrid--loading": isLoading,
|
||||
})}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import React, { useState } from "react";
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { expect } from "vitest";
|
||||
import {
|
||||
Checkbox,
|
||||
CheckboxGroup,
|
||||
@@ -171,4 +172,18 @@ describe("<Checkbox/>", () => {
|
||||
expect(input.checked).toEqual(false);
|
||||
screen.getByText("Checked = false|");
|
||||
});
|
||||
it("renders with className", async () => {
|
||||
render(
|
||||
<Checkbox label="Agree" checked={true} className="my-custom-class" />,
|
||||
);
|
||||
expect(
|
||||
document.querySelector(".c__checkbox.my-custom-class"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
it("renders group with className", async () => {
|
||||
render(<CheckboxGroup className="my-custom-class" />);
|
||||
expect(
|
||||
document.querySelector(".c__checkbox__group.my-custom-class"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -22,7 +22,6 @@ const Template: StoryFn<typeof Checkbox> = (args) => (
|
||||
|
||||
export const Default = {
|
||||
render: Template,
|
||||
args: {},
|
||||
};
|
||||
|
||||
export const Checked = {
|
||||
|
||||
@@ -49,7 +49,7 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
|
||||
|
||||
return (
|
||||
<label
|
||||
className={classNames("c__checkbox", {
|
||||
className={classNames("c__checkbox", className, {
|
||||
"c__checkbox--disabled": props.disabled,
|
||||
"c__checkbox--full-width": props.fullWidth,
|
||||
})}
|
||||
@@ -59,7 +59,6 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
|
||||
<div className="c__checkbox__wrapper">
|
||||
<input
|
||||
type="checkbox"
|
||||
className={className}
|
||||
{...inputProps}
|
||||
onChange={(e) => {
|
||||
setValue(e.target.checked);
|
||||
@@ -86,10 +85,11 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
|
||||
|
||||
export const CheckboxGroup = ({
|
||||
children,
|
||||
className,
|
||||
...props
|
||||
}: PropsWithChildren & FieldProps) => {
|
||||
return (
|
||||
<Field className="c__checkbox__group" {...props}>
|
||||
<Field className={classNames("c__checkbox__group", className)} {...props}>
|
||||
<div className="c__checkbox__group__list">{children}</div>
|
||||
</Field>
|
||||
);
|
||||
|
||||
@@ -1448,4 +1448,15 @@ describe("<DatePicker/>", () => {
|
||||
// Make sure value is selected, with the same time as the initial value.
|
||||
screen.getByText(`Value = 2023-04-12T12:00:00.000Z|`);
|
||||
});
|
||||
|
||||
it("renders with className", async () => {
|
||||
render(
|
||||
<CunninghamProvider>
|
||||
<DatePicker label="Date" className="my-custom-class" />
|
||||
</CunninghamProvider>,
|
||||
);
|
||||
expect(
|
||||
document.querySelector(".c__field.my-custom-class"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -57,6 +57,7 @@ export type DatePickerAuxProps = PropsWithChildren &
|
||||
const DatePickerAux = forwardRef(
|
||||
(
|
||||
{
|
||||
className,
|
||||
pickerState,
|
||||
pickerProps,
|
||||
onClear,
|
||||
@@ -86,7 +87,7 @@ const DatePickerAux = forwardRef(
|
||||
<I18nProvider locale={locale || currentLocale}>
|
||||
<Field
|
||||
{...props}
|
||||
className={classNames({
|
||||
className={classNames(className, {
|
||||
"c__date-picker__range__container": isRange,
|
||||
})}
|
||||
>
|
||||
|
||||
@@ -1175,4 +1175,18 @@ describe("<DateRangePicker/>", () => {
|
||||
datepickerEnd: "",
|
||||
});
|
||||
});
|
||||
it("renders with className", async () => {
|
||||
render(
|
||||
<CunninghamProvider>
|
||||
<DateRangePicker
|
||||
startLabel="Start"
|
||||
endLabel="End"
|
||||
className="my-custom-class"
|
||||
/>
|
||||
</CunninghamProvider>,
|
||||
);
|
||||
expect(
|
||||
document.querySelector(".c__field.my-custom-class"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { act, render, screen } from "@testing-library/react";
|
||||
import React, { useRef, useState } from "react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { expect } from "vitest";
|
||||
import { CunninghamProvider } from ":/components/Provider";
|
||||
import {
|
||||
FileUploader,
|
||||
@@ -273,6 +274,17 @@ describe("<FileUploader />", () => {
|
||||
});
|
||||
screen.getByText("Value: |");
|
||||
});
|
||||
|
||||
it("renders with className", async () => {
|
||||
render(
|
||||
<CunninghamProvider>
|
||||
<FileUploader className="my-custom-class" />
|
||||
</CunninghamProvider>,
|
||||
);
|
||||
expect(
|
||||
document.querySelector(".c__field.my-custom-class"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
describe("Multi", () => {
|
||||
const expectFiles = (expectedFiles: { name: string; specs: string }[]) => {
|
||||
|
||||
@@ -28,7 +28,7 @@ export interface FileUploaderRefType {
|
||||
export const FileUploader = forwardRef<FileUploaderRefType, FileUploaderProps>(
|
||||
({ fullWidth, ...props }, ref) => {
|
||||
return (
|
||||
<Field fullWidth={fullWidth}>
|
||||
<Field fullWidth={fullWidth} className={props.className}>
|
||||
{props.multiple ? (
|
||||
<FileUploaderMulti {...props} ref={ref} />
|
||||
) : (
|
||||
|
||||
@@ -235,4 +235,11 @@ describe("<Input/>", () => {
|
||||
render(<Input {...propsInput} />);
|
||||
expect(spyError).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("renders with className", async () => {
|
||||
render(<Input label="First name" className="my-custom-class" />);
|
||||
expect(
|
||||
document.querySelector(".c__field.my-custom-class"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -39,9 +39,6 @@ export const Input = forwardRef<HTMLInputElement, InputProps>(
|
||||
ref,
|
||||
) => {
|
||||
const classes = ["c__input"];
|
||||
if (className) {
|
||||
classes.push(className);
|
||||
}
|
||||
const inputRef = useRef<HTMLInputElement | null>(null);
|
||||
const [inputFocus, setInputFocus] = useState(false);
|
||||
const [value, setValue] = useState(defaultValue || props.value || "");
|
||||
@@ -82,7 +79,7 @@ export const Input = forwardRef<HTMLInputElement, InputProps>(
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<Field {...props} rightText={rightTextToUse}>
|
||||
<Field {...props} rightText={rightTextToUse} className={className}>
|
||||
{/* We disabled linting for this specific line because we consider that the onClick props is only used for */}
|
||||
{/* mouse users, so this do not engender any issue for accessibility. */}
|
||||
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import React from "react";
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { expect } from "vitest";
|
||||
import {
|
||||
Radio,
|
||||
RadioGroup,
|
||||
@@ -138,4 +139,17 @@ describe("<Radio/>", () => {
|
||||
render(<Radio {...propsInput} />);
|
||||
expect(spyError).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("renders with className", async () => {
|
||||
render(<Radio label="Agree" checked={true} className="my-custom-class" />);
|
||||
expect(
|
||||
document.querySelector(".c__checkbox.my-custom-class"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
it("renders group with className", async () => {
|
||||
render(<RadioGroup className="my-custom-class" />);
|
||||
expect(
|
||||
document.querySelector(".c__checkbox__group.my-custom-class"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -16,7 +16,7 @@ export type RadioProps = InputHTMLAttributes<HTMLInputElement> &
|
||||
RadioOnlyProps;
|
||||
|
||||
export const Radio = forwardRef<HTMLInputElement, RadioProps>(
|
||||
({ label, ...props }: RadioProps, ref) => {
|
||||
({ className, label, ...props }: RadioProps, ref) => {
|
||||
const {
|
||||
compact,
|
||||
fullWidth,
|
||||
@@ -29,7 +29,7 @@ export const Radio = forwardRef<HTMLInputElement, RadioProps>(
|
||||
|
||||
return (
|
||||
<label
|
||||
className={classNames("c__checkbox", "c__radio", {
|
||||
className={classNames("c__checkbox", "c__radio", className, {
|
||||
"c__checkbox--disabled": props.disabled,
|
||||
"c__checkbox--full-width": props.fullWidth,
|
||||
})}
|
||||
@@ -46,13 +46,14 @@ export const Radio = forwardRef<HTMLInputElement, RadioProps>(
|
||||
);
|
||||
|
||||
export const RadioGroup = ({
|
||||
className,
|
||||
children,
|
||||
style,
|
||||
...props
|
||||
}: PropsWithChildren & FieldProps & { style?: React.CSSProperties }) => {
|
||||
return (
|
||||
<Field
|
||||
className="c__radio__group c__checkbox__group"
|
||||
className={classNames("c__radio__group c__checkbox__group", className)}
|
||||
compact={true}
|
||||
{...props}
|
||||
>
|
||||
|
||||
@@ -1976,4 +1976,23 @@ describe("<Select/>", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("renders with className", async () => {
|
||||
render(
|
||||
<CunninghamProvider>
|
||||
<Select
|
||||
label="City"
|
||||
options={[
|
||||
{
|
||||
label: "Paris",
|
||||
},
|
||||
]}
|
||||
className="my-custom-class"
|
||||
/>
|
||||
</CunninghamProvider>,
|
||||
);
|
||||
expect(
|
||||
document.querySelector(".c__field.my-custom-class"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1871,4 +1871,24 @@ describe("<Select multi={true} />", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("renders with className", async () => {
|
||||
render(
|
||||
<CunninghamProvider>
|
||||
<Select
|
||||
label="City"
|
||||
options={[
|
||||
{
|
||||
label: "Paris",
|
||||
},
|
||||
]}
|
||||
multi={true}
|
||||
className="my-custom-class"
|
||||
/>
|
||||
</CunninghamProvider>,
|
||||
);
|
||||
expect(
|
||||
document.querySelector(".c__field.my-custom-class"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -156,4 +156,11 @@ describe("<Switch/>", () => {
|
||||
render(<Switch {...propsInput} />);
|
||||
expect(spyError).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("renders with className", async () => {
|
||||
render(<Switch className="my-custom-class" />);
|
||||
expect(
|
||||
document.querySelector(".c__switch.my-custom-class"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,6 +15,7 @@ export const Switch = forwardRef<HTMLInputElement, SwitchProps>(
|
||||
({ label, labelSide = "left", ...props }: SwitchProps, ref) => {
|
||||
const {
|
||||
compact,
|
||||
className,
|
||||
fullWidth,
|
||||
rightText,
|
||||
state,
|
||||
@@ -23,19 +24,22 @@ export const Switch = forwardRef<HTMLInputElement, SwitchProps>(
|
||||
...inputProps
|
||||
} = props;
|
||||
|
||||
const { className: excludeClassName, ...fieldProps } = props;
|
||||
|
||||
return (
|
||||
<label
|
||||
className={classNames(
|
||||
"c__checkbox",
|
||||
"c__switch",
|
||||
"c__switch--" + labelSide,
|
||||
className,
|
||||
{
|
||||
"c__checkbox--disabled": props.disabled,
|
||||
"c__switch--full-width": props.fullWidth,
|
||||
},
|
||||
)}
|
||||
>
|
||||
<Field compact={true} {...props}>
|
||||
<Field compact={true} {...fieldProps}>
|
||||
<div className="c__checkbox__container">
|
||||
{label && <div className="c__checkbox__label">{label}</div>}
|
||||
<div className="c__switch__rail__wrapper">
|
||||
|
||||
@@ -191,4 +191,12 @@ describe("<TextArea/>", () => {
|
||||
await user.clear(textarea);
|
||||
screen.getByText("Value: .");
|
||||
});
|
||||
|
||||
it("renders with className", async () => {
|
||||
render(<TextArea className="my-custom-class" />);
|
||||
screen.debug();
|
||||
expect(
|
||||
document.querySelector(".c__field--textarea.my-custom-class"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -44,12 +44,13 @@ export const TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(
|
||||
setValue(props.value || "");
|
||||
}, [props.value]);
|
||||
|
||||
const { fullWidth, rightText, text, textItems, ...areaProps } = props;
|
||||
const { fullWidth, rightText, text, textItems, className, ...areaProps } =
|
||||
props;
|
||||
|
||||
return (
|
||||
<Field
|
||||
{...props}
|
||||
className="c__field--textarea"
|
||||
className={classNames("c__field--textarea", className)}
|
||||
rightText={rightTextToUse}
|
||||
>
|
||||
{/* We disabled linting for this specific line because we consider that the onClick props is only used for */}
|
||||
|
||||
Reference in New Issue
Block a user