Skip to content

Tile support of native pictogram #428

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 12, 2025
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
6 changes: 3 additions & 3 deletions scripts/picto-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,9 @@ async function generateComponent(svgPath: string, outputDir: string): Promise<st
const cleanedSvg = extractSvgInnerContent(await cleanSvgContent(svgData));

const template = `import React from 'react';
import { createIcon } from './utils/IconWrapper';
import { createPicto } from './utils/PictoWrapper';

export default createIcon(
export default createPicto(
<>
{{& svgContent }}
</>,
Expand Down Expand Up @@ -167,7 +167,7 @@ async function generateTypes(outputDir: string): Promise<string> {
const iconNames = files.map(f => pascalCaseName(path.basename(f, ".tsx")));
const filePath = path.join(outputDir, "index.d.ts");

const header = `import { IconWrapper } from './utils/IconWrapper';\n\ntype SvgIconComponent = typeof IconWrapper;\n\n`;
const header = `import { PictoWrapper } from './utils/PictoWrapper';\n\ntype SvgIconComponent = typeof PictoWrapper;\n\n`;
const lines = iconNames.map(name => `export const ${name}: SvgIconComponent;`);

const content = `${header}${lines.join("\n")}\n`;
Expand Down
93 changes: 56 additions & 37 deletions src/Tile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,6 @@ export type TileProps = {
desc?: ReactNode;
detail?: ReactNode;
start?: ReactNode;
imageUrl?: string;
imageAlt?: string;
/**
* @deprecated imageWidth has no effect
*/
imageWidth?: string | number;
/**
* @deprecated imageHeight has no effect
*/
imageHeight?: string | number;
imageSvg?: boolean;
grey?: boolean;
/** make the whole tile clickable */
enlargeLinkOrButton?: boolean;
Expand Down Expand Up @@ -60,7 +49,8 @@ export type TileProps = {
noBackground?: boolean;
disabled?: boolean;
style?: CSSProperties;
} & (TileProps.WithLink | TileProps.WithButton | TileProps.Unclickable);
} & (TileProps.WithImage | TileProps.WithPicto) &
(TileProps.WithLink | TileProps.WithButton | TileProps.Unclickable);

export namespace TileProps {
export type Unclickable = {
Expand All @@ -78,6 +68,30 @@ export namespace TileProps {
linkProps?: never;
buttonProps: ComponentProps<"button">;
};

export type WithImage = {
imageUrl?: string;
imageAlt?: string;
/**
* @deprecated imageWidth has no effect
*/
imageWidth?: string | number;
/**
* @deprecated imageHeight has no effect
*/
imageHeight?: string | number;
imageSvg?: boolean;
pictogram?: never;
};

export type WithPicto = {
imageUrl?: never;
imageAlt?: never;
imageWidth?: never;
imageHeight?: never;
imageSvg?: never;
pictogram: ReactNode;
};
}

/** @see <https://components.react-dsfr.codegouv.studio/?path=/docs/components-tile> */
Expand All @@ -99,6 +113,7 @@ export const Tile = memo(
imageWidth,
imageHeight,
imageSvg = false,
pictogram,
orientation = "vertical",
small = false,
noBorder = false,
Expand Down Expand Up @@ -189,33 +204,37 @@ export const Tile = memo(
</div>
</div>

{imageUrl !== undefined && imageUrl.length > 0 && (
{((imageUrl !== undefined && imageUrl.length > 0) || pictogram !== undefined) && (
<div className={cx(fr.cx("fr-tile__header"), classes.header)}>
{imageSvg ? (
{imageSvg || pictogram !== undefined ? (
<div className={cx(fr.cx("fr-tile__pictogram"), classes.img)}>
<svg
aria-hidden={true}
className={cx(fr.cx("fr-artwork"), classes.artwork)}
viewBox="0 0 80 80"
width="80px"
height="80px"
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
>
{(
[
"artwork-decorative",
"artwork-minor",
"artwork-major"
] as const
).map(label => (
<use
key={label}
className={fr.cx(`fr-${label}`)}
xlinkHref={`${imageUrl}#${label}`}
/>
))}
</svg>
{pictogram !== undefined ? (
pictogram
) : (
<svg
aria-hidden={true}
className={cx(fr.cx("fr-artwork"), classes.artwork)}
viewBox="0 0 80 80"
width="80px"
height="80px"
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
>
{(
[
"artwork-decorative",
"artwork-minor",
"artwork-major"
] as const
).map(label => (
<use
key={label}
className={fr.cx(`fr-${label}`)}
xlinkHref={`${imageUrl}#${label}`}
/>
))}
</svg>
)}
</div>
) : (
<div className={cx(fr.cx("fr-tile__img"), classes.img)}>
Expand Down
4 changes: 2 additions & 2 deletions src/picto/Accessibility.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path
Expand Down
4 changes: 2 additions & 2 deletions src/picto/Airport.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path
Expand Down
4 changes: 2 additions & 2 deletions src/picto/Application.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path d="M33 38H29C28.4477 38 28 38.4477 28 39V41C28 41.5523 28.4477 42 29 42H33C33.5523 42 34 41.5523 34 41V39C34 38.4477 33.5523 38 33 38Z" />
Expand Down
4 changes: 2 additions & 2 deletions src/picto/Archive.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path
Expand Down
4 changes: 2 additions & 2 deletions src/picto/ArmyTank.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path d="M19 51C20.1046 51 21 50.1046 21 49C21 47.8954 20.1046 47 19 47C17.8954 47 17 47.8954 17 49C17 50.1046 17.8954 51 19 51Z" />
Expand Down
4 changes: 2 additions & 2 deletions src/picto/Art.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path
Expand Down
4 changes: 2 additions & 2 deletions src/picto/Astronaut.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path
Expand Down
4 changes: 2 additions & 2 deletions src/picto/Audio.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path
Expand Down
4 changes: 2 additions & 2 deletions src/picto/Avatar.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path d="M42.1481 10C58.7166 10 72.1481 23.4315 72.1481 40C72.1481 40.5523 71.7004 41 71.1481 41C70.5958 41 70.1481 40.5523 70.1481 40C70.1481 24.536 57.6121 12 42.1481 12C26.6841 12 14.1481 24.536 14.1481 40C14.1481 55.464 26.6841 68 42.1481 68C53.3028 68 63.2553 61.4175 67.7265 51.4083C67.9518 50.9041 68.5432 50.6779 69.0474 50.9031C69.5517 51.1284 69.7778 51.7198 69.5526 52.224C64.7624 62.9473 54.099 70 42.1481 70C25.5796 70 12.1481 56.5685 12.1481 40C12.1481 23.4315 25.5796 10 42.1481 10Z" />
Expand Down
4 changes: 2 additions & 2 deletions src/picto/Backpack.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path
Expand Down
4 changes: 2 additions & 2 deletions src/picto/Base.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path
Expand Down
4 changes: 2 additions & 2 deletions src/picto/Binders.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path d="M55.7 69.3129C55.5 69.3129 55.2 69.2129 55.1 69.1129C54.9 68.9129 54.8 68.7129 54.7 68.4129L50 12.6129C50 12.0129 50.4 11.6129 50.9 11.5129L68.8 10.0129C69.4 9.91287 69.8 10.4129 69.9 10.9129L70.1 13.5129L74.6 66.8129C74.6 67.3129 74.2 67.8129 73.7 67.9129L55.7 69.3129ZM52.1 13.4129L56.6 67.2129L72.5 65.9129L68 12.1129L52.1 13.4129Z" />
Expand Down
4 changes: 2 additions & 2 deletions src/picto/Book.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path d="M31 32C31 31.4477 30.5523 31 30 31C29.4477 31 29 31.4477 29 32C29 32.5523 29.4477 33 30 33C30.5523 33 31 32.5523 31 32Z" />
Expand Down
4 changes: 2 additions & 2 deletions src/picto/Calendar.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path d="M69.5518 69.3258C64.4014 73.4965 56.845 72.7023 52.6742 67.5518C48.5035 62.4014 49.2977 54.845 54.4482 50.6742C59.5986 46.5035 67.155 47.2977 71.3258 52.4482C71.6733 52.8774 71.6071 53.5071 71.1779 53.8546C70.7487 54.2022 70.119 54.136 69.7715 53.7068C66.2958 49.4147 59.9989 48.7529 55.7068 52.2285C51.4147 55.7042 50.7529 62.0011 54.2285 66.2932C57.7042 70.5853 64.0011 71.2471 68.2932 67.7715C71.0207 65.5628 72.3571 62.1366 71.9191 58.7185C71.8489 58.1707 72.2361 57.6697 72.7839 57.5995C73.3317 57.5293 73.8327 57.9165 73.9029 58.4643C74.4281 62.5633 72.8238 66.6762 69.5518 69.3258Z" />
Expand Down
4 changes: 2 additions & 2 deletions src/picto/Catalog.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path d="M34.5547 63.1679C34.3904 63.0584 34.1974 63 34 63H14L13.8834 63.0067C13.386 63.0645 13 63.4872 13 64L13.0067 64.1166C13.0645 64.614 13.4872 65 14 65H33.705L33.8051 65.0652C35.8457 66.3489 37.9148 67 40 67L40.3678 66.9932C42.3286 66.9212 44.2743 66.2734 46.1949 65.0652L46.294 65H66L66.1166 64.9933C66.614 64.9355 67 64.5128 67 64C67 63.4477 66.5523 63 66 63H46L45.8823 63.007C45.7265 63.0254 45.5767 63.0803 45.4453 63.1679C43.6023 64.3966 41.7921 65 40 65C38.2079 65 36.3977 64.3966 34.5547 63.1679Z" />
Expand Down
4 changes: 2 additions & 2 deletions src/picto/CityHall.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path d="M44.9933 9.88338C44.9355 9.38604 44.5128 9 44 9C43.4477 9 43 9.44772 43 10V14L43.0067 14.1166C43.0645 14.614 43.4872 15 44 15C44.5523 15 45 14.5523 45 14V10L44.9933 9.88338Z" />
Expand Down
4 changes: 2 additions & 2 deletions src/picto/Coding.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path
Expand Down
4 changes: 2 additions & 2 deletions src/picto/Community.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path d="M37 23C37 22.4477 36.5523 22 36 22H24L23.8834 22.0067C23.386 22.0645 23 22.4872 23 23C23 23.5523 23.4477 24 24 24H36L36.1166 23.9933C36.614 23.9355 37 23.5128 37 23Z" />
Expand Down
4 changes: 2 additions & 2 deletions src/picto/Companie.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path
Expand Down
4 changes: 2 additions & 2 deletions src/picto/Compass.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path d="M48.82 39.9C48.75 39.9 48.68 39.9 48.6 39.89C47.75 39.8 47.06 39.2 46.86 38.36C46.56 37.09 45.91 35.93 44.99 35.01C44.07 34.09 42.91 33.44 41.64 33.14C41.1 33.01 40.77 32.47 40.9 31.93C41.03 31.39 41.57 31.06 42.11 31.19C43.74 31.58 45.22 32.41 46.41 33.6C47.6 34.79 48.43 36.27 48.82 37.9L54.84 25.17L46.67 29.04C46.17 29.28 45.58 29.06 45.34 28.56C45.1 28.06 45.32 27.46 45.82 27.23L56.52 22.16C56.9 21.98 57.36 22.06 57.65 22.36C57.95 22.66 58.03 23.11 57.85 23.5L50.62 38.76C50.28 39.46 49.59 39.89 48.82 39.9Z" />
Expand Down
4 changes: 2 additions & 2 deletions src/picto/Conclusion.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path d="M68.1999 67.8523C69.194 67.8523 69.9999 67.0464 69.9999 66.0523C69.9999 65.0582 69.194 64.2523 68.1999 64.2523C67.2058 64.2523 66.3999 65.0582 66.3999 66.0523C66.3999 67.0464 67.2058 67.8523 68.1999 67.8523Z" />
Expand Down
4 changes: 2 additions & 2 deletions src/picto/ConnectionLost.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path d="M54.1056 40.5528C54.4547 39.8545 55.4171 39.8178 55.8308 40.4425L55.8944 40.5528L67.8944 64.5528C68.2094 65.1827 67.792 65.918 67.1151 65.9936L67 66H63C62.4477 66 62 65.5523 62 65C62 64.4872 62.386 64.0645 62.8834 64.0067L63 64H65.381L55 43.236L44.618 64H59C59.5128 64 59.9355 64.386 59.9933 64.8834L60 65C60 65.5128 59.614 65.9355 59.1166 65.9933L59 66H43C42.2958 66 41.8247 65.2979 42.0598 64.6586L42.1056 64.5528L54.1056 40.5528Z" />
Expand Down
4 changes: 2 additions & 2 deletions src/picto/Contract.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path
Expand Down
4 changes: 2 additions & 2 deletions src/picto/Culture.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { createIcon } from "./utils/IconWrapper";
import { createPicto } from "./utils/PictoWrapper";

export default createIcon(
export default createPicto(
<>
<g className="fr-artwork-minor">
<path d="M27.0144 31.57C19.3475 33.0262 12.6391 37.1038 6.91221 43.7721C6.64728 44.0806 6.59552 44.5187 6.78129 44.8805L7.29883 45.8488L7.9007 46.9303L8.40715 47.8135C8.49467 47.9642 8.58374 48.1166 8.67432 48.2706L9.23586 49.2136C11.1682 52.4186 13.2942 55.5544 15.5538 58.389C15.7574 58.6445 15.9609 58.8961 16.1642 59.1437L16.7735 59.8744C22.9621 67.1812 28.9681 70.7279 34.5066 68.7121C40.6898 66.4616 43.618 59.8503 43.415 49.1257C43.4045 48.5735 42.9484 48.1343 42.3962 48.1448C41.8441 48.1553 41.4049 48.6114 41.4154 49.1636C41.604 59.1294 39.0319 64.9367 33.8226 66.8327C29.342 68.4635 23.9827 65.2835 18.2983 58.5793L17.7091 57.8733C17.5123 57.6338 17.3152 57.3901 17.1177 57.1424C14.9181 54.383 12.8393 51.3168 10.9486 48.1809C10.7595 47.8672 10.5761 47.5591 10.3987 47.2575L9.8848 46.3726L9.40797 45.5304L9.18383 45.1265L8.87606 44.5626L9.21265 44.1871C14.4735 38.3802 20.5251 34.8383 27.3876 33.5349C27.9302 33.4318 28.2865 32.9084 28.1834 32.3658C28.0804 31.8232 27.557 31.4669 27.0144 31.57Z" />
Expand Down
Loading