Skip to content
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

Info Banner web-component #151

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
bcba493
Updated docs on dark mode and dependencies
dgibson666 Jun 20, 2024
8126cc4
Add new typography variant of heading-dialog
dgibson666 Jun 20, 2024
c7b1766
Added accessibilityText to drawer story and format component code
dgibson666 Jun 20, 2024
37e6cbe
First cut of dialog, with dark mode
dgibson666 Jun 20, 2024
a736ae7
Add danger variant and code cleanup
dgibson666 Jun 20, 2024
b8884dc
Update reqs doc
dgibson666 Jun 20, 2024
c388fd2
cbp-banner creation in the web-components space, ticket TCS-2309
Jun 21, 2024
af30d80
Remove commented code and drawer references.
dgibson666 Jun 21, 2024
8fb8a14
Merge pull request #149 from US-CBP/feature/cbp-modal
dgibson666 Jun 21, 2024
9882232
Update the way typography sets dark mode colors
dgibson666 Jun 21, 2024
059364d
Update panel and drawer stories to remove the context prop on the hea…
dgibson666 Jun 21, 2024
80a6936
Remove panel heading color dark mode variable that doesn't change
dgibson666 Jun 21, 2024
23cd2e9
Merge pull request #150 from US-CBP/bugfix/panel-header
dgibson666 Jun 24, 2024
e6dc59e
Merge branch 'develop' into feature_infoBanner
Jun 24, 2024
dc97fb7
adding index.ts
bagrub Jun 24, 2024
bae5f2a
update icon mapping for infoBanner needs
bagrub Jun 24, 2024
df64eab
resolve comments from code review, still WIP
bagrub Jun 25, 2024
fd8cf09
Updates based on code review during 1:1 call
bagrub Jun 25, 2024
831b623
update color mapping for info banner
bagrub Jun 25, 2024
51b6cd7
update classname
bagrub Jun 25, 2024
204bbca
Merge pull request #152 from US-CBP/feature_infoBanner
bagrub Jun 25, 2024
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
8 changes: 8 additions & 0 deletions dependencies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Dependencies

The follow major dependencies are used in this repo and devops pipeline:

* StencilJS
* Storybook
* Vite
* Bitovi GitHub Action to publish Storybook to GitHub Pages: https://github.com/bitovi/github-actions-storybook-to-github-pages
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ export const CbpAccordionItem = /*@__PURE__*/createReactComponent<JSX.CbpAccordi
export const CbpApp = /*@__PURE__*/createReactComponent<JSX.CbpApp, HTMLCbpAppElement>('cbp-app');
export const CbpAppHeader = /*@__PURE__*/createReactComponent<JSX.CbpAppHeader, HTMLCbpAppHeaderElement>('cbp-app-header');
export const CbpBadge = /*@__PURE__*/createReactComponent<JSX.CbpBadge, HTMLCbpBadgeElement>('cbp-badge');
export const CbpBanner = /*@__PURE__*/createReactComponent<JSX.CbpBanner, HTMLCbpBannerElement>('cbp-banner');
export const CbpButton = /*@__PURE__*/createReactComponent<JSX.CbpButton, HTMLCbpButtonElement>('cbp-button');
export const CbpCard = /*@__PURE__*/createReactComponent<JSX.CbpCard, HTMLCbpCardElement>('cbp-card');
export const CbpChip = /*@__PURE__*/createReactComponent<JSX.CbpChip, HTMLCbpChipElement>('cbp-chip');
export const CbpContainer = /*@__PURE__*/createReactComponent<JSX.CbpContainer, HTMLCbpContainerElement>('cbp-container');
export const CbpDialog = /*@__PURE__*/createReactComponent<JSX.CbpDialog, HTMLCbpDialogElement>('cbp-dialog');
export const CbpDrawer = /*@__PURE__*/createReactComponent<JSX.CbpDrawer, HTMLCbpDrawerElement>('cbp-drawer');
export const CbpExpand = /*@__PURE__*/createReactComponent<JSX.CbpExpand, HTMLCbpExpandElement>('cbp-expand');
export const CbpFlex = /*@__PURE__*/createReactComponent<JSX.CbpFlex, HTMLCbpFlexElement>('cbp-flex');
Expand Down
33 changes: 33 additions & 0 deletions packages/web-components/src/components/cbp-banner/cbp-banner.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

:root {
--cbp-banner-color-bg: var(--cbp-color-info-dark);
--cbp-banner-color: var(--cbp-color-text-lightest);
}

cbp-banner {
display: flex;
flex-direction: row;
gap: var(--cbp-space-4x);
padding: var(--cbp-space-4x) var(--cbp-responsive-spacing-outer);
background-color: var(--cbp-banner-color-bg);


.cbp-banner-icon-container{
align-content: center;
}

.cbp-banner-text-container{
display: flex;
flex-grow: 1;
flex-direction: column;
color: var(--cbp-banner-color);
}

/** Info Banner*/
&[color='info']{
--cbp-banner-color-bg: var(--cbp-color-info-dark);
--cbp-banner-color: var(--cbp-color-text-lightest);
}

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Meta } from '@storybook/addon-docs';

<Meta title="Components/Banner/Specifications" />

# cbp-banner

## Purpose

The Banner is a container spanning the entire viewport meant to highlight urgent or important content.

## Functional Requirements

* Informational banners are the only supported variation of banner currently supported for web Components.
* These banner contain an icon as well as a heading followed by descriptive text.
* These banner contain a button to dismiss the banner.

### Responsiveness

* The banners are responsive and content will wrap and reflow down to phone viewport sizes.

### Accessibility

* Ideally, only one banner should be present at a time.
* In the event that more than one banner is present, the "dismiss" buttons will need to be uniquely labelled. Adding an `id` to the heading element and referencing the respective heading `id` as the value of an `aria-describedby` attribute on the dismiss button is recommended.

### Additional Notes and Considerations

* A dismissed banner may be brought back into view by removing the `hidden` attribute from its outer wrapping element.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
export default {
title: 'Components/Banner',
tags: ['autodocs'],
argTypes: {
bannerTitle: {
name: 'Banner title',
description: 'Text to fill the banner h2',
control: 'text',
},
bannerContent:{
name: 'Banner Content',
description: 'Text to fill the banner Content',
control: 'text',
},
},
args: {
},
};

const Template = ({ bannerTitle, bannerContent}) => {
return `
<cbp-banner>
<cbp-typography
slot='cbp-banner-title'
tag='div'
variant='heading-lg'
context='dark-always'
>
${bannerTitle}
</cbp-typography>
${bannerContent}
</cbp-banner>
`;
};

export const Banner = Template.bind({});
Banner.args = {
bannerTitle: 'Scheduled Maintenance Notice',
bannerContent: 'This application will be undergoing scheduled maintenance from 10/5/XXXX to 10/31/XXXX from 12am - 3am and wil be unavaliable during these times.'
};
56 changes: 56 additions & 0 deletions packages/web-components/src/components/cbp-banner/cbp-banner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Component, Prop, Element, Event, EventEmitter, h, Host} from '@stencil/core';

@Component({
tag: 'cbp-banner',
styleUrl: 'cbp-banner.scss',
})
export class CbpBanner {

@Element() host: HTMLElement;

/** Specifies a color variant for the banner. */
@Prop({reflect: true}) color: 'info' = 'info'; //intended to be used for different statuses (error, warning, etc)

/** A custom event emitted with the Banner is dismissed. */
@Event() bannerDismiss: EventEmitter;
handleDismiss() {
this.host.setAttribute('hidden', '');
this.bannerDismiss.emit({
host: this.host
})
}

render() {
return (
<Host>
<cbp-icon
class='cbp-banner-icon-container'
name='exclamation-circle'
color='var(--cbp-color-text-lighter)'
size='3rem'
/>
<div class='cbp-banner-text-container'>
<slot name='cbp-banner-title' />
<p>
<slot />
</p>
<cbp-button
type='button'
fill='solid'
color='primary'
context='dark-always'
onButtonClick={ () => {this.handleDismiss()}}
>
<cbp-icon
name='times'
sx={{"margin-inline-end": "var(--cbp-space-1x)"}}
/>
Dismiss
</cbp-button>
</div>

</Host>
);
}

}
120 changes: 120 additions & 0 deletions packages/web-components/src/components/cbp-dialog/cbp-dialog.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
:root {
--cbp-dialog-color: var(--cbp-color-text-darkest);
--cbp-dialog-color-dark: var(--cbp-color-text-lightest);

--cbp-dialog-color-bg: var(--cbp-color-white);
--cbp-dialog-color-bg-dark: var(--cbp-color-gray-cool-60);

--cbp-dialog-padding: var(--cbp-space-5x);
--cbp-dialog-border-radius: var(--cbp-border-radius-softer);
--cbp-dialog-shadow: var(--cbp-shadow-level-5-center);
--cbp-dialog-width: 20rem;
--cbp-dialog-height: auto;
}

/*
* Dark Mode - display dark design based on mode or context
*/
[data-cbp-theme=light] cbp-dialog[context*=dark],
[data-cbp-theme=dark] cbp-dialog:not([context=dark-inverts]):not([context=light-always]) {
--cbp-dialog-color: var(--cbp-dialog-color-dark);
--cbp-dialog-color-bg: var(--cbp-dialog-color-bg-dark);
}

cbp-dialog {
display: none;
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 999;
overflow: hidden;
background-color: rgba(0, 0, 0, 0.3); // backdrop

&[open] {
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}

&[color=danger] {
--cbp-dialog-color-bg: var(--cbp-color-danger-lighter);
--cbp-dialog-color-bg-dark: var(--cbp-color-danger-darker);
}

div[role=dialog] {
opacity: 1;
display: flex;
flex-direction: column;
position: fixed;
overflow-y: auto;
z-index: 9;
width: var(--cbp-dialog-width);
height: var(--cbp-dialog-height);
max-width: 100%;
max-height: 90vh;
box-shadow: var(--cbp-dialog-shadow);
border-radius: var(--cbp-dialog-border-radius);

.cbp-dialog-body {
color: var(--cbp-dialog-color);
background-color: var(--cbp-dialog-color-bg);
padding: var(--cbp-dialog-padding);
border-radius: var(--cbp-dialog-border-radius) var(--cbp-dialog-border-radius) 0 0;
}

[slot=cbp-dialog-actions] {
display: flex;

cbp-button {
--cbp-button-border-radius: 0;
width: 100%;

&:first-child {
--cbp-button-border-radius: 0 0 0 var(--cbp-border-radius-softer);
}

&:last-child {
--cbp-button-border-radius: 0 0 var(--cbp-border-radius-softer) 0;
}

&:first-child:last-child {
--cbp-button-border-radius: 0 0 var(--cbp-border-radius-softer) var(--cbp-border-radius-softer);
}

button,
a {
padding-block: var(--cbp-space-3x);
width: 100%;
}
}
}
}
}


@media (max-width: 37.5em) {
cbp-dialog {
&[open] {
align-items: end;
}

div[role=dialog] {
margin-bottom: var(--cbp-space-5x);
}
}
}

@media print {
cbp-dialog[open] div[role=dialog] {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 999;
background-color: var(--cbp-dialog-background-color)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Meta } from '@storybook/addon-docs';

<Meta title="Components/Dialog/Specifications" />

# cbp-dialog

## Purpose

The Dialog component represents a dialog overlaid on top of the web page, which can be used similar to an alert/confirm dialog or contain a small form.

## Functional Requirements

* The Dialog component will cover the page in the background with a translucent backdrop to put visual focus on the dialog, which is centered in the display on larger screens.
* At small screen sizes, the Dialog shall be positioned near the bottom of the screen.
* Furthermore, the underlying page will not be accessible while the dialog is open.
* The Dialog component defines a danger color variants as well, based on design tokens.
* The Dialog may optionally contain a title and/or actions in the form of buttons (or links).

## Technical Specifications

### User Interactions

* In most cases, a control on the page should be visible to reveal the Dialog. This is typically a Button component and is not part of the dialog component.
* When an action button in the dialog is activated by user interaction, it emits a custom event (native to the button, not dialog) that can be listened for.

### Responsiveness

* The default width of the dialog is `20rem` (320px), which should fit on a mobile device.
* Under 600px (37.5rem), the dialog will be positioned near the bottom of the viewport for easier thumb access.
* The dialog has `max-width: 100%` and `max-height: 90vh` so that it will never stretch larger than the viewport.

### Accessibility

* The dialog has `role="dialog"` and `aria-modal="true"` applied to it automatically.
* The dialog should have an accessible label specified via the `accessibilityText` property, which applies an `aria-label` on the `role="dialog"` element.
* When the dialog is opened, or if it is open by default on page load, focus will be sent to the first focusable element within the dialog.
* TODO: When the dialog is open, focus shall be trapped within the dialog and the background page is not accessible.
* TODO: When the dialog is closed, focus shall be sent back to the control used to open it.

### Additional Notes and Considerations

TBD.
Loading
Loading