Esikatselu
const ExampleMainBar = () => {
return (
<MainBar>
<MainBarAction>Logo</MainBarAction>
<MainBarActionGroup>
<MainBarAction>Lorem</MainBarAction>
<MainBarAction>Ipsum</MainBarAction>
</MainBarActionGroup>
</MainBar>
);
};
render(<ExampleMainBar />);
Käyttötarkoitus
MainBar
on palvelukohtainen työkalupalkki sivun ylätunnisteeseen. Komponenttiin
on tarkoitus koota koko palvelua koskevia toimintoja, kuten kielenvalinta, haku sekä
sisään- ja uloskirjautuminen. Mobiilinäkymässä työkalupalkki sisältää myös navigaatiovalikon avauspainikkeen.
Toimintopalkin sisällön tulisi toistua identtisenä kaikkialla palvelussa. Näkymän mukaan jatkuvasti vaihtuvat toiminnot ovat usein käytettävyyden kannalta ongelmallisia. Toiminnoilla
tulee olla aina tunnistamista helpottava käyttöliittymäkuvake.
Komponentin responsiivinen toteutus on osittain kehittäjän vastuulla. Lähtökohtaisesti painiketekstien tulee näkyä myös kapeilla näytöillä. Mobiilinäkymässä toimintoja voi esittää vain rajoitetun määrän. Työkalupalkki ei kuitenkaan saa rivittyä usealle riville.
Varmista, että toimintojen järjestys näyttäytyy johdonmukaisena myös silloin, kun käyttäjä siirtyy saman organisaation verkkopalvelusta toiseen.
- Kielenvalinnan tulisi sijaita samalla paikalla kaikissa eri palveluissa. Saavutettavuuden kannalta paras paikka valinnalle on dokumentin alussa.
- Sisään- ja uloskirjautuminen esitetään aina työkalupalkin oikeassa reunassa.
Saavutettavuus
Toimintolinkkien ja -painikkeiden saavutettavuus on kehittäjän vastuulla, jos painikkeiden tekstejä joudutaan piilottamaan.
Lisää toiminnoille tarpeen mukaan aria-label
-attribuutit.
Esimerkit
Esimerkki MainBarin toteuttamisesta
const ExampleMainBar = () => {
const [isExampleOpen, setIsExampleOpen] = useState(false);
return (
<MainBar stackOnMobile>
<MainBarAction icon={<IconPlaceholder />} onClick={(e) => alert("onClick")}>
Painike
</MainBarAction>
<MainBarActionGroup>
<MainBarAction as="a" href="#" icon={<IconPlaceholder />} aria-label="Linkki">
Linkki
</MainBarAction>
<Dropdown isOpen={isExampleOpen} onClick={() => setIsExampleOpen(!isExampleOpen)}>
<DropdownToggle as={MainBarAction} icon={<IconPlaceholder />} aria-label="Valikko">
Valikko
</DropdownToggle>
<DropdownMenu>
<DropdownMenuGroupHeading>Otsikko</DropdownMenuGroupHeading>
<DropdownMenuGroup>
<DropdownMenuItem href="#">Linkki</DropdownMenuItem>
<DropdownMenuItem href="#">Linkki</DropdownMenuItem>
<DropdownMenuItem href="#">Linkki</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenu>
</Dropdown>
</MainBarActionGroup>
</MainBar>
);
};
render(<ExampleMainBar />);
Aktiivisen toiminnon visuaalinen korostus
Käytä MainBarAction
-komponentin active
-tilaa korostamaan aktiivista tai valittua toimintoa. Muista tarvittaessa lisätä aria-current
-attribuutti ruudunlukijoille.
const ExampleMainBar = () => {
const [isExampleOpen, setIsExampleOpen] = useState(false);
return (
<MainBar stackOnMobile>
<MainBarAction icon={<IconPlaceholder />} onClick={(e) => alert("onClick")}>
Painike
</MainBarAction>
<MainBarActionGroup>
<MainBarAction as="a" href="#" icon={<IconPlaceholder />} aria-label="Linkki" active>
Linkki
</MainBarAction>
<Dropdown isOpen={isExampleOpen} onClick={() => setIsExampleOpen(!isExampleOpen)}>
<DropdownToggle as={MainBarAction} icon={<IconPlaceholder />} aria-label="Valikko">
Valikko
</DropdownToggle>
<DropdownMenu>
<DropdownMenuGroupHeading>Otsikko</DropdownMenuGroupHeading>
<DropdownMenuGroup>
<DropdownMenuItem href="#">Linkki</DropdownMenuItem>
<DropdownMenuItem href="#">Linkki</DropdownMenuItem>
<DropdownMenuItem href="#">Linkki</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenu>
</Dropdown>
</MainBarActionGroup>
</MainBar>
);
};
render(<ExampleMainBar />);
Animoitu valikkopainike mobiilinavigaatiolle
const ExampleMainBar = () => {
const [isMenuOpen, setIsMenuOpen] = useState(false);
return (
<MainBar stackOnMobile>
<MainBarActionGroup>
<MainBarMenuButton isOpen={isMenuOpen} onClick={() => setIsMenuOpen(!isMenuOpen)}>
{!isMenuOpen && <span className="kds-sr-only">Avaa valikko</span>}
{isMenuOpen && <span className="kds-sr-only">Sulje valikko</span>}
<span aria-hidden>Valikko</span>
</MainBarMenuButton>
</MainBarActionGroup>
</MainBar>
);
};
render(<ExampleMainBar />);
MainBarin keskittäminen kapeampaan palstaan
MainBar voidaan keskittää ja esittää kapeammassa palstassa MainBarContainer
- ja Container
-komponenttien yhdistelmällä.
const ExampleMainBarContainer = () => {
const [isLoginOpen, setIsLoginOpen] = useState(false);
const [isLangOpen, setIsLangOpen] = useState(false);
const [isMenuOpen, setIsMenuOpen] = useState(false);
return (
<MainBarContainer>
<Container maxWidth="2xl" gx={0} fluid>
<MainBar stackOnMobile as="div" shadow={false}>
<MainBarAction as="a" href="#">
<LogoKelaWhite height="45" width="80" />
</MainBarAction>
<MainBarActionGroup useGroupItems={true}>
<MainBarActionGroupItem>
<Dropdown isOpen={isLangOpen} onClick={() => setIsLangOpen(!isLangOpen)}>
<DropdownToggle as={MainBarAction} icon={<IconGlobe />} aria-label="Suomi">
Suomi
</DropdownToggle>
<DropdownMenu>
<DropdownMenuGroupHeading>Valitse kieli</DropdownMenuGroupHeading>
<DropdownMenuGroup>
<DropdownMenuItem href="#">På svenska</DropdownMenuItem>
<DropdownMenuItem href="#">In english</DropdownMenuItem>
<DropdownMenuItem href="#">Saameksi</DropdownMenuItem>
<DropdownMenuItem href="#">Selkosuomeksi</DropdownMenuItem>
<DropdownMenuItem href="#">Viittomakielellä</DropdownMenuItem>
<DropdownMenuItem href="#">På teckenspråk</DropdownMenuItem>
<DropdownMenuItem href="#">Other languages</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenu>
</Dropdown>
</MainBarActionGroupItem>
<MainBarActionGroupItem>
<Dropdown isOpen={isLoginOpen} onClick={() => setIsLoginOpen(!isLoginOpen)}>
<DropdownToggle as={MainBarAction} icon={<IconLock />} aria-label="Kirjaudu">
Kirjaudu
</DropdownToggle>
<DropdownMenu>
<DropdownMenuGroupHeading>Henkilöasiakkaat</DropdownMenuGroupHeading>
<DropdownMenuGroup>
<DropdownMenuItem href="#" iconAfter={<IconCaretRight />}>
Palvelu A
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuItem divider />
<DropdownMenuGroupHeading>Työnantajat</DropdownMenuGroupHeading>
<DropdownMenuGroup>
<DropdownMenuItem href="#" iconAfter={<IconCaretRight />}>
Palvelu B
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuItem divider />
<DropdownMenuGroupHeading>Yhteistyökumppanit</DropdownMenuGroupHeading>
<DropdownMenuGroup>
<DropdownMenuItem href="#" iconAfter={<IconCaretRight />}>
Palvelu C
</DropdownMenuItem>
<DropdownMenuItem href="#" iconAfter={<IconCaretRight />}>
Palvelu D
</DropdownMenuItem>
<DropdownMenuItem href="#" iconAfter={<IconCaretRight />}>
Palvelu E
</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenu>
</Dropdown>
</MainBarActionGroupItem>
<MainBarActionGroupItem className="md:kds-hidden">
<MainBarMenuButton isOpen={isMenuOpen} onClick={() => setIsMenuOpen(!isMenuOpen)}>
{!isMenuOpen && <span className="kds-sr-only">Avaa valikko</span>}
{isMenuOpen && <span className="kds-sr-only">Sulje valikko</span>}
<span aria-hidden>Valikko</span>
</MainBarMenuButton>
</MainBarActionGroupItem>
</MainBarActionGroup>
</MainBar>
</Container>
</MainBarContainer>
);
};
render(<ExampleMainBarContainer />);
Hakukentän toteutus
Hakukentän voi toteuttaa MainBarSearchV2
-komponentilla. Komponentti tuottaa yksinkertaisen hakukentän, joka ei ota kantaa itse hakutoiminnallisuuteen, vaan tarjoaa vain valmiin ulkoasun.
Toistaiseksi mobiilihakukentän toteuttaminen ja responsiivisuus jää sovelluksen kehittäjien vastuulle. Alla olevassa esimerkissä lomakekenttä vaihtuu lg
-breakpointin kohdalla hakua symboloivaan kuvakkeeseen. Mobiilihaku avautuu kuvaketta klikkaamalla.
const ExampleMainBarSearchV2 = () => {
return (
<MainBarContainer>
<Container maxWidth="2xl" gx={2} fluid>
<MainBar stackOnMobile as="div" shadow={false}>
<MainBarActionGroup useGroupItems={true}>
<MainBarActionGroupItem className="kds-hidden lg:kds-flex">
<MainBarSearchV2
search={({ searchClassName, inputClassName, btnClassName, iconClassName }) => (
<form className={searchClassName}>
<Input
type="text"
size="sm"
className={inputClassName}
placeholder="Kirjoita hakusana"
addonBefore={<IconMagnifyingGlass size="s" className={iconClassName} />}
addonAfter={<Button className={btnClassName}>Hae</Button>}
/>
</form>
)}
/>
</MainBarActionGroupItem>
<MainBarActionGroupItem className="kds-flex lg:kds-hidden">
<MainBarAction icon={<IconMagnifyingGlass />}>Haku</MainBarAction>
</MainBarActionGroupItem>
</MainBarActionGroup>
</MainBar>
</Container>
</MainBarContainer>
);
};
render(<ExampleMainBarSearchV2 />);
Avautuva haku (poistuva ominaisuus)
Huom! MainBarSearch
-komponentti poistuu versiossa 15.0.0.
Hakukentän saa automaattisesti avautumaan antamalla MainBarSearch
-komponentille breakpoint
-attribuutin. Tällöin hakukenttä avautuu ja sulkeutuu riippuen käytettävästä ruudun leveydestä.
Breakpoint
-arvoa käyttäessä hakukenttä ei avaudu automaattisesti, jos käyttäjä on sen kertaalleen sulkenut.
const ExampleDeprecatedMainBarSearch = () => {
const [isExampleOpen, setIsExampleOpen] = useState(false);
return (
<MainBar stackOnMobile>
<MainBarAction icon={<IconPlaceholder />} onClick={(e) => alert("onClick")}>
Painike
</MainBarAction>
<MainBarActionGroup>
<MainBarSearch
breakpoint="lg"
search={(ref, inputClassNames, btnUtilClasses) => (
<>
<input type="text" ref={ref} className={inputClassNames} placeholder="Render prop" />
<Button appearance="outline" variant="light" className={btnUtilClasses}>
Button
</Button>
</>
)}
aria-label="Haku"
closeLabel="Sulje haku"
>
Haku
</MainBarSearch>
<MainBarAction as="a" href="#" icon={<IconPlaceholder />} aria-label="Linkki">
Linkki
</MainBarAction>
<Dropdown isOpen={isExampleOpen} onClick={() => setIsExampleOpen(!isExampleOpen)}>
<DropdownToggle as={MainBarAction} icon={<IconPlaceholder />} aria-label="Valikko">
Valikko
</DropdownToggle>
<DropdownMenu>
<DropdownMenuGroupHeading>Otsikko</DropdownMenuGroupHeading>
<DropdownMenuGroup>
<DropdownMenuItem href="#">Linkki</DropdownMenuItem>
<DropdownMenuItem href="#">Linkki</DropdownMenuItem>
<DropdownMenuItem href="#">Linkki</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenu>
</Dropdown>
</MainBarActionGroup>
</MainBar>
);
};
render(<ExampleDeprecatedMainBarSearch />);
MainBar Kanta-logolla
Määrittele palkissa näytettävän logon mitat siten, että tarvittava suoja-alue toteutuu.
Huomioi myös työkalupalkkiin asetettavien elementtien määrä. Kanta- ja OmaKanta-logot ovat mittasuhteeltaan melko leveitä, ja pienillä näytöillä tilaa on rajallisesti.
const KantaMainBar = () => {
const [isLangOpen, setIsLangOpen] = useState(false);
return (
<MainBar stackOnMobile>
<MainBarAction as="a" href="#">
<LogoKantaWhite height="20" width="85" />
</MainBarAction>
<MainBarActionGroup>
<Dropdown key="lang-dropdown" isOpen={isLangOpen} onClick={() => setIsLangOpen(!isLangOpen)}>
<DropdownToggle as={MainBarAction} icon={<IconGlobe />} aria-label="Suomi">
Suomi
</DropdownToggle>
<DropdownMenu>
<DropdownMenuGroupHeading>Valitse kieli</DropdownMenuGroupHeading>
<DropdownMenuGroup>
<DropdownMenuItem href="#">Suomeksi</DropdownMenuItem>
<DropdownMenuItem href="#">På svenska</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenu>
</Dropdown>
</MainBarActionGroup>
</MainBar>
);
};
render(<KantaMainBar />);
Palveluesimerkit
Kela.fi
const KelafiMainBar = () => {
const [isLoginOpen, setIsLoginOpen] = useState(false);
const [isLangOpen, setIsLangOpen] = useState(false);
const [isMenuOpen, setIsMenuOpen] = useState(false);
return (
<MainBarContainer>
<Container maxWidth="2xl" gx={0} fluid>
<MainBar stackOnMobile as="div" shadow={false}>
<MainBarAction as="a" href="#">
<LogoKelaWhite height="45" width="80" />
</MainBarAction>
<MainBarActionGroup useGroupItems={true}>
<MainBarActionGroupItem className="kds-hidden lg:kds-flex">
<MainBarSearchV2
search={({ searchClassName, inputClassName, btnClassName, iconClassName }) => (
<form className={searchClassName}>
<Input
type="text"
size="sm"
className={inputClassName}
placeholder="Kirjoita hakusana"
addonBefore={<IconMagnifyingGlass size="s" className={iconClassName} />}
addonAfter={<Button className={btnClassName}>Hae</Button>}
/>
</form>
)}
/>
</MainBarActionGroupItem>
<MainBarActionGroupItem className="kds-flex lg:kds-hidden">
<MainBarAction icon={<IconMagnifyingGlass />}>Haku</MainBarAction>
</MainBarActionGroupItem>
<MainBarActionGroupItem>
<Dropdown isOpen={isLangOpen} onClick={() => setIsLangOpen(!isLangOpen)}>
<DropdownToggle as={MainBarAction} icon={<IconGlobe />} aria-label="Suomi">
Suomi
</DropdownToggle>
<DropdownMenu>
<DropdownMenuGroupHeading>Valitse kieli</DropdownMenuGroupHeading>
<DropdownMenuGroup>
<DropdownMenuItem href="#">På svenska</DropdownMenuItem>
<DropdownMenuItem href="#">In english</DropdownMenuItem>
<DropdownMenuItem href="#">Saameksi</DropdownMenuItem>
<DropdownMenuItem href="#">Selkosuomeksi</DropdownMenuItem>
<DropdownMenuItem href="#">Viittomakielellä</DropdownMenuItem>
<DropdownMenuItem href="#">På teckenspråk</DropdownMenuItem>
<DropdownMenuItem href="#">Other languages</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenu>
</Dropdown>
</MainBarActionGroupItem>
<MainBarActionGroupItem>
<Dropdown isOpen={isLoginOpen} onClick={() => setIsLoginOpen(!isLoginOpen)}>
<DropdownToggle as={MainBarAction} icon={<IconLock />} aria-label="Kirjaudu">
Kirjaudu
</DropdownToggle>
<DropdownMenu>
<DropdownMenuGroupHeading>Henkilöasiakkaat</DropdownMenuGroupHeading>
<DropdownMenuGroup>
<DropdownMenuItem href="#" iconAfter={<IconCaretRight />}>
Palvelu A
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuItem divider />
<DropdownMenuGroupHeading>Työnantajat</DropdownMenuGroupHeading>
<DropdownMenuGroup>
<DropdownMenuItem href="#" iconAfter={<IconCaretRight />}>
Palvelu B
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuItem divider />
<DropdownMenuGroupHeading>Yhteistyökumppanit</DropdownMenuGroupHeading>
<DropdownMenuGroup>
<DropdownMenuItem href="#" iconAfter={<IconCaretRight />}>
Palvelu C
</DropdownMenuItem>
<DropdownMenuItem href="#" iconAfter={<IconCaretRight />}>
Palvelu D
</DropdownMenuItem>
<DropdownMenuItem href="#" iconAfter={<IconCaretRight />}>
Palvelu E
</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenu>
</Dropdown>
</MainBarActionGroupItem>
<MainBarActionGroupItem className="md:kds-hidden">
<MainBarMenuButton isOpen={isMenuOpen} onClick={() => setIsMenuOpen(!isMenuOpen)}>
{!isMenuOpen && <span className="kds-sr-only">Avaa valikko</span>}
{isMenuOpen && <span className="kds-sr-only">Sulje valikko</span>}
<span aria-hidden>Valikko</span>
</MainBarMenuButton>
</MainBarActionGroupItem>
</MainBarActionGroup>
</MainBar>
</Container>
</MainBarContainer>
);
};
render(<KelafiMainBar />);
Asiointi
const OmaKelaMainBar = () => {
const [isLoginOpen, setIsLoginOpen] = useState(false);
const [isLangOpen, setIsLangOpen] = useState(false);
const [isMenuOpen, setIsMenuOpen] = useState(false);
return (
<MainBar stackOnMobile>
<MainBarMenuButton
isOpen={isMenuOpen}
onClick={() => setIsMenuOpen(!isMenuOpen)}
className="md:kds-hidden"
aria-haspopup="true"
aria-expanded="false"
>
{!isMenuOpen && <span className="kds-sr-only">Avaa valikko</span>}
{isMenuOpen && <span className="kds-sr-only">Sulje valikko</span>}
<span aria-hidden>Valikko</span>
</MainBarMenuButton>
<MainBarActionGroup>
<Dropdown key="lang-dropdown" isOpen={isLangOpen} onClick={() => setIsLangOpen(!isLangOpen)}>
<DropdownToggle as={MainBarAction} icon={<IconGlobe />} aria-label="Suomi">
Suomi
</DropdownToggle>
<DropdownMenu>
<DropdownMenuGroupHeading>Valitse kieli</DropdownMenuGroupHeading>
<DropdownMenuGroup>
<DropdownMenuItem href="#">Suomeksi</DropdownMenuItem>
<DropdownMenuItem href="#">På svenska</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenu>
</Dropdown>
<Dropdown key="profile-dropdown" isOpen={isLoginOpen} onClick={() => setIsLoginOpen(!isLoginOpen)}>
<DropdownToggle as={MainBarAction} icon={<IconPerson />} aria-label="Anni-Onni Suominen">
Anni-Onni Suominen
</DropdownToggle>
<DropdownMenu>
<DropdownMenuGroupHeading>Anni-Onni Suominen</DropdownMenuGroupHeading>
<DropdownMenuGroup>
<DropdownMenuItem href="#" iconBefore={<IconPersons />}>
Asioi toisen puolesta
</DropdownMenuItem>
<DropdownMenuItem href="#" iconBefore={<IconEdit />}>
Muokkaa omia tietoja
</DropdownMenuItem>
<DropdownMenuItem href="#" iconBefore={<IconLock />}>
Kirjaudu ulos
</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenu>
</Dropdown>
</MainBarActionGroup>
</MainBar>
);
};
render(<OmaKelaMainBar />);