Skip to content

feat(navigation, navigation-logo, navigation-user): Add navigation, navigation-logo & navigation-user components. #6873

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 84 commits into from
May 22, 2023
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
8bdfbc3
feat(nav,nav-logo,nav-user): Add nav, nav-logo & nav-user components.
anveshmekala Apr 27, 2023
b5906c1
add more 2e2 tests
anveshmekala Apr 27, 2023
c2b64e0
rename prop in nav and add e2e test
anveshmekala Apr 27, 2023
ad24c69
add demo-dom-swapper wrapper in demo files
anveshmekala Apr 27, 2023
d91619b
remove default decorator options
anveshmekala Apr 27, 2023
991691c
Merge branch 'master' into anveshmekala/6531-feat-navigation-component
anveshmekala Apr 27, 2023
bf16349
update readme files
anveshmekala Apr 27, 2023
199f634
Update stories
macandcheese Apr 28, 2023
95d13b9
Merge branch 'anveshmekala/6531-feat-navigation-component' of https:/…
anveshmekala Apr 28, 2023
ffeb67e
feedback changes
anveshmekala Apr 28, 2023
db19d11
rename menuAction prop and fix e2e tests
anveshmekala Apr 29, 2023
b2f3254
remove async for common tests
anveshmekala May 1, 2023
a97cb56
test errors
anveshmekala May 1, 2023
cc8224c
restore stencil config
anveshmekala May 1, 2023
80966ae
Merge branch 'master' into anveshmekala/6531-feat-navigation-component
anveshmekala May 1, 2023
40793f4
update stories
anveshmekala May 1, 2023
cf105fb
clean up
anveshmekala May 1, 2023
7a0769f
doc related changes
anveshmekala May 2, 2023
2fecbe5
doc changes
anveshmekala May 2, 2023
25573e1
more feedback changes
anveshmekala May 2, 2023
675dd86
doc changes
anveshmekala May 2, 2023
109a141
Merge branch 'master' into anveshmekala/6531-feat-navigation-component
anveshmekala May 3, 2023
1ec3c32
Merge branch 'master' into anveshmekala/6531-feat-navigation-component
anveshmekala May 3, 2023
ef32860
Merge branch 'master' into anveshmekala/6531-feat-navigation-component
anveshmekala May 3, 2023
cef8b07
Merge branch 'master' into anveshmekala/6531-feat-navigation-component
anveshmekala May 3, 2023
b53d6ca
Merge branch 'master' into anveshmekala/6531-feat-navigation-component
anveshmekala May 5, 2023
98fc70c
parse label from nav-user to avatar
anveshmekala May 5, 2023
777ee50
update demo
anveshmekala May 5, 2023
ab36471
feat(nav,nav-logo,nav-user): Add nav, nav-logo & nav-user components.
anveshmekala Apr 27, 2023
357fee2
add more 2e2 tests
anveshmekala Apr 27, 2023
245728b
rename prop in nav and add e2e test
anveshmekala Apr 27, 2023
d2d0216
add demo-dom-swapper wrapper in demo files
anveshmekala Apr 27, 2023
4323093
remove default decorator options
anveshmekala Apr 27, 2023
d07aab6
update readme files
anveshmekala Apr 27, 2023
8aed351
Update stories
macandcheese Apr 28, 2023
1f6e312
feedback changes
anveshmekala Apr 28, 2023
98f816f
rename menuAction prop and fix e2e tests
anveshmekala Apr 29, 2023
784d6c8
remove async for common tests
anveshmekala May 1, 2023
230e102
test errors
anveshmekala May 1, 2023
a0d18b1
restore stencil config
anveshmekala May 1, 2023
a1c3700
update stories
anveshmekala May 1, 2023
4ca74e1
clean up
anveshmekala May 1, 2023
31515b1
doc related changes
anveshmekala May 2, 2023
4255077
doc changes
anveshmekala May 2, 2023
52be92c
more feedback changes
anveshmekala May 2, 2023
fbfb464
doc changes
anveshmekala May 2, 2023
1f98e24
parse label from nav-user to avatar
anveshmekala May 5, 2023
9343a9e
update demo
anveshmekala May 5, 2023
13fe1c3
Merge branch 'anveshmekala/6531-feat-navigation-component' of https:/…
anveshmekala May 9, 2023
a731b90
fix screenshot tests
anveshmekala May 9, 2023
6912e84
update common util tests to use describe
anveshmekala May 9, 2023
ad2eb87
refactor css files and remove redundancy
anveshmekala May 9, 2023
27ddef7
Merge branch 'master' into anveshmekala/6531-feat-navigation-component
anveshmekala May 9, 2023
db51915
fix positioning issue in stories
anveshmekala May 10, 2023
6708a1c
Merge branch 'master' into anveshmekala/6531-feat-navigation-component
anveshmekala May 10, 2023
8b22471
remove redundant slots in nav stories
anveshmekala May 10, 2023
2f76ede
screenshot feedback changes
anveshmekala May 10, 2023
01ce5d0
Merge branch 'master' into anveshmekala/6531-feat-navigation-component
anveshmekala May 10, 2023
266da9c
Pr feedback
macandcheese May 12, 2023
856933b
Merge branch 'master' into anveshmekala/6531-feat-navigation-component
anveshmekala May 12, 2023
af705d6
feedback changes
anveshmekala May 15, 2023
86180ad
Merge branch 'master' into anveshmekala/6531-feat-navigation-component
anveshmekala May 15, 2023
e30fa6f
change names
anveshmekala May 15, 2023
82331d0
clean up
anveshmekala May 15, 2023
e424aea
fix tests
anveshmekala May 16, 2023
f453574
fix typo
anveshmekala May 16, 2023
042e763
clean css
anveshmekala May 16, 2023
27550ac
replace anchor with button in navigation-user
anveshmekala May 16, 2023
b563d75
update readme files
anveshmekala May 17, 2023
92830f7
Merge branch 'master' into anveshmekala/6531-feat-navigation-component
anveshmekala May 17, 2023
2c7dcd5
refactor(navigation): allow nesting secondary and tertiary navigation…
macandcheese May 18, 2023
bfaf90e
Merge branch 'master' into anveshmekala/6531-feat-navigation-component
anveshmekala May 19, 2023
6095842
remove nav abbreviations from story files
anveshmekala May 19, 2023
bd29cf8
Merge branch 'master' into anveshmekala/6531-feat-navigation-component
anveshmekala May 19, 2023
7b88d1a
more feedback changes
anveshmekala May 19, 2023
680ab82
Merge branch 'master' into anveshmekala/6531-feat-navigation-component
anveshmekala May 19, 2023
c920b5f
add rel & target props to logo
anveshmekala May 19, 2023
66da54a
fix logo slot issue in navigation
anveshmekala May 20, 2023
58943da
change text and subText to heading & desctiption in logo
anveshmekala May 22, 2023
58269bc
Merge branch 'master' into anveshmekala/6531-feat-navigation-component
anveshmekala May 22, 2023
11f42a2
remove textEnabled prop from nav-logo
anveshmekala May 22, 2023
07d01cb
fix navigation screenshot test
anveshmekala May 22, 2023
7e462f8
remove tabindex and focus logo only if href is provided
anveshmekala May 22, 2023
9b1ad85
update readme files
anveshmekala May 22, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions src/components/nav-logo/nav-logo.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { newE2EPage } from "@stencil/core/testing";
import { html } from "../../../support/formatting";
import { accessible, hidden, reflects, renders } from "../../tests/commonTests";

describe("calcite-nav-logo", () => {
describe("renders", () => {
renders("calcite-nav-logo", { display: "inline-flex" });
});

it("honors hidden attribute", () => hidden("calcite-nav-logo"));

describe("accessible", () => {
accessible("calcite-nav-logo");
});

it("reflects", () =>
reflects("calcite-nav-logo", [
{
propertyName: "active",
value: "true"
},
{
propertyName: "href",
value: "#logo"
},
{
propertyName: "textEnabled",
value: "true"
}
]));

it("should emit calciteNavLogoSelect event on user click", async () => {
const page = await newE2EPage();
await page.setContent(html`<calcite-nav-logo text="esri" id="esri" text-enabled></calcite-nav-logo>`);

const element = await page.find("calcite-nav-logo");
const eventSpy = await element.spyOnEvent("calciteNavLogoSelect");

await element.click();
await page.waitForChanges();
expect(await page.evaluate(() => document.activeElement.id)).toBe("esri");
expect(eventSpy).toHaveReceivedEventTimes(1);
});

it("should emit calciteNavLogoSelect event when user select using Enter & Space key", async () => {
const page = await newE2EPage();
await page.setContent(html` <calcite-nav-logo text="esri" id="esri" text-enabled></calcite-nav-logo> `);

const element = await page.find("calcite-nav-logo");
const eventSpy = await element.spyOnEvent("calciteNavLogoSelect");

await page.keyboard.press("Tab");
expect(await page.evaluate(() => document.activeElement.id)).toBe("esri");
expect(eventSpy).not.toHaveReceivedEvent();

await page.keyboard.press("Enter");
expect(await page.evaluate(() => document.activeElement.id)).toBe("esri");
expect(eventSpy).toHaveReceivedEventTimes(1);

await page.keyboard.press("Space");
expect(await page.evaluate(() => document.activeElement.id)).toBe("esri");
expect(eventSpy).toHaveReceivedEventTimes(2);
});
});
54 changes: 54 additions & 0 deletions src/components/nav-logo/nav-logo.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
:host {
@apply inline-flex outline-none;
& a {
@apply flex m-0 items-center justify-center cursor-pointer transition-default focus-base no-underline;
border-block-end: 2px solid transparent;
}
& img {
@apply flex h-7 m-0;
}
}

a:hover,
a:focus {
@apply bg-foreground-2;
}
a:focus {
@apply focus-inset;
}
a:active {
@apply bg-foreground-3;
}
img {
@apply px-4 pl-4;
}
img ~ .text-container {
@apply pl-0;
}
:host(:active) a {
@apply text-color-1;
}
:host([active]) a {
z-index: 9;

@apply text-color-1;
border-color: var(--calcite-ui-brand);
--calcite-ui-icon-color: var(--calcite-ui-brand);
}

.text-container {
@apply flex px-4 truncate;
flex-direction: column;
text-align: start;
}

.logo-text {
@apply text-0 ml-0 truncate text-color-1;
font-weight: 500;
margin-block-start: 2px;
}

.logo-subtext {
@apply text-color-2 truncate;
font-size: var(--calcite-font-size--1);
}
70 changes: 70 additions & 0 deletions src/components/nav-logo/nav-logo.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { boolean, storyFilters } from "../../../.storybook/helpers";
import { placeholderImage } from "../../../.storybook/placeholderImage";
import readme from "./readme.md";
import { html } from "../../../support/formatting";
import { text } from "@storybook/addon-knobs";

export default {
title: "Components/Nav/Nav Logo",
parameters: {
notes: readme
},
...storyFilters()
};

export const simple = (): string =>
html`<calcite-nav>
<calcite-nav-logo
slot="logo"
sub-text="${text("sub-text", "City of AcmeCo")}"
text="${text("text", "ArcGIS Online")}"
thumbnail="${placeholderImage({ width: 50, height: 50 })}"
${boolean("active", false)}
${boolean("text-enabled", true)}
/>
</calcite-nav-logo></calcite-nav>`;

export const text_TestOnly = (): string => html` <calcite-shell>
<calcite-nav slot="header">
<calcite-nav-logo slot="logo" text="ArcGIS Online" />
</calcite-nav>
</calcite-shell>`;

export const subText_TestOnly = (): string => html` <calcite-shell>
<calcite-nav slot="header">
<calcite-nav-logo slot="logo" sub-text="City of AcmeCo" />
</calcite-nav>
</calcite-shell>`;

export const thumbnail_TestOnly = (): string => html` <calcite-shell>
<calcite-nav slot="header">
<calcite-nav-logo slot="logo" thumbnail="${placeholderImage({ width: 50, height: 50 })}" />
</calcite-nav>
</calcite-shell>`;

export const textAndThumbnail_TestOnly = (): string => html` <calcite-shell>
<calcite-nav slot="header">
<calcite-nav-logo slot="logo" text="ArcGIS Online" thumbnail="${placeholderImage({ width: 50, height: 50 })}" />
</calcite-nav>
</calcite-shell>`;

export const subTextAndThumbnail_TestOnly = (): string => html` <calcite-shell>
<calcite-nav slot="header">
<calcite-nav-logo
slot="logo"
sub-text="City of AcmeCo"
thumbnail="${placeholderImage({ width: 50, height: 50 })}"
/>
</calcite-nav>
</calcite-shell>`;

export const All_TestOnly = (): string => html` <calcite-shell>
<calcite-nav slot="header">
<calcite-nav-logo
slot="logo"
text="ArcGIS Online"
sub-text="City of AcmeCo"
thumbnail="${placeholderImage({ width: 50, height: 50 })}"
/>
</calcite-nav>
</calcite-shell>`;
105 changes: 105 additions & 0 deletions src/components/nav-logo/nav-logo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { Component, Element, EventEmitter, h, Host, Prop, Event } from "@stencil/core";
import { CSS } from "./resources";

@Component({
tag: "calcite-nav-logo",
styleUrl: "nav-logo.scss",
shadow: {
delegatesFocus: true
}
})
export class CalciteNavLogo {
//--------------------------------------------------------------------------
//
// Element
//
//--------------------------------------------------------------------------
@Element() el: HTMLCalciteNavLogoElement;

//--------------------------------------------------------------------------
//
// Public Properties
//
//--------------------------------------------------------------------------
/** When `true`, visually highlight the component */
@Prop({ reflect: true }) active: boolean;

/** Specifies the href destination of the component */
@Prop({ reflect: true }) href: string;

/** Specifies accesible label for the component */
@Prop() label: string;

/** Specifies the subtext to display, for example an organization or application description */
@Prop() subText: string;

/** Specifies the text to display, for example a product name */
@Prop() text: string;

/** When `true`, makes `text` and `subText` visible */
@Prop({ reflect: true }) textEnabled: boolean;

/** Specifies the `src` to an image */
@Prop() thumbnail: string;

//--------------------------------------------------------------------------
//
// Events
//
//--------------------------------------------------------------------------

/** Emits when user select the component. */
@Event() calciteNavLogoSelect: EventEmitter<void>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since there is no selection state, how is this (and other select events for navigation and menu components) different from a "click" event? If there's no distinction, I'd suggest removing them and have developers rely on the event target or provide specific event handlers to these components.

For background: we did something similar some time ago with action and removed the redundant custom click event.


// --------------------------------------------------------------------------
//
// Private Methods
//
// --------------------------------------------------------------------------

private clickHandler = (): void => {
this.calciteNavLogoSelect.emit();
};

private keyDownHandler = (event: KeyboardEvent): void => {
if (event.key === "Enter" || event.key === " ") {
this.calciteNavLogoSelect.emit();
event.preventDefault();
}
};

// --------------------------------------------------------------------------
//
// Render Methods
//
// --------------------------------------------------------------------------
render() {
return (
<Host>
<a
aria-label={this.label}
href={this.href}
onClick={this.clickHandler}
onKeyDown={this.keyDownHandler}
tabIndex={0}
>
{this.thumbnail && <img src={this.thumbnail} />}
{(this.text || this.subText) && this.textEnabled && (
<div class={CSS.textContainer}>
{this.text && this.textEnabled ? (
<span class={CSS.logoText} key={CSS.logoText}>
{this.text}
</span>
) : null}
{this.subText && this.textEnabled ? (
<span class={CSS.logoSubtext} key={CSS.logoSubtext}>
{this.subText}
</span>
) : null}
</div>
)}
</a>
</Host>
);
}
}
25 changes: 25 additions & 0 deletions src/components/nav-logo/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# calcite-nav-logo

<!-- Auto Generated Below -->

## Properties

| Property | Attribute | Description | Type | Default |
| ------------- | -------------- | ---------------------------------------------------------------------------------------- | --------- | ----------- |
| `active` | `active` | When `true`, visually highlight the component | `boolean` | `undefined` |
| `href` | `href` | Specifies the href destination of the component | `string` | `undefined` |
| `label` | `label` | Specifies accesible label for the component | `string` | `undefined` |
| `subText` | `sub-text` | Specifies the subtext to display, for example an organization or application description | `string` | `undefined` |
| `text` | `text` | Specifies the text to display, for example a product name | `string` | `undefined` |
| `textEnabled` | `text-enabled` | When `true`, makes `text` and `subText` visible | `boolean` | `undefined` |
| `thumbnail` | `thumbnail` | Specifies the `src` to an image | `string` | `undefined` |

## Events

| Event | Description | Type |
| ---------------------- | ------------------------------------- | ------------------- |
| `calciteNavLogoSelect` | Emits when user select the component. | `CustomEvent<void>` |

---

_Built with [StencilJS](https://stenciljs.com/)_
5 changes: 5 additions & 0 deletions src/components/nav-logo/resources.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const CSS = {
textContainer: "text-container",
logoText: "logo-text",
logoSubtext: "logo-subtext"
};
3 changes: 3 additions & 0 deletions src/components/nav-logo/usage/Basic.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```html
<calcite-nav-logo active thumbnail="./_assets/images/esri-logo.svg"></calcite-nav-user>
```
59 changes: 59 additions & 0 deletions src/components/nav-user/nav-user.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { newE2EPage } from "@stencil/core/testing";
import { html } from "../../../support/formatting";
import { accessible, hidden, reflects, renders } from "../../tests/commonTests";

describe("calcite-nav-user", () => {
describe("renders", () => {
renders("calcite-nav-user", { display: "inline-flex" });
});

it("honors hidden attribute", () => hidden("calcite-nav-user"));

describe("accessible", () => {
accessible("calcite-nav-user");
});

it("reflects", () =>
reflects("calcite-nav-user", [
{
propertyName: "active",
value: "true"
},
{
propertyName: "hideText",
value: ""
}
]));

it("should emit calciteNavUserSelect event on user click", async () => {
const page = await newE2EPage();
await page.setContent(html` <calcite-nav-user id="batman" username="batman"></calcite-nav-user> `);

const element = await page.find("calcite-nav-user");
const eventSpy = await element.spyOnEvent("calciteNavUserSelect");

await element.click();
expect(await page.evaluate(() => document.activeElement.id)).toBe("batman");
expect(eventSpy).toHaveReceivedEventTimes(1);
});

it("should emit calciteNavUserSelect event when user select using Enter or Space key", async () => {
const page = await newE2EPage();
await page.setContent(html` <calcite-nav-user username="batman" id="batman"></calcite-nav-user> `);

const element = await page.find("calcite-nav-user");
const eventSpy = await element.spyOnEvent("calciteNavUserSelect");

await page.keyboard.press("Tab");
expect(await page.evaluate(() => document.activeElement.id)).toBe("batman");
expect(eventSpy).not.toHaveReceivedEvent();

await page.keyboard.press("Enter");
expect(await page.evaluate(() => document.activeElement.id)).toBe("batman");
expect(eventSpy).toHaveReceivedEventTimes(1);

await page.keyboard.press("Space");
expect(await page.evaluate(() => document.activeElement.id)).toBe("batman");
expect(eventSpy).toHaveReceivedEventTimes(2);
});
});
Loading