Skip to content

Commit 1a4a19c

Browse files
authored
chore(components, styles): remove standard html banners (#6078)
## πŸ“„ Description This PR remove the HTML banner examples and integrated the banner styles to the `post-banner` web component. --- ## πŸ“ Checklist - βœ… My code follows the style guidelines of this project - πŸ› οΈ I have performed a self-review of my own code - πŸ“„ I have made corresponding changes to the documentation - ⚠️ My changes generate no new warnings or errors - πŸ§ͺ I have added tests that prove my fix is effective or that my feature works - βœ”οΈ New and existing unit tests pass locally with my changes
1 parent 5253ee2 commit 1a4a19c

File tree

22 files changed

+203
-533
lines changed

22 files changed

+203
-533
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@swisspost/design-system-components': patch
3+
---
4+
5+
Updated the `post-banner` icons.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
'@swisspost/design-system-styles': major
3+
'@swisspost/design-system-documentation': major
4+
---
5+
6+
Removed the Standard HTML Banner component (`.banner`, `.banner-*`) in favor of the `post-banner` web component.
7+
8+
BEFORE:
9+
10+
```html
11+
<div role="alert" class="banner banner-success">
12+
<p>Contentus momentus vero siteos et accusam iretea et justo.</p>
13+
</div>
14+
```
15+
16+
AFTER:
17+
18+
```html
19+
<post-banner type="success">
20+
<p>This is the content of the banner. It helps to draw attention to critical messages.</p>
21+
</post-banner>
22+
```

β€Žpackages/components/cypress/e2e/banner.cy.tsβ€Ž

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
const BANNER_ID = '8fd36823-966e-46a8-8432-a4439f6e208f';
1+
const BANNER_ID = '105e67d8-31e9-4d0b-87ff-685aba31fd4c';
22

33
describe('banner', () => {
44
describe('default', () => {
55
beforeEach(() => {
6-
cy.getComponent('post-banner', BANNER_ID);
6+
cy.getComponent('banner', BANNER_ID);
77
});
88

99
it('should render', () => {
@@ -17,7 +17,7 @@ describe('banner', () => {
1717

1818
describe('dismissible', () => {
1919
beforeEach(() => {
20-
cy.getComponent('post-banner', BANNER_ID, 'dismissible');
20+
cy.getComponent('banner', BANNER_ID, 'dismissible');
2121
});
2222

2323
it('should have a close button', () => {
@@ -33,7 +33,7 @@ describe('banner', () => {
3333

3434
describe('Accessibility', () => {
3535
it('Has no detectable a11y violations on load for all variants', () => {
36-
cy.getSnapshots('post-banner');
36+
cy.getSnapshots('banner');
3737
cy.checkA11y('#root-inner');
3838
});
3939
});
Lines changed: 87 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,96 @@
1-
@use '@swisspost/design-system-styles/components/banner';
21
@use '@swisspost/design-system-styles/components/close';
3-
@use '@swisspost/design-system-styles/core' as post;
2+
3+
@use '@swisspost/design-system-styles/mixins/utilities';
4+
@use '@swisspost/design-system-styles/mixins/icons';
5+
@use '@swisspost/design-system-styles/mixins/media';
6+
@use '@swisspost/design-system-styles/mixins/color-scheme';
7+
8+
@use '@swisspost/design-system-styles/variables/components/notification';
9+
@use '@swisspost/design-system-styles/variables/spacing';
10+
11+
@use '@swisspost/design-system-styles/tokens/components';
12+
@use '@swisspost/design-system-styles/functions/tokens';
13+
14+
tokens.$default-map: components.$post-banner;
415

516
:host {
6-
display: block;
17+
position: relative;
18+
display: grid;
19+
grid-template-columns: 1fr;
20+
grid-auto-rows: auto;
21+
grid-auto-flow: row;
22+
row-gap: tokens.get('banner-content-gap');
23+
min-height: calc(#{tokens.get('banner-icon-size')} + (2 * #{tokens.get('banner-padding')}));
24+
padding: tokens.get('banner-padding');
25+
padding-inline-start: calc(#{tokens.get('banner-padding')} + #{tokens.get('banner-icon-size')} + #{tokens.get('banner-gap')});
26+
color: var(--post-current-fg);
27+
border-style: tokens.get('banner-border-style');
28+
border-width: tokens.get('banner-border-width');
29+
border-radius: tokens.get('banner-border-radius');
30+
box-shadow: tokens.get('banner-elevation');
31+
32+
&::before {
33+
content: '';
34+
display: block;
35+
position: absolute;
36+
height: tokens.get('banner-icon-size');
37+
width: tokens.get('banner-icon-size');
38+
inset-block-start: tokens.get('banner-padding');
39+
inset-inline-start: tokens.get('banner-padding');
40+
}
741

842
::slotted(*) {
9-
margin: 0 !important;
43+
margin-block: 0 !important;
1044
}
1145
}
1246

13-
.visually-hidden {
14-
@include post.visuallyhidden();
47+
@each $name in 'info', 'success', 'warning', 'error' {
48+
:host([type="#{$name}"]) {
49+
background-color: tokens.get('banner-#{$name}-bg');
50+
border-color: tokens.get('banner-#{$name}-border-color');
51+
@include color-scheme.set(tokens.get('post-banner-#{$name}-bg-scheme'));
52+
53+
&::before {
54+
background-image: var(--post-signal-icon-#{$name});
55+
}
56+
}
57+
}
58+
59+
:host([dismissible]) {
60+
pointer-events: auto;
61+
position: relative;
62+
63+
> .btn-close {
64+
position: absolute;
65+
inset-block-start: tokens.get('banner-padding');
66+
inset-inline-end: tokens.get('banner-padding');
67+
68+
> span {
69+
@include utilities.visuallyhidden();
70+
}
71+
}
72+
}
73+
74+
.actions {
75+
display: flex;
76+
flex-direction: row-reverse;
77+
justify-content: flex-start;
78+
align-items: center;
79+
margin-block-start: tokens.get('banner-actions-margin-top');
80+
gap: tokens.get('banner-actions-gap');
81+
82+
@include media.only(mobile) {
83+
flex-direction: column;
84+
align-items: stretch;
85+
}
86+
}
87+
88+
@include utilities.high-contrast-mode {
89+
:host {
90+
border-color: CanvasText;
91+
92+
&::before {
93+
color: CanvasText;
94+
}
95+
}
1596
}

β€Žpackages/components/src/components/post-banner/post-banner.tsxβ€Ž

Lines changed: 33 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import { version } from '@root/package.json';
1414
import { fadeOut } from '@/animations';
1515
import { checkRequiredAndType, checkEmptyOrOneOf } from '@/utils';
1616
import { BANNER_TYPES, BannerType } from './banner-types';
17-
import { nanoid } from 'nanoid';
1817

1918
/**
2019
* @slot heading - Slot for placing custom content within the banner's heading.
@@ -28,18 +27,16 @@ import { nanoid } from 'nanoid';
2827
shadow: true,
2928
})
3029
export class PostBanner {
30+
private mutationObserver = new MutationObserver(this.checkContent.bind(this));
31+
3132
@Element() host: HTMLPostBannerElement;
3233

33-
@State() bannerId = `p${nanoid(6)}`;
34-
@State() classes: string;
35-
@State() hasActions: boolean;
36-
@State() hasHeading: boolean;
37-
@State() onDismissButtonClick = () => this.dismiss();
34+
@State() hasActions = false;
3835

3936
/**
4037
* If `true`, a close button (Γ—) is displayed and the banner can be dismissed by the user.
4138
*/
42-
@Prop() readonly dismissible: boolean = false;
39+
@Prop({reflect: true}) readonly dismissible: boolean = false;
4340

4441
@Watch('dismissible')
4542
checkDismissible() {
@@ -58,7 +55,7 @@ export class PostBanner {
5855
/**
5956
* The type of the banner.
6057
*/
61-
@Prop() readonly type: BannerType = 'info';
58+
@Prop({reflect: true}) readonly type: BannerType = 'info';
6259

6360
@Watch('type')
6461
validateType() {
@@ -71,18 +68,18 @@ export class PostBanner {
7168
*/
7269
@Event() postDismissed: EventEmitter<void>;
7370

71+
connectedCallback() {
72+
this.mutationObserver.observe(this.host, { childList: true });
73+
}
74+
7475
componentDidLoad() {
76+
this.checkContent();
7577
this.checkDismissible();
7678
this.validateType();
7779
}
7880

79-
componentWillRender() {
80-
this.hasHeading = this.host.querySelectorAll('[slot=heading]').length > 0;
81-
this.hasActions = this.host.querySelectorAll('[slot=actions]').length > 0;
82-
83-
this.classes = `banner ${this.type ? 'banner-' + this.type : ''}`;
84-
if (this.dismissible) this.classes += ' banner-dismissible';
85-
if (this.hasActions) this.classes += ' banner-action';
81+
disconnectedCallback() {
82+
this.mutationObserver.disconnect();
8683
}
8784

8885
/**
@@ -98,36 +95,29 @@ export class PostBanner {
9895
this.postDismissed.emit();
9996
}
10097

101-
render() {
102-
const defaultBannerContent = [
103-
this.hasHeading && (
104-
<div key={`${this.bannerId}-heading`} class="banner-heading">
105-
<slot name="heading" />
106-
</div>
107-
),
108-
<slot key={`${this.bannerId}-message`} />,
109-
];
110-
111-
const actionBannerContent = [
112-
<div key={`${this.bannerId}-content`} class="banner-content">
113-
{defaultBannerContent}
114-
</div>,
115-
<div key={`${this.bannerId}-buttons`} class="banner-buttons">
116-
<slot name="actions" />
117-
</div>,
118-
];
98+
private checkContent() {
99+
this.hasActions = this.host.querySelectorAll('[slot="actions"]').length > 0;
100+
}
119101

102+
render() {
120103
return (
121-
<Host data-version={version}>
122-
<div role="alert" class={this.classes} part={this.classes}>
123-
{this.dismissible && (
124-
<button class="btn-close" onClick={this.onDismissButtonClick}>
125-
<span class="visually-hidden">{this.dismissLabel}</span>
126-
</button>
127-
)}
128-
129-
{this.hasActions ? actionBannerContent : defaultBannerContent}
130-
</div>
104+
<Host data-version={version} role="alert">
105+
{this.dismissible && (
106+
<button class="btn-close" onClick={() => this.dismiss()}>
107+
<span>{this.dismissLabel}</span>
108+
</button>
109+
)}
110+
111+
112+
<slot name="heading" />
113+
114+
<slot />
115+
116+
{this.hasActions && (
117+
<div class="actions">
118+
<slot name="actions" />
119+
</div>
120+
)}
131121
</Host>
132122
);
133123
}
Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
describe('Banner', () => {
22
it('default', () => {
33
cy.visit('/iframe.html?id=snapshots--banner');
4-
cy.get('.banner post-icon', { timeout: 30000 }).should('be.visible');
5-
cy.percySnapshot('Banners (Standard HTML)', { widths: [320, 1440] });
6-
});
7-
8-
it('post-banner', () => {
9-
cy.visit('/iframe.html?id=snapshots--post-banner');
104
cy.get('post-icon', { timeout: 30000 }).should('be.visible');
11-
cy.percySnapshot('Banners (Web Component)', { widths: [320, 1440] });
5+
cy.percySnapshot('Banners', { widths: [320, 1440] });
126
});
137
});
File renamed without changes.

0 commit comments

Comments
Β (0)