diff --git a/web-wallet/CHANGELOG.md b/web-wallet/CHANGELOG.md
index f7f7b5cf00..c6cab6622f 100644
--- a/web-wallet/CHANGELOG.md
+++ b/web-wallet/CHANGELOG.md
@@ -17,10 +17,12 @@ 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]
## [0.5.0] - 2024-03-27
@@ -232,6 +234,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
diff --git a/web-wallet/src/lib/dusk/components/Stepper/Stepper.svelte b/web-wallet/src/lib/dusk/components/Stepper/Stepper.svelte
index 33804cf27a..779e4996e6 100644
--- a/web-wallet/src/lib/dusk/components/Stepper/Stepper.svelte
+++ b/web-wallet/src/lib/dusk/components/Stepper/Stepper.svelte
@@ -1,43 +1,98 @@
+
+
-
-
-
- {#if steps >= 2}
-
- {#each Array(steps).keys() as currentStep (currentStep)}
-
= 2}
+
+ {#if Array.isArray(steps)}
+ {#each steps as currentStep, idx (currentStep)}
+ {@const id = `step-${randomUUID()}`}
+
+ class:dusk-stepper__step--processed={idx <= activeStep}
+ aria-current={idx === activeStep ? "step" : undefined}
+ aria-labelledby={id}
+ >
+ {#if currentStep.iconPath}
+
+ {:else}
+ {showStepNumbers ? idx + 1 : ""}
+ {/if}
+
+ {currentStep.label}
{/each}
-
- {/if}
-
+ {:else}
+ {#each Array(steps).keys() as idx (idx)}
+
{showStepNumbers ? idx + 1 : ""}
+ {/each}
+ {/if}
+
+{/if}
diff --git a/web-wallet/src/lib/dusk/components/Wizard/WizardStep.svelte b/web-wallet/src/lib/dusk/components/Wizard/WizardStep.svelte
index 444fbaf5e9..1183692daa 100644
--- a/web-wallet/src/lib/dusk/components/Wizard/WizardStep.svelte
+++ b/web-wallet/src/lib/dusk/components/Wizard/WizardStep.svelte
@@ -90,7 +90,7 @@
{#if step === currentStep}
{#if showStepper}
-
+
{/if}
diff --git a/web-wallet/src/lib/dusk/components/__tests__/Stepper.spec.js b/web-wallet/src/lib/dusk/components/__tests__/Stepper.spec.js
index 9f531ae969..4630d1063d 100644
--- a/web-wallet/src/lib/dusk/components/__tests__/Stepper.spec.js
+++ b/web-wallet/src/lib/dusk/components/__tests__/Stepper.spec.js
@@ -1,39 +1,91 @@
-import { afterEach, describe, expect, it } from "vitest";
+import { afterAll, afterEach, describe, expect, it, vi } from "vitest";
import { cleanup, render } from "@testing-library/svelte";
+import { mdiCheckDecagramOutline } from "@mdi/js";
import { Stepper } from "..";
+vi.mock("$lib/dusk/string", async (importOriginal) => {
+ /** @type {typeof import("$lib/dusk/string")} */
+ const original = await importOriginal();
+
+ return {
+ ...original,
+ randomUUID: () => "some-generated-id",
+ };
+});
+
describe("Stepper", () => {
+ const baseProps = {
+ activeStep: 2,
+ steps: [
+ { label: "foo" },
+ { label: "bar" },
+ { label: "baz" },
+ { label: "qux" },
+ { iconPath: mdiCheckDecagramOutline, label: "quux" },
+ ],
+ };
+ const baseOptions = {
+ props: baseProps,
+ target: document.body,
+ };
+
afterEach(cleanup);
- it("renders the Stepper component with two steps", () => {
- const { container } = render(Stepper, {
- props: { activeStep: 0, steps: 2 },
- });
+ afterAll(() => {
+ vi.doUnmock("$lib/dusk/string");
+ });
+
+ it("should render the `Stepper` component accepting an array of `StepperStep` objects as steps", async () => {
+ const { container, rerender } = render(Stepper, baseOptions);
+
+ expect(container.firstChild).toMatchSnapshot();
+
+ await rerender({ ...baseProps, activeStep: 3 });
expect(container.firstChild).toMatchSnapshot();
});
- it("renders the Stepper component with a completed step", () => {
- const { container } = render(Stepper, {
- props: { activeStep: 1, steps: 2 },
- });
+ it("should render the `Stepper` component accepting a number as the amount of steps", async () => {
+ const props = { ...baseProps, steps: 5 };
+ const { container, rerender } = render(Stepper, { ...baseOptions, props });
+
+ expect(container.firstChild).toMatchSnapshot();
+
+ await rerender({ ...baseProps, activeStep: 3 });
+
+ expect(container.firstChild).toMatchSnapshot();
+ });
+
+ it("should pass additional class names and attributes to the rendered element", () => {
+ const props = {
+ ...baseProps,
+ className: "foo bar",
+ id: "some-id",
+ };
+ const { container } = render(Stepper, { ...baseOptions, props });
expect(container.firstChild).toMatchSnapshot();
});
- it("renders the Stepper component with five steps", () => {
- const { container } = render(Stepper, {
- props: { activeStep: 0, steps: 5 },
- });
+ it("should add the proper class name for the desired variant", () => {
+ const props = {
+ ...baseProps,
+
+ /** @type {StepperVariant} */
+ variant: "secondary",
+ };
+ const { container } = render(Stepper, { ...baseOptions, props });
expect(container.firstChild).toMatchSnapshot();
});
- it("renders the Stepper component with five steps, with the third one being active, and the first two – completed", () => {
- const { container } = render(Stepper, {
- props: { activeStep: 3, steps: 5 },
- });
+ it("should allow to hide the step numbers", () => {
+ const props = {
+ ...baseProps,
+ showStepNumbers: false,
+ };
+ const { container } = render(Stepper, { ...baseOptions, props });
expect(container.firstChild).toMatchSnapshot();
});
diff --git a/web-wallet/src/lib/dusk/components/__tests__/__snapshots__/Stepper.spec.js.snap b/web-wallet/src/lib/dusk/components/__tests__/__snapshots__/Stepper.spec.js.snap
index aeb0ef98a3..e0ac9f7bad 100644
--- a/web-wallet/src/lib/dusk/components/__tests__/__snapshots__/Stepper.spec.js.snap
+++ b/web-wallet/src/lib/dusk/components/__tests__/__snapshots__/Stepper.spec.js.snap
@@ -1,155 +1,541 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
-exports[`Stepper > renders the Stepper component with a completed step 1`] = `
+exports[`Stepper > should add the proper class name for the desired variant 1`] = `
-
-
-
+
+ 1
+
+
+
+ foo
+
+
+ 2
+
+
+
+ bar
+
+
+ 3
+
+
+
+ baz
+
+
+ 4
+
+
+
+ qux
+
+
+
+
+
+
+
+
+
+ quux
+
+
+
+`;
+
+exports[`Stepper > should allow to hide the step numbers 1`] = `
+
+
+
+
+
+
+ foo
+
+
+
+
+
+
+ bar
+
+
+
+
+
+
+ baz
+
+
+
+
+
+
+ qux
+
+
+
+
+
+
+
+
+
+ quux
+
+
+
+`;
+
+exports[`Stepper > should pass additional class names and attributes to the rendered element 1`] = `
+
+
+ 1
+
+
+
+ foo
+
+
+ 2
+
+
+
+ bar
+
+
+ 3
+
+
+
+ baz
+
+
+ 4
+
+
+
+ qux
+
+
+
+
+
+
+
+
+
+ quux
+
+
`;
-exports[`Stepper > renders the Stepper component with five steps 1`] = `
+exports[`Stepper > should render the \`Stepper\` component accepting a number as the amount of steps 1`] = `
-
-
-
+
+ 1
+
+
+ 2
+
+
+ 3
+
+
+ 4
+
+
+ 5
+
+
`;
-exports[`Stepper > renders the Stepper component with five steps, with the third one being active, and the first two – completed 1`] = `
+exports[`Stepper > should render the \`Stepper\` component accepting a number as the amount of steps 2`] = `
-
-
-
+
+ 1
+
+
+
+ foo
+
+
+ 2
+
+
+
+ bar
+
+
+ 3
+
+
+
+ baz
+
+
+ 4
+
+
+
+ qux
+
+
+
+
+
+
+
+
+
+ quux
+
+
`;
-exports[`Stepper > renders the Stepper component with two steps 1`] = `
+exports[`Stepper > should render the \`Stepper\` component accepting an array of \`StepperStep\` objects as steps 1`] = `
-
-
-
+
+ 1
+
+
+
+ foo
+
+
+ 2
+
+
+
+ bar
+
+
+ 3
+
+
+
+ baz
+
+
+ 4
+
+
+
+ qux
+
+
+
+
+
+
+
+
+
+ quux
+
+
+
+`;
+
+exports[`Stepper > should render the \`Stepper\` component accepting an array of \`StepperStep\` objects as steps 2`] = `
+
+
+ 1
+
+
+
+ foo
+
+
+ 2
+
+
+
+ bar
+
+
+ 3
+
+
+
+ baz
+
+
+ 4
+
+
+
+ qux
+
+
+
+
+
+
+
+
+
+ quux
+
+
`;
diff --git a/web-wallet/src/lib/dusk/components/dusk.components.d.ts b/web-wallet/src/lib/dusk/components/dusk.components.d.ts
index 6ef80fece2..0412d875e6 100644
--- a/web-wallet/src/lib/dusk/components/dusk.components.d.ts
+++ b/web-wallet/src/lib/dusk/components/dusk.components.d.ts
@@ -34,6 +34,13 @@ type SelectOption = {
value: string;
};
+type StepperStep = {
+ iconPath?: string;
+ label: string;
+};
+
+type StepperVariant = "primary" | "secondary";
+
type SuspenseErrorVariant = "alert" | "details";
type TabItem = {
diff --git a/web-wallet/src/routes/(welcome)/setup/create/__tests__/__snapshots__/page.spec.js.snap b/web-wallet/src/routes/(welcome)/setup/create/__tests__/__snapshots__/page.spec.js.snap
index 7a9f01b3f1..95d257c130 100644
--- a/web-wallet/src/routes/(welcome)/setup/create/__tests__/__snapshots__/page.spec.js.snap
+++ b/web-wallet/src/routes/(welcome)/setup/create/__tests__/__snapshots__/page.spec.js.snap
@@ -19,53 +19,43 @@ exports[`Create > correctly renders the Mnemonic Preview page 1`] = `
-
-
-
+ 2
+
+
+ 3
+
+
+ 4
+
+
+ 5
+
+
+ 6
+
+
+
correctly renders the Mnemonic Verification page 1`] = `
-
-
-
+ 2
+
+
+ 3
+
+
+ 4
+
+
+ 5
+
+
+ 6
+
+
+
doesn't let the user proceed if they have entered mismatching
-
-
-
+ 2
+
+
+ 3
+
+
+ 4
+
+
+ 5
+
+
+ 6
+
+
+
ensures that the Undo button on the Mnemonic Validate step wor
-
-
-
+ 2
+
+
+ 3
+
+
+ 4
+
+
+ 5
+
+
+ 6
+
+
+
ensures the All Done step renders as expected 1`] = `
-
-
-
+ 2
+
+
+ 3
+
+
+ 4
+
+
+ 5
+
+
+ 6
+
+
+
ensures the Password step renders as expected 1`] = `
-
-
-
+ 2
+
+
+ 3
+
+
+ 4
+
+
+ 5
+
+
+ 6
+
+
+
ensures the Password step renders as expected 2`] = `
-
-
-
+ 2
+
+
+ 3
+
+
+ 4
+
+
+ 5
+
+
+ 6
+
+
+
ensures the Swap To Native Dusk step renders as expected 1`] =
-
-
-
+ 2
+
+
+ 3
+
+
+ 4
+
+
+ 5
+
+
+ 6
+
+
+
The ERC20 token swap functionality is currently disabled and will be provided
@@ -2227,53 +2147,43 @@ exports[`Create > lets the user proceed if they have entered a matching Mnemonic
-
-
-
+ 2
+
+
+ 3
+
+
+ 4
+
+
+ 5
+
+
+ 6
+
+
+
should render the \`Securely store your seed phrase!\` agreeme
-
-
-
+ 2
+
+
+ 3
+
+
+ 4
+
+
+ 5
+
+
+ 6
+
+
+
should render the Mnemonic Authenticate step after accepting
+
+
-
-
-
+
+
+
diff --git a/web-wallet/src/style/dusk-components/stepper.css b/web-wallet/src/style/dusk-components/stepper.css
index 9318fe4146..8b98cd84ba 100644
--- a/web-wallet/src/style/dusk-components/stepper.css
+++ b/web-wallet/src/style/dusk-components/stepper.css
@@ -1,38 +1,76 @@
.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);
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-rail-color);
}
-.dusk-stepper__steps {
- display: flex;
- justify-content: space-between;
- width: 100%;
+.dusk-stepper--variant--secondary::before {
+ background-color: var(--stepper-rail-color-variant-secondary);
+}
+
+.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-rail-color);
+ color: var(--stepper-on-rail-color);
border-radius: 50%;
z-index: 1;
+ margin: 0 auto;
+}
+
+.dusk-stepper--variant--secondary
+ .dusk-stepper__step:not(.dusk-stepper__step--processed) {
+ background-color: var(--stepper-rail-color-variant-secondary);
+ color: var(--stepper-on-rail-variant-secondary-color);
}
.dusk-stepper__step--processed {
- background-color: var(--progress-filler-color);
+ background-color: var(--stepper-filler-color);
+ color: var(--stepper-on-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;
}
diff --git a/web-wallet/src/style/dusk/language.css b/web-wallet/src/style/dusk/language.css
index 00c49de720..0e094d6e0e 100644
--- a/web-wallet/src/style/dusk/language.css
+++ b/web-wallet/src/style/dusk/language.css
@@ -84,12 +84,22 @@
--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-rail-color: var(--background-color);
+ --stepper-rail-color-variant-secondary: var(--primary-color);
+ --stepper-filler-color: var(--success-color);
+ --stepper-on-filler-color: var(--on-success-color);
+ --stepper-on-rail-color: var(--on-background-color);
+ --stepper-on-rail-variant-secondary-color: var(--on-primary-color);
+
/* Checkbox control */
--checkbox-control-size: 1.2em;
diff --git a/web-wallet/src/style/main.css b/web-wallet/src/style/main.css
index ff620c4135..3e99a04f9c 100644
--- a/web-wallet/src/style/main.css
+++ b/web-wallet/src/style/main.css
@@ -32,17 +32,33 @@
@font-face {
font-family: "Soehne";
font-style: normal;
+ font-display: swap;
font-weight: 400;
src: url("/fonts/soehne-buch.woff2") format("woff2");
- font-display: swap;
}
@font-face {
font-family: "Soehne";
font-style: normal;
+ font-display: swap;
font-weight: 500;
src: url("/fonts/soehne-kraftig.woff2") format("woff2");
+}
+
+@font-face {
+ font-family: "Soehne Mono";
+ font-style: normal;
font-display: swap;
+ font-weight: 400;
+ src: url("/fonts/soehne-mono-buch.woff2") format("woff2");
+}
+
+@font-face {
+ font-family: "Soehne Mono";
+ font-style: normal;
+ font-display: swap;
+ font-weight: 500;
+ src: url("/fonts/soehne-mono-kraftig.woff2") format("woff2");
}
* {
diff --git a/web-wallet/static/fonts/soehne-mono-buch.woff2 b/web-wallet/static/fonts/soehne-mono-buch.woff2
new file mode 100644
index 0000000000..4fc6eb90b5
Binary files /dev/null and b/web-wallet/static/fonts/soehne-mono-buch.woff2 differ
diff --git a/web-wallet/static/fonts/soehne-mono-kraftig.woff2 b/web-wallet/static/fonts/soehne-mono-kraftig.woff2
new file mode 100644
index 0000000000..f17feb5289
Binary files /dev/null and b/web-wallet/static/fonts/soehne-mono-kraftig.woff2 differ