diff --git a/COMPONENTS.md b/COMPONENTS.md index c803b95f9..ce489798f 100644 --- a/COMPONENTS.md +++ b/COMPONENTS.md @@ -40,4 +40,4 @@ - [ ] Tag - [ ] Download - [ ] Transcription -- [ ] Tile +- [x] Tile diff --git a/package.json b/package.json index 4ec9f9880..80c485bbe 100644 --- a/package.json +++ b/package.json @@ -123,6 +123,7 @@ "./next": "./dist/next.js", "./mui": "./dist/mui.js", "./lib": "./dist/lib/index.js", + "./Tile": "./dist/Tile.js", "./Tabs": "./dist/Tabs.js", "./Summary": "./dist/Summary.js", "./Stepper": "./dist/Stepper.js", diff --git a/src/Tile.tsx b/src/Tile.tsx new file mode 100644 index 000000000..7dc9018db --- /dev/null +++ b/src/Tile.tsx @@ -0,0 +1,99 @@ +import React, { memo, forwardRef } from "react"; +import type { ReactNode } from "react"; +import { symToStr } from "tsafe/symToStr"; +import { assert } from "tsafe/assert"; +import type { Equals } from "tsafe"; +import { RegisteredLinkProps, fr } from "./lib"; +import { cx } from "./lib/tools/cx"; +import { getLink } from "./lib/routing"; + +//https://main--ds-gouv.netlify.app/example/component/tile/ +export type TileProps = { + className?: string; + title: ReactNode; + linkProps: RegisteredLinkProps; + desc?: ReactNode; + imageUrl?: string; + imageAlt?: string; + grey?: boolean; + + /** make the whole tile clickable */ + enlargeLink?: boolean; + classes?: Partial< + Record<"root" | "title" | "link" | "body" | "desc" | "img" | "imgTag", string> + >; + /** Default false */ + horizontal?: boolean; +}; + +export namespace TileProps {} + +/** @see */ +export const Tile = memo( + forwardRef((props, ref) => { + const { + className, + title, + linkProps, + desc, + imageUrl, + imageAlt, + horizontal = false, + grey = false, + classes = {}, + enlargeLink = true, + ...rest + } = props; + + assert>(); + + const { Link } = getLink(); + + return ( +
+
+

+ + {title} + +

+

{desc}

+
+ {(imageUrl !== undefined && imageUrl.length && ( +
+ {imageAlt} +
+ )) || + null} +
+ ); + }) +); + +Tile.displayName = symToStr({ Tile }); + +export default Tile; diff --git a/stories/Tile.stories.tsx b/stories/Tile.stories.tsx new file mode 100644 index 000000000..c7c98317e --- /dev/null +++ b/stories/Tile.stories.tsx @@ -0,0 +1,60 @@ +import { Tile } from "../dist/Tile"; +import { sectionName } from "./sectionName"; +import { getStoryFactory } from "./getStory"; + +const { meta, getStory } = getStoryFactory({ + sectionName, + "wrappedComponent": { Tile }, + defaultContainerWidth: 300, + "description": ` +- [See DSFR documentation](//www.systeme-de-design.gouv.fr/elements-d-interface/composants/tuile) +- [See DSFR demos](https://main--ds-gouv.netlify.app/example/component/tile/) +- [See source code](//github.com/codegouvfr/react-dsfr/blob/main/src/Tile.tsx)`, + "disabledProps": ["lang"] +}); + +export default meta; + +export const Default = getStory({ + linkProps: { href: "#" }, + title: "Titre de la tuile", + desc: "Lorem ipsum dolor sit amet, consectetur adipiscing, incididunt, ut labore et dol", + enlargeLink: true, + horizontal: false +}); + +export const TileWithoutEnlargeLink = getStory({ + linkProps: { href: "#" }, + title: "Titre de la tuile", + desc: "Lorem ipsum dolor sit amet, consectetur adipiscing, incididunt, ut labore et dol", + enlargeLink: false +}); + +export const TileWithImage = getStory({ + linkProps: { href: "#" }, + title: "Titre de la tuile", + desc: "Lorem ipsum dolor sit amet, consectetur adipiscing, incididunt, ut labore et dol", + enlargeLink: false, + imageUrl: "//www.gouvernement.fr/sites/default/files/static_assets/placeholder.1x1.png" +}); + +export const TileWithImageGrey = getStory({ + linkProps: { href: "#" }, + title: "Titre de la tuile", + desc: "Lorem ipsum dolor sit amet, consectetur adipiscing, incididunt, ut labore et dol", + enlargeLink: false, + imageUrl: "//www.gouvernement.fr/sites/default/files/static_assets/placeholder.1x1.png", + grey: true +}); + +export const TileHorizontalWithImage = getStory( + { + linkProps: { href: "#" }, + horizontal: true, + title: "Titre de la tuile", + desc: "Lorem ipsum dolor sit amet, consectetur adipiscing, incididunt, ut labore et dol", + enlargeLink: true, + imageUrl: "//www.gouvernement.fr/sites/default/files/static_assets/placeholder.1x1.png" + }, + { defaultContainerWidth: "100%" } +); diff --git a/stories/getStory.tsx b/stories/getStory.tsx index 5608151fd..3f1ae9df0 100644 --- a/stories/getStory.tsx +++ b/stories/getStory.tsx @@ -94,7 +94,7 @@ export function getStoryFactory>(params: { function getStory( props: Props, - params?: { defaultContainerWidth?: number; description?: string } + params?: { defaultContainerWidth?: number | string; description?: string } ): typeof Template { const { defaultContainerWidth: defaultContainerWidthStoryLevel, description } = params ?? {};