Skip to content

Commit

Permalink
feat: nav mode for skiplinks
Browse files Browse the repository at this point in the history
  • Loading branch information
astagi committed Dec 4, 2024
1 parent a235d9d commit 2dc384e
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 18 deletions.
19 changes: 16 additions & 3 deletions src/Skiplink/Skiplink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,29 @@ import React, { FC, HTMLAttributes, ElementType } from 'react';
import classNames from 'classnames';

export interface SkiplinkProps extends HTMLAttributes<HTMLElement> {
ariaLabel?: string;
/** Utilizzarlo in caso di utilizzo di componenti personalizzati */
tag?: ElementType;
/** Utilizzare il componente in modalità `nav` */
nav?: boolean;
/** Classi aggiuntive da usare per il componente Skiplink */
className?: string;
testId?: string;
}

export const Skiplink: FC<SkiplinkProps> = ({ className, tag = 'div', testId, ...attributes }) => {
const Tag = tag;
export const Skiplink: FC<SkiplinkProps> = ({ ariaLabel=null, className, tag = 'div', nav=false, testId, children, ...attributes }) => {
const Tag = nav ? 'nav' : tag;
const classes = classNames(className, 'skiplinks');
if (nav) {
return (
<Tag aria-label={ariaLabel} className={classes} {...attributes} data-testid={testId} >
<ul>
{children}
</ul>
</Tag>
)

return <Tag className={classes} {...attributes} data-testid={testId} />;
} else {
return <Tag aria-label={ariaLabel} className={classes} {...attributes} data-testid={testId} />;
}
};
13 changes: 12 additions & 1 deletion src/Skiplink/SkiplinkItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import classNames from 'classnames';
export interface SkiplinkItemProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
/** Utilizzarlo in caso di utilizzo di componenti personalizzati */
tag?: ElementType;
/** Utilizzare il componente come elemento di uno Skiplink in modalità `nav` */
navItem?: boolean;
/** Classi aggiuntive da usare per il componente Skiplink */
className?: string;
/** Abilitare questo attributo per renderizzare lo SkipLinkItem al focus */
Expand All @@ -15,6 +17,7 @@ export const SkiplinkItem: FC<SkiplinkItemProps> = ({
className,
tag = 'a',
focusable = true,
navItem = false,
testId,
...attributes
}) => {
Expand All @@ -26,5 +29,13 @@ export const SkiplinkItem: FC<SkiplinkItemProps> = ({
// Add an extra href for focusable if the user passes an onClick rather than href prop
const extraHref = attributes.onClick ? { href: '#' } : {};

return <Tag className={classes} {...attributes} {...extraHref} data-testid={testId} />;
if (navItem) {
return (
<li className={classes} >
<Tag {...attributes} {...extraHref} data-testid={testId} />
</li>
);
} else {
return <Tag className={classes} {...attributes} {...extraHref} data-testid={testId} />;
}
};
32 changes: 32 additions & 0 deletions stories/Components/Skiplinks.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,38 @@ const EsempiWithHooks = () => {
);
};

const EsempiWithNav = () => {
const containerRef = useRef(null);
const footerRef = useRef(null);

useEffect(() => {
// We focus the container here since it is hosted inside Storybook's iframe
// @ts-expect-error: with no types annotated, never is inferred here
containerRef.current?.focus();
}, []);

const onClick = () => {
// @ts-expect-error: with no types annotated, never is inferred here
footerRef.current?.scrollIntoView();
};

return (
<section tabIndex={-1} ref={containerRef}>
<div id='#main' />
<div id='#footer' ref={footerRef} />

<Skiplink nav aria-label='Scorciatoie di navigazione'>
<SkiplinkItem navItem href='#main'>Skip to main content</SkiplinkItem>
<SkiplinkItem navItem onClick={onClick}>Skip to footer</SkiplinkItem>
</Skiplink>
</section>
);
};

export const _Esempi: Story = {
render: () => <EsempiWithHooks />
};

export const _EsempiWithNav: Story = {
render: () => <EsempiWithNav />
};
15 changes: 14 additions & 1 deletion stories/Documentation/Skiplinks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as SkiplinksStories from '../Components/Skiplinks.stories';

# Skiplinks

## Gli Skiplink sono collegamento interno alla pagina che consentono agli utenti di accedere direttamente al contenuto principale della pagina saltando il menu di navigazione.
Gli Skiplink sono collegamento interno alla pagina che consentono agli utenti di accedere direttamente al contenuto principale della pagina saltando il menu di navigazione.

È un componente particolarmente utile per coloro che accedono con screen reader e/o da tastiera.

Expand Down Expand Up @@ -47,3 +47,16 @@ return (
</section>
);
```


## Elenco
Se la pagina è particolarmente complessa si possono inserire più collegamenti che permettano di saltare direttamente ai blocchi principali.

Nell'esempio che segue, implementato per il sito [Designers Italia](https://designers.italia.it), sono inseriti due collegamenti che è utile approfondire:

- un salto ad un **modulo per chiedere alle persone come stanno valutando l'esperienza d'uso** della pagina. Il testo dello skiplink anticipa già la domanda;
- un **collegamento diretto alla Dichiarazione di accessibilità disponibile sul form AgID**, che accompagnerà il necessario link presente anche nel piede di pagina, per permettere a chi naviga con strumenti assistivi di trovarla facilmente senza dover scansionare tutti i contennuti.

Consigliamo di non eccedere con il numero di elementi scorciatoia, altrimenti emergerebbe il bisogno di poter saltare le stesse scorciatoie.

<Canvas of={SkiplinksStories._EsempiWithNav} />
53 changes: 40 additions & 13 deletions test/__snapshots__/Storybook.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -12150,20 +12150,47 @@ exports[`Stories Snapshots Documentazione/Componenti/Skiplinks _Esempi 1`] = `
/>
<div
class="skiplinks"
/>
</section>
</div>
`;

exports[`Stories Snapshots Documentazione/Componenti/Skiplinks _EsempiWithNav 1`] = `
<div>
<section
tabindex="-1"
>
<div
id="#main"
/>
<div
id="#footer"
/>
<nav
aria-label="Scorciatoie di navigazione"
class="skiplinks"
>
<a
class="visually-hidden-focusable"
href="#main"
>
Skip to main content
</a>
<a
class="visually-hidden-focusable"
href="#"
>
Skip to footer
</a>
</div>
<ul>
<li
class="visually-hidden-focusable"
>
<a
href="#main"
>
Skip to main content
</a>
</li>
<li
class="visually-hidden-focusable"
>
<a
href="#"
>
Skip to footer
</a>
</li>
</ul>
</nav>
</section>
</div>
`;
Expand Down

0 comments on commit 2dc384e

Please sign in to comment.