Skip to content

Commit 8ee63d6

Browse files
authored
Merge pull request #21 from codegouvfr/feat/add-skiplinks-component
Feat/add skiplinks component
2 parents 86ea7a5 + 3cfbd43 commit 8ee63d6

File tree

3 files changed

+117
-0
lines changed

3 files changed

+117
-0
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@
124124
"./mui": "./dist/mui.js",
125125
"./lib": "./dist/lib/index.js",
126126
"./Tabs": "./dist/Tabs.js",
127+
"./SkipLinks": "./dist/SkipLinks.js",
127128
"./Notice": "./dist/Notice.js",
128129
"./Highlight": "./dist/Highlight.js",
129130
"./Header": "./dist/Header/index.js",

src/SkipLinks.tsx

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import React, { forwardRef, memo } from "react";
2+
import { assert, Equals } from "tsafe";
3+
import { symToStr } from "tsafe/symToStr";
4+
import { fr } from "./lib";
5+
import { createComponentI18nApi } from "./lib/i18n";
6+
import { cx } from "./lib/tools/cx";
7+
8+
export type SkipLink = {
9+
label: string;
10+
anchor: `${string}`;
11+
};
12+
13+
export type SkipLinksProps = {
14+
className?: string;
15+
links: SkipLink[];
16+
classes?: Partial<Record<"root" | "list" | "link", string>>;
17+
};
18+
19+
/** @see <https://react-dsfr-components.etalab.studio/?path=/docs/components-skiplinks> */
20+
export const SkipLinks = memo(
21+
forwardRef<HTMLDivElement, SkipLinksProps>((props, ref) => {
22+
const { className, classes = {}, links, ...rest } = props;
23+
const { t } = useTranslation();
24+
assert<Equals<keyof typeof rest, never>>();
25+
26+
return (
27+
<div className={cx(fr.cx("fr-skiplinks"), classes.root, className)} ref={ref} {...rest}>
28+
<nav className={fr.cx("fr-container")} role="navigation" aria-label={t("label")}>
29+
<ul className={cx(fr.cx("fr-skiplinks__list"), classes.list)}>
30+
{links &&
31+
links.map(link => (
32+
<li key={link.anchor}>
33+
<a
34+
className={cx(fr.cx("fr-link"), classes.link)}
35+
href={link.anchor}
36+
>
37+
{link.label}
38+
</a>
39+
</li>
40+
))}
41+
</ul>
42+
</nav>
43+
</div>
44+
);
45+
})
46+
);
47+
48+
SkipLinks.displayName = symToStr({ SkipLinks });
49+
50+
const { useTranslation, addSkipLinksTranslations } = createComponentI18nApi({
51+
"componentName": symToStr({ SkipLinks }),
52+
"frMessages": {
53+
/* spell-checker: disable */
54+
"label": "Accès rapide"
55+
/* spell-checker: enable */
56+
}
57+
});
58+
59+
addSkipLinksTranslations({
60+
"lang": "en",
61+
"messages": {
62+
"label": "Quick access"
63+
}
64+
});
65+
addSkipLinksTranslations({
66+
"lang": "es",
67+
"messages": {
68+
"label": "Acceso rapido"
69+
}
70+
});
71+
addSkipLinksTranslations({
72+
"lang": "de",
73+
"messages": {
74+
"label": "Schneller Zugang"
75+
}
76+
});
77+
78+
export default SkipLinks;

stories/SkipLinks.stories.tsx

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { SkipLinks } from "../dist/SkipLinks";
2+
import type { SkipLinksProps } from "../src/SkipLinks";
3+
import { sectionName } from "./sectionName";
4+
import { getStoryFactory } from "./getStory";
5+
6+
const { meta, getStory } = getStoryFactory<SkipLinksProps>({
7+
sectionName,
8+
wrappedComponent: { SkipLinks },
9+
description: `
10+
- [See DSFR documentation](https://www.systeme-de-design.gouv.fr/elements-d-interface/composants/liens-d-evitement)
11+
- [See source code](https://github.com/codegouvfr/react-dsfr/blob/main/src/SkipLinks.tsx)`
12+
});
13+
14+
export default meta;
15+
16+
export const Default = getStory({
17+
links: [
18+
{
19+
label: "Contenu",
20+
anchor: "#contenu"
21+
},
22+
{
23+
label: "Menu",
24+
anchor: "#header-navigation"
25+
},
26+
{
27+
label: "Recherche",
28+
anchor: "#header-search"
29+
},
30+
{
31+
label: "Pied de page",
32+
anchor: "#footer"
33+
}
34+
],
35+
classes: {
36+
root: "fr-mt-9v" // Just to fix storybook preview toolbar overlapping
37+
}
38+
});

0 commit comments

Comments
 (0)