Skip to content

Commit

Permalink
feat(core:navigation): mvp cds-navigation
Browse files Browse the repository at this point in the history
- this is vertical axis only
- custom expand/collapse icons for root navigation and navigation groups
- navigation groups
- arrow and home and end key navigation
- adds mdx and demos to core storybook

Signed-off-by: Matt Hippely <mhippely@vmware.com>
  • Loading branch information
hippee-lee committed Jul 8, 2021
1 parent 29218a4 commit a80cfc5
Show file tree
Hide file tree
Showing 36 changed files with 3,901 additions and 703 deletions.
1 change: 1 addition & 0 deletions packages/core/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ const config = {
'./src/internal-components/overlay',
'./src/internal-components/panel',
'./src/modal',
'./src/navigation',
'./src/pagination',
'./src/password',
'./src/progress-circle',
Expand Down
5 changes: 5 additions & 0 deletions packages/core/src/internal/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,8 @@ export {
} from './motion/animations/cds-accordion-panel-open.js';
export { AnimationHingeConfig, AnimationHingeName } from './motion/animations/cds-overlay-hinge-example.js';
export { AnimationShakeConfig, AnimationShakeName } from './motion/animations/cds-component-shake.js';
export {
AnimationNavigationGroupOpenConfig,
AnimationNavigationGroupOpenName,
} from './motion/animations/cds-navigation-group-open.js';
export { AnimationNavigationOpenConfig, AnimationNavigationOpenName } from './motion/animations/cds-navigation-open.js';
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2016-2021 VMware, Inc. All Rights Reserved.
* This software is released under MIT license.
* The full license information can be found in LICENSE in the root directory of this project.
*/

import { TargetedAnimation } from '../interfaces.js';

export const AnimationNavigationGroupOpenName = 'cds-navigation-group-open';
export const AnimationNavigationGroupOpenConfig: TargetedAnimation[] = [
{
target: '.navigation-group-items',
animation: [
{ opacity: 0, height: '0' },
{ opacity: 1, height: 'from:cds-navigation-group' },
],
options: {
duration: '--animation-duration',
easing: '--animation-easing',
fill: 'forwards',
},
},
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright (c) 2016-2021 VMware, Inc. All Rights Reserved.
* This software is released under MIT license.
* The full license information can be found in LICENSE in the root directory of this project.
*/

import { TargetedAnimation } from '../interfaces.js';

export const AnimationNavigationOpenName = 'cds-navigation-open';
export const AnimationNavigationOpenConfig: TargetedAnimation[] = [
{
target: 'cds-navigation',
animation: [{ width: 'var(--collapsed-width)' }, { width: 'var(--expanded-width)' }],
options: {
duration: '--animation-duration',
easing: '--animation-easing',
fill: 'forwards',
},
},
];
6 changes: 6 additions & 0 deletions packages/core/src/internal/services/i18n.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ export const componentStringsDefault = {
contentBox: 'Scrollable Modal Body',
contentEnd: 'End of Modal Content',
},
navigation: {
navigationElement: 'navigation',
navigationLabel: 'navigation menu',
navigationAbridgedText: 'View abridged menu',
navigationUnabridgedText: 'View unabridged menu',
},
password: {
showButtonAriaLabel: 'Show password',
hideButtonAriaLabel: 'Hide password',
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/internal/utils/array.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 VMware, Inc. All Rights Reserved.
* Copyright (c) 2016-2021 VMware, Inc. All Rights Reserved.
* This software is released under MIT license.
* The full license information can be found in LICENSE in the root directory of this project.
*/
Expand Down
8 changes: 8 additions & 0 deletions packages/core/src/internal/utils/lit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,11 @@ export function syncProps(
.filter(c => conditions[c])
.forEach(c => (target[c] = source[c]));
}

export function syncPropsForAllItems(
targets: { [prop: string]: any }[],
source: { [prop: string]: any },
conditions: { [prop: string]: boolean }
) {
targets.forEach(target => syncProps(target, source, conditions));
}
12 changes: 12 additions & 0 deletions packages/core/src/navigation/entrypoint.tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"extends": "../../tsconfig.lib.json",
"compilerOptions": {
"composite": true
},
"references": [
{ "path": "../button/entrypoint.tsconfig.json" },
{ "path": "../divider/entrypoint.tsconfig.json" },
{ "path": "../internal/entrypoint.tsconfig.json" },
{ "path": "../icon/entrypoint.tsconfig.json" }
]
}
10 changes: 10 additions & 0 deletions packages/core/src/navigation/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* Copyright (c) 2016-2021 VMware, Inc. All Rights Reserved.
* This software is released under MIT license.
* The full license information can be found in LICENSE in the root directory of this project.
*/

export * from './navigation.element.js';
export * from './navigation-group.element.js';
export * from './navigation-start.element.js';
export * from './navigation-item.element.js';
13 changes: 13 additions & 0 deletions packages/core/src/navigation/interfaces/navigation.interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Copyright (c) 2016-2021 VMware, Inc. All Rights Reserved.
* This software is released under MIT license.
* The full license information can be found in LICENSE in the root directory of this project.
*/

export interface FocusableItem {
id: string;
hasFocus: boolean;
focusElement: HTMLElement;
}

export type NavigationFocusState = true | false;
48 changes: 48 additions & 0 deletions packages/core/src/navigation/navigation-group.element.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*!
* Copyright (c) 2016-2021 VMware, Inc. All Rights Reserved.
* This software is released under MIT license.
* The full license information can be found in LICENSE in the root directory of this project.
*/

@import './../styles/tokens/generated/index';

:host {
--animation-duration: #{$cds-global-animation-duration-secondary};
--animation-easing: #{$cds-global-animation-easing-primary};
--background: inherit;
}

.navigation-group-items {
height: 0;
overflow-y: hidden;
}

:host([cds-motion='off']) {
.navigation-group-items {
height: 0;
}
}

:host([cds-motion='off'][expanded]) {
.navigation-group-items {
height: auto;
}
}

:host([cds-motion][_cds-animation-status='ready']:not([cds-motion='off'])) {
.navigation-group-items {
height: 0;
}
}

:host([cds-motion][expanded][_cds-animation-status='ready']:not([cds-motion='off'])) {
.navigation-group-items {
height: auto !important;
transform: none;
}
}

.group-items-container,
.group-items-wrapper {
width: 100%;
}
84 changes: 84 additions & 0 deletions packages/core/src/navigation/navigation-group.element.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright (c) 2016-2021 VMware, Inc. All Rights Reserved.
* This software is released under MIT license.
* The full license information can be found in LICENSE in the root directory of this project.
*/

import { html } from 'lit';
import { createTestElement, componentIsStable, removeTestElement } from '@cds/core/test';
import { CdsNavigationGroup, CdsNavigationStart } from '@cds/core/navigation';
import '@cds/core/navigation/register.js';
import Spy = jasmine.Spy;

describe('cds-navigation-group', () => {
let component: CdsNavigationGroup;
let element: HTMLElement;
let click: MouseEvent;

beforeEach(async () => {
element = await createTestElement(html`
<cds-navigation-group>
<cds-navigation-start id="start">Group nav start</cds-navigation-start>
<cds-navigation-item>group nav item</cds-navigation-item>
</cds-navigation-group>
`);
component = element.querySelector<CdsNavigationGroup>('cds-navigation-group');
click = new MouseEvent('click');
});

afterEach(() => {
removeTestElement(element);
});

it('should create a navigation group component', async () => {
await componentIsStable(component);
expect(component).toBeTruthy();
});

it('expands and collapses', async () => {
await componentIsStable(component);
const items = component.shadowRoot.querySelector('.navigation-group-items');
expect(items.getAttribute('aria-expanded')).toBe('false');
component.expanded = true;
await componentIsStable(component);
expect(items.getAttribute('aria-expanded')).toBe('true');
});

it('emits the expandedChange event', async () => {
await componentIsStable(component);
let count = 0;
const expandedSpy: Spy = jasmine.createSpy('expandedChange').and.callFake(() => {
count++;
});
component.addEventListener('expandedChange', expandedSpy);
const startEle = component.querySelector<CdsNavigationStart>('cds-navigation-start');
startEle.dispatchEvent(click);
await componentIsStable(component);
expect(count).toBe(1);
});

it('has accessible navigationGroupId', async () => {
await componentIsStable(component);
expect(component.navigationGroupId).toBeTruthy();
const itemWrapper = component.shadowRoot.querySelector('.group-items-wrapper');
expect(itemWrapper.getAttribute('aria-labelledby')).toBe(component.navigationGroupId);
});

it('can be active', async () => {
await componentIsStable(component);
component.setAttribute('active', '');
await componentIsStable(component);
expect(component.active).toBe(true);
});

it('syncs expandedState down to children items', async () => {
await componentIsStable(component);
const startEle = component.querySelector<CdsNavigationStart>('cds-navigation-start');
expect(startEle.navigationGroupId).toBe(component.navigationGroupId);
expect(startEle.isGroupStart).toBe(true);
expect(startEle.expanded).toBe(component.expanded);
component.setAttribute('expanded', '');
await componentIsStable(component);
expect(startEle.expanded).toBe(component.expanded);
});
});
Loading

0 comments on commit a80cfc5

Please sign in to comment.