Skip to content

Commit

Permalink
Merge pull request #229 from US-CBP/App-header-Nav-Item
Browse files Browse the repository at this point in the history
App Header Nav
  • Loading branch information
bagrub authored Dec 9, 2024
2 parents 1a27df7 + 4c89b31 commit eb3bd4e
Show file tree
Hide file tree
Showing 6 changed files with 262 additions and 148 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { Meta, Markdown } from "@storybook/blocks";
import Docs from './readme.md?raw';
import NavItemDocs from '../cbp-nav-item/readme.md?raw';

<Meta title="Components/Application Header/API Docs" />

<Markdown>{Docs}</Markdown>

<Markdown>{NavItemDocs}</Markdown>
Original file line number Diff line number Diff line change
Expand Up @@ -2,97 +2,16 @@
/*** Base variables ***
* @Prop --cbp-app-header-color-background: var(--cbp-color-white)
* @Prop --cbp-app-header-color-background-dark: var(--cbp-color-base-neutral-dark);
/*** Child variables ***
* @Prop --cbp-app-header-child-color: var(--cbp-color-interactive-secondary-darker);
* @Prop --cbp-app-header-child-color-dark: var(--cbp-color-interactive-secondary-lighter);
* @Prop --cbp-app-header-child-color-background: transparent;
* @Prop --cbp-app-header-child-color-background-dark: transparent;
* @Prop --cbp-app-header-child-color-border: transparent;
* @Prop --cbp-app-header-child-color-border-dark: transparent;
* @Prop --cbp-app-header-child-color-outline: var(--cbp-color-white);
* @Prop --cbp-app-header-child-color-outline-dark: transparent;
/*** Hover variables ***
* @Prop --cbp-app-header-child-color-text-hover: var(--cbp-color-interactive-secondary-darker);
* @Prop --cbp-app-header-child-color-text-hover-dark: var(--cbp-color-interactive-secondary-lighter);
* @Prop --cbp-app-header-child-color-background-hover: var(--cbp-color-interactive-secondary-lighter);
* @Prop --cbp-app-header-child-color-background-hover-dark: var(--cbp-color-interactive-secondary-darker);
* @Prop --cbp-app-header-child-color-border-hover: var(--cbp-color-interactive-secondary-darker);
* @Prop --cbp-app-header-child-color-border-hover-dark: var(--cbp-color-interactive-secondary-lighter);
/*** Focus variables ***
* @Prop --cbp-app-header-child-color-text-focus: var(--cbp-color-text-lightest);
* @Prop --cbp-app-header-child-color-text-focus-dark: var(--cbp-color-text-darkest);
* @Prop --cbp-app-header-child-color-background-focus: var(--cbp-color-interactive-focus-dark);
* @Prop --cbp-app-header-child-color-background-focus-dark: var(--cbp-color-interactive-focus-light);
* @Prop --cbp-app-header-child-color-border-focus: var(--cbp-color-interactive-focus-dark);
* @Prop --cbp-app-header-child-color-border-focus-dark: transparent;
* @Prop --cbp-app-header-child-color-outline-focus: var(--cbp-color-white);
* @Prop --cbp-app-header-child-color-outline-focus-dark: var(--cbp-color-black);
/*** Active variables ***
* @Prop --cbp-app-header-child-color-background-active: var(--cbp-color-interactive-active-dark);
* @Prop --cbp-app-header-child-color-background-active-dark: var(--cbp-color-interactive-focus-light);
* @Prop --cbp-app-header-child-color-border-active: var(--cbp-color-interactive-active-dark);
* @Prop --cbp-app-header-child-color-border-active-dark: var(--cbp-color-text-darkest);
* */
*/

:root {
--cbp-app-header-color-background: var(--cbp-color-white);
--cbp-app-header-color-background-dark: var(--cbp-color-base-neutral-dark);

--cbp-app-header-child-color: var(--cbp-color-interactive-secondary-darker);
--cbp-app-header-child-color-dark: var(--cbp-color-interactive-secondary-lighter);
--cbp-app-header-child-color-background: transparent;
--cbp-app-header-child-color-background-dark: transparent;
--cbp-app-header-child-color-border: transparent;
--cbp-app-header-child-color-border-dark: transparent;
--cbp-app-header-child-color-outline: var(--cbp-color-white);
--cbp-app-header-child-color-outline-dark: transparent;

--cbp-app-header-child-color-text-hover: var(--cbp-color-interactive-secondary-darker);
--cbp-app-header-child-color-text-hover-dark: var(--cbp-color-interactive-secondary-lighter);
--cbp-app-header-child-color-background-hover: var(--cbp-color-interactive-secondary-lighter);
--cbp-app-header-child-color-background-hover-dark: var(--cbp-color-interactive-secondary-darker);
--cbp-app-header-child-color-border-hover: var(--cbp-color-interactive-secondary-darker);
--cbp-app-header-child-color-border-hover-dark: var(--cbp-color-interactive-secondary-lighter);

--cbp-app-header-child-color-text-focus: var(--cbp-color-text-lightest);
--cbp-app-header-child-color-text-focus-dark: var(--cbp-color-text-darkest);
--cbp-app-header-child-color-background-focus: var(--cbp-color-interactive-focus-dark);
--cbp-app-header-child-color-background-focus-dark: var(--cbp-color-interactive-focus-light);
--cbp-app-header-child-color-border-focus: var(--cbp-color-interactive-focus-dark);
--cbp-app-header-child-color-border-focus-dark: transparent;
--cbp-app-header-child-color-outline-focus: var(--cbp-color-white);
--cbp-app-header-child-color-outline-focus-dark: var(--cbp-color-black);

--cbp-app-header-child-color-background-active: var(--cbp-color-interactive-active-dark);
--cbp-app-header-child-color-background-active-dark: var(--cbp-color-interactive-focus-light);
--cbp-app-header-child-color-border-active: var(--cbp-color-interactive-active-dark);
--cbp-app-header-child-color-border-active-dark: var(--cbp-color-text-darkest);
}

[data-cbp-theme=light] cbp-app-header[context*=dark]:not([context=light-always]),
[data-cbp-theme=dark] cbp-app-header:not([context=dark-inverts]):not([context=light-always]) {
--cbp-app-header-color-background: var(--cbp-app-header-color-background-dark);

--cbp-app-header-child-color: var(--cbp-app-header-child-color-dark);
--cbp-app-header-child-color-background: var(--cbp-app-header-child-color-background-dark);
--cbp-app-header-child-color-border: var(--cbp-app-header-child-color-border-dark);
--cbp-app-header-child-color-outline: var(--cbp-app-header-child-color-outline-dark);

--cbp-app-header-child-color-text-hover: var(--cbp-app-header-child-color-text-hover-dark);
--cbp-app-header-child-color-background-hover: var(--cbp-app-header-child-color-background-hover-dark);
--cbp-app-header-child-color-border-hover: var(--cbp-app-header-child-color-border-hover-dark);

--cbp-app-header-child-color-text-focus: var(--cbp-app-header-child-color-text-focus-dark);
--cbp-app-header-child-color-background-focus: var(--cbp-app-header-child-color-background-focus-dark);
--cbp-app-header-child-color-border-focus: var(--cbp-app-header-child-color-border-focus-dark);
--cbp-app-header-child-color-outline-focus: var(--cbp-app-header-child-color-outline-focus-dark);

--cbp-app-header-child-color-background-active: var(--cbp-app-header-child-color-background-active-dark);
--cbp-app-header-child-color-border-active: var(--cbp-app-header-child-color-border-active-dark);
}

cbp-app-header {
Expand All @@ -108,60 +27,4 @@ cbp-app-header {
box-shadow: var(--cbp-shadow-level-3-down);
z-index: var(--cbp-z-index-level-1);

// Style all nav items consistently, whether links or button controls for menu/dropdown.
// This may need to be refactored or pulled out and placed into a new component, e.g., cbp-nav-item.
// Actually rendering them as cbp-button components would cut down on the redundant CSS and support most cases as drawer controls and links.
//.nav-home,
//.cbp-nav-item,
//.cbp-menu-dropdown,
button, a {
display: flex;
align-items: center;
height: 100%;
min-height: var(--cbp-space-14x);
padding: 0 var(--cbp-space-3x);
color: var(--cbp-app-header-child-color);
background-color: var(--cbp-app-header-child-color-background);
font-size: var(--cbp-font-size-heading-xs);
font-weight: var(--cbp-font-weight-medium);
text-decoration: none;
white-space: nowrap;
border-color: var(--cbp-app-header-child-color-border);
border-style: solid;
border-width: 0 0 var(--cbp-border-size-xl) 0;
outline-color: var(--cbp-app-header-child-color-outline);
outline-style: solid;
outline-width: 0;
outline-offset: calc(-1 * var(--cbp-space-1x));
cursor: pointer;

&:hover {
color: var(--cbp-app-header-child-color-text-hover);
background-color: var(--cbp-app-header-child-color-background-hover);
border-color: var(--cbp-app-header-child-color-border-hover);
}

&:focus {
color: var(--cbp-app-header-child-color-text-focus);
background-color: var(--cbp-app-header-child-color-background-focus);
border-color: var(--cbp-app-header-child-color-border-focus);
outline-width: var(--cbp-border-size-md);
outline-color: var(--cbp-app-header-child-color-outline-focus);

}

&:active {
background-color: var(--cbp-app-header-child-color-background-active);
border: var(--cbp-app-header-child-color-border-active);
}
}

[slot=cbp-home] {
font-size: var(--cbp-font-size-heading-sm);
font-weight: var(--cbp-font-weight-bold);
padding-left: var(--cbp-space-5x);
padding-right: var(--cbp-space-5x);
margin-left: calc(-1 * var(--cbp-space-5x));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,67 @@ export default {
layout: 'fullscreen',
},
argTypes: {
context : {
control: 'select',
options: [ "light-inverts", "light-always", "dark-inverts", "dark-always"]
},
sx: {
description: 'Supports adding inline styles as an object of key-value pairs comprised of CSS properties and values. Values should reference design tokens when possible.',
control: 'object',
},
},
};

const Template = ({ context, sx }) => {
function generateNavItems(navItems){
const html = navItems.map(({html, selected}) => {
return `<cbp-nav-item ${selected ? 'selected' : ''}> ${html}</cbp-nav-item>`;
}
);
return html.join('');
}


const Template = ({ navItems, sx }) => {
return `
<cbp-app-header
context="${context}"
${sx ? `sx=${JSON.stringify(sx)}` : ''}
>
<a slot="cbp-home" href="/" class="nav-home">Application Name</a>
${generateNavItems(navItems)}
</cbp-app-header>
`;
};

export const ApplicationHeader = Template.bind({});

ApplicationHeader.args = {
navItems: [
{
html: ` <cbp-button
tag='a'
fill="ghost"
color="secondary"
href='./?path=/story/components-application-header--application-header#'
>
Application Name
</cbp-button>`,
selected: true
},{
html: ` <cbp-button
tag='a'
fill="ghost"
color="secondary"
href='./?path=/story/components-application-header--application-header#'
>
Single Nav Item 1
</cbp-button>`,
selected: false,
},
{
html: ` <cbp-button
tag='a'
fill="ghost"
color="secondary"
href='./?path=/story/components-application-header--application-header#'
>
Single Nav Item 2
</cbp-button>`,
selected: false
},
]
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, Host, h, Prop } from '@stencil/core';
import { Component, Element, Host, h } from '@stencil/core';

@Component({
tag: 'cbp-app-header',
Expand All @@ -7,8 +7,44 @@ import { Component, Host, h, Prop } from '@stencil/core';
export class CbpAppHeader {


/** Specifies the context of the component as it applies to the visual design and whether it inverts when light/dark mode is toggled. Default behavior is "light-inverts" and does not have to be specified. */
@Prop({ reflect: true }) context: "light-inverts" | "light-always" | "dark-inverts" | "dark-always";
private navItems: HTMLCbpNavItemElement[] = [];

@Element() host: HTMLElement;

initNavItemset() {
// check for a default navItem, otherwise set the first one active
let activeNavItem;
activeNavItem = this.host.querySelector('cbp-nav-item[selected]');

this.setActiveNav(activeNavItem);
}

setActiveNav(activatedNav) {
this.navItems.forEach((navItem: HTMLCbpNavItemElement) => {
let link = navItem.querySelector('a, button');

if (activatedNav == navItem){
navItem.selected = true;
link.setAttribute('aria-current', 'true');
} else {
navItem.selected = false;
link.removeAttribute('aria-current');
}
})
}

componentWillLoad() {
this.navItems = Array.from(this.host.querySelectorAll('cbp-nav-item'));

// Attach event listeners to the child navItem
this.navItems.forEach(navItem => {
navItem.addEventListener('navClicked', e => this.setActiveNav(e.detail.host));
});
}

componentDidLoad() {
this.initNavItemset();
}

render() {
return (
Expand All @@ -19,3 +55,4 @@ export class CbpAppHeader {
);
}
}

Loading

0 comments on commit eb3bd4e

Please sign in to comment.