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

feat(alert-banner): add alert banner component #4266

Open
wants to merge 35 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
9b3175a
feat(alert-banner): create alert banner component
Apr 12, 2024
b387b39
feat(alert-banner): add alert-banner to elements bundle
Apr 12, 2024
1145fca
feat(alert-banner): add alert banner tokens in global vars
Apr 12, 2024
9bee350
feat(alert-banner): add stories
Apr 12, 2024
6caaa8c
feat(alert-banner): update readme
Apr 12, 2024
3ce0607
feat(alert-banner): add tests
Apr 12, 2024
ca1fd66
feat(alert-banner): use define element to register component
Apr 15, 2024
7401d7a
feat(alert-banner): add missing dependencies
Apr 15, 2024
ab2ecbe
feat(alert-banner): update golden image cache key
Apr 15, 2024
41cef88
feat(alert-banner): update package version
Apr 15, 2024
0e2fc28
feat(alert-banner): fix wrong import
Apr 15, 2024
7f3f056
feat(alert-banner): update readme
Apr 15, 2024
af13501
feat(alert-banner): address review feedback
Apr 24, 2024
41f49f8
Merge branch 'main' into lspataru/alert-banner
Apr 24, 2024
5909508
feat(alert-banner): update golden image hash
Apr 25, 2024
b6a83d2
feat(alert-banner): revert renovate file
Apr 25, 2024
7e33a0f
feat(alert-banner): add multilangiage story
Apr 25, 2024
af2c057
feat(alert-banner): update args
Apr 25, 2024
2d5adb5
Merge branch 'main' into lspataru/alert-banner
Apr 26, 2024
afac40f
feat(alert-banner): update golden image hash
Apr 26, 2024
706c622
feat(alert-banner): fix typo
Apr 30, 2024
8b83f2a
Merge branch 'main' into lspataru/alert-banner
Apr 30, 2024
7acf7e1
Merge branch 'main' into lspataru/alert-banner
May 22, 2024
8c26e20
feat(alert-banner): fix after main sync
May 22, 2024
6acd39c
feat(alert-banner): update spectrum-css version
May 23, 2024
db2cd1f
feat(alert-banner): update golden image hash
May 23, 2024
bd3765a
Merge branch 'main' into lspataru/alert-banner
loredanaspataru May 23, 2024
9a80f42
feat(alert-banner): revert hash
May 23, 2024
8630a16
feat(alert-banner): update golden image hash
May 23, 2024
780f478
Merge branch 'main' into lspataru/alert-banner
May 24, 2024
4e0978d
feat(alert-banner): update golden image hash
May 24, 2024
7aca227
feat(alert-banner): update global vars
May 24, 2024
4e3f7c2
Merge branch 'main' into lspataru/alert-banner
May 27, 2024
b8166a7
feat(alert-banner): update golden image hash
May 27, 2024
e39c453
feat(alert-banner): update readme
May 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Expand Up @@ -10,7 +10,7 @@ executors:
parameters:
current_golden_images_hash:
type: string
default: fa04f9511c2ba8d512fa189d6e511f3c6c51d933
default: 7401d7aba308d4421ae1b77bd696e06d03697d9a
wireit_cache_name:
type: string
default: wireit
Expand Down
2 changes: 2 additions & 0 deletions packages/alert-banner/.npmignore
@@ -0,0 +1,2 @@
stories
test
97 changes: 97 additions & 0 deletions packages/alert-banner/README.md
@@ -0,0 +1,97 @@
## Description

The `sp-alert-banner` shows pressing and high-signal messages, such as system alerts. It is meant to be noticed and prompt users to take action.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
The `sp-alert-banner` shows pressing and high-signal messages, such as system alerts. It is meant to be noticed and prompt users to take action.
The `<sp-alert-banner>` shows pressing and high-signal messages, such as system alerts. It is meant to be noticed and prompt users to take action.


### Usage

[![See it on NPM!](https://img.shields.io/npm/v/@spectrum-web-components/alert-banner?style=for-the-badge)](https://www.npmjs.com/package/@spectrum-web-components/alert-banner)
[![How big is this package in your project?](https://img.shields.io/bundlephobia/minzip/@spectrum-web-components/alert-banner?style=for-the-badge)](https://bundlephobia.com/result?p=@spectrum-web-components/alert-banner)

```
yarn add @spectrum-web-components/alert-banner
```

Import the side effectful registration of `<sp-alert-banner>` via:

```
import '@spectrum-web-components/alert-banner/sp-alert-banner.js';
```

When looking to leverage the `AlertBanner` base class as a type and/or for extension purposes, do so via:

```
import { AlertBanner } from '@spectrum-web-components/alert-banner';
```

## Examples

The alert banner accepts text context in the default slot provided:

```html
<sp-alert-banner open>
All documents in this folder have been archived
</sp-alert-banner>
```

### Dismissible

Use the `dismissible` attribute to include an icon-only close button to dismiss the alert banner:

```html
<sp-alert-banner open dismissible>
All documents in this folder have been archived
</sp-alert-banner>
```

### Actionable

Use the action slot for the contextual action that a user can take in response to the issue described:

```html
<sp-alert-banner open dismissible>
Your trial has expired
<sp-button treatment="outline" static="white" slot="action">
Buy now
</sp-button>
</sp-alert-banner>
```

## Variants

### Info

```html
<sp-alert-banner open variant="info" dismissible>
Your trial will expire in 3 days
<sp-button treatment="outline" static="white" slot="action">
Buy now
</sp-button>
</sp-alert-banner>
```

### Negative

```html
<sp-alert-banner open variant="negative" dismissible>
Connection interupted. Check your network to continue
</sp-alert-banner>
```

## Closing the alert banner

Alert banners should be used for system-level messages and they should be dismissed only as a result of a user action or if the internal state that triggered the alert has been resolved.

The alert can be dismissed by triggering the close button in case of a dismissible alert. It also exposes a public `close` method to allow consumers to close the alert programmatically.

The component dispatches a `close` event to announce that the alert banner has been closed. This can be prevented by using the `event.preventDefault()` API.

## Accesibility
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
## Accesibility
## Accessibility


loredanaspataru marked this conversation as resolved.
Show resolved Hide resolved
The `sp-alert-banner` element is rendered with a `role` of `alert`, to inform screen readers and notify users accordingly. When rendering the element on a page, it should be placed in a container with a `role` of `region`. The component should not interfere with the user’s current workflow by changing page focus.

The alert banner supports keyboard interaction as follows:

- _Tab_ should place focus on the next interactive element, which can be either the actionable button or the close button.
- _Tab + Shift_ should place focus on the previous interactive element.
- _Space_ or _Enter_ should trigger the interaction if one of the buttons is focused, thus dismissing the alert in case of the close button or triggering the corresponding contextual action.
- _Esc_ will dismiss an alert banner if it’s a dismissible alert.
4 changes: 4 additions & 0 deletions packages/alert-banner/exports.json
@@ -0,0 +1,4 @@
{
"./src/*": "./src/*.js",
"./sp-alert-banner.js": "./sp-alert-banner.js"
}
73 changes: 73 additions & 0 deletions packages/alert-banner/package.json
@@ -0,0 +1,73 @@
{
"name": "@spectrum-web-components/alert-banner",
"version": "0.0.1",
"publishConfig": {
"access": "public"
},
"description": "Web component implementation of a Spectrum design AlertBanner",
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/adobe/spectrum-web-components.git",
"directory": "packages/alert-banner"
},
"author": "",
"homepage": "https://adobe.github.io/spectrum-web-components/components/alert-banner",
"bugs": {
"url": "https://github.com/adobe/spectrum-web-components/issues"
},
"main": "src/index.js",
"module": "src/index.js",
"type": "module",
"exports": {
".": {
"development": "./src/index.dev.js",
"default": "./src/index.js"
},
"./package.json": "./package.json",
"./src/AlertBanner.js": {
"development": "./src/AlertBanner.dev.js",
"default": "./src/AlertBanner.js"
},
"./src/alert-banner.css.js": "./src/alert-banner.css.js",
"./src/index.js": {
"development": "./src/index.dev.js",
"default": "./src/index.js"
},
"./sp-alert-banner.js": {
"development": "./sp-alert-banner.dev.js",
"default": "./sp-alert-banner.js"
}
},
"scripts": {
"test": "echo \"Error: run tests from mono-repo root.\" && exit 1"
},
"files": [
"**/*.d.ts",
"**/*.js",
"**/*.js.map",
"custom-elements.json",
"!stories/",
"!test/"
],
"keywords": [
"spectrum css",
"web components",
"lit-element",
"lit-html"
],
"dependencies": {
"@spectrum-web-components/base": "^0.42.2",
"@spectrum-web-components/button": "^0.42.2",
"@spectrum-web-components/icons-workflow": "^0.42.2"
},
"devDependencies": {
"@spectrum-css/alertbanner": "^1.1.39"
},
"types": "./src/index.d.ts",
"customElements": "custom-elements.json",
"sideEffects": [
"./sp-*.js",
"./**/*.dev.js"
]
}
21 changes: 21 additions & 0 deletions packages/alert-banner/sp-alert-banner.ts
@@ -0,0 +1,21 @@
/*
Copyright 2024 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License.
*/
import { AlertBanner } from './src/AlertBanner.js';
import { defineElement } from '@spectrum-web-components/base/src/define-element.js';

defineElement('sp-alert-banner', AlertBanner);

declare global {
interface HTMLElementTagNameMap {
'sp-alert-banner': AlertBanner;
}
}
146 changes: 146 additions & 0 deletions packages/alert-banner/src/AlertBanner.ts
@@ -0,0 +1,146 @@
/*
Copyright 2024 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License.
*/
import {
CSSResultArray,
html,
SpectrumElement,
TemplateResult,
} from '@spectrum-web-components/base';
import { property } from '@spectrum-web-components/base/src/decorators.js';
import '@spectrum-web-components/button/sp-close-button.js';
import '@spectrum-web-components/icons-workflow/icons/sp-icon-alert.js';
import '@spectrum-web-components/icons-workflow/icons/sp-icon-info.js';
import styles from './alert-banner.css.js';

export type AlertBannerVariants = 'neutral' | 'info' | 'negative' | '';
const VALID_VARIANTS = ['neutral', 'info', 'negative'];
loredanaspataru marked this conversation as resolved.
Show resolved Hide resolved

/**
* @element sp-alert-banner
*/
export class AlertBanner extends SpectrumElement {
public static override get styles(): CSSResultArray {
return [styles];
}

@property({ type: Boolean, reflect: true })
public open = false;

@property({ type: Boolean, reflect: true })
public dismissible = false;
loredanaspataru marked this conversation as resolved.
Show resolved Hide resolved

/**
* The variant applies specific styling when set to `negative` or `info`;
* `variant` attribute is removed when it's passed an invalid variant.
*
* @param {String} variant
*/
@property({ type: String })
public set variant(variant: AlertBannerVariants) {
if (variant === this.variant) {
return;
}
const oldValue = this.variant;
if (this._isValidVariant(variant)) {
this.setAttribute('variant', variant);
this._variant = variant;
} else {
this.removeAttribute('variant');
this._variant = '';
}
this.requestUpdate('variant', oldValue);
}

public get variant(): AlertBannerVariants {
return this._variant;
}

private _variant: AlertBannerVariants = '';

protected _isValidVariant(variant: string): boolean {
return VALID_VARIANTS.includes(variant);
}

protected renderIcon(variant: string): TemplateResult {
switch (variant) {
case 'info':
return html`
<sp-icon-info
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this not customisable?

label="Information"
class="type"
></sp-icon-info>
`;
case 'negative':
return html`
<sp-icon-alert label="Error" class="type"></sp-icon-alert>
`;
default:
return html``;
}
}

private _shouldClose(): void {
loredanaspataru marked this conversation as resolved.
Show resolved Hide resolved
const applyDefault = this.dispatchEvent(
new CustomEvent('close', {
composed: true,
bubbles: true,
cancelable: true,
})
);
if (applyDefault) {
this.close();
}
}

public close(): void {
this.open = false;
}

private _handleKeydown(event: KeyboardEvent): void {
if (event.code === 'Escape' && this.dismissible) {
this._shouldClose();
}
}
loredanaspataru marked this conversation as resolved.
Show resolved Hide resolved

protected override render(): TemplateResult {
return html`
<div class="body" role="alert">
<div class="content">
${this.renderIcon(this.variant)}
<div class="text"><slot></slot></div>
</div>
<slot name="action"></slot>
loredanaspataru marked this conversation as resolved.
Show resolved Hide resolved
</div>
<div class="end">
${this.dismissible
? html`
<sp-close-button
@click=${this._shouldClose}
label="Close"
static="white"
loredanaspataru marked this conversation as resolved.
Show resolved Hide resolved
></sp-close-button>
`
: html``}
</div>
`;
}

public override connectedCallback(): void {
super.connectedCallback();
this.addEventListener('keydown', this._handleKeydown.bind(this));
}

public override disconnectedCallback(): void {
super.disconnectedCallback();
this.removeEventListener('keydown', this._handleKeydown.bind(this));
loredanaspataru marked this conversation as resolved.
Show resolved Hide resolved
}
}
17 changes: 17 additions & 0 deletions packages/alert-banner/src/alert-banner.css
@@ -0,0 +1,17 @@
/*
Copyright 2024 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License.
*/

@import url('./spectrum-alert-banner.css');

:host {
--spectrum-alert-banner-size: 100%;
loredanaspataru marked this conversation as resolved.
Show resolved Hide resolved
}
12 changes: 12 additions & 0 deletions packages/alert-banner/src/index.ts
@@ -0,0 +1,12 @@
/*
Copyright 2024 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License.
*/
export * from './AlertBanner.js';