@@ -10,8 +10,7 @@ import type { MainNavigationProps } from "./MainNavigation";
1010import { MainNavigation } from "./MainNavigation" ;
1111import { assert } from "tsafe/assert" ;
1212import type { Equals } from "tsafe" ;
13-
14- //NOTE: WIP
13+ import type { FrIconClassName , RiIconClassName } from "../lib/generatedFromCss/classNames" ;
1514
1615export type HeaderProps = {
1716 className ?: string ;
@@ -21,6 +20,21 @@ export type HeaderProps = {
2120 /** Don't forget the title on the link for accessibility*/
2221 homeLinkProps : LinkProps ;
2322 mainNavigationProps ?: MainNavigationProps ;
23+ /** There should be at most three of them */
24+ quickAccessLinks ?: HeaderProps . QuickAccessLink [ ] ;
25+ renderSearchInput ?: (
26+ /**
27+ * id and name must be forwarded to the <input /> component
28+ * the others params can, but it's not mandatory.
29+ **/
30+ params : {
31+ id : string ;
32+ name : string ;
33+ type : "search" ;
34+ className : string ;
35+ placeholder : string ;
36+ }
37+ ) => JSX . Element ;
2438 classes ?: Partial <
2539 Record <
2640 | "root"
@@ -40,6 +54,30 @@ export type HeaderProps = {
4054 > ;
4155} ;
4256
57+ export namespace HeaderProps {
58+ export type QuickAccessLink = QuickAccessLink . Link | QuickAccessLink . Button ;
59+
60+ export namespace QuickAccessLink {
61+ export type Common = {
62+ iconId : FrIconClassName | RiIconClassName ;
63+ text : ReactNode ;
64+ } ;
65+
66+ export type Link = Common & {
67+ linkProps : LinkProps ;
68+ buttonProps ?: undefined ;
69+ } ;
70+
71+ export type Button = Common & {
72+ linkProps ?: undefined ;
73+ buttonProps : React . DetailedHTMLProps <
74+ React . ButtonHTMLAttributes < HTMLButtonElement > ,
75+ HTMLButtonElement
76+ > ;
77+ } ;
78+ }
79+ }
80+
4381/** @see <https://react-dsfr-components.etalab.studio/?path=/docs/components-header> */
4482export const Header = memo (
4583 forwardRef < HTMLDivElement , HeaderProps > ( ( props , ref ) => {
@@ -50,6 +88,8 @@ export const Header = memo(
5088 serviceTagline,
5189 homeLinkProps,
5290 mainNavigationProps,
91+ quickAccessLinks = [ ] ,
92+ renderSearchInput,
5393 classes = { } ,
5494 ...rest
5595 } = props ;
@@ -142,6 +182,94 @@ export const Header = memo(
142182 </ div >
143183 ) }
144184 </ div >
185+
186+ { ( quickAccessLinks . length > 0 || renderSearchInput !== undefined ) && (
187+ < div className = { fr . cx ( "fr-header__tools" ) } >
188+ { quickAccessLinks . length > 0 && (
189+ < div className = { fr . cx ( "fr-header__tools-links" ) } >
190+ < ul className = { fr . cx ( "fr-btns-group" ) } >
191+ { quickAccessLinks . map (
192+ (
193+ { iconId, text, buttonProps, linkProps } ,
194+ i
195+ ) => (
196+ < li key = { i } >
197+ { linkProps !== undefined ? (
198+ < Link
199+ { ...linkProps }
200+ className = { cx (
201+ fr . cx ( "fr-btn" , iconId ) ,
202+ linkProps . className
203+ ) }
204+ >
205+ { text }
206+ </ Link >
207+ ) : (
208+ < button
209+ { ...buttonProps }
210+ className = { cx (
211+ fr . cx ( "fr-btn" , iconId ) ,
212+ buttonProps . className
213+ ) }
214+ >
215+ { text }
216+ </ button >
217+ ) }
218+ </ li >
219+ )
220+ ) }
221+ </ ul >
222+ </ div >
223+ ) }
224+
225+ { renderSearchInput !== undefined && (
226+ < div
227+ className = { fr . cx ( "fr-header__search" , "fr-modal" ) }
228+ id = "modal-474"
229+ >
230+ < div
231+ className = { fr . cx (
232+ "fr-container" ,
233+ "fr-container-lg--fluid"
234+ ) }
235+ >
236+ < button
237+ className = { fr . cx ( "fr-btn--close" , "fr-btn" ) }
238+ aria-controls = "modal-474"
239+ title = { t ( "close" ) }
240+ >
241+ { t ( "close" ) }
242+ </ button >
243+ < div
244+ className = { fr . cx ( "fr-search-bar" ) }
245+ id = "search-473"
246+ role = "search"
247+ >
248+ < label
249+ className = { fr . cx ( "fr-label" ) }
250+ htmlFor = "search-473-input"
251+ >
252+ { t ( "search" ) }
253+ </ label >
254+ { renderSearchInput ( {
255+ "className" : fr . cx ( "fr-input" ) ,
256+ "id" : "search-473-input" ,
257+ "name" : "search-473-input" ,
258+ "placeholder" : t ( "search" ) ,
259+ "type" : "search"
260+ } ) }
261+ < button
262+ className = { fr . cx ( "fr-btn" ) }
263+ title = { t ( "search" ) }
264+ >
265+ { t ( "search" ) }
266+ </ button >
267+ </ div >
268+ </ div >
269+ </ div >
270+ ) }
271+ </ div >
272+ ) }
145273 </ div >
146274 </ div >
147275 </ div >
@@ -178,15 +306,17 @@ const { useTranslation, addHeaderTranslations } = createComponentI18nApi({
178306 "frMessages" : {
179307 /* spell-checker: disable */
180308 "menu" : "Menu" ,
181- "close" : "Fermer"
309+ "close" : "Fermer" ,
310+ "search" : "Rechercher"
182311 /* spell-checker: enable */
183312 }
184313} ) ;
185314
186315addHeaderTranslations ( {
187316 "lang" : "en" ,
188317 "messages" : {
189- "close" : "Close"
318+ "close" : "Close" ,
319+ "search" : "Search"
190320 }
191321} ) ;
192322
0 commit comments