Skip to content

Commit 334b804

Browse files
committed
fix(Tag): fully convert Tag as parahraph element by default
1 parent 1f54b1f commit 334b804

File tree

1 file changed

+104
-93
lines changed

1 file changed

+104
-93
lines changed

src/Tag.tsx

Lines changed: 104 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ type DataAttribute = Record<`data-${string}`, string | boolean | null | undefine
2222

2323
export type TagProps = TagProps.Common &
2424
(TagProps.WithIcon | TagProps.WithoutIcon) &
25-
(TagProps.AsAnchor | TagProps.AsButton | TagProps.AsSpan);
25+
(TagProps.AsAnchor | TagProps.AsButton | TagProps.AsParagraph);
2626
export namespace TagProps {
2727
export type Common = {
2828
id?: string;
@@ -47,134 +47,145 @@ export namespace TagProps {
4747
linkProps: RegisteredLinkProps;
4848
onClick?: never;
4949
nativeButtonProps?: never;
50+
/** @deprecated Tag is now <p> by default. Use `nativeParagraphProps` instead. */
5051
nativeSpanProps?: never;
52+
nativeParagraphProps?: never;
5153
dismissible?: never;
5254
pressed?: never;
5355
};
5456
export type AsButton = {
5557
linkProps?: never;
58+
/** @deprecated Tag is now <p> by default. Use `nativeParagraphProps` instead. */
5659
nativeSpanProps?: never;
60+
nativeParagraphProps?: never;
5761
/** Default: false */
5862
dismissible?: boolean;
5963
pressed?: boolean;
6064
onClick?: React.MouseEventHandler<HTMLButtonElement>;
6165
nativeButtonProps?: ComponentProps<"button"> & DataAttribute;
6266
};
63-
export type AsSpan = {
67+
export type AsParagraph = {
6468
linkProps?: never;
6569
onClick?: never;
6670
dismissible?: never;
6771
pressed?: never;
6872
nativeButtonProps?: never;
73+
/** @deprecated Tag is now <p> by default. Use `nativeParagraphProps` instead. */
6974
nativeSpanProps?: ComponentProps<"span"> & DataAttribute;
75+
nativeParagraphProps?: ComponentProps<"p"> & DataAttribute;
7076
};
77+
78+
/** @deprecated Tag is now <p> by default. Use `AsParagraph` instead. */
79+
export type AsSpan = AsParagraph;
7180
}
7281

7382
/** @see <https://components.react-dsfr.codegouv.studio/?path=/docs/components-tag> */
7483
export const Tag = memo(
75-
forwardRef<HTMLButtonElement | HTMLAnchorElement | HTMLSpanElement, TagProps>((props, ref) => {
76-
const {
77-
id: id_props,
78-
className: prop_className,
79-
children,
80-
title,
81-
iconId,
82-
small = false,
83-
pressed,
84-
dismissible = false,
85-
linkProps,
86-
nativeButtonProps,
87-
nativeSpanProps,
88-
style,
89-
onClick,
90-
...rest
91-
} = props;
84+
forwardRef<HTMLButtonElement | HTMLAnchorElement | HTMLParagraphElement, TagProps>(
85+
(props, ref) => {
86+
const {
87+
id: id_props,
88+
className: prop_className,
89+
children,
90+
title,
91+
iconId,
92+
small = false,
93+
pressed,
94+
dismissible = false,
95+
linkProps,
96+
nativeButtonProps,
97+
nativeParagraphProps,
98+
style,
99+
onClick,
100+
...rest
101+
} = props;
92102

93-
assert<Equals<keyof typeof rest, never>>();
103+
assert<Equals<keyof typeof rest, "nativeSpanProps">>();
94104

95-
const id = useAnalyticsId({
96-
"defaultIdPrefix": "fr-tag",
97-
"explicitlyProvidedId": id_props
98-
});
105+
const id = useAnalyticsId({
106+
"defaultIdPrefix": "fr-tag",
107+
"explicitlyProvidedId": id_props
108+
});
99109

100-
const { Link } = getLink();
110+
const { Link } = getLink();
101111

102-
const className = cx(
103-
fr.cx(
104-
"fr-tag",
105-
small && `fr-tag--sm`,
106-
iconId,
107-
iconId && "fr-tag--icon-left", // actually, it's always left but we need it in order to have the icon rendering
108-
dismissible && "fr-tag--dismiss"
109-
),
110-
linkProps !== undefined && linkProps.className,
111-
prop_className
112-
);
112+
const className = cx(
113+
fr.cx(
114+
"fr-tag",
115+
small && `fr-tag--sm`,
116+
iconId,
117+
iconId && "fr-tag--icon-left", // actually, it's always left but we need it in order to have the icon rendering
118+
dismissible && "fr-tag--dismiss"
119+
),
120+
linkProps !== undefined && linkProps.className,
121+
prop_className
122+
);
113123

114-
return (
115-
<>
116-
{linkProps !== undefined && (
117-
<Link
118-
{...linkProps}
119-
id={id_props ?? linkProps.id ?? id}
120-
title={title ?? linkProps.title}
121-
className={cx(linkProps?.className, className)}
122-
style={{
123-
...linkProps?.style,
124-
...style
125-
}}
126-
ref={ref as React.ForwardedRef<HTMLAnchorElement>}
127-
{...rest}
128-
>
129-
{children}
130-
</Link>
131-
)}
132-
{nativeButtonProps !== undefined && (
133-
<button
134-
{...nativeButtonProps}
135-
id={id_props ?? nativeButtonProps.id ?? id}
136-
className={cx(nativeButtonProps?.className, className)}
137-
style={{
138-
...nativeButtonProps?.style,
139-
...style
140-
}}
141-
title={title ?? nativeButtonProps?.title}
142-
onClick={onClick ?? nativeButtonProps?.onClick}
143-
disabled={nativeButtonProps?.disabled}
144-
ref={ref as React.ForwardedRef<HTMLButtonElement>}
145-
aria-pressed={pressed}
146-
{...rest}
147-
>
148-
{children}
149-
</button>
150-
)}
151-
{linkProps === undefined && nativeButtonProps === undefined && (
152-
<p
153-
{...nativeSpanProps}
154-
id={id_props ?? nativeSpanProps?.id ?? id}
155-
className={cx(nativeSpanProps?.className, className)}
156-
style={{
157-
...nativeSpanProps?.style,
158-
...style
159-
}}
160-
title={title ?? nativeSpanProps?.title}
161-
ref={ref as React.ForwardedRef<HTMLParagraphElement>}
162-
{...rest}
163-
>
164-
{children}
165-
</p>
166-
)}
167-
</>
168-
);
169-
})
124+
return (
125+
<>
126+
{linkProps !== undefined && (
127+
<Link
128+
{...linkProps}
129+
id={id_props ?? linkProps.id ?? id}
130+
title={title ?? linkProps.title}
131+
className={cx(linkProps?.className, className)}
132+
style={{
133+
...linkProps?.style,
134+
...style
135+
}}
136+
ref={ref as React.ForwardedRef<HTMLAnchorElement>}
137+
{...rest}
138+
>
139+
{children}
140+
</Link>
141+
)}
142+
{nativeButtonProps !== undefined && (
143+
<button
144+
{...nativeButtonProps}
145+
id={id_props ?? nativeButtonProps.id ?? id}
146+
className={cx(nativeButtonProps?.className, className)}
147+
style={{
148+
...nativeButtonProps?.style,
149+
...style
150+
}}
151+
title={title ?? nativeButtonProps?.title}
152+
onClick={onClick ?? nativeButtonProps?.onClick}
153+
disabled={nativeButtonProps?.disabled}
154+
ref={ref as React.ForwardedRef<HTMLButtonElement>}
155+
aria-pressed={pressed}
156+
{...rest}
157+
>
158+
{children}
159+
</button>
160+
)}
161+
{linkProps === undefined && nativeButtonProps === undefined && (
162+
<p
163+
{...nativeParagraphProps}
164+
id={id_props ?? nativeParagraphProps?.id ?? id}
165+
className={cx(nativeParagraphProps?.className, className)}
166+
style={{
167+
...nativeParagraphProps?.style,
168+
...style
169+
}}
170+
title={title ?? nativeParagraphProps?.title}
171+
ref={ref as React.ForwardedRef<HTMLParagraphElement>}
172+
{...rest}
173+
>
174+
{children}
175+
</p>
176+
)}
177+
</>
178+
);
179+
}
180+
)
170181
) as MemoExoticComponent<
171182
ForwardRefExoticComponent<
172183
TagProps.Common &
173184
(TagProps.WithIcon | TagProps.WithoutIcon) &
174185
(
175186
| (TagProps.AsAnchor & RefAttributes<HTMLAnchorElement>)
176187
| (TagProps.AsButton & RefAttributes<HTMLButtonElement>)
177-
| (TagProps.AsSpan & RefAttributes<HTMLSpanElement>)
188+
| (TagProps.AsParagraph & RefAttributes<HTMLParagraphElement>)
178189
)
179190
>
180191
>;

0 commit comments

Comments
 (0)