Skip to content

Commit

Permalink
feat(sbb-stepper): introduce sbb-stepper component (#2491)
Browse files Browse the repository at this point in the history
---------

Co-authored-by: Tommmaso Menga <[email protected]>
Co-authored-by: Davide Mininni <[email protected]>
  • Loading branch information
3 people authored Jun 6, 2024
1 parent 2059719 commit d389572
Show file tree
Hide file tree
Showing 30 changed files with 2,758 additions and 3 deletions.
10 changes: 10 additions & 0 deletions src/elements/core/styles/a11y.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,13 @@
.sbb-screen-reader-only {
@include a11y.screen-reader-only;
}

.sbb-focus-outline:focus-visible {
@include a11y.focus-outline;
}

.sbb-focus-outline-dark:focus-visible {
@include a11y.focus-outline;

--sbb-focus-outline-color: var(--sbb-focus-outline-color-dark);
}
3 changes: 3 additions & 0 deletions src/elements/stepper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './stepper/step.js';
export * from './stepper/step-label.js';
export * from './stepper/stepper.js';
1 change: 1 addition & 0 deletions src/elements/stepper/step-label.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './step-label/step-label.js';
132 changes: 132 additions & 0 deletions src/elements/stepper/step-label/__snapshots__/step-label.spec.snap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/* @web/test-runner snapshot v1 */
export const snapshots = {};

snapshots["sbb-step-label renders DOM"] =
`<sbb-step-label
data-action=""
data-button=""
dir="ltr"
id="sbb-step-label-0"
role="tab"
slot="step-label"
tabindex="-1"
>
Label
</sbb-step-label>
`;
/* end snapshot sbb-step-label renders DOM */

snapshots["sbb-step-label renders Shadow DOM"] =
`<div class="sbb-step-label">
<span class="sbb-step-label__prefix">
<slot name="icon">
</slot>
</span>
<span class="sbb-step-label__text">
<slot>
</slot>
</span>
</div>
`;
/* end snapshot sbb-step-label renders Shadow DOM */

snapshots["sbb-step-label renders with icon DOM"] =
`<sbb-step-label
data-action=""
data-button=""
dir="ltr"
icon-name="tick-small"
id="sbb-step-label-2"
role="tab"
slot="step-label"
tabindex="-1"
>
Label
</sbb-step-label>
`;
/* end snapshot sbb-step-label renders with icon DOM */

snapshots["sbb-step-label renders with icon Shadow DOM"] =
`<div class="sbb-step-label">
<span class="sbb-step-label__prefix">
<slot name="icon">
<sbb-icon
aria-hidden="true"
data-namespace="default"
name="tick-small"
role="img"
>
</sbb-icon>
</slot>
</span>
<span class="sbb-step-label__text">
<slot>
</slot>
</span>
</div>
`;
/* end snapshot sbb-step-label renders with icon Shadow DOM */

snapshots["sbb-step-label renders disabled DOM"] =
`<sbb-step-label
data-action=""
data-button=""
data-disabled=""
dir="ltr"
disabled=""
id="sbb-step-label-4"
role="tab"
slot="step-label"
tabindex="-1"
>
Label
</sbb-step-label>
`;
/* end snapshot sbb-step-label renders disabled DOM */

snapshots["sbb-step-label renders disabled Shadow DOM"] =
`<div class="sbb-step-label">
<span class="sbb-step-label__prefix">
<slot name="icon">
</slot>
</span>
<span class="sbb-step-label__text">
<slot>
</slot>
</span>
</div>
`;
/* end snapshot sbb-step-label renders disabled Shadow DOM */

snapshots["sbb-step-label A11y tree Chrome"] =
`<p>
{
"role": "WebArea",
"name": "",
"children": [
{
"role": "tab",
"name": "Label"
}
]
}
</p>
`;
/* end snapshot sbb-step-label A11y tree Chrome */

snapshots["sbb-step-label A11y tree Firefox"] =
`<p>
{
"role": "document",
"name": "",
"children": [
{
"role": "tab",
"name": "Label"
}
]
}
</p>
`;
/* end snapshot sbb-step-label A11y tree Firefox */

54 changes: 54 additions & 0 deletions src/elements/stepper/step-label/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
Use the `sbb-step-label` with the `sbb-stepper` to display a step label.

```html
<sbb-step-label>Step label</sbb-step-label>
```

## Slots

It has an implicit slot named `step-label`.

## States

The component can be displayed in `disabled` state using the self-named property.

```html
<sbb-step-label disabled>Step label</sbb-step-label>
```

## Style

If it is used in an `sbb-stepper` and no `icon-name` is specified, it displays a counter in the label prefix to keep track of the step number.

```html
<!-- Displays a tick icon in the prefix circle -->
<sbb-step-label icon-name="tick-small">Step label</sbb-step-label>

<!-- Displays a number in the prefix circle -->
<sbb-step-label>Step label</sbb-step-label>
```

## Accessibility

The accessibility properties `aria-controls`, `aria-setsize`, `aria-posinset` are set automatically.

<!-- Auto Generated Below -->

## Properties

| Name | Attribute | Privacy | Type | Default | Description |
| ---------- | ----------- | ------- | ------------------------ | ---------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `disabled` | `disabled` | public | `boolean` | `false` | Whether the component is disabled. |
| `form` | `form` | public | `string \| undefined` | | The <form> element to associate the button with. |
| `iconName` | `icon-name` | public | `string \| undefined` | | The icon name we want to use, choose from the small icon variants from the ui-icons category from here https://icons.app.sbb.ch. |
| `name` | `name` | public | `string` | | The name of the button element. |
| `step` | - | public | `SbbStepElement \| null` | `null` | The step controlled by the label. |
| `type` | `type` | public | `SbbButtonType` | `'button'` | The type attribute to use for the button. |
| `value` | `value` | public | `string` | | The value of the button element. |

## Slots

| Name | Description |
| ------ | ------------------------------------------------ |
| | Use the unnamed slot to provide a label. |
| `icon` | Use this to display an icon in the label bubble. |
153 changes: 153 additions & 0 deletions src/elements/stepper/step-label/step-label.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
@use '../../core/styles' as sbb;

// Box-sizing rules contained in typography are not traversing Shadow DOM boundaries. We need to include box-sizing mixin in every component.
@include sbb.box-sizing;

:host {
--sbb-step-label-color: var(--sbb-color-iron);
--sbb-step-label-animation-duration: var(
--sbb-disable-animation-zero-time,
var(--sbb-animation-duration-2x)
);
--sbb-step-label-prefix-size: var(--sbb-size-element-xxs);
--sbb-step-label-prefix-border-style: solid;
--sbb-step-label-prefix-border-color: var(--sbb-color-cloud);
--sbb-step-label-prefix-background-color: var(--sbb-color-white);

position: relative;
min-width: 0;
max-width: fit-content;

&::before {
@include sbb.text-xxs--regular;
@include sbb.absolute-center-x-y;

cursor: var(--sbb-step-label-cursor);
color: var(--sbb-step-label-color);

// The `--sbb-font-size-text-l` is beign used here to align the bubble's inner text to
// the label text which includes the `sbb.text-l--bold` mixin.
inset-block-start: calc(
var(--sbb-font-size-text-l) * (var(--sbb-typo-line-height-body-text) / 2) +
(var(--sbb-border-width-1x) / 2)
);
inset-inline-start: calc(var(--sbb-step-label-prefix-size) / 2);
line-height: 1;
z-index: 1;
transform: translate(
-50%,
calc(-50% + var(--sbb-step-label-translate-y-content-hover, #{sbb.px-to-rem-build(0)}))
);
transition: transform var(--sbb-step-label-animation-duration) var(--sbb-animation-easing);
}

@include sbb.if-forced-colors {
--sbb-step-label-color: ButtonText;
--sbb-step-label-prefix-border-color: ButtonText;
}
}

:host([data-selected]) {
@include sbb.text-xxs--bold;

--sbb-step-label-color: var(--sbb-color-charcoal);

@include sbb.if-forced-colors {
--sbb-step-label-color: Highlight !important;
}
}

:host([disabled]) {
--sbb-step-label-color: var(--sbb-color-granite);
--sbb-step-label-prefix-border-style: dashed;

@include sbb.if-forced-colors {
--sbb-step-label-color: GrayText !important;
}
}

:host(:hover:not([disabled])) {
@include sbb.hover-mq($hover: true) {
--sbb-step-label-cursor: pointer;
--sbb-step-label-prefix-background-color: var(--sbb-color-milk);
--sbb-step-label-translate-y-content-hover: #{sbb.px-to-rem-build(-1)};
--sbb-step-label-prefix-size-grow-hover: calc(var(--sbb-border-width-2x) * -1);
}
}

// Hide focus outline when focus origin is mouse or touch. This is being used as a workaround in various components.
:host(:focus-visible:not([data-focus-origin='mouse'], [data-focus-origin='touch'])) {
@include sbb.focus-outline;

border-radius: var(--sbb-border-radius-1x);
}

:host([data-orientation='vertical']) {
transition: margin var(--sbb-stepper-animation-duration) var(--sbb-animation-easing);
}

:host([data-orientation='vertical']:not(:first-of-type)) {
margin-block-start: var(--sbb-spacing-fixed-6x);
}

:host([data-selected][data-orientation='vertical']) {
margin-block-end: var(--sbb-spacing-fixed-8x);
}

.sbb-step-label {
@include sbb.text-l--bold;

cursor: var(--sbb-step-label-cursor);
position: relative;
display: flex;
gap: var(--sbb-spacing-fixed-4x);
color: var(--sbb-step-label-color);
}

.sbb-step-label__prefix {
position: relative;
display: flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
width: var(--sbb-step-label-prefix-size);
height: var(--sbb-step-label-prefix-size);
inset-block-start: calc(
1em * (var(--sbb-typo-line-height-body-text) / 2) + (var(--sbb-border-width-1x) / 2) -
(var(--sbb-step-label-prefix-size) / 2)
);

&::before {
content: '';
position: absolute;
inset: calc(var(--sbb-step-label-prefix-size-grow-hover, #{sbb.px-to-rem-build(0)}));
border-radius: var(--sbb-border-radius-infinity);
border: var(--sbb-border-width-1x) var(--sbb-step-label-prefix-border-style)
var(--sbb-step-label-prefix-border-color);
background-color: var(--sbb-step-label-prefix-background-color);
transition: {
duration: var(--sbb-step-label-animation-duration);
timing-function: var(--sbb-animation-easing);
property: background-color, inset;
}
}
}

.sbb-step-label__text {
:host([data-orientation='horizontal']) & {
@include sbb.ellipsis;
}
}

::slotted(sbb-icon),
sbb-icon {
z-index: 1;
background-color: var(--sbb-step-label-prefix-background-color);
border-radius: var(--sbb-border-radius-infinity);
transform: translateY(var(--sbb-step-label-translate-y-content-hover, #{sbb.px-to-rem-build(0)}));
transition: {
duration: var(--sbb-step-label-animation-duration);
timing-function: var(--sbb-animation-easing);
property: background-color, transform;
}
}
Loading

0 comments on commit d389572

Please sign in to comment.