🐛(react) fix inputs overflowing placeholder
The oveflowing labels were spreading on two lines. I had to wrap a span inside a label in order to be able to deal with the text-oveflow plus the absolute positionning.
This commit is contained in:
5
.changeset/soft-files-grin.md
Normal file
5
.changeset/soft-files-grin.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@openfun/cunningham-react": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix inputs overflowing placeholder
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
import { Meta } from "@storybook/react";
|
||||||
|
import React from "react";
|
||||||
|
import { Input } from ":/components/Forms/Input";
|
||||||
|
import { Checkbox } from ":/components/Forms/Checkbox";
|
||||||
|
import { Button } from ":/components/Button";
|
||||||
|
import { Select } from ":/components/Forms/Select";
|
||||||
|
import { CunninghamProvider } from ":/components/Provider";
|
||||||
|
import { FileUploader } from ":/components/Forms/FileUploader";
|
||||||
|
import { Switch } from ":/components/Forms/Switch";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: "Components/Forms/Examples/Edge Cases",
|
||||||
|
} as Meta;
|
||||||
|
|
||||||
|
export const OverflowLabels = () => {
|
||||||
|
const overflow = " and some very long overflowing text";
|
||||||
|
return (
|
||||||
|
<CunninghamProvider>
|
||||||
|
<form
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
gap: "1rem",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<h1
|
||||||
|
className="fs-h3 fw-bold clr-greyscale-900"
|
||||||
|
style={{ textAlign: "center" }}
|
||||||
|
>
|
||||||
|
Application
|
||||||
|
</h1>
|
||||||
|
<Select
|
||||||
|
label={"Context" + overflow}
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
label: "Ask a document",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Download files",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Ask for help",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
fullWidth={true}
|
||||||
|
/>
|
||||||
|
<div style={{ display: "flex", gap: "1rem" }}>
|
||||||
|
<div style={{ flexGrow: 1 }}>
|
||||||
|
<Input label={"First name" + overflow} fullWidth={true} />
|
||||||
|
</div>
|
||||||
|
<div style={{ flexGrow: 1 }}>
|
||||||
|
<Input label={"Last name" + overflow} fullWidth={true} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Input
|
||||||
|
label={"Email address" + overflow}
|
||||||
|
fullWidth={true}
|
||||||
|
text="Only @acme.com domain is authorized"
|
||||||
|
/>
|
||||||
|
<div style={{ display: "flex", gap: "1rem" }}>
|
||||||
|
<div style={{ width: "25%" }}>
|
||||||
|
<Input label={"ZIP" + overflow} fullWidth={true} />
|
||||||
|
</div>
|
||||||
|
<Input label={"City" + overflow} fullWidth={true} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="fs-l clr-greyscale-800 mb-t">
|
||||||
|
Your curriculum vitae
|
||||||
|
</div>
|
||||||
|
<FileUploader
|
||||||
|
fullWidth={true}
|
||||||
|
text="pdf only ( 4mb maximum )"
|
||||||
|
accept="application/pdf"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Switch label="SMS Notification" fullWidth={true} />
|
||||||
|
<Switch label="Subscribe to newsletter" fullWidth={true} />
|
||||||
|
</div>
|
||||||
|
<Checkbox label="Agree to the terms and services" fullWidth={true} />
|
||||||
|
<Button fullWidth={true}>Apply</Button>
|
||||||
|
<a
|
||||||
|
href="/#"
|
||||||
|
className="clr-greyscale-800 fs-m"
|
||||||
|
style={{ textAlign: "center" }}
|
||||||
|
>
|
||||||
|
Need help ?
|
||||||
|
</a>
|
||||||
|
</form>
|
||||||
|
</CunninghamProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -51,7 +51,7 @@ describe("<Input/>", () => {
|
|||||||
const input2: HTMLInputElement = screen.getByRole("textbox", {
|
const input2: HTMLInputElement = screen.getByRole("textbox", {
|
||||||
name: "Second name",
|
name: "Second name",
|
||||||
});
|
});
|
||||||
const label = screen.getByText("First name");
|
const label = screen.getByText("First name")!.parentElement!;
|
||||||
expect(Array.from(label.classList)).toContain("placeholder");
|
expect(Array.from(label.classList)).toContain("placeholder");
|
||||||
|
|
||||||
// Clicking on the input should remove the placeholder class.
|
// Clicking on the input should remove the placeholder class.
|
||||||
|
|||||||
@@ -15,12 +15,21 @@
|
|||||||
top: 0.5rem;
|
top: 0.5rem;
|
||||||
transition: all var(--c--theme--transitions--duration) var(--c--theme--transitions--ease-out);
|
transition: all var(--c--theme--transitions--duration) var(--c--theme--transitions--ease-out);
|
||||||
color: var(--c--components--forms-labelledbox--label-color--small);
|
color: var(--c--components--forms-labelledbox--label-color--small);
|
||||||
|
// Enable text overflow ellipsis.
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
|
|
||||||
&.placeholder {
|
&.placeholder {
|
||||||
@extend %text-style;
|
@extend %text-style;
|
||||||
top: 16px;
|
top: 16px;
|
||||||
color: var(--c--components--forms-labelledbox--label-color--big);
|
color: var(--c--components--forms-labelledbox--label-color--big);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__children {
|
&__children {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export const LabelledBox = ({
|
|||||||
htmlFor={htmlFor}
|
htmlFor={htmlFor}
|
||||||
id={labelId}
|
id={labelId}
|
||||||
>
|
>
|
||||||
{label}
|
<span>{label}</span>
|
||||||
</label>
|
</label>
|
||||||
)}
|
)}
|
||||||
<div className="labelled-box__children">{children}</div>
|
<div className="labelled-box__children">{children}</div>
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
label {
|
label {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
// In case of text-overflow we do not want the text to render above the toggle button arrow.
|
||||||
|
max-width: calc(100% - 1.5rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|||||||
@@ -868,7 +868,7 @@ describe("<Select/>", () => {
|
|||||||
const menu: HTMLDivElement = screen.getByRole("listbox", {
|
const menu: HTMLDivElement = screen.getByRole("listbox", {
|
||||||
name: "City",
|
name: "City",
|
||||||
});
|
});
|
||||||
const label = screen.getByText("City");
|
const label = screen.getByText("City")!.parentElement!;
|
||||||
const valueRendered = document.querySelector(".c__select__inner__value");
|
const valueRendered = document.querySelector(".c__select__inner__value");
|
||||||
|
|
||||||
// Make sure no value is rendered.
|
// Make sure no value is rendered.
|
||||||
@@ -1445,7 +1445,7 @@ describe("<Select/>", () => {
|
|||||||
screen.getByRole("combobox", {
|
screen.getByRole("combobox", {
|
||||||
name: "City",
|
name: "City",
|
||||||
});
|
});
|
||||||
const label = screen.getByText("City");
|
const label = screen.getByText("City")!.parentElement!;
|
||||||
expect(Array.from(label.classList)).toContain("offscreen");
|
expect(Array.from(label.classList)).toContain("offscreen");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ describe("<Select multi={true} />", () => {
|
|||||||
const menu: HTMLDivElement = screen.getByRole("listbox", {
|
const menu: HTMLDivElement = screen.getByRole("listbox", {
|
||||||
name: "Cities",
|
name: "Cities",
|
||||||
});
|
});
|
||||||
const label = screen.getByText("Cities");
|
const label = screen.getByText("Cities")!.parentElement!;
|
||||||
|
|
||||||
// Expect no options to be selected.
|
// Expect no options to be selected.
|
||||||
expectSelectedOptions([]);
|
expectSelectedOptions([]);
|
||||||
@@ -721,7 +721,7 @@ describe("<Select multi={true} />", () => {
|
|||||||
screen.getByRole("combobox", {
|
screen.getByRole("combobox", {
|
||||||
name: "Cities",
|
name: "Cities",
|
||||||
});
|
});
|
||||||
const label = screen.getByText("Cities");
|
const label = screen.getByText("Cities")!.parentElement!;
|
||||||
expect(Array.from(label.classList)).toContain("offscreen");
|
expect(Array.from(label.classList)).toContain("offscreen");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user