UNPKG

3.46 kBTypeScriptView Raw
1import React, { memo, forwardRef, type ReactNode, type CSSProperties } from "react";
2import { symToStr } from "tsafe/symToStr";
3import { assert } from "tsafe/assert";
4import type { Equals } from "tsafe";
5import type { RegisteredLinkProps } from "./link";
6import { getLink } from "./link";
7import { fr } from "./fr";
8import { cx } from "./tools/cx";
9import { useAnalyticsId } from "./tools/useAnalyticsId";
10
11//https://main--ds-gouv.netlify.app/example/component/tile/
12export type TileProps = {
13 id?: string;
14 className?: string;
15 title: ReactNode;
16 linkProps: RegisteredLinkProps;
17 desc?: ReactNode;
18 imageUrl?: string;
19 imageAlt?: string;
20 imageWidth?: string | number;
21 imageHeight?: string | number;
22 grey?: boolean;
23
24 /** make the whole tile clickable */
25 enlargeLink?: boolean;
26 classes?: Partial<
27 Record<"root" | "title" | "link" | "body" | "desc" | "img" | "imgTag", string>
28 >;
29 /** Default false */
30 horizontal?: boolean;
31 style?: CSSProperties;
32};
33
34export namespace TileProps {}
35
36/** @see <https://components.react-dsfr.codegouv.studio/?path=/docs/components-tile> */
37export const Tile = memo(
38 forwardRef<HTMLDivElement, TileProps>((props, ref) => {
39 const {
40 id: id_props,
41 className,
42 title,
43 linkProps,
44 desc,
45 imageUrl,
46 imageAlt,
47 imageWidth,
48 imageHeight,
49 horizontal = false,
50 grey = false,
51 classes = {},
52 enlargeLink = true,
53 style,
54 ...rest
55 } = props;
56
57 assert<Equals<keyof typeof rest, never>>();
58
59 const { Link } = getLink();
60
61 const id = useAnalyticsId({
62 "defaultIdPrefix": "fr-tile",
63 "explicitlyProvidedId": id_props
64 });
65
66 return (
67 <div
68 id={id}
69 className={cx(
70 fr.cx(
71 "fr-tile",
72 enlargeLink && "fr-enlarge-link",
73 horizontal && "fr-tile--horizontal",
74 grey && "fr-tile--grey"
75 ),
76 classes.root,
77 className
78 )}
79 ref={ref}
80 style={style}
81 {...rest}
82 >
83 <div className={cx(fr.cx("fr-tile__body"), classes.body)}>
84 <h3 className={cx(fr.cx("fr-tile__title"), classes.title)}>
85 <Link {...linkProps} className={cx(classes.link, linkProps.className)}>
86 {title}
87 </Link>
88 </h3>
89 <p className={cx(fr.cx("fr-tile__desc"), classes.desc)}>{desc}</p>
90 </div>
91 {(imageUrl !== undefined && imageUrl.length && (
92 <div className={cx(fr.cx("fr-tile__img"), classes.img)}>
93 <img
94 className={cx(fr.cx("fr-responsive-img"), classes.imgTag)}
95 src={imageUrl}
96 alt={imageAlt}
97 width={imageWidth}
98 height={imageHeight}
99 />
100 </div>
101 )) ||
102 null}
103 </div>
104 );
105 })
106);
107
108Tile.displayName = symToStr({ Tile });
109
110export default Tile;
111
\No newline at end of file