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(sbb-container): first implementation #2271

Merged
merged 63 commits into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
077d69e
feat: generate components
MarioCastigliano Nov 20, 2023
81d5a54
feat: implement components and stories
MarioCastigliano Nov 27, 2023
3b20987
feat: create a module for container and sticky-bar
MarioCastigliano Nov 28, 2023
ac01975
feat: implement bar animation and color variants
MarioCastigliano Dec 7, 2023
dfa630c
refactor: use new naming convention
MarioCastigliano Dec 7, 2023
4b2a006
fix: address comments
MarioCastigliano Dec 11, 2023
7dc43d0
fix: address comments
MarioCastigliano Dec 11, 2023
4964f4e
fix: tests
MarioCastigliano Dec 11, 2023
a633788
refactor: improve tests
MarioCastigliano Dec 13, 2023
f3a723f
feat: create css variable to handle width
MarioCastigliano Dec 14, 2023
cd2b55f
fix: make sticky-bar handle animation
MarioCastigliano Dec 14, 2023
da9ba2c
feat: improve stories
MarioCastigliano Jan 2, 2024
a63157b
feat: implement review changes
MarioCastigliano Jan 2, 2024
18ceb4b
feat: implement review changes
MarioCastigliano Jan 2, 2024
e257712
fix: standalone error
MarioCastigliano Jan 3, 2024
bf202f9
fix: tests
MarioCastigliano Jan 3, 2024
0177a03
fix: integrity
MarioCastigliano Jan 3, 2024
72fb2bf
feat: use intersection observer
MarioCastigliano Jan 4, 2024
5d273e7
test: fix spec and implement scrolling behavior tests
MarioCastigliano Jan 8, 2024
4a1a8ea
feat: create new stories
MarioCastigliano Jan 8, 2024
d6d5fd4
feat: slot implementation proposal
MarioCastigliano Jan 8, 2024
e1aacd4
fix: animation starting too early
MarioCastigliano Jan 9, 2024
dba9c96
test: expanded property
MarioCastigliano Jan 9, 2024
9df7292
feat: invert animation mechanism
MarioCastigliano Jan 14, 2024
85271b5
docs: update documentation
MarioCastigliano Jan 14, 2024
2434e74
fix: stories and docs as per review
MarioCastigliano Jan 14, 2024
1728787
fix: tests
MarioCastigliano Jan 15, 2024
95068c1
fix: lint
MarioCastigliano Jan 23, 2024
ddcb15f
fix: stories
MarioCastigliano Jan 24, 2024
0c0267c
fix: live review
MarioCastigliano Jan 24, 2024
bd42f47
refactor: review
MarioCastigliano Jan 24, 2024
f2ceded
feat: add color property to sticky-bar
MarioCastigliano Jan 25, 2024
30fa005
fix: improve intersection observer on windows
MarioCastigliano Jan 26, 2024
a6d54d8
fix: high contrast has border instead of shadow
MarioCastigliano Jan 26, 2024
deeec7b
docs: reference sbb-container inside page-spacing docs
MarioCastigliano Jan 26, 2024
520d199
fix: background color on wider screens
MarioCastigliano Jan 26, 2024
0669ba9
docs: update docs
MarioCastigliano Jan 29, 2024
ab4bf8e
fix: styling
MarioCastigliano Jan 29, 2024
b375de5
fix: styling
MarioCastigliano Jan 29, 2024
263d6b1
fix: animation
MarioCastigliano Jan 29, 2024
42a6e49
refactor: improve css (#2375)
jeripeierSBB Jan 30, 2024
a575078
docs: improve display contents docs
jeripeierSBB Jan 30, 2024
e735726
feat: add disable animation prop
MarioCastigliano Jan 30, 2024
050b0fa
feat: improve stories
MarioCastigliano Jan 30, 2024
8a3ef5e
fix: disable animation on first load
MarioCastigliano Jan 30, 2024
e538c85
fix: tests
MarioCastigliano Jan 30, 2024
3dbfdcc
refactor: fix names
jeripeierSBB Jan 30, 2024
660656d
fix: sticky bar behavior on fixed heights
MarioCastigliano Jan 31, 2024
07ef35c
fix: sticky bar behavior on fixed heights
MarioCastigliano Jan 31, 2024
30a7dc1
refactor: position sticky on host
jeripeierSBB Jan 31, 2024
c34fcc6
fix: tests
MarioCastigliano Jan 31, 2024
77cc542
feat: improve stories
MarioCastigliano Jan 31, 2024
54392fe
feat: improve stories
MarioCastigliano Jan 31, 2024
2b6ce99
fix: order of definitions
jeripeierSBB Jan 31, 2024
2a209df
feat: remove midnight variant
MarioCastigliano Feb 1, 2024
5de8818
fix: transparent variant animation
MarioCastigliano Feb 1, 2024
f92441f
fix: using contain: layout
jeripeierSBB Feb 1, 2024
3cc055e
fix: restore behavior on both mac and windows
MarioCastigliano Feb 5, 2024
1f849cb
refactor: use var for intersector overlapping
jeripeierSBB Feb 5, 2024
784867c
feat: improve stories
MarioCastigliano Feb 5, 2024
6ae241f
fix: remove shadow from the bottom of the sticky-bar
MarioCastigliano Feb 5, 2024
774402c
fix: use white as default for container
MarioCastigliano Feb 7, 2024
1bbe7bd
fix: integrity
MarioCastigliano Feb 7, 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
16 changes: 16 additions & 0 deletions src/components/container/container/container.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { assert, fixture } from '@open-wc/testing';
import { html } from 'lit/static-html.js';

import { SbbContainerElement } from './container';

describe('sbb-container', () => {
let element: SbbContainerElement;

beforeEach(async () => {
element = await fixture(html`<sbb-container></sbb-container>`);
});

it('renders', async () => {
assert.instanceOf(element, SbbContainerElement);
});
});
26 changes: 26 additions & 0 deletions src/components/container/container/container.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
@use '../../core/styles' as sbb;

// Default component properties, defined for :host. Properties which can not
// travel the shadow boundary are defined through this mixin
@include sbb.host-component-properties;

:host([color='white']) {
--sbb-container-background-color: var(--sbb-color-white-default);
}

:host([color='milk']) {
--sbb-container-background-color: var(--sbb-color-milk-default);
}

.sbb-container {
background-color: var(--sbb-container-background-color, transparent);
contain: layout;

:host(:not([expanded])) & {
@include sbb.page-spacing;
}

:host([expanded]) & {
@include sbb.page-spacing-expanded;
}
}
20 changes: 20 additions & 0 deletions src/components/container/container/container.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { expect, fixture } from '@open-wc/testing';
import { html } from 'lit/static-html.js';
import './container';

describe('sbb-container', () => {
it('renders', async () => {
const root = await fixture(html`<sbb-container></sbb-container>`);

expect(root).dom.to.be.equal(`<sbb-container color="white"></sbb-container>`);

expect(root).shadowDom.to.equal(
`<div class="sbb-container">
<slot>
</slot>
</div>
<slot name="sticky-bar"></slot>
`,
);
});
});
94 changes: 94 additions & 0 deletions src/components/container/container/container.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import type { InputType } from '@storybook/types';
import type { ArgTypes, Args, Meta, StoryObj } from '@storybook/web-components';
import { type TemplateResult, html, nothing } from 'lit';

import { sbbSpread } from '../../core/dom';

import '../../button';
import '../../title';
import './container';

import readme from './readme.md?raw';

const containerContent = (title: string, last = false): TemplateResult => html`
<sbb-title level="4">${title}</sbb-title>
<p class="sbb-text-s">The container component will give its content the correct spacing.</p>
<p class="sbb-text-s">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco
laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
voluptate velit esse cillum dolore eu fugiat nulla pariatur.
</p>
<sbb-button variant="secondary" style=${last ? 'margin-block-end: 3rem;' : nothing}
>See more</sbb-button
>
`;

const expanded: InputType = {
control: {
type: 'boolean',
},
};

const color: InputType = {
control: {
type: 'select',
},
options: ['white', 'transparent', 'milk'],
};

const defaultArgTypes: ArgTypes = {
expanded,
color,
};

const defaultArgs: Args = {
expanded: false,
color: color.options[0],
};

const DefaultTemplate = ({ color, ...args }: Args): TemplateResult => html`
<sbb-container ${sbbSpread(args)} color=${color}>
${containerContent('Example title')} ${containerContent('Another one')}
${containerContent('And another one', true)}
</sbb-container>
`;

export const Default: StoryObj = {
MarioCastigliano marked this conversation as resolved.
Show resolved Hide resolved
render: DefaultTemplate,
argTypes: defaultArgTypes,
args: { ...defaultArgs },
};

export const Transparent: StoryObj = {
render: DefaultTemplate,
argTypes: defaultArgTypes,
args: { ...defaultArgs, color: color.options[1] },
};

export const Milk: StoryObj = {
render: DefaultTemplate,
argTypes: defaultArgTypes,
args: { ...defaultArgs, color: color.options[2] },
};

export const Expanded: StoryObj = {
render: DefaultTemplate,
argTypes: defaultArgTypes,
args: { ...defaultArgs, expanded: true },
};

const meta: Meta = {
parameters: {
backgrounds: {
disable: true,
},
docs: {
extractComponentDescription: () => readme,
},
layout: 'fullscreen',
},
title: 'components/sbb-container/sbb-container',
MarioCastigliano marked this conversation as resolved.
Show resolved Hide resolved
};

export default meta;
61 changes: 61 additions & 0 deletions src/components/container/container/container.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import {
type CSSResultGroup,
html,
LitElement,
type PropertyValueMap,
type TemplateResult,
} from 'lit';
import { customElement, property } from 'lit/decorators.js';

import { toggleDatasetEntry } from '../../core/dom';

import style from './container.scss?lit&inline';

/**
* It displays its content with the default page spacing.
*
* @slot - Use the unnamed slot to add anything to the container.
* @slot sticky-bar - The slot used by the sbb-sticky-bar component.
*/
@customElement('sbb-container')
export class SbbContainerElement extends LitElement {
public static override styles: CSSResultGroup = style;

/** Whether the container is expanded. */
@property({ type: Boolean, reflect: true }) public expanded = false;

/** Color of the container, like transparent, white etc. */
@property({ reflect: true }) public color: 'transparent' | 'white' | 'milk' = 'white';

private _updateStickyBar(): void {
const stickyBar = this.querySelector?.('sbb-sticky-bar');
if (stickyBar) {
toggleDatasetEntry(stickyBar, 'expanded', this.expanded);
toggleDatasetEntry(stickyBar, 'transparent', this.color === 'transparent');
}
}

protected override willUpdate(
_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>,
): void {
if (_changedProperties.has('expanded') || _changedProperties.has('color')) {
this._updateStickyBar();
}
}

protected override render(): TemplateResult {
return html`
<div class="sbb-container">
<slot></slot>
</div>
<slot name="sticky-bar"></slot>
MarioCastigliano marked this conversation as resolved.
Show resolved Hide resolved
MarioCastigliano marked this conversation as resolved.
Show resolved Hide resolved
`;
}
}

declare global {
interface HTMLElementTagNameMap {
// eslint-disable-next-line @typescript-eslint/naming-convention
'sbb-container': SbbContainerElement;
}
}
1 change: 1 addition & 0 deletions src/components/container/container/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './container';
41 changes: 41 additions & 0 deletions src/components/container/container/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
The `sbb-container` is a component that displays its content with the default page spacing. It also supports the slotting of a `sbb-sticky-bar`.

```html
<sbb-container>
<!-- Any other kind of content. -->
...

<!-- Sticky bar should go last. -->
<sbb-sticky-bar> ... </sbb-sticky-bar>
</sbb-container>
```

## Slots

The `sbb-container` content is provided via an unnamed slot.

## Style

By default `sbb-container` uses the `page spacing` defined in the [layout documentation](/docs/styles-layout--docs). Optionally the user can use the `expanded` property (default: `false`) to switch to the `page spacing expanded` layout.
Spacing options are applied to all of the container's content, including the `sbb-sticky-bar`.
The component has also four color variants that can be set using the `color` property (default: `white`).

```html
<sbb-container expanded variant="milk"> ... </sbb-container>
```

<!-- Auto Generated Below -->

## Properties

| Name | Attribute | Privacy | Type | Default | Description |
| ---------- | ---------- | ------- | ------------------------------------ | --------- | ---------------------------------------------------- |
| `expanded` | `expanded` | public | `boolean` | `false` | Whether the container is expanded. |
| `color` | `color` | public | `'transparent' \| 'white' \| 'milk'` | `'white'` | Color of the container, like transparent, white etc. |

## Slots

| Name | Description |
| ------------ | ------------------------------------------------------ |
| | Use the unnamed slot to add anything to the container. |
| `sticky-bar` | The slot used by the sbb-sticky-bar component. |
2 changes: 2 additions & 0 deletions src/components/container/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './container';
export * from './sticky-bar';
1 change: 1 addition & 0 deletions src/components/container/sticky-bar/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './sticky-bar';
34 changes: 34 additions & 0 deletions src/components/container/sticky-bar/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
The `sbb-sticky-bar` is a component meant to be slotted inside a `sbb-container` component.
MarioCastigliano marked this conversation as resolved.
Show resolved Hide resolved
It is displayed with sticky positioning at the bottom of the container that contains it.

```html
<sbb-container>
<sbb-sticky-bar>
<!-- Sticky bar content. -->
</sbb-sticky-bar>
</sbb-container>
```

## Slots

The `sbb-sticky-bar` content is provided via an unnamed slot.

## Style

The `sbb-sticky-bar` inherits its variant from the `sbb-container` it's placed in.
Optionally the user can set the `color` property on the `sbb-sticky-bar` in order to override the one inherited by the `sbb-container`. The color is only applied when the sticky bar is sticking, and will become transparent once it settles on the bottom of the container.

<!-- Auto Generated Below -->

## Properties

| Name | Attribute | Privacy | Type | Default | Description |
| ------------------ | ------------------- | ------- | -------------------------------- | ------- | ---------------------------------------------------- |
| `color` | `color` | public | `'white' \| 'milk' \| undefined` | | Color of the container, like transparent, white etc. |
| `disableAnimation` | `disable-animation` | public | `boolean` | `false` | Whether the animation is enabled. |

## Slots

| Name | Description |
| ---- | ------------------------------------------------------ |
| | Use the unnamed slot to add content to the sticky bar. |
88 changes: 88 additions & 0 deletions src/components/container/sticky-bar/sticky-bar.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { assert, expect, fixture } from '@open-wc/testing';
import { setViewport } from '@web/test-runner-commands';
import { html } from 'lit/static-html.js';

import { waitForCondition, waitForLitRender } from '../../core/testing';
import type { SbbContainerElement } from '../container';

import { SbbStickyBarElement } from './sticky-bar';

import '../container';

describe('sbb-sticky-bar', () => {
let container: SbbContainerElement;
let stickyBar: SbbStickyBarElement;
const getIsSticking = (): boolean => {
return stickyBar.hasAttribute('data-sticking');
};

beforeEach(async () => {
await setViewport({ width: 320, height: 500 });
container = await fixture(html`
<sbb-container>
${[...Array(15).keys()].map(
(value) =>
html` <div>
<p>Situation ${value}</p>
</div>`,
)}
<sbb-sticky-bar></sbb-sticky-bar>
</sbb-container>
`);
stickyBar = container.querySelector('sbb-sticky-bar')!;
});

it('renders', async () => {
assert.instanceOf(stickyBar, SbbStickyBarElement);
});

it('stops sticking when scrolling to bottom', async () => {
await waitForCondition(async () => getIsSticking());
expect(getIsSticking()).to.equal(true);

window.scrollTo(0, 400);

await waitForCondition(async () => !getIsSticking());

expect(getIsSticking()).to.equal(false);
});

it('is settled when content is not long enough', async () => {
await setViewport({ width: 320, height: 600 });
container = await fixture(html`
<sbb-container>
<button>Container button</button>
<sbb-sticky-bar>
<button>Sticky bar button</button>
</sbb-sticky-bar>
</sbb-container>
`);
stickyBar = container.querySelector('sbb-sticky-bar')!;

await waitForCondition(async () => !getIsSticking());

expect(getIsSticking()).to.equal(false);
});

it('renders with expanded layout', async () => {
container = await fixture(html`
<sbb-container expanded>
<button>Container button</button>
<sbb-sticky-bar>
<button>Sticky bar button</button>
</sbb-sticky-bar>
</sbb-container>
`);
stickyBar = container.querySelector('sbb-sticky-bar')!;

expect(stickyBar).to.have.attribute('data-expanded');
});

it('expands the sticky-bar when container is expanded', async () => {
container.expanded = true;

await waitForLitRender(container);

expect(stickyBar).to.have.attribute('data-expanded');
});
});
Loading
Loading