Skip to content

Commit

Permalink
Feat(web): Introduce Navigation and NavigationLink components #DS-155…
Browse files Browse the repository at this point in the history
…1 #DS-1530
  • Loading branch information
crishpeen committed Dec 12, 2024
1 parent 2b717aa commit cff16a1
Show file tree
Hide file tree
Showing 12 changed files with 396 additions and 0 deletions.
89 changes: 89 additions & 0 deletions packages/web/src/scss/components/Navigation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Navigation

The `Navigation` component is a container for the navigation links of the application.

It consists of these parts:

- [Navigation](#navigation)
- [NavigationLink](#navigationlink)

## Navigation

The `Navigation` is a `nav` wrapper for lists of links or other navigation components.

```html
<nav class="Navigation" aria-label="Main Navigation">
<ul>
<li>
<!-- link -->
</li>
</ul>
</nav>
```

It centers its children vertically and if the children are not NavigationLink components,
it will insert a gap between them.

ℹ️ If you plan to provide a list of links, wrap them in a `ul` and `li` elements. If not, you can use the
`nav` element directly.

ℹ️ Don't forget to add the `aria-label` attribute to the `Navigation` component for correct accessible state.

## NavigationLink

The `NavigationLink` is component that is styled to be used as a navigation link.

```html
<a class="NavigationLink" href="#">Link</a>
```

It can obtain `selected` or `disabled` states by adding the respective classes.

```html
<a class="NavigationLink NavigationLink--selected" href="#" aria-current="page">Selected Link</a>
<span class="NavigationLink NavigationLink--disabled">Disabled Link</span>
```

ℹ️ Don't forget to add the `aria-current="page"` attribute for correct accessible state if selected.

ℹ️ Please note that in the `disabled` state the `NavigationLink` should not be an `a` tag.

If the `NavigationLink` is inside a [`UNSTABLE_Header`][web-unstable-header] component, it will
inherit the height of the `Header`.

### Full Example

With NavigationLink components:

```html
<nav class="Navigation" aria-label="Main Navigation">
<ul>
<li>
<a class="NavigationLink NavigationLink--selected" href="#" aria-current="page">Selected Link</a>
</li>
<li>
<span class="NavigationLink NavigationLink--disabled">Disabled Link</span>
</li>
<li>
<a class="NavigationLink" href="#">Link</a>
</li>
</ul>
</nav>
```

With Buttons:

```html
<nav class="Navigation" aria-label="Secondary Navigation">
<ul>
<li>
<a href="#" class="Button Button--medium Button--primary">Button</a>
</li>
<li>
<a href="#" class="Button Button--medium Button--secondary">Button</a>
</li>
</ul>
</nav>
```

[web-unstable-header]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web/src/scss/components/UNSTABLE_Header/README.md
23 changes: 23 additions & 0 deletions packages/web/src/scss/components/Navigation/_Navigation.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
@use '@tokens' as tokens;
@use '../../tools/reset';
@use 'theme';

.Navigation,
.Navigation > ul,
.Navigation > ul > li {
display: flex;
}

.Navigation:has(.NavigationLink) {
height: var(--#{tokens.$css-variable-prefix}navigation-height, theme.$height);
}

.Navigation:not(:has(.NavigationLink)),
.Navigation:not(:has(.NavigationLink)) > ul {
gap: theme.$spacing;
align-content: center;
}

.Navigation > ul {
@include reset.list();
}
57 changes: 57 additions & 0 deletions packages/web/src/scss/components/Navigation/_NavigationLink.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// 1. We need to set the top border too, otherwise the content won't be aligned properly.

@use '@tokens' as tokens;
@use '../../tools/typography';
@use 'theme';

.NavigationLink {
@include typography.generate(theme.$link-typography);

position: relative;
display: flex;
align-items: center;
justify-content: center;
padding-inline: theme.$link-spacing;
color: theme.$link-color-state-default;
border-top: theme.$link-border-bottom-width theme.$link-border-bottom-style transparent; // 1.
border-bottom: theme.$link-border-bottom-width theme.$link-border-bottom-style
theme.$link-border-bottom-color-state-default;
background-color: theme.$link-background-color-state-default;

@media (hover: hover) {
&:hover {
text-decoration: none;
color: theme.$link-color-state-hover;
border-bottom-color: theme.$link-border-bottom-color-state-hover;
background-color: theme.$link-background-color-state-hover;
}
}

&:active {
text-decoration: none;
color: theme.$link-color-state-active;
border-bottom-color: theme.$link-border-bottom-color-state-active;
background-color: theme.$link-background-color-state-active;
}
}

.NavigationLink--selected {
color: theme.$link-color-state-selected;
border-bottom-color: theme.$link-border-bottom-color-selected-state-default;
background-color: theme.$link-background-color-state-selected;

@media (hover: hover) {
&:hover {
border-bottom-color: theme.$link-border-bottom-color-selected-state-hover;
}
}

&:active {
border-bottom-color: theme.$link-border-bottom-color-selected-state-active;
}
}

.NavigationLink--disabled {
color: theme.$link-color-state-disabled;
pointer-events: none;
}
24 changes: 24 additions & 0 deletions packages/web/src/scss/components/Navigation/_theme.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
@use '@tokens' as tokens;

$spacing: tokens.$space-700;
$height: 50px;

$link-typography: tokens.$body-small-semibold;
$link-spacing: tokens.$space-600;
$link-color-state-default: tokens.$component-header-item-state-default;
$link-color-state-hover: tokens.$component-header-item-state-hover;
$link-color-state-active: tokens.$component-header-item-state-active;
$link-color-state-selected: tokens.$component-header-item-state-selected;
$link-color-state-disabled: tokens.$disabled-content;
$link-border-bottom-width: tokens.$border-width-200;
$link-border-bottom-style: solid;
$link-border-bottom-color-state-default: transparent;
$link-border-bottom-color-state-hover: tokens.$component-header-stripe-state-unselected;
$link-border-bottom-color-state-active: tokens.$component-header-stripe-state-unselected;
$link-border-bottom-color-selected-state-default: tokens.$component-header-stripe-state-selected;
$link-border-bottom-color-selected-state-hover: tokens.$component-header-stripe-state-selected;
$link-border-bottom-color-selected-state-active: tokens.$component-header-stripe-state-selected;
$link-background-color-state-default: tokens.$component-header-item-background-state-default;
$link-background-color-state-hover: tokens.$component-header-item-background-state-hover;
$link-background-color-state-active: tokens.$component-header-item-background-state-active;
$link-background-color-state-selected: tokens.$component-header-item-background-state-selected;
84 changes: 84 additions & 0 deletions packages/web/src/scss/components/Navigation/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
{{#> web/layout/default title="Navigation" parentPageName="Components" }}

<section class="UNSTABLE_Section">

<div class="Container">

<h2 class="docs-Heading">Navigation</h2>

<div class="docs-Stack docs-Stack--stretch">

<div style="--spirit-header-height: 72px;">
<nav class="Navigation" aria-label="Main Navigation">
<ul>
<li>
Item
</li>
</ul>
</nav>
</div>

</div>

</div>

</section>

<section class="UNSTABLE_Section">

<div class="Container">

<h2 class="docs-Heading">NavigationLink</h2>

<div class="docs-Stack docs-Stack--stretch">

<nav class="Navigation" aria-label="Main Navigation">
<ul>
<li>
<a href="#" class="NavigationLink">Link</a>
</li>
<li>
<a href="#" class="NavigationLink NavigationLink--selected" aria-current="page">Selected</a>
</li>
<li>
<span class="NavigationLink NavigationLink--disabled">Disabled</span>
</li>
</ul>
</nav>

</div>

</div>

</section>

<section class="UNSTABLE_Section">

<div class="Container">

<h2 class="docs-Heading">Navigation with Buttons</h2>

<div class="docs-Stack docs-Stack--stretch">

<nav class="Navigation" aria-label="Navigation with Buttons">
<ul>
<li>
<a href="#" class="Button Button--medium Button--primary">
Button
</a>
</li>
<li>
<a href="#" class="Button Button--medium Button--secondary">
Button
</a>
</li>
</ul>
</nav>

</div>

</div>

</section>

{{/web/layout/default }}
2 changes: 2 additions & 0 deletions packages/web/src/scss/components/Navigation/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@forward 'Navigation';
@forward 'NavigationLink';
57 changes: 57 additions & 0 deletions packages/web/src/scss/components/UNSTABLE_Header/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,5 +117,62 @@ If you need the whole Header fluid you can do it by adding the `Container--fluid
</header>
```

## With Navigation

You can use the [`Navigation`][web-navigation] component inside the `UNSTABLE_Header` component.

The `NavigationLink` components will inherit the `UNSTABLE_Header` height and set the navigation
link height to the same value.

Use the composition mentioned above to create the layout you need.

```html
<header class="UNSTABLE_Header">
<div class="Container">
<div
class="Flex Flex--row Flex--noWrap Flex--alignmentXLeft Flex--alignmentYCenter"
style="--flex-spacing-x: var(--spirit-space-1000);"
>
<a href="#" aria-label="JobBoard homepage" class="UNSTABLE_HeaderLogo">
<div class="ProductLogo">{{> web/assets/jobBoardLogo }}</div>
</a>

<nav class="Navigation" aria-label="Main Navigation">
<ul>
<li>
<a href="#" class="NavigationLink">Link</a>
</li>
<li>
<a href="#" class="NavigationLink NavigationLink--selected" aria-current="page">Selected</a>
</li>
<li>
<a href="#" class="NavigationLink NavigationLink--disabled">Disabled</a>
</li>
</ul>
</nav>

<nav class="Navigation ml-auto" aria-label="Secondary Navigation">
<ul>
<li>
<button class="Button Button--tertiary Button--medium Button--symmetrical">
<svg width="24" height="24" aria-hidden="true">
<use xlink:href="/assets/icons/svg/sprite.svg#search" />
</svg>
</button>
</li>
<li>
<a href="#" class="Button Button--secondary Button--medium">Sign up</a>
</li>
<li>
<a href="#" class="Button Button--primary Button--medium">Post a job</a>
</li>
</ul>
</nav>
</div>
</div>
</header>
```

[web-container]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web/src/scss/components/Container/README.md
[web-flex]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web/src/scss/components/Flex/README.md
[web-navigation]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web/src/scss/components/Navigation/README.md
Loading

0 comments on commit cff16a1

Please sign in to comment.