Skip to content

Commit a49450a

Browse files
committed
Readd explicit labels
1 parent 149de83 commit a49450a

File tree

6 files changed

+53
-101
lines changed

6 files changed

+53
-101
lines changed

src/components/controls/Input.tsx

Lines changed: 9 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import { twMerge } from "tailwind-merge";
44

55
import { RequiredKeys } from "@/types/utility";
66

7-
import Label, { style as labelStyle } from "./Label";
8-
97
export const style = cva("w-full rounded-full py-2 px-3 border-2", {
108
variants: {
119
color: {
@@ -18,94 +16,29 @@ export const style = cva("w-full rounded-full py-2 px-3 border-2", {
1816
}
1917
});
2018

21-
const borderStyle = cva("absolute inset-0 border-2 top-[-9px] rounded-[inherit] pl-[var(--label-inset)] pointer-events-none", {
22-
variants: {
23-
color: {
24-
primary: "border-primary",
25-
secondary: "border-secondary"
26-
},
27-
}
28-
});
29-
30-
export type BaseProps = {
31-
inputClassName?: string;
32-
labelClassName?: string;
33-
fieldsetClassName?: string;
34-
labelInset?: string;
35-
label?: ReactNode;
36-
};
37-
3819
export type TagProps = Omit<InputHTMLAttributes<HTMLInputElement>, "color">;
3920
export type VariantProps = GetVariantProps<typeof style>;
40-
export type InputProps = BaseProps & TagProps & RequiredKeys<VariantProps, "color">;
21+
export type InputProps = TagProps & RequiredKeys<VariantProps, "color">;
4122

4223
const Input = forwardRef((
4324
{
4425
className,
45-
inputClassName,
46-
labelClassName,
47-
fieldsetClassName,
48-
labelInset = "1.5rem",
49-
label,
5026
color,
51-
id,
5227
...props
5328
}: InputProps,
5429
ref: ForwardedRef<HTMLInputElement>
5530
) => {
5631

57-
const fallbackId = useId();
58-
59-
const computedClassName = useMemo(
60-
() => twMerge("relative rounded-full", className),
61-
[className]
62-
);
63-
64-
const computedInputClassName = useMemo(
65-
() => twMerge(
66-
style({ color }),
67-
"rounded-[inherit]",
68-
label ? "border-transparent" : "",
69-
inputClassName
70-
),
71-
[inputClassName, color, label]
72-
);
73-
74-
const computedLabelClassName = useMemo(
75-
() => twMerge("absolute left-[var(--label-inset)] top-0 translate-x-[2px] -translate-y-1/2 px-1", labelClassName),
76-
[labelClassName]
77-
);
78-
79-
const computedFieldsetClassName = useMemo(
80-
() => twMerge(borderStyle({ color }), fieldsetClassName),
81-
[color, fieldsetClassName]
82-
);
83-
84-
const computedLegendClassName = useMemo(
85-
() => twMerge(labelStyle(), "px-1 opacity-0"),
86-
[computedLabelClassName]
87-
);
88-
89-
const insetProps = useMemo<Record<string, string>>(
90-
() => ({ "--label-inset": labelInset }),
91-
[labelInset]
92-
);
32+
const computedClassName = useMemo(() => {
33+
return twMerge(style({ color }), className);
34+
}, [className, color]);
9335

9436
return (
95-
<div className={computedClassName}>
96-
{label && <Label className={computedLabelClassName} htmlFor={id ?? fallbackId} style={insetProps}>
97-
{label}
98-
</Label>}
99-
{label && <fieldset aria-hidden className={computedFieldsetClassName} style={insetProps}>
100-
<legend className={computedLegendClassName}>{label}</legend>
101-
</fieldset>}
102-
<input
103-
ref={ref}
104-
className={computedInputClassName}
105-
id={id ?? fallbackId}
106-
{...props}
107-
/>
108-
</div>
37+
<input
38+
ref={ref}
39+
className={computedClassName}
40+
{...props}
41+
/>
10942
);
11043
});
11144

src/components/controls/Label.tsx

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,37 @@
1-
import { cva } from "class-variance-authority";
1+
import { RequiredKeys } from "@/types/utility";
2+
import { cva, VariantProps as GetVariantProps } from "class-variance-authority";
23
import React, { DetailedHTMLProps, ForwardedRef, LabelHTMLAttributes, forwardRef, useMemo } from "react";
34
import { twMerge } from "tailwind-merge";
45

5-
export interface LabelProps extends DetailedHTMLProps<LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement> {
6-
htmlFor: string;
7-
}
86

9-
export const style = cva("text-sm font-bold block");
107

11-
const Label = forwardRef(({ className, ...props }: LabelProps, ref: ForwardedRef<HTMLLabelElement>) => {
8+
export const style = cva("text-sm font-bold block text-start", {
9+
variants: {
10+
inset: {
11+
true: "ml-4",
12+
false: ""
13+
}
14+
},
15+
defaultVariants: {
16+
inset: true
17+
}
18+
});
19+
20+
export type VariantProps = GetVariantProps<typeof style>;
21+
export type TagProps = RequiredKeys<DetailedHTMLProps<LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>, "htmlFor">;
22+
23+
export type LabelProps = VariantProps & TagProps;
24+
25+
const Label = forwardRef(({ className, inset, ...props }: LabelProps, ref: ForwardedRef<HTMLLabelElement>) => {
1226

1327
const computedClassName = useMemo(
14-
() => twMerge(style(), className),
15-
[className]
28+
() => twMerge(style({ inset }), className),
29+
[className, inset]
1630
);
1731

1832
return (
1933
<label
34+
ref={ref}
2035
className={computedClassName}
2136
{...props}
2237
/>

src/components/controls/TextArea.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { RequiredKeys } from "@/types/utility";
55

66
import { style as inputStyle, VariantProps as InputVariantProps } from "./Input";
77

8-
export const style: typeof inputStyle = (props) => twMerge(inputStyle(props), "rounded-lg");
8+
export const style: typeof inputStyle = (props) => twMerge(inputStyle(props), "rounded-2xl");
99

1010
export type TagProps = DetailedHTMLProps<TextareaHTMLAttributes<HTMLTextAreaElement>, HTMLTextAreaElement>;
1111
export type VariantProps = InputVariantProps;

src/components/pages/contribute/FeedbackSection.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ const FeedbackSection = () => {
6565
oneTime
6666
>
6767
<div className="w-full">
68-
<Label htmlFor="message-input" className="text-start text-secondary">
68+
<Label htmlFor="message-input" className="text-start text-primary">
6969
Your Message:
7070
</Label>
7171
<TextArea

src/components/pages/front/SignupSection.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import Heading from "@/components/layout/Heading";
1515
import { backend } from "@/utils/wretch";
1616
import useFormMutation from "@/hooks/useMutation";
1717
import { sendSubscribeEvent } from "@/api/analytics";
18+
import Label from "@/components/controls/Label";
1819

1920
const signupSchema = z.object({
2021
email: z.string().email().min(5, "Your email must at least contain 5 characters")
@@ -77,15 +78,14 @@ const SignupSection = () => {
7778
oneTime
7879
>
7980
<div className="w-full">
81+
<Label htmlFor="signup-email-input" className="text-primary ml-7">
82+
Email:
83+
</Label>
8084
<Input
8185
id="signup-email-input"
8286
color="primary"
83-
className="w-full text-lg md:text-xl"
84-
inputClassName="p-4"
87+
className="w-full text-lg md:text-xl p-4"
8588
placeholder="your@email.com"
86-
label="Email:"
87-
labelInset="2rem"
88-
labelClassName="text-primary"
8989
{...register("email")}
9090
/>
9191
<Error className="w-full px-2 text-start" state={formState} name="email" />

src/pages/mail/unsubscribe.tsx

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import Input from "@/components/controls/Input";
1717
import Form from "@/components/controls/Form";
1818
import Heading from "@/components/layout/Heading";
1919
import Button from "@/components/controls/Button";
20+
import Label from "@/components/controls/Label";
2021

2122

2223
const unsubscribeSchema = z.object({
@@ -36,8 +37,8 @@ const UnsubscribePage: Page = ({ pathname }) => {
3637
backend.url("/email/unsubscribe")
3738
.post({ email })
3839
.json((res: BackendResponse) => {
39-
if (res.success) sendUnsubscribeEvent()
40-
setResponse(res)
40+
if (res.success) sendUnsubscribeEvent();
41+
setResponse(res);
4142
});
4243
});
4344

@@ -61,14 +62,17 @@ const UnsubscribePage: Page = ({ pathname }) => {
6162
<p className="max-w-md">
6263
Once you unsubscribe you won't receive any more emails from us and your email will be immediately deleted from our records.
6364
</p>
64-
<Input
65-
id="email-input"
66-
color="secondary"
67-
placeholder="your@email.com"
68-
label="Email:"
69-
labelClassName="text-secondary"
70-
{...register("email")}
71-
/>
65+
<div>
66+
<Label htmlFor="email-input" className="text-secondary">
67+
Email:
68+
</Label>
69+
<Input
70+
id="email-input"
71+
color="secondary"
72+
placeholder="your@email.com"
73+
{...register("email")}
74+
/>
75+
</div>
7276
<Button type="submit" color="secondary">
7377
{!loading
7478
? "Unsubscribe"

0 commit comments

Comments
 (0)