Skip to content

Commit

Permalink
web-wallet: Update Stepper component to new design
Browse files Browse the repository at this point in the history
- Added missing "Soehne Mono" font and its `@font-face` definition

Resolves #2071
  • Loading branch information
ascartabelli committed Aug 9, 2024
1 parent 29df7cc commit 938a7cd
Show file tree
Hide file tree
Showing 9 changed files with 276 additions and 49 deletions.
5 changes: 5 additions & 0 deletions web-wallet/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Update anchor colors to ensure better accessibility [#1765]
- Update Transactions list design [#1922]
- Update Buttons to match the design system [#1606]
- Update `Stepper` component to new design [#2071]

### Fixed

- Fix Receive tab content overflows [#1901]
- Add missing "Soehne Mono" and its `@font-face` definition [#2071]

Resolves #2071

## [0.5.0] - 2024-03-27

Expand Down Expand Up @@ -232,6 +236,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#1922]: https://github.com/dusk-network/rusk/issues/1922
[#2026]: https://github.com/dusk-network/rusk/issues/2026
[#2000]: https://github.com/dusk-network/rusk/issues/2000
[#2071]: https://github.com/dusk-network/rusk/issues/2071

<!-- VERSIONS -->

Expand Down
98 changes: 72 additions & 26 deletions web-wallet/src/lib/dusk/components/Stepper/Stepper.svelte
Original file line number Diff line number Diff line change
@@ -1,43 +1,89 @@
<script>
import { makeClassName, randomUUID } from "$lib/dusk/string";
import { Icon } from "..";
/**
* The number of steps – should be greater or equal to two.
* The current active step.
* The value starts from zero as it refers
* to the `steps` array elements.
* @type {number}
*/
export let activeStep;
/** @type {string | undefined} */
export let className = undefined;
/**
* Whether to show step numbers or not.
* @type {boolean}
*/
export let showStepNumbers = true;
/**
* The number of steps, greater or equal to two,
* if a number is passed.
* An array of `StepperStep` objects otherwise.
*
* @type {StepperStep[] | number}
*/
export let steps;
/** @type {number} */
export let activeStep;
$: classes = makeClassName(["dusk-stepper", className]);
$: stepsAmount = Array.isArray(steps) ? steps.length : steps;
/**
* Calculates the progress percentage based on the active step in a stepper.
* The width of the bar connecting the steps, based on
* the active step and on the amount of steps.
* As the steps are in a grid and centered in the containing
* cell, the width doesn't represent the actual progress percentage.
*
* @constant
* @type {string}
*
* @example
* // If there are 5 steps in total and the active step is 2
* // progress will be "width: 50%;"
*
* @param {number} steps - Total number of steps in the stepper.
* @param {number} activeStep - The current active step index (starting from 0).
* With 2 steps, if the active step is 1 the width will be 80%.
* The remaining 20% is the blank space before and after the steps.
*
* If there are 5 steps in total and the active step is 2,
* the width will be 40%.
*/
$: progress = `width: ${(100 / (steps - 1)) * activeStep}%;`;
$: progressWidth = `${(100 * activeStep) / stepsAmount}%`;
</script>

<div class="dusk-stepper" role="tablist">
<div class="dusk-stepper__progress-bar">
<div class="dusk-stepper__progress-filler" style={progress} />
</div>

{#if steps >= 2}
<div class="dusk-stepper__steps">
{#each Array(steps).keys() as currentStep (currentStep)}
<div
{#if stepsAmount >= 2}
<div
class={classes}
style:--columns={stepsAmount}
style:--progress-width={progressWidth}
{...$$restProps}
>
{#if Array.isArray(steps)}
{#each steps as currentStep, idx (currentStep)}
{@const id = `step-${randomUUID()}`}
<span
class="dusk-stepper__step"
class:dusk-stepper__step--processed={idx <= activeStep}
aria-current={idx === activeStep ? "step" : undefined}
aria-labelledby={id}
>
{#if currentStep.iconPath}
<Icon path={currentStep.iconPath} />
{:else}
{showStepNumbers ? idx + 1 : ""}
{/if}
</span>
<span class="dusk-stepper__step-label" {id}>{currentStep.label}</span>
{/each}
{:else}
{#each Array(steps).keys() as idx (idx)}
<span
class="dusk-stepper__step"
class:dusk-stepper__step--processed={currentStep <= activeStep}
aria-selected={currentStep === activeStep}
aria-disabled="true"
/>
class:dusk-stepper__step--processed={idx <= activeStep}
aria-current={idx === activeStep ? "step" : undefined}
>{showStepNumbers ? idx + 1 : ""}</span
>
{/each}
</div>
{/if}
</div>
{/if}
</div>
{/if}
5 changes: 5 additions & 0 deletions web-wallet/src/lib/dusk/components/dusk.components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ type SelectOption = {
value: string;
};

type StepperStep = {
iconPath?: string;
label: string;
};

type SuspenseErrorVariant = "alert" | "details";

type TabItem = {
Expand Down
130 changes: 126 additions & 4 deletions web-wallet/src/routes/components-showcase/Steppers.svelte
Original file line number Diff line number Diff line change
@@ -1,8 +1,130 @@
<svelte:options immutable={true} />

<script>
import { Stepper } from "$lib/dusk/components";
import { get, writable } from "svelte/store";
import {
mdiCheckDecagramOutline,
mdiFlaskEmpty,
mdiFlaskEmptyOutline,
} from "@mdi/js";
import { Button, Stepper } from "$lib/dusk/components";
const stepperA = writable({
step: 1,
steps: [
{ iconPath: mdiFlaskEmptyOutline, label: "foo bar baz" },
{ iconPath: mdiFlaskEmpty, label: "baz qux quux foo bar baz" },
],
});
const stepperB = writable({
step: 2,
steps: [
{ label: "foo" },
{ label: "bar" },
{ label: "baz" },
{ label: "qux" },
{ iconPath: mdiCheckDecagramOutline, label: "quux" },
],
});
const stepperC = writable({
step: 3,
steps: [
{ label: "foo" },
{ label: "bar" },
{ label: "baz" },
{ label: "qux" },
{ iconPath: mdiCheckDecagramOutline, label: "quux" },
],
});
/** @param {MouseEvent} evt */
function handleStepChange(evt) {
const btn = /** @type {HTMLButtonElement} */ (evt.currentTarget);
const step = btn.matches("button:first-of-type") ? -1 : 1;
const steppersContainer = btn.parentElement?.parentElement;
const stepperStoreIdx = Array.prototype.indexOf.call(
steppersContainer?.parentElement?.children,
steppersContainer
);
const stepperStore = [stepperA, stepperB, stepperC][stepperStoreIdx];
const { step: stepperStep, steps: stepperSteps } = get(stepperStore);
const wantedStep = stepperStep + step;
let newStep;
if (wantedStep === stepperSteps.length) {
newStep = 0;
} else if (wantedStep === -1) {
newStep = stepperSteps.length - 1;
} else {
newStep = wantedStep;
}
stepperStore.set({ step: newStep, steps: stepperSteps });
}
$: ({ step: stepA, steps: stepsA } = $stepperA);
$: ({ step: stepB, steps: stepsB } = $stepperB);
$: ({ step: stepC, steps: stepsC } = $stepperC);
</script>
<section>
<Stepper steps={2} activeStep={1} />
<Stepper steps={5} activeStep={2} />
<section class="steppers__section">
<div class="steppers__container">
<Stepper steps={stepsA} activeStep={stepA} />
<div class="steppers__buttons">
<Button on:click={handleStepChange} text="Previous" size="small" />
<Button on:click={handleStepChange} text="Next" size="small" />
</div>
</div>
<div class="steppers__container">
<Stepper steps={stepsB} activeStep={stepB} />
<div class="steppers__buttons">
<Button on:click={handleStepChange} text="Previous" size="small" />
<Button on:click={handleStepChange} text="Next" size="small" />
</div>
</div>
<div class="steppers__container">
<Stepper showStepNumbers={false} steps={stepsC} activeStep={stepC} />
<div class="steppers__buttons">
<Button on:click={handleStepChange} text="Previous" size="small" />
<Button on:click={handleStepChange} text="Next" size="small" />
</div>
</div>
<div class="steppers__container">
<Stepper showStepNumbers={false} steps={8} activeStep={6} />
</div>
</section>
<style lang="postcss">
:global {
.steppers__section {
flex-direction: column;
gap: var(--large-gap) !important;
}
.steppers__container,
.steppers__buttons {
display: flex;
gap: var(--default-gap);
}
.steppers__container {
width: 80%;
padding: 2rem;
background-color: var(--surface-color);
border-radius: var(--control-border-radius-size);
flex-direction: column;
}
.steppers__buttons {
justify-content: space-around;
}
}
</style>
61 changes: 44 additions & 17 deletions web-wallet/src/style/dusk-components/stepper.css
Original file line number Diff line number Diff line change
@@ -1,38 +1,65 @@
.dusk-stepper {
--step-size: 1.5em;

position: relative;
width: 100%;
display: grid;
row-gap: var(--default-gap);
grid-template-columns: repeat(var(--columns), 1fr);
justify-content: space-between;
}

.dusk-stepper__progress-bar {
.dusk-stepper::before,
.dusk-stepper::after {
--left-offset: calc(50% / var(--columns));

content: "";
display: block;
position: absolute;
top: 50%;
top: calc(var(--step-size) / 2);
left: var(--left-offset);
transform: translateY(-50%);
width: 100%;
height: var(--progress-bar-height);
background-color: var(--progress-bg-color);
height: var(--stepper-bar-height);
background-color: var(--stepper-bg-color);
border-radius: var(--control-border-radius-size);
overflow: hidden;
}

.dusk-stepper__progress-filler {
height: 100%;
background-color: var(--progress-filler-color);
.dusk-stepper::before {
width: calc(100% - var(--left-offset) * 2);
background-color: var(--stepper-bg-color);
}

.dusk-stepper__steps {
display: flex;
justify-content: space-between;
width: 100%;
.dusk-stepper::after {
width: var(--progress-width);
background-color: var(--stepper-filler-color);
}

.dusk-stepper__step {
width: 0.625em;
height: 0.625em;
background-color: var(--progress-bg-color);
grid-row: 1;
display: inline-flex;
align-items: center;
justify-content: center;
width: var(--step-size);
height: var(--step-size);
font-family: var(--mono-font-family);
line-height: 1;
background-color: var(--stepper-bg-color);
border-radius: 50%;
z-index: 1;
margin: 0 auto;
}

.dusk-stepper__step--processed {
background-color: var(--progress-filler-color);
background-color: var(--stepper-filler-color);
}

.dusk-stepper__step-label {
grid-row: 2;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-family: var(--mono-font-family);
font-size: 0.5em;
text-transform: uppercase;
text-align: center;
}
8 changes: 7 additions & 1 deletion web-wallet/src/style/dusk/language.css
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,18 @@
--anchor-color-hover: var(--secondary-color-variant-light);
--anchor-color-active: var(--secondary-color-variant-light);

/* Progress-related components (Stepper, Progress Bar, etc */
/* Progress bars */

--progress-bar-height: 0.3125em;
--progress-bg-color: var(--primary-color);
--progress-filler-color: var(--success-color);

/* Steppers */

--stepper-bar-height: 0.3125em;
--stepper-bg-color: var(--light-grey);
--stepper-filler-color: var(--success-color);

/* Checkbox control */

--checkbox-control-size: 1.2em;
Expand Down
Loading

0 comments on commit 938a7cd

Please sign in to comment.