diff --git a/src/Card.tsx b/src/Card.tsx index 3d6c03d78..e74c986e1 100644 --- a/src/Card.tsx +++ b/src/Card.tsx @@ -17,13 +17,10 @@ export type CardProps = { title: ReactNode; titleAs?: `h${2 | 3 | 4 | 5 | 6}`; desc?: ReactNode; - imageUrl?: string; - imageAlt?: string; start?: ReactNode; detail?: ReactNode; end?: ReactNode; endDetail?: ReactNode; - badge?: ReactNode; /** where actions can be placed */ footer?: ReactNode; /** Default: "medium", only affect the text */ @@ -58,9 +55,9 @@ export type CardProps = { > >; style?: CSSProperties; - /** Default false */ - horizontal?: boolean; -} & (CardProps.EnlargedLink | CardProps.NotEnlargedLink); +} & (CardProps.EnlargedLink | CardProps.NotEnlargedLink) & + (CardProps.Horizontal | CardProps.Vertical) & + (CardProps.WithImageLink | CardProps.WithImageComponent | CardProps.WithoutImage); export namespace CardProps { export type EnlargedLink = { @@ -73,6 +70,39 @@ export namespace CardProps { linkProps?: RegisteredLinkProps; iconId?: never; }; + + export type Horizontal = { + /** Default false */ + horizontal: true; + ratio?: "33/66" | "50/50"; + }; + + export type Vertical = { + /** Default false */ + horizontal?: false; + ratio?: never; + }; + + export type WithImageLink = { + badge?: ReactNode; + imageUrl: string; + imageAlt: string; + imageComponent?: never; + }; + + export type WithImageComponent = { + badge?: ReactNode; + imageUrl?: never; + imageAlt?: never; + imageComponent: ReactNode; + }; + + export type WithoutImage = { + badge?: never; + imageUrl?: never; + imageAlt?: never; + imageComponent?: never; + }; } /** @see */ @@ -87,6 +117,7 @@ export const Card = memo( desc, imageUrl, imageAlt, + imageComponent, start, detail, end, @@ -94,6 +125,7 @@ export const Card = memo( badge, footer, horizontal = false, + ratio, size = "medium", classes = {}, enlargeLink = false, @@ -123,6 +155,9 @@ export const Card = memo( "fr-card", enlargeLink && "fr-enlarge-link", horizontal && "fr-card--horizontal", + horizontal && + ratio !== undefined && + `fr-card--horizontal-${ratio === "33/66" ? "tier" : "half"}`, (() => { switch (size) { case "large": @@ -201,6 +236,18 @@ export const Card = memo( )} )} + {imageComponent !== undefined && ( +
+
+ {imageComponent} +
+ {badge !== undefined && ( + + )} +
+ )} ); }) diff --git a/stories/Card.stories.tsx b/stories/Card.stories.tsx index c741a854e..573f8a9fc 100644 --- a/stories/Card.stories.tsx +++ b/stories/Card.stories.tsx @@ -7,6 +7,9 @@ import { getStoryFactory } from "./getStory"; import { assert } from "tsafe/assert"; import type { Equals } from "tsafe"; +import artworkOvoidSvgUrl from "../dist/dsfr/artwork/background/ovoid.svg"; +import artworkTechnicalErrorSvgUrl from "../dist/dsfr/artwork/pictograms/system/technical-error.svg"; + import { fr } from "../dist"; const { meta, getStory } = getStoryFactory({ @@ -151,7 +154,7 @@ export const CardWithShadow = getStory( ); export const CardWithoutImage = getStory( - { ...defaultProps, "imageUrl": undefined }, + { ...defaultProps }, { "description": "Carte sans image" } ); @@ -310,6 +313,24 @@ export const CardHorizontal = getStory( { "description": "Carte horizontale", "defaultContainerWidth": 700 } ); +export const CardHorizontalTierRatio = getStory( + { + ...defaultProps, + "horizontal": true, + ratio: "33/66" + }, + { "description": "Carte horizontale", "defaultContainerWidth": 700 } +); + +export const CardHorizontalHalfRatio = getStory( + { + ...defaultProps, + "horizontal": true, + ratio: "50/50" + }, + { "description": "Carte horizontale", "defaultContainerWidth": 700 } +); + export const CardHorizontalSM = getStory( { ...defaultProps, @@ -333,7 +354,6 @@ export const CardHorizontalWithoutImage = getStory( ...defaultProps, "horizontal": true, "size": "large", - "imageUrl": undefined, "start": (