diff --git a/COMPONENTS.md b/COMPONENTS.md index c48c557b6..c803b95f9 100644 --- a/COMPONENTS.md +++ b/COMPONENTS.md @@ -35,7 +35,7 @@ - [ ] Share - [x] Footer - [ ] Translate -- [ ] Summary +- [x] Summary - [ ] Table - [ ] Tag - [ ] Download diff --git a/package.json b/package.json index a1a0648f9..6d8cc90c7 100644 --- a/package.json +++ b/package.json @@ -124,6 +124,7 @@ "./mui": "./dist/mui.js", "./lib": "./dist/lib/index.js", "./Tabs": "./dist/Tabs.js", + "./Summary": "./dist/Summary.js", "./Stepper": "./dist/Stepper.js", "./SkipLinks": "./dist/SkipLinks.js", "./Quote": "./dist/Quote.js", diff --git a/src/Summary.tsx b/src/Summary.tsx new file mode 100644 index 000000000..6917d8971 --- /dev/null +++ b/src/Summary.tsx @@ -0,0 +1,100 @@ +import React, { memo, forwardRef, useId } from "react"; +import { symToStr } from "tsafe/symToStr"; +import { assert } from "tsafe/assert"; +import type { Equals } from "tsafe"; + +import { createComponentI18nApi } from "./lib/i18n"; +import { cx } from "./lib/tools/cx"; +import { fr, RegisteredLinkProps } from "./lib"; +import { getLink } from "./lib/routing"; + +import "./dsfr/component/summary/summary.css"; + +type SummaryLink = { + text: string; + linkProps: RegisteredLinkProps; +}; + +export type SummaryProps = { + className?: string; + links: SummaryLink[]; + title?: string; + /** Default: "p" */ + as?: "p" | "h2" | "h3" | "h4" | "h5" | "h6"; + classes?: Partial>; +}; + +/** @see */ +export const Summary = memo( + forwardRef((props, ref) => { + const { className, links, as = "p", title, classes = {}, ...rest } = props; + + const { t } = useTranslation(); + + const titleId = useId(); + const summaryTitle = title ?? t("title"); + + const { Link } = getLink(); + + assert>(); + + return ( + + ); + }) +); + +Summary.displayName = symToStr({ Summary }); + +const { useTranslation, addSummaryTranslations } = createComponentI18nApi({ + "componentName": symToStr({ Summary }), + "frMessages": { + /* spell-checker: disable */ + "title": "Sommaire" + /* spell-checker: enable */ + } +}); + +addSummaryTranslations({ + "lang": "en", + "messages": { + "title": "Summary" + } +}); + +export { addSummaryTranslations }; + +export default Summary; diff --git a/stories/Summary.stories.tsx b/stories/Summary.stories.tsx new file mode 100644 index 000000000..76ea3ff60 --- /dev/null +++ b/stories/Summary.stories.tsx @@ -0,0 +1,73 @@ +import { Summary } from "../dist/Summary"; +import { sectionName } from "./sectionName"; +import { getStoryFactory } from "./getStory"; + +const { meta, getStory } = getStoryFactory({ + sectionName, + "wrappedComponent": { Summary }, + "description": ` +- [See DSFR documentation](//www.systeme-de-design.gouv.fr/elements-d-interface/composants/sommaire) +- [See source code](//github.com/codegouvfr/react-dsfr/blob/main/src/Summary.tsx)`, + "disabledProps": ["lang"] +}); + +export default meta; + +export const Default = getStory({ + links: [ + { + linkProps: { href: "#" }, + text: "Titre de l’ancre" + }, + { + linkProps: { href: "#" }, + + text: "Titre de l’ancre" + }, + { + linkProps: { href: "#" }, + + text: "Titre de l’ancre" + }, + { + linkProps: { href: "#" }, + + text: "Titre de l’ancre" + }, + { + linkProps: { href: "#" }, + + text: "Titre de l’ancre" + } + ] +}); + +export const SummaryWithCustomTitle = getStory({ + title: "Sommaire personnalisé", + links: [ + { + linkProps: { href: "#" }, + text: "Titre de l’ancre" + }, + { + linkProps: { href: "#" }, + + text: "Titre de l’ancre" + }, + { + linkProps: { href: "#" }, + + text: "Titre de l’ancre" + }, + { + linkProps: { href: "#" }, + + text: "Titre de l’ancre" + }, + { + linkProps: { href: "#" }, + + text: "Titre de l’ancre" + } + ] +});