diff --git a/libs/design-system/buttons/navigation-toggle/ng-package.json b/libs/design-system/buttons/navigation-toggle/ng-package.json
new file mode 100644
index 0000000..dc244f1
--- /dev/null
+++ b/libs/design-system/buttons/navigation-toggle/ng-package.json
@@ -0,0 +1,7 @@
+{
+ "lib": {
+ "cssUrl": "inline",
+ "entryFile": "src/index.ts",
+ "styleIncludePaths": ["../../src/sass"]
+ }
+}
diff --git a/libs/design-system/buttons/navigation-toggle/src/index.ts b/libs/design-system/buttons/navigation-toggle/src/index.ts
new file mode 100644
index 0000000..bbdd2d1
--- /dev/null
+++ b/libs/design-system/buttons/navigation-toggle/src/index.ts
@@ -0,0 +1 @@
+export { NavigationToggle } from './lib/navigation-toggle';
diff --git a/libs/design-system/buttons/navigation-toggle/src/lib/navigation-toggle.html b/libs/design-system/buttons/navigation-toggle/src/lib/navigation-toggle.html
new file mode 100644
index 0000000..951605e
--- /dev/null
+++ b/libs/design-system/buttons/navigation-toggle/src/lib/navigation-toggle.html
@@ -0,0 +1,9 @@
+
diff --git a/libs/design-system/buttons/navigation-toggle/src/lib/navigation-toggle.scss b/libs/design-system/buttons/navigation-toggle/src/lib/navigation-toggle.scss
new file mode 100644
index 0000000..b938abe
--- /dev/null
+++ b/libs/design-system/buttons/navigation-toggle/src/lib/navigation-toggle.scss
@@ -0,0 +1,49 @@
+@use '@angular/material' as mat;
+@use 'internal/token-utils';
+@use './tokens' as *;
+
+:host {
+ display: block;
+ width: fit-content;
+
+ @include mat.button-overrides(
+ (
+ text-container-height: 3rem,
+ text-label-text-color: token-utils.slot(label-color, $config),
+ text-icon-spacing: 0.125rem,
+ text-label-text-font: token-utils.slot(label-font, $config),
+ text-label-text-size: token-utils.slot(label-font-size, $config),
+ text-label-text-tracking: token-utils.slot(label-letter-spacing, $config),
+ text-label-text-weight: token-utils.slot(label-font-weight, $config),
+ text-with-icon-horizontal-padding: 0.75rem,
+ text-state-layer-color: transparent,
+ )
+ );
+
+ @include mat.icon-overrides(
+ (
+ color: token-utils.slot(icon-color, $config),
+ )
+ );
+
+ .ang-navigation-toggle-button {
+ &:focus-visible {
+ outline: solid 0.125rem token-utils.slot(focus-outline-color, $config);
+ }
+
+ :is(&.ang-navigation-toggle-selected, &:hover, &:active, &:focus-visible) {
+ .ang-navigation-toggle-text {
+ text-decoration: underline;
+ text-underline-offset: 0.25rem;
+ text-decoration-thickness: 0.125rem;
+ text-decoration-color: token-utils.slot(underline-color, $config);
+ }
+ }
+
+ .ang-navigation-toggle-icon {
+ height: 1.25rem;
+ width: 1.25rem;
+ font-size: 1.25rem;
+ }
+ }
+}
diff --git a/libs/design-system/buttons/navigation-toggle/src/lib/navigation-toggle.spec.ts b/libs/design-system/buttons/navigation-toggle/src/lib/navigation-toggle.spec.ts
new file mode 100644
index 0000000..d1cf697
--- /dev/null
+++ b/libs/design-system/buttons/navigation-toggle/src/lib/navigation-toggle.spec.ts
@@ -0,0 +1,37 @@
+import { render, screen } from '@testing-library/angular';
+import userEvent from '@testing-library/user-event';
+import { NavigationToggle } from './navigation-toggle';
+
+describe('NavigationToggle', () => {
+ async function setup(link: string | null = null) {
+ const user = userEvent.setup();
+ const rendered = await render(`Category`, {
+ imports: [NavigationToggle],
+ componentProperties: {
+ link,
+ },
+ });
+
+ return {
+ user,
+ ...rendered,
+ };
+ }
+
+ it('toggles state when clicked', async () => {
+ const { user } = await setup();
+ const toggle = screen.getByText('Category').closest('.ang-navigation-toggle-button');
+
+ expect(toggle).toBeTruthy();
+
+ const icon = toggle?.querySelector('.ang-navigation-toggle-icon');
+
+ expect(icon).toHaveAttribute('data-mat-icon-name', 'expand_more');
+
+ await user.click(toggle as Element);
+ expect(icon).toHaveAttribute('data-mat-icon-name', 'expand_less');
+
+ await user.click(toggle as Element);
+ expect(icon).toHaveAttribute('data-mat-icon-name', 'expand_more');
+ });
+});
diff --git a/libs/design-system/buttons/navigation-toggle/src/lib/navigation-toggle.stories.ts b/libs/design-system/buttons/navigation-toggle/src/lib/navigation-toggle.stories.ts
new file mode 100644
index 0000000..5437d43
--- /dev/null
+++ b/libs/design-system/buttons/navigation-toggle/src/lib/navigation-toggle.stories.ts
@@ -0,0 +1,22 @@
+import { Meta, StoryObj } from '@storybook/angular';
+import { NavigationToggle } from './navigation-toggle';
+
+const meta: Meta = {
+ component: NavigationToggle,
+ title: 'Design System/Buttons/Navigation Toggle',
+ parameters: {
+ design: {
+ type: 'figma',
+ url: 'https://www.figma.com/design/BCEJn9KCIbBJ5MzqnojKQp/AtlasNG-Components?node-id=2101-11132',
+ },
+ },
+ render: (args) => ({
+ props: args,
+ template: `Label`,
+ }),
+};
+
+export default meta;
+type Story = StoryObj;
+
+export const Default: Story = {};
diff --git a/libs/design-system/buttons/navigation-toggle/src/lib/navigation-toggle.ts b/libs/design-system/buttons/navigation-toggle/src/lib/navigation-toggle.ts
new file mode 100644
index 0000000..526286d
--- /dev/null
+++ b/libs/design-system/buttons/navigation-toggle/src/lib/navigation-toggle.ts
@@ -0,0 +1,20 @@
+import { ChangeDetectionStrategy, Component, model } from '@angular/core';
+import { MatButtonModule } from '@angular/material/button';
+import { MatIconModule } from '@angular/material/icon';
+import { TrackClick } from '@atlasng/analytics';
+
+@Component({
+ selector: 'ang-navigation-toggle',
+ imports: [MatButtonModule, MatIconModule, TrackClick],
+ templateUrl: './navigation-toggle.html',
+ styleUrl: './navigation-toggle.scss',
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ host: {
+ '[class.ang-navigation-toggle-selected]': 'selected()',
+ '(click)': 'selected.update(s => !s)',
+ },
+})
+export class NavigationToggle {
+ /** Whether the button is currently selected */
+ readonly selected = model(false);
+}
diff --git a/libs/design-system/buttons/navigation-toggle/src/lib/tokens.scss b/libs/design-system/buttons/navigation-toggle/src/lib/tokens.scss
new file mode 100644
index 0000000..48237ca
--- /dev/null
+++ b/libs/design-system/buttons/navigation-toggle/src/lib/tokens.scss
@@ -0,0 +1,19 @@
+@use 'internal/token-utils';
+
+$config: (
+ namespace: 'navigation',
+ tokens: (
+ label-color: token-utils.sys-token(on-surface),
+ icon-color: token-utils.sys-token(on-surface-variant),
+ underline-color: token-utils.sys-token(primary),
+ focus-outline-color: token-utils.sys-token(on-surface),
+ label-font: token-utils.sys-token(title-medium-font),
+ label-font-size: token-utils.sys-token(title-medium-size),
+ label-letter-spacing: token-utils.sys-token(title-medium-tracking),
+ label-font-weight: token-utils.sys-token(title-medium-weight),
+ ),
+);
+
+@mixin overrides($overrides) {
+ @include token-utils.apply-overrides($overrides, $config);
+}
diff --git a/libs/design-system/buttons/navigation/ng-package.json b/libs/design-system/buttons/navigation/ng-package.json
new file mode 100644
index 0000000..dc244f1
--- /dev/null
+++ b/libs/design-system/buttons/navigation/ng-package.json
@@ -0,0 +1,7 @@
+{
+ "lib": {
+ "cssUrl": "inline",
+ "entryFile": "src/index.ts",
+ "styleIncludePaths": ["../../src/sass"]
+ }
+}
diff --git a/libs/design-system/buttons/navigation/src/index.ts b/libs/design-system/buttons/navigation/src/index.ts
new file mode 100644
index 0000000..820fd64
--- /dev/null
+++ b/libs/design-system/buttons/navigation/src/index.ts
@@ -0,0 +1 @@
+export { Navigation } from './lib/navigation';
diff --git a/libs/design-system/buttons/navigation/src/lib/navigation.html b/libs/design-system/buttons/navigation/src/lib/navigation.html
new file mode 100644
index 0000000..4453b9c
--- /dev/null
+++ b/libs/design-system/buttons/navigation/src/lib/navigation.html
@@ -0,0 +1,11 @@
+
+
+
diff --git a/libs/design-system/buttons/navigation/src/lib/navigation.scss b/libs/design-system/buttons/navigation/src/lib/navigation.scss
new file mode 100644
index 0000000..be9c185
--- /dev/null
+++ b/libs/design-system/buttons/navigation/src/lib/navigation.scss
@@ -0,0 +1,37 @@
+@use '@angular/material' as mat;
+@use 'internal/token-utils';
+@use './tokens' as *;
+
+:host {
+ display: block;
+ width: fit-content;
+
+ @include mat.button-overrides(
+ (
+ text-container-height: 3rem,
+ text-label-text-color: token-utils.slot(label-color, $config),
+ text-icon-spacing: 0.125rem,
+ text-label-text-font: token-utils.slot(label-font, $config),
+ text-label-text-size: token-utils.slot(label-font-size, $config),
+ text-label-text-tracking: token-utils.slot(label-letter-spacing, $config),
+ text-label-text-weight: token-utils.slot(label-font-weight, $config),
+ text-with-icon-horizontal-padding: 0.75rem,
+ text-state-layer-color: transparent,
+ )
+ );
+
+ .ang-navigation-button {
+ &:focus-visible {
+ outline: solid 0.125rem token-utils.slot(focus-outline-color, $config);
+ }
+
+ :is(&:hover, &:active, &:focus-visible) {
+ .ang-navigation-text {
+ text-decoration: underline;
+ text-underline-offset: 0.25rem;
+ text-decoration-thickness: 0.125rem;
+ text-decoration-color: token-utils.slot(underline-color, $config);
+ }
+ }
+ }
+}
diff --git a/libs/design-system/buttons/navigation/src/lib/navigation.spec.ts b/libs/design-system/buttons/navigation/src/lib/navigation.spec.ts
new file mode 100644
index 0000000..2f558b4
--- /dev/null
+++ b/libs/design-system/buttons/navigation/src/lib/navigation.spec.ts
@@ -0,0 +1,30 @@
+import { render, screen } from '@testing-library/angular';
+import userEvent from '@testing-library/user-event';
+import { Navigation } from './navigation';
+
+describe('Navigation', () => {
+ async function setup(link: string | null = null) {
+ const user = userEvent.setup();
+
+ await render(`Go to Docs`, {
+ imports: [Navigation],
+ componentProperties: {
+ link,
+ },
+ });
+
+ const button = screen.getByRole('link', { name: 'Go to Docs' });
+
+ return {
+ user,
+ button,
+ };
+ }
+
+ it('renders projected content inside the navigation button', async () => {
+ const { button } = await setup();
+
+ expect(button).toBeInTheDocument();
+ expect(button).toHaveTextContent('Go to Docs');
+ });
+});
diff --git a/libs/design-system/buttons/navigation/src/lib/navigation.stories.ts b/libs/design-system/buttons/navigation/src/lib/navigation.stories.ts
new file mode 100644
index 0000000..78bfa4d
--- /dev/null
+++ b/libs/design-system/buttons/navigation/src/lib/navigation.stories.ts
@@ -0,0 +1,25 @@
+import { Meta, StoryObj } from '@storybook/angular';
+import { Navigation } from './navigation';
+
+const meta: Meta = {
+ component: Navigation,
+ title: 'Design System/Buttons/Navigation',
+ parameters: {
+ design: {
+ type: 'figma',
+ url: 'https://www.figma.com/design/BCEJn9KCIbBJ5MzqnojKQp/AtlasNG-Components?node-id=7493-48830',
+ },
+ },
+ args: {
+ link: 'https://example.com',
+ },
+ render: (args) => ({
+ props: args,
+ template: `Label`,
+ }),
+};
+
+export default meta;
+type Story = StoryObj;
+
+export const Default: Story = {};
diff --git a/libs/design-system/buttons/navigation/src/lib/navigation.ts b/libs/design-system/buttons/navigation/src/lib/navigation.ts
new file mode 100644
index 0000000..6f18f71
--- /dev/null
+++ b/libs/design-system/buttons/navigation/src/lib/navigation.ts
@@ -0,0 +1,16 @@
+import { ChangeDetectionStrategy, Component, input } from '@angular/core';
+import { MatButtonModule } from '@angular/material/button';
+import { TrackClick } from '@atlasng/analytics';
+import { AnyLink, AnyLinkCommand } from '@atlasng/common';
+
+@Component({
+ selector: 'ang-navigation',
+ imports: [MatButtonModule, AnyLink, TrackClick],
+ templateUrl: './navigation.html',
+ styleUrl: './navigation.scss',
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class Navigation {
+ /** The link to navigate to */
+ readonly link = input();
+}
diff --git a/libs/design-system/buttons/navigation/src/lib/tokens.scss b/libs/design-system/buttons/navigation/src/lib/tokens.scss
new file mode 100644
index 0000000..48237ca
--- /dev/null
+++ b/libs/design-system/buttons/navigation/src/lib/tokens.scss
@@ -0,0 +1,19 @@
+@use 'internal/token-utils';
+
+$config: (
+ namespace: 'navigation',
+ tokens: (
+ label-color: token-utils.sys-token(on-surface),
+ icon-color: token-utils.sys-token(on-surface-variant),
+ underline-color: token-utils.sys-token(primary),
+ focus-outline-color: token-utils.sys-token(on-surface),
+ label-font: token-utils.sys-token(title-medium-font),
+ label-font-size: token-utils.sys-token(title-medium-size),
+ label-letter-spacing: token-utils.sys-token(title-medium-tracking),
+ label-font-weight: token-utils.sys-token(title-medium-weight),
+ ),
+);
+
+@mixin overrides($overrides) {
+ @include token-utils.apply-overrides($overrides, $config);
+}
diff --git a/tsconfig.base.json b/tsconfig.base.json
index 62dee4c..d1ad99d 100644
--- a/tsconfig.base.json
+++ b/tsconfig.base.json
@@ -30,6 +30,10 @@
"@atlasng/design-system": ["./libs/design-system/src/index.ts"],
"@atlasng/design-system/buttons/breadcrumbs": ["./libs/design-system/buttons/breadcrumbs/src/index.ts"],
"@atlasng/design-system/buttons/help": ["./libs/design-system/buttons/help/src/index.ts"],
+ "@atlasng/design-system/buttons/navigation": ["./libs/design-system/buttons/navigation/src/index.ts"],
+ "@atlasng/design-system/buttons/navigation-toggle": [
+ "./libs/design-system/buttons/navigation-toggle/src/index.ts"
+ ],
"@atlasng/design-system/buttons/social-media": ["./libs/design-system/buttons/social-media/src/index.ts"],
"@atlasng/design-system/indicators/end-of-results": [
"./libs/design-system/indicators/end-of-results/src/index.ts"