Skip to content

Commit 04b4207

Browse files
authored
Merge pull request #235 from codegouvfr/feat/header-operator-link
feat: header operator link
2 parents eb22dd1 + 6413dcd commit 04b4207

File tree

2 files changed

+161
-120
lines changed

2 files changed

+161
-120
lines changed

src/Header/Header.tsx

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,12 @@ export type HeaderProps = {
4242
* If "horizontal": 16x9
4343
*/
4444
imgUrl: string;
45-
/** Textual alternative of the image, it MUST include the text present in the image*/
45+
/** Textual alternative of the image, it MUST include the text present in the image */
4646
alt: string;
47+
/**
48+
* Custom link props, if not provided, the operator logo will be wrapped in a link that points to the home page
49+
*/
50+
linkProps?: RegisteredLinkProps & { title: string };
4751
};
4852
renderSearchInput?: (
4953
/**
@@ -168,6 +172,8 @@ export const Header = memo(
168172
</ul>
169173
);
170174

175+
const hasOperatorLink = operatorLogo?.linkProps !== undefined;
176+
171177
return (
172178
<>
173179
<Display />
@@ -184,7 +190,10 @@ export const Header = memo(
184190
<div className={cx(fr.cx("fr-header__body-row"), classes.bodyRow)}>
185191
<div
186192
className={cx(
187-
fr.cx("fr-header__brand", "fr-enlarge-link"),
193+
fr.cx(
194+
"fr-header__brand",
195+
!hasOperatorLink && "fr-enlarge-link"
196+
),
188197
classes.brand
189198
)}
190199
>
@@ -210,30 +219,45 @@ export const Header = memo(
210219
{operatorLogo !== undefined && (
211220
<div
212221
className={cx(
213-
fr.cx("fr-header__operator"),
222+
fr.cx(
223+
"fr-header__operator",
224+
hasOperatorLink && "fr-enlarge-link"
225+
),
214226
classes.operator
215227
)}
216228
>
217-
<Link {...homeLinkProps}>
218-
<img
219-
className={cx(
220-
fr.cx("fr-responsive-img"),
221-
classes.operator
222-
)}
223-
style={(() => {
224-
switch (operatorLogo.orientation) {
225-
case "vertical":
226-
return { "width": "3.5rem" };
227-
case "horizontal":
228-
return {
229-
"maxWidth": "9.0625rem"
230-
};
231-
}
232-
})()}
233-
src={operatorLogo.imgUrl}
234-
alt={operatorLogo.alt}
235-
/>
236-
</Link>
229+
{(() => {
230+
const children = (
231+
<img
232+
className={cx(
233+
fr.cx("fr-responsive-img"),
234+
classes.operator
235+
)}
236+
style={(() => {
237+
switch (operatorLogo.orientation) {
238+
case "vertical":
239+
return {
240+
"width": "3.5rem"
241+
};
242+
case "horizontal":
243+
return {
244+
"maxWidth": "9.0625rem"
245+
};
246+
}
247+
})()}
248+
src={operatorLogo.imgUrl}
249+
alt={operatorLogo.alt}
250+
/>
251+
);
252+
253+
return hasOperatorLink ? (
254+
<Link {...operatorLogo.linkProps}>
255+
{children}
256+
</Link>
257+
) : (
258+
children
259+
);
260+
})()}
237261
</div>
238262
)}
239263

@@ -276,7 +300,10 @@ export const Header = memo(
276300
{serviceTitle !== undefined && (
277301
<div
278302
className={cx(
279-
fr.cx("fr-header__service"),
303+
fr.cx(
304+
"fr-header__service",
305+
hasOperatorLink && "fr-enlarge-link"
306+
),
280307
classes.service
281308
)}
282309
>

stories/Header.stories.tsx

Lines changed: 110 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -500,110 +500,124 @@ export const HeaderWithQuickAccessItemsNavItemsAndSearchEngine = getStory(
500500
}
501501
);
502502

503-
export const HeaderWithVerticalOperatorLogo = getStory(
504-
{
505-
"id": "fr-header-header-with-vertical-operator-logo",
506-
"brandTop": (
507-
<>
508-
INTITULE
509-
<br />
510-
OFFICIEL
511-
</>
512-
),
513-
"homeLinkProps": {
514-
"href": "/",
515-
"title":
516-
"Accueil - [À MODIFIER - texte alternatif de l’image : nom de l'opérateur ou du site serviciel] - République Française"
517-
},
518-
"onSearchButtonClick": text => alert(`TODO: implement search with text: ${text}`),
519-
"operatorLogo": {
520-
"orientation": "vertical",
521-
"imgUrl": placeholder_9x16ImgUrl,
522-
"alt": "[À MODIFIER - texte alternatif de l’image]"
523-
}
503+
export const HeaderWithVerticalOperatorLogo = getStory({
504+
"id": "fr-header-header-with-vertical-operator-logo",
505+
"brandTop": (
506+
<>
507+
INTITULE
508+
<br />
509+
OFFICIEL
510+
</>
511+
),
512+
"homeLinkProps": {
513+
"href": "/",
514+
"title":
515+
"Accueil - [À MODIFIER - texte alternatif de l’image : nom de l'opérateur ou du site serviciel] - République Française"
524516
},
525-
526-
{
527-
"description": `
528-
529-
\`\`\`tsx
530-
531-
<Header
532-
//...
533-
renderSearchInput={({ className, id, placeholder, type }) =>
534-
<input className={className} id={id} placeholder={placeholder} type={type} />
517+
"onSearchButtonClick": text => alert(`TODO: implement search with text: ${text}`),
518+
"operatorLogo": {
519+
"orientation": "vertical",
520+
"imgUrl": placeholder_9x16ImgUrl,
521+
"alt": "[À MODIFIER - texte alternatif de l’image]"
535522
}
536-
/>
537-
538-
\`\`\`
539-
540-
`
541-
}
542-
);
523+
});
543524

544-
export const WithHorizontalOperatorLogo = getStory(
545-
{
546-
"id": "fr-header-with-horizontal-operator-logo",
547-
"brandTop": (
548-
<>
549-
INTITULE
550-
<br />
551-
OFFICIEL
552-
</>
553-
),
554-
"homeLinkProps": {
555-
"href": "/",
556-
"title": "Accueil - Nom de l’entité (ministère, secrétariat d‘état, gouvernement)"
525+
export const WithHorizontalOperatorLogo = getStory({
526+
"id": "fr-header-with-horizontal-operator-logo",
527+
"brandTop": (
528+
<>
529+
INTITULE
530+
<br />
531+
OFFICIEL
532+
</>
533+
),
534+
"homeLinkProps": {
535+
"href": "/",
536+
"title": "Accueil - Nom de l’entité (ministère, secrétariat d‘état, gouvernement)"
537+
},
538+
"serviceTitle": "Nom du site / service",
539+
"serviceTagline": "baseline - précisions sur l'organisation",
540+
"quickAccessItems": [
541+
{
542+
"iconId": "fr-icon-add-circle-line",
543+
"text": "Créer un espace",
544+
"linkProps": {
545+
"href": "#"
546+
}
557547
},
558-
"serviceTitle": "Nom du site / service",
559-
"serviceTagline": "baseline - précisions sur l'organisation",
560-
"quickAccessItems": [
561-
{
562-
"iconId": "fr-icon-add-circle-line",
563-
"text": "Créer un espace",
564-
"linkProps": {
565-
"href": "#"
566-
}
567-
},
568-
{
569-
"iconId": "fr-icon-lock-line",
570-
"text": "Se connecter",
571-
"linkProps": {
572-
"href": "#"
573-
}
574-
},
575-
{
576-
"iconId": "fr-icon-account-line",
577-
"text": "S’enregistrer",
578-
"linkProps": {
579-
"href": "#"
580-
}
548+
{
549+
"iconId": "fr-icon-lock-line",
550+
"text": "Se connecter",
551+
"linkProps": {
552+
"href": "#"
553+
}
554+
},
555+
{
556+
"iconId": "fr-icon-account-line",
557+
"text": "S’enregistrer",
558+
"linkProps": {
559+
"href": "#"
581560
}
582-
],
583-
"onSearchButtonClick": text => alert(`TODO: implement search with text: ${text}`),
584-
"operatorLogo": {
585-
"orientation": "horizontal",
586-
"imgUrl": placeholder_16x9ImgUrl,
587-
"alt": "[À MODIFIER - texte alternatif de l’image]"
588561
}
589-
},
590-
{
591-
"description": `
592-
593-
\`\`\`tsx
594-
595-
<Header
596-
//...
597-
renderSearchInput={({ className, id, name, placeholder, type }) =>
598-
<input className={className} id={id} name={name} placeholder={placeholder} type={type} />
562+
],
563+
"onSearchButtonClick": text => alert(`TODO: implement search with text: ${text}`),
564+
"operatorLogo": {
565+
"orientation": "horizontal",
566+
"imgUrl": placeholder_16x9ImgUrl,
567+
"alt": "[À MODIFIER - texte alternatif de l’image]"
599568
}
600-
/>
601-
602-
\`\`\`
603-
604-
`
569+
});
570+
571+
export const WithOperatorLogoWithLink = getStory({
572+
"id": "fr-header-with-operator-logo-with-link",
573+
"brandTop": (
574+
<>
575+
INTITULE
576+
<br />
577+
OFFICIEL
578+
</>
579+
),
580+
"homeLinkProps": {
581+
"href": "/",
582+
"title": "Accueil - Nom de l’entité (ministère, secrétariat d‘état, gouvernement)"
583+
},
584+
"serviceTitle": "Nom du site / service",
585+
"serviceTagline": "baseline - précisions sur l'organisation",
586+
"quickAccessItems": [
587+
{
588+
"iconId": "fr-icon-add-circle-line",
589+
"text": "Créer un espace",
590+
"linkProps": {
591+
"href": "#"
592+
}
593+
},
594+
{
595+
"iconId": "fr-icon-lock-line",
596+
"text": "Se connecter",
597+
"linkProps": {
598+
"href": "#"
599+
}
600+
},
601+
{
602+
"iconId": "fr-icon-account-line",
603+
"text": "S’enregistrer",
604+
"linkProps": {
605+
"href": "#"
606+
}
607+
}
608+
],
609+
"onSearchButtonClick": text => alert(`TODO: implement search with text: ${text}`),
610+
"operatorLogo": {
611+
"orientation": "horizontal",
612+
"imgUrl": placeholder_16x9ImgUrl,
613+
"alt": "[À MODIFIER - texte alternatif de l’image]",
614+
"linkProps": {
615+
"href": "#",
616+
"title":
617+
"Accueil - [À MODIFIER - texte alternatif de l’image : nom de l'opérateur ou du site serviciel] - République Française"
618+
}
605619
}
606-
);
620+
});
607621

608622
export const NavigationAsCustomNode = getStory(
609623
{

0 commit comments

Comments
 (0)