diff --git a/.eslintignore b/.eslintignore index 5169dece6..c783be4f4 100644 --- a/.eslintignore +++ b/.eslintignore @@ -4,4 +4,4 @@ CHANGELOG.md .yarn_home/ /test/integration/ /storybook-static/ -!.storybook + diff --git a/.storybook/DocsContainer.tsx b/.storybook/DocsContainer.js similarity index 56% rename from .storybook/DocsContainer.tsx rename to .storybook/DocsContainer.js index 38fa534c4..868a401fb 100644 --- a/.storybook/DocsContainer.tsx +++ b/.storybook/DocsContainer.js @@ -1,10 +1,7 @@ -import React, { PropsWithChildren, useEffect } from "react"; -import { - DocsContainer as BaseContainer, - DocsContainerProps, - Unstyled -} from "@storybook/addon-docs/blocks"; -import { useDarkMode } from "@vueless/storybook-dark-mode"; + +import React, { useEffect } from "react"; +import { DocsContainer as BaseContainer } from "@storybook/addon-docs"; +import { useDarkMode } from "storybook-dark-mode"; import { darkTheme, lightTheme } from "./customTheme"; import "../dist/dsfr/utility/icons/icons.min.css"; import "../dist/dsfr/dsfr.css"; @@ -12,33 +9,25 @@ import { useIsDark } from "../dist/useIsDark"; import { startReactDsfr } from "../dist/spa"; import { fr } from "../dist/fr"; import { MuiDsfrThemeProvider } from "../dist/mui"; -import { TableOfContentsCustom, TocType } from "./TableOfContents"; startReactDsfr({ "defaultColorScheme": "system", "useLang": () => "fr" }); -export const DocsContainer = ({ children, context }: PropsWithChildren) => { +export const DocsContainer = ({ children, context }) => { const isStorybookUiDark = useDarkMode(); const { setIsDark } = useIsDark(); - useEffect(() => { - setIsDark(isStorybookUiDark); - }, [isStorybookUiDark]); + useEffect( + ()=> { + setIsDark(isStorybookUiDark); + }, + [isStorybookUiDark] + ); const backgroundColor = fr.colors.decisions.background.default.grey.default; - // took from addon-docs/src/blocks/DocsContainer.tsx - let toc: TocType | undefined; - try { - const meta = context.resolveOf("meta", ["meta"]); - toc = meta.preparedMeta.parameters?.docs?.toc; - } catch (err) { - // No meta, falling back to project annotations - toc = context?.projectAnnotations?.parameters?.docs?.toc; - } - return ( <> - + { + const storyContext = context.storyById(id); + return { + ...storyContext, + "parameters": { + ...storyContext?.parameters, + "docs": { + ...storyContext?.parameters?.docs, + "theme": isStorybookUiDark ? darkTheme : lightTheme + } + } + }; + } + }} + > - - {toc && } - {children} - + {children} diff --git a/.storybook/Stories.tsx b/.storybook/Stories.tsx deleted file mode 100644 index 77bde5d3c..000000000 --- a/.storybook/Stories.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from "react"; -import { Stories as BaseStories } from "@storybook/addon-docs/blocks"; -import { type PropsOf } from "@emotion/react"; - -export const Stories = (props: PropsOf) => { - return ; -}; diff --git a/.storybook/TableOfContents.tsx b/.storybook/TableOfContents.tsx deleted file mode 100644 index 74e37d69b..000000000 --- a/.storybook/TableOfContents.tsx +++ /dev/null @@ -1,156 +0,0 @@ -import { styled } from "storybook/theming"; -import SideMenu, { SideMenuProps } from "../dist/SideMenu"; -import Channel from "storybook/internal/channels"; -import { NAVIGATE_URL } from "storybook/internal/core-events"; -import React, { useEffect, useState } from "react"; -import { DocsTypes } from "@storybook/addon-docs"; - -export type TocType = Exclude["docs"]["toc"], undefined>; - -const Aside = styled.div` - position: fixed; - right: 4rem; - top: 0; - bottom: 0; - width: 16rem; - z-index: 1; - overflow: auto; - padding-top: 4rem; - padding-bottom: 2rem; - padding-left: 1rem; - padding-right: 1rem; - - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); - -webkit-overflow-scrolling: touch; - - @media (max-width: 768px) { - display: none; - } - - & .fr-sidemenu__inner { - padding: 0; - } - - & .fr-sidemenu__link { - padding: 0.5rem 0.75rem; - } -`; - -/** - * Hook pour détecter le heading actuellement visible avec IntersectionObserver - */ -function useActiveHeading(headings: HTMLHeadingElement[]) { - const [activeId, setActiveId] = useState(""); - - useEffect(() => { - if (headings.length === 0) return; - - // Map pour stocker les ratios d'intersection de chaque heading - const headingObservers = new Map(); - - const observer = new IntersectionObserver( - entries => { - // Mettre à jour le ratio d'intersection pour chaque heading observé - entries.forEach(entry => { - const id = entry.target.id; - if (entry.isIntersecting) { - headingObservers.set(id, entry.intersectionRatio); - } else { - headingObservers.set(id, 0); - } - }); - - // Trouver le heading avec le plus grand ratio d'intersection - let maxRatio = 0; - let activeHeadingId = ""; - - headingObservers.forEach((ratio, id) => { - if (ratio > maxRatio) { - maxRatio = ratio; - activeHeadingId = id; - } - }); - - // Ne mettre à jour que si on a trouvé un heading visible - // Sinon on garde l'état précédent - if (activeHeadingId && activeHeadingId !== activeId) { - setActiveId(activeHeadingId); - } else if (!activeId && headings.length > 0) { - // Cas initial : si aucun heading n'est actif encore, prendre le premier - setActiveId(headings[0].id); - } - }, - { - // rootMargin négatif = créer une zone "active" au centre du viewport - // "-20% 0px -35% 0px" = zone active entre 20% du haut et 65% du bas - rootMargin: "-20% 0px -35% 0px", - threshold: [0, 0.25, 0.5, 0.75, 1] // Observer à différents niveaux de visibilité - } - ); - - // Observer tous les headings - headings.forEach(heading => { - if (heading.id) { - observer.observe(heading); - headingObservers.set(heading.id, 0); - } - }); - - return () => { - observer.disconnect(); - }; - }, [headings, activeId]); - - return activeId; -} - -interface TableOfContentsCustomProps { - channel: Channel; -} - -export const TableOfContentsCustom = ({ channel }: TableOfContentsCustomProps) => { - const [headingElements, setHeadingElements] = useState([]); - - // Initialiser les headings une seule fois - useEffect(() => { - const contentElement = document.querySelector(".sbdocs-content"); - const elements = Array.from( - contentElement?.querySelectorAll( - "h3:not(.docs-story *, .skip-toc)" - ) ?? [] - ); - setHeadingElements(elements); - }, []); - - // Utiliser le hook pour tracker l'ID actif - const activeId = useActiveHeading(headingElements); - - // Créer les items avec isActive - const headings = headingElements.map(heading => ({ - text: (heading.innerText || heading.textContent).trim(), - isActive: heading.id === activeId, - linkProps: { - href: `#${heading.id}`, - onClick(e) { - e.preventDefault(); - if (e.currentTarget instanceof HTMLAnchorElement) { - const [, headerId] = e.currentTarget.href.split("#"); - if (headerId) { - channel.emit(NAVIGATE_URL, { url: `#${headerId}` }); - document.querySelector(`#${heading.id}`)?.scrollIntoView({ - behavior: "smooth" - }); - } - } - } - } - })); - - return ( - - ); -}; diff --git a/.storybook/customTheme.js b/.storybook/customTheme.js new file mode 100644 index 000000000..fac2e29a0 --- /dev/null +++ b/.storybook/customTheme.js @@ -0,0 +1,35 @@ +import { create } from "@storybook/theming"; + +const brandImage= "logo.png"; +const brandTitle= "@codegouvfr/react-dsfr"; +const brandUrl= "https://github.com/codegouvfr/react-dsfr"; +const fontBase= '"Marianne", arial, sans-serif'; +const fontCode= "monospace"; + +export const darkTheme = create({ + "base": "dark", + "appBg": "#1E1E1E", + "appContentBg": "#161616", + "barBg": "#161616", + "colorSecondary": "#8585F6", + "textColor": "#FFFFFF", + brandImage, + brandTitle, + brandUrl, + fontBase, + fontCode +}); + +export const lightTheme = create({ + "base": "light", + "appBg": "#F6F6F6", + "appContentBg": "#FFFFFF", + "barBg": "#FFFFFF", + "colorSecondary": "#000091", + "textColor": "#212121", + brandImage, + brandTitle, + brandUrl, + fontBase, + fontCode +}); diff --git a/.storybook/customTheme.ts b/.storybook/customTheme.ts deleted file mode 100644 index 54e08e63b..000000000 --- a/.storybook/customTheme.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { create } from "storybook/theming"; - -const brandImage = "logo.png"; -const brandTitle = "@codegouvfr/react-dsfr"; -const brandUrl = "https://github.com/codegouvfr/react-dsfr"; -const fontBase = '"Marianne", arial, sans-serif'; -const fontCode = "monospace"; - -export const darkTheme = create({ - base: "dark", - appBg: "#1E1E1E", - appContentBg: "#161616", - barBg: "#161616", - colorSecondary: "#8585F6", - textColor: "#FFFFFF", - brandImage, - brandTitle, - brandUrl, - fontBase, - fontCode -}); - -export const lightTheme = create({ - base: "light", - appBg: "#F6F6F6", - appContentBg: "#FFFFFF", - barBg: "#FFFFFF", - colorSecondary: "#000091", - textColor: "#212121", - brandImage, - brandTitle, - brandUrl, - fontBase, - fontCode -}); diff --git a/.storybook/main.js b/.storybook/main.js new file mode 100644 index 000000000..8ae8ed940 --- /dev/null +++ b/.storybook/main.js @@ -0,0 +1,19 @@ +module.exports = { + "stories": [ + "../stories/*.stories.mdx", + "../stories/*.stories.@(ts|tsx)", + "../stories/blocks/*.stories.@(ts|tsx)", + "../stories/charts/*.stories.@(ts|tsx)", + "../stories/picto/*.stories.@(ts|tsx)", + ], + "addons": [ + "@storybook/addon-links", + "@storybook/addon-essentials", + "storybook-dark-mode", + "@storybook/addon-a11y" + ], + "core": { + "builder": "webpack5" + }, + "staticDirs": ["../dist", "./static"] +}; diff --git a/.storybook/main.ts b/.storybook/main.ts deleted file mode 100644 index 361d39f5c..000000000 --- a/.storybook/main.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { defineMain } from "@storybook/react-vite/node"; - -export default defineMain({ - framework: "@storybook/react-vite", - features: { - backgrounds: false - }, - stories: [ - "../stories/*.mdx", - "../stories/*.stories.@(ts|tsx)", - "../stories/blocks/*.stories.@(ts|tsx)", - "../stories/charts/*.stories.@(ts|tsx)" - ], - addons: [ - "@vueless/storybook-dark-mode", - "@storybook/addon-links", - "@storybook/addon-a11y", - "@storybook/addon-docs" - ], - staticDirs: ["../dist", "./static"] -}); diff --git a/.storybook/manager-head.html b/.storybook/manager-head.html index 4c56c0f76..69d9dc1da 100644 --- a/.storybook/manager-head.html +++ b/.storybook/manager-head.html @@ -33,24 +33,4 @@ [data-parent-id^="hidden"] { display: none !important; } - - /* full manager loader (circle) */ - body.dark div[aria-label^="Content is loading..."] { - border-color: rgb(133, 133, 246) rgba(130, 130, 243, 0.29) rgba(130, 130, 243, 0.29) !important; - mix-blend-mode: normal !important; - } - - body:not(.dark) div[aria-label^="Content is loading..."] { - border-color: rgb(0, 0, 145) rgba(0, 0, 142, 0.29) rgba(0, 0, 142, 0.29) !important; - mix-blend-mode: normal !important; - } - - /* full manager page loader (dsfr vars not available) */ - body.dark section[aria-labelledby="main-preview-heading"] div:has(+ #storybook-preview-wrapper) { - background-color: #161616 !important; - } - - body:not(.dark) section[aria-labelledby="main-preview-heading"] div:has(+ #storybook-preview-wrapper) { - background-color: #ffffff !important; - } \ No newline at end of file diff --git a/.storybook/preview-head.html b/.storybook/preview-head.html deleted file mode 100644 index 62389d135..000000000 --- a/.storybook/preview-head.html +++ /dev/null @@ -1,53 +0,0 @@ - \ No newline at end of file diff --git a/.storybook/preview.js b/.storybook/preview.js new file mode 100644 index 000000000..e1cbc3033 --- /dev/null +++ b/.storybook/preview.js @@ -0,0 +1,128 @@ +import { darkTheme, lightTheme } from "./customTheme"; +import { DocsContainer } from "./DocsContainer"; + +export const parameters = { + "actions": { "argTypesRegex": "^on[A-Z].*" }, + "controls": { + "matchers": { + "color": /(background|color)$/i, + "date": /Date$/, + }, + }, + "backgrounds": { "disable": true }, + "darkMode": { + "light": lightTheme, + "dark": darkTheme, + }, + "docs": { + "container": DocsContainer + }, + "viewport": { + "viewports": { + "1440p": { + "name": "1440p", + "styles": { + "width": "2560px", + "height": "1440px", + }, + }, + "fullHD": { + "name": "Full HD", + "styles": { + "width": "1920px", + "height": "1080px", + }, + }, + "macBookProBig": { + "name": "MacBook Pro Big", + "styles": { + "width": "1024px", + "height": "640px", + }, + }, + "macBookProMedium": { + "name": "MacBook Pro Medium", + "styles": { + "width": "1440px", + "height": "900px", + }, + }, + "macBookProSmall": { + "name": "MacBook Pro Small", + "styles": { + "width": "1680px", + "height": "1050px", + }, + }, + "pcAgent": { + "name": "PC Agent", + "styles": { + "width": "960px", + "height": "540px", + }, + }, + "iphone12Pro": { + "name": "Iphone 12 pro", + "styles": { + "width": "390px", + "height": "844px", + }, + }, + "iphone5se":{ + "name": "Iphone 5/SE", + "styles": { + "width": "320px", + "height": "568px", + }, + }, + "ipadPro": { + "name": "Ipad pro", + "styles": { + "width": "1240px", + "height": "1366px", + }, + }, + "Galaxy s9+": { + "name": "Galaxy S9+", + "styles": { + "width": "320px", + "height": "658px", + }, + } + }, + }, + "options": { + "storySort": (a, b) => + getHardCodedWeight(b[1].kind) - getHardCodedWeight(a[1].kind), + }, +}; + +const { getHardCodedWeight } = (() => { + + const orderedPagesPrefix = [ + "🇫🇷 Introduction", + //"components", + "components/Header", + "components/Footer", + "components/consentManagement", + "components/Alert", + "components/Tabs", + "components/Stepper", + "components/Button", + "components/FranceConnectButton", + "components/ProConnectButton" + ]; + + function getHardCodedWeight(kind) { + + for (let i = 0; i < orderedPagesPrefix.length; i++) { + if (kind.toLowerCase().startsWith(orderedPagesPrefix[i].toLowerCase())) { + return orderedPagesPrefix.length - i; + } + } + + return 0; + } + + return { getHardCodedWeight }; +})(); diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx deleted file mode 100644 index cd7d8382c..000000000 --- a/.storybook/preview.tsx +++ /dev/null @@ -1,162 +0,0 @@ -import { darkTheme, lightTheme } from "./customTheme"; -import { DocsContainer } from "./DocsContainer"; -import { definePreview } from "@storybook/react-vite"; -import addonDocs from "@storybook/addon-docs"; -import addonLinks from "@storybook/addon-links"; -import addonA11y from "@storybook/addon-a11y"; -import { AddonTypes, PreviewAddon } from "storybook/internal/csf"; -import { ThemeVars } from "storybook/theming"; -import { ViewMode } from "storybook/internal/types"; - -interface DarkModeTypes extends AddonTypes { - parameters: { - darkMode?: { - light: ThemeVars; - dark: ThemeVars; - }; - }; -} - -interface ViewModeTypes extends AddonTypes { - parameters: { - viewMode?: ViewMode; - }; -} - -interface PreviewTabsTypes extends AddonTypes { - parameters: { - previewTabs?: { - [key: string]: { - hidden: boolean; - }; - }; - }; -} - -const noop = () => ({} as PreviewAddon); - -export default definePreview({ - // CSF Next syntax with custom additions for autocompletion - addons: [ - addonDocs(), - addonLinks(), - addonA11y(), - noop(), - noop(), - noop() - ], - tags: ["autodocs"], - parameters: { - actions: { argTypesRegex: "^on[A-Z].*" }, - controls: { - matchers: { - color: /(background|color)$/i, - date: /Date$/ - } - }, - viewMode: "canvas", - darkMode: { - light: lightTheme, - dark: darkTheme - }, - docs: { - container: DocsContainer, - toc: true - }, - viewport: { - options: { - "1440p": { - "name": "1440p", - "styles": { - "width": "2560px", - "height": "1440px" - } - }, - "fullHD": { - "name": "Full HD", - "styles": { - "width": "1920px", - "height": "1080px" - } - }, - "macBookProBig": { - "name": "MacBook Pro Big", - "styles": { - "width": "1024px", - "height": "640px" - } - }, - "macBookProMedium": { - "name": "MacBook Pro Medium", - "styles": { - "width": "1440px", - "height": "900px" - } - }, - "macBookProSmall": { - "name": "MacBook Pro Small", - "styles": { - "width": "1680px", - "height": "1050px" - } - }, - "pcAgent": { - "name": "PC Agent", - "styles": { - "width": "960px", - "height": "540px" - } - }, - "iphone12Pro": { - "name": "Iphone 12 pro", - "styles": { - "width": "390px", - "height": "844px" - } - }, - "iphone5se": { - "name": "Iphone 5/SE", - "styles": { - "width": "320px", - "height": "568px" - } - }, - "ipadPro": { - "name": "Ipad pro", - "styles": { - "width": "1240px", - "height": "1366px" - } - }, - "Galaxy s9+": { - "name": "Galaxy S9+", - "styles": { - "width": "320px", - "height": "658px" - } - } - } - }, - options: { - storySort: { - method: "alphabetical", - order: [ - "🇫🇷 Introduction", - "components", - [ - "Header", - "Footer", - "consentManagement", - "Alert", - "Tabs", - "Stepper", - "Button", - "FranceConnectButton", - "ProConnectButton", - "*" - ] - ] - } - } - } -}); diff --git a/package.json b/package.json index 4a3c207c3..a13d9e053 100644 --- a/package.json +++ b/package.json @@ -22,9 +22,8 @@ "_format": "prettier '**/*.{ts,tsx,json,md}'", "format": "yarn _format --write", "format:check": "yarn _format --list-different", - "storybook": "storybook dev -p 6006", - "storybook:dev": "storybook dev -p 6006", - "build-storybook": "storybook build", + "storybook": "start-storybook -p 6006", + "build-storybook": "build-storybook", "prestorybook": "yarn build && node dist/bin/react-dsfr update-icons", "prebuild-storybook": "yarn prestorybook" }, @@ -84,10 +83,15 @@ "@gouvfr/dsfr-chart": "^1.0.0", "@mui/icons-material": "^5.14.18", "@mui/material": "^5.14.18", - "@storybook/addon-a11y": "10.2.1", - "@storybook/addon-docs": "10.2.1", - "@storybook/addon-links": "10.2.1", - "@storybook/react-vite": "^10.2.1", + "@storybook/addon-a11y": "^6.5.16", + "@storybook/addon-actions": "^6.5.13", + "@storybook/addon-essentials": "^6.5.13", + "@storybook/addon-interactions": "^6.5.13", + "@storybook/addon-links": "^6.5.13", + "@storybook/builder-webpack5": "^6.5.13", + "@storybook/manager-webpack5": "^6.5.13", + "@storybook/react": "^6.5.13", + "@storybook/testing-library": "^0.0.13", "@tanstack/react-virtual": "^3.0.0-beta.39", "@types/css": "^0.0.33", "@types/jsdom": "^21.1.7", @@ -96,16 +100,14 @@ "@types/node": "^18.7.18", "@types/react": "18.0.21", "@types/react-dom": "18.0.6", - "@types/yargs-parser": "^21.0.3", "@typescript-eslint/eslint-plugin": "^5.43.0", "@typescript-eslint/parser": "^5.43.0", - "@vueless/storybook-dark-mode": "^10.0.7", "babel-loader": "^8.3.0", "chromatic": "^6.17.2", "css": "^3.0.0", - "eslint": "^8", + "eslint": "^7.26.0", "eslint-config-prettier": "^8.3.0", - "eslint-plugin-storybook": "10.2.1", + "eslint-plugin-storybook": "^0.6.7", "evt": "^2.4.2", "fzf": "^0.5.1", "husky": "^4.3.8", @@ -121,13 +123,12 @@ "react": "18.2.0", "react-dom": "18.2.0", "remixicon": "^4.2.0", - "storybook": "10.2.1", + "storybook-dark-mode": "^1.1.2", "svgo": "^3.3.2", "ts-node": "^10.9.1", "tss-react": "^4.9.1", "type-route": "^1.0.1", "typescript": "^4.9.1", - "vite": "^7.0.0", "vitest": "^0.24.3" }, "main": "dist/fr/index.js", diff --git a/src/Table.tsx b/src/Table.tsx index 898bafa57..7a67b7a84 100644 --- a/src/Table.tsx +++ b/src/Table.tsx @@ -31,17 +31,7 @@ export namespace TableProps { type ExtractColorVariant = FrClassName extends `fr-table--${infer AccentColor}` ? Exclude< AccentColor, - | "no-scroll" - | "no-caption" - | "caption-bottom" - | "layout-fixed" - | "bordered" - | "sm" - | "md" - | "lg" - | "xl" - | "xs" - | "multiline" + "no-scroll" | "no-caption" | "caption-bottom" | "layout-fixed" | "bordered" > : never; diff --git a/stories/Accordion.stories.tsx b/stories/Accordion.stories.tsx index 4bc31786f..3f867037b 100644 --- a/stories/Accordion.stories.tsx +++ b/stories/Accordion.stories.tsx @@ -1,7 +1,9 @@ import { Accordion } from "../dist/Accordion"; import { getStoryFactory, logCallbacks } from "./getStory"; +import { sectionName } from "./sectionName"; const { meta, getStory } = getStoryFactory({ + sectionName, "wrappedComponent": { Accordion }, argTypes: { "label": { @@ -58,7 +60,7 @@ function ControlledAccordion() { "disabledProps": ["lang"] }); -export default { ...meta, title: "components/Accordion" }; +export default meta; export const Default = getStory({ "label": "Name of the Accordion", diff --git a/stories/AgentConnectButton.stories.tsx b/stories/AgentConnectButton.stories.tsx index 49e23bb32..73ca74e27 100644 --- a/stories/AgentConnectButton.stories.tsx +++ b/stories/AgentConnectButton.stories.tsx @@ -1,14 +1,16 @@ import { AgentConnectButton } from "../dist/AgentConnectButton"; +import { sectionName } from "./sectionName"; import { getStoryFactory, logCallbacks } from "./getStory"; const { meta, getStory } = getStoryFactory({ + sectionName, "wrappedComponent": { AgentConnectButton }, "description": ` - [See AgentConnect documentation](https://github.com/france-connect/Documentation-AgentConnect/blob/main/doc_fs/implementation_fca/bouton_fca.md) - [See source code](https://github.com/codegouvfr/react-dsfr/blob/main/src/AgentConnectButton.tsx)` }); -export default { ...meta, title: "components/AgentConnectButton" }; +export default meta; export const Default = getStory({ "url": "https://example.com" diff --git a/stories/Alert.stories.tsx b/stories/Alert.stories.tsx index a3bb5ea46..0eb80fd58 100644 --- a/stories/Alert.stories.tsx +++ b/stories/Alert.stories.tsx @@ -1,10 +1,11 @@ import { Alert, type AlertProps } from "../dist/Alert"; - +import { sectionName } from "./sectionName"; import { getStoryFactory, logCallbacks } from "./getStory"; import { assert } from "tsafe/assert"; import type { Equals } from "tsafe"; const { meta, getStory } = getStoryFactory({ + sectionName, "wrappedComponent": { Alert }, "description": ` - [See DSFR documentation](https://www.systeme-de-design.gouv.fr/elements-d-interface/composants/alerte) @@ -77,13 +78,13 @@ const [ isClosed, setIsClosed ] = useState(false); this means that when the close button is clicked the \`onClose()\` callback will be called but you are responsible for setting \`isClosed\` to \`false\`, the \`\` wont close itself.`, - "control": false + "control": { "type": null } } }, "disabledProps": ["lang"] }); -export default { ...meta, title: "components/Alert" }; +export default meta; export const Default = getStory({ "severity": "success", diff --git a/stories/Badge.stories.tsx b/stories/Badge.stories.tsx index 010f5155f..724774c7d 100644 --- a/stories/Badge.stories.tsx +++ b/stories/Badge.stories.tsx @@ -1,10 +1,11 @@ import { Badge, type BadgeProps } from "../dist/Badge"; - +import { sectionName } from "./sectionName"; import { getStoryFactory } from "./getStory"; import { assert } from "tsafe/assert"; import type { Equals } from "tsafe"; const { meta, getStory } = getStoryFactory({ + sectionName, "wrappedComponent": { Badge }, description: ` - [See DSFR documentation](https://www.systeme-de-design.gouv.fr/elements-d-interface/composants/badge) @@ -48,7 +49,7 @@ const { meta, getStory } = getStoryFactory({ "disabledProps": ["lang"] }); -export default { ...meta, title: "components/Badge" }; +export default meta; export const Default = getStory({ "severity": "success", diff --git a/stories/Breadcrumb.stories.tsx b/stories/Breadcrumb.stories.tsx index 5f0d4c047..51a812bc3 100644 --- a/stories/Breadcrumb.stories.tsx +++ b/stories/Breadcrumb.stories.tsx @@ -1,8 +1,9 @@ import { Breadcrumb } from "../dist/Breadcrumb"; - +import { sectionName } from "./sectionName"; import { getStoryFactory } from "./getStory"; const { meta, getStory } = getStoryFactory({ + sectionName, "wrappedComponent": { Breadcrumb }, "description": ` - [See DSFR documentation](https://www.systeme-de-design.gouv.fr/elements-d-interface/composants/fil-d-ariane) @@ -10,7 +11,7 @@ const { meta, getStory } = getStoryFactory({ "disabledProps": ["lang"] }); -export default { ...meta, title: "components/Breadcrumb" }; +export default meta; export const Default = getStory({ "homeLinkProps": { "href": "/" }, diff --git a/stories/Button.stories.tsx b/stories/Button.stories.tsx index 12e8561d7..eee756cf3 100644 --- a/stories/Button.stories.tsx +++ b/stories/Button.stories.tsx @@ -1,10 +1,11 @@ import { Button, type ButtonProps } from "../dist/Button"; - +import { sectionName } from "./sectionName"; import { getStoryFactory, logCallbacks } from "./getStory"; import { assert } from "tsafe/assert"; import type { Equals } from "tsafe"; const { meta, getStory } = getStoryFactory({ + sectionName, "wrappedComponent": { Button }, "description": ` - [See DSFR documentation](https://www.systeme-de-design.gouv.fr/elements-d-interface/composants/bouton) @@ -63,17 +64,17 @@ const { meta, getStory } = getStoryFactory({ "nativeButtonProps": { "description": `Can be used to attach extra props to the underlying native button. Example: \`{ "aria-controls": "fr-modal-1", onMouseEnter: event => {...} }\``, - "control": false + "control": { "type": null } }, "children": { "description": "The label of the button", - "control": { "type": "text" } + "control": { "type": "string" } } }, "disabledProps": ["lang"] }); -export default { ...meta, title: "components/Button" }; +export default meta; export const Default = getStory({ "children": "Label button", diff --git a/stories/ButtonsGroup.stories.tsx b/stories/ButtonsGroup.stories.tsx index d77046180..2fd3be8a1 100644 --- a/stories/ButtonsGroup.stories.tsx +++ b/stories/ButtonsGroup.stories.tsx @@ -1,10 +1,11 @@ import { ButtonsGroup, type ButtonsGroupProps } from "../dist/ButtonsGroup"; - +import { sectionName } from "./sectionName"; import { getStoryFactory } from "./getStory"; import { assert } from "tsafe/assert"; import type { Equals } from "tsafe"; const { meta, getStory } = getStoryFactory({ + sectionName, "wrappedComponent": { ButtonsGroup }, "description": ` - [See DSFR documentation](https://www.systeme-de-design.gouv.fr/elements-d-interface/composants/groupe-de-boutons) @@ -88,14 +89,14 @@ const { meta, getStory } = getStoryFactory({ }, "buttons": { "description": `An array of ButtonProps (at least 1)`, - "control": false + "control": { "type": null } } }, "disabledProps": ["lang"], "defaultContainerWidth": 800 }); -export default { ...meta, title: "components/ButtonsGroup" }; +export default meta; export const Default = getStory({ "buttons": [ diff --git a/stories/CallOut.stories.tsx b/stories/CallOut.stories.tsx index 5c23c2a87..9732d3f98 100644 --- a/stories/CallOut.stories.tsx +++ b/stories/CallOut.stories.tsx @@ -1,10 +1,11 @@ import { CallOut, type CallOutProps } from "../dist/CallOut"; - +import { sectionName } from "./sectionName"; import { getStoryFactory, logCallbacks } from "./getStory"; import { assert } from "tsafe/assert"; import type { Equals } from "tsafe"; const { meta, getStory } = getStoryFactory({ + sectionName, "wrappedComponent": { CallOut }, "description": ` - [See DSFR documentation](https://www.systeme-de-design.gouv.fr/elements-d-interface/composants/mise-en-avant) @@ -14,10 +15,6 @@ const { meta, getStory } = getStoryFactory({ "title": { "description": "Optional" }, - "children": { - "description": "Optional", - "control": { "type": "text" } - }, "colorVariant": { "options": (() => { const options = [ @@ -66,12 +63,12 @@ const { meta, getStory } = getStoryFactory({ "buttonProps": { "description": "The same props you would pass to a `