Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 53 additions & 6 deletions src/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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 = {
Expand All @@ -73,6 +70,39 @@ export namespace CardProps {
linkProps?: RegisteredLinkProps;
iconId?: never;
};

export type Horizontal = {
/** Default false */
horizontal: true;
ratio?: "33/66" | "50/50";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldnt we use "tier" | "half" here ?

};

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 <https://components.react-dsfr.codegouv.studio/?path=/docs/components-card> */
Expand All @@ -87,13 +117,15 @@ export const Card = memo(
desc,
imageUrl,
imageAlt,
imageComponent,
start,
detail,
end,
endDetail,
badge,
footer,
horizontal = false,
ratio,
size = "medium",
classes = {},
enlargeLink = false,
Expand Down Expand Up @@ -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":
Expand Down Expand Up @@ -201,6 +236,18 @@ export const Card = memo(
)}
</div>
)}
{imageComponent !== undefined && (
<div className={cx(fr.cx("fr-card__header"), classes.header)}>
<div className={cx(fr.cx("fr-card__img"), classes.img)}>
{imageComponent}
</div>
{badge !== undefined && (
<ul className={cx(fr.cx("fr-badges-group"), classes.badge)}>
<li>{badge}</li>
</ul>
)}
</div>
)}
</div>
);
})
Expand Down
62 changes: 58 additions & 4 deletions stories/Card.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down Expand Up @@ -151,7 +154,7 @@ export const CardWithShadow = getStory(
);

export const CardWithoutImage = getStory(
{ ...defaultProps, "imageUrl": undefined },
{ ...defaultProps },
{ "description": "Carte sans image" }
);

Expand Down Expand Up @@ -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,
Expand All @@ -333,7 +354,6 @@ export const CardHorizontalWithoutImage = getStory(
...defaultProps,
"horizontal": true,
"size": "large",
"imageUrl": undefined,
"start": (
<ul className={fr.cx("fr-badges-group")}>
<li>
Expand All @@ -353,8 +373,7 @@ export const CardHorizontalWithoutImageAndEnlargeLink = getStory(
...defaultProps,
"horizontal": true,
"enlargeLink": false,
"size": "large",
"imageUrl": undefined
"size": "large"
},
{ "description": "Carte horizontale sans image", "defaultContainerWidth": 900 }
);
Expand Down Expand Up @@ -414,3 +433,38 @@ export const CardNoLink = getStory(
},
{ "description": "Carte horizontale sans lien", "defaultContainerWidth": 900 }
);

export const CardWithImageComponent = getStory({
...defaultProps,
enlargeLink: false,
imageUrl: undefined,
imageAlt: undefined,
imageComponent: (
<svg
xmlns="http://www.w3.org/2000/svg"
className="fr-responsive-img fr-artwork"
aria-hidden="true"
viewBox="0 0 160 200"
>
<use className="fr-artwork-motif" href={`${artworkOvoidSvgUrl}#artwork-motif`}></use>
<use
className="fr-artwork-background"
href={`${artworkOvoidSvgUrl}#artwork-background`}
></use>
<g transform="translate(40, 60)">
<use
className="fr-artwork-decorative"
href={`${artworkTechnicalErrorSvgUrl}#artwork-decorative`}
></use>
<use
className="fr-artwork-minor"
href={`${artworkTechnicalErrorSvgUrl}#artwork-minor`}
></use>
<use
className="fr-artwork-major"
href={`${artworkTechnicalErrorSvgUrl}#artwork-major`}
></use>
</g>
</svg>
)
});