Skip to content

Commit

Permalink
web-wallet: Add UsageIndicator component
Browse files Browse the repository at this point in the history
Resolves #2073
  • Loading branch information
ascartabelli committed Aug 7, 2024
1 parent f8ba62b commit 7b2cebf
Show file tree
Hide file tree
Showing 8 changed files with 244 additions and 2 deletions.
76 changes: 76 additions & 0 deletions web-wallet/src/lib/components/UsageIndicator/UsageIndicator.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<svelte:options immutable={true} />

<script>
import { mdiShieldLock, mdiShieldLockOpenOutline } from "@mdi/js";
import { makeClassName } from "$lib/dusk/string";
import { Icon } from "$lib/dusk/components";
/** @type {string | undefined} */
export let className = undefined;
/** @type {number} */
export let value;
$: classes = makeClassName(["usage-indicator", className]);
$: valueToShow = +value.toFixed(2);
$: shieldedText = `You have put ${valueToShow}% of your funds in your shielded account`;
$: unshieldedText = `You have put ${+(100 - valueToShow).toFixed(2)}% of your funds in your unshielded account`;
</script>

<div class={classes}>
<Icon
className="usage-indicator__icon"
data-tooltip-id="main-tooltip"
data-tooltip-text={shieldedText}
path={mdiShieldLock}
/>
<div
class="usage-indicator__meter"
role="meter"
aria-valuemax="100"
aria-valuemin="0"
aria-valuenow={valueToShow}
aria-valuetext={shieldedText}
>
<div
aria-hidden="true"
class="usage-indicator__meter-bar"
style:width={`${valueToShow}%`}
></div>
</div>
<Icon
className="usage-indicator__icon"
data-tooltip-id="main-tooltip"
data-tooltip-text={unshieldedText}
path={mdiShieldLockOpenOutline}
/>
</div>

<style lang="postcss">
:global {
.usage-indicator {
display: flex;
align-items: center;
justify-content: center;
gap: var(--small-gap);
}
.usage-indicator__icon {
cursor: help;
}
.usage-indicator__meter {
flex: 1;
height: 1rem;
background-color: var(--success-color);
overflow: hidden;
border-radius: var(--control-border-radius-size);
}
.usage-indicator__meter-bar {
background-color: var(--success-color-variant-dark);
height: 100%;
}
}
</style>
55 changes: 55 additions & 0 deletions web-wallet/src/lib/components/__tests__/UsageIndicator.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { afterEach, describe, expect, it } from "vitest";
import { cleanup, getAllByRole, render } from "@testing-library/svelte";

import { UsageIndicator } from "..";

const getPercentages = () =>
getAllByRole(document.body, "graphics-symbol").map((el) =>
Number(
el
.getAttribute("data-tooltip-text")
?.replace(/^.*?(\d+(\.\d+)?)%.*?$/, "$1")
)
);

describe("UsageIndicator", () => {
const baseProps = {
value: 45,
};
const baseOptions = {
props: baseProps,
target: document.body,
};

afterEach(cleanup);

it("should render the `UsageIndicator` component and react to value changes", async () => {
const { container, rerender } = render(UsageIndicator, baseOptions);

expect(getPercentages()).toStrictEqual([45, 55]);
expect(container.firstChild).toMatchSnapshot();

await rerender({ value: 80 });

expect(getPercentages()).toStrictEqual([80, 20]);
expect(container.firstChild).toMatchSnapshot();
});

it("should accept additional class names", () => {
const props = { ...baseProps, className: "foo bar" };
const { container } = render(UsageIndicator, { ...baseOptions, props });

expect(container.firstChild).toHaveClass("usage-indicator foo bar");
});

it("should round decimal values at two decimals", async () => {
const props = { ...baseProps, value: 45.7687 };
const { rerender } = render(UsageIndicator, { ...baseOptions, props });

expect(getPercentages()).toStrictEqual([45.77, 54.23]);

await rerender({ value: 0.005 });

expect(getPercentages()).toStrictEqual([0.01, 99.99]);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`UsageIndicator > should render the \`UsageIndicator\` component and react to value changes 1`] = `
<div
class="usage-indicator"
>
<svg
class="dusk-icon dusk-icon--size--default usage-indicator__icon"
data-tooltip-id="main-tooltip"
data-tooltip-text="You have put 45% of your funds in your shielded account"
role="graphics-symbol"
viewBox="0 0 24 24"
>
<path
d="M12,1L3,5V11C3,16.55 6.84,21.74 12,23C17.16,21.74 21,16.55 21,11V5L12,1M12,7C13.4,7 14.8,8.1 14.8,9.5V11C15.4,11 16,11.6 16,12.3V15.8C16,16.4 15.4,17 14.7,17H9.2C8.6,17 8,16.4 8,15.7V12.2C8,11.6 8.6,11 9.2,11V9.5C9.2,8.1 10.6,7 12,7M12,8.2C11.2,8.2 10.5,8.7 10.5,9.5V11H13.5V9.5C13.5,8.7 12.8,8.2 12,8.2Z"
/>
</svg>
<div
aria-valuemax="100"
aria-valuemin="0"
aria-valuenow="45"
aria-valuetext="You have put 45% of your funds in your shielded account"
class="usage-indicator__meter"
role="meter"
>
<div
aria-hidden="true"
class="usage-indicator__meter-bar"
style="width: 45%;"
/>
</div>
<svg
class="dusk-icon dusk-icon--size--default usage-indicator__icon"
data-tooltip-id="main-tooltip"
data-tooltip-text="You have put 55% of your funds in your unshielded account"
role="graphics-symbol"
viewBox="0 0 24 24"
>
<path
d="M21 11C21 16.5 17.2 21.7 12 23C6.8 21.7 3 16.5 3 11V5L12 1L21 5V11M12 21C15.8 20 19 15.5 19 11.2V6.3L12 3.2L5 6.3V11.2C5 15.5 8.2 20 12 21M14.8 11H10.5V8.5C10.5 7.7 11.2 7.2 12 7.2S13.5 7.7 13.5 8.5V9H14.8V8.5C14.8 7.1 13.4 6 12 6S9.2 7.1 9.2 8.5V11C8.6 11 8 11.6 8 12.2V15.7C8 16.4 8.6 17 9.2 17H14.7C15.4 17 16 16.4 16 15.8V12.3C16 11.6 15.4 11 14.8 11Z"
/>
</svg>
</div>
`;

exports[`UsageIndicator > should render the \`UsageIndicator\` component and react to value changes 2`] = `
<div
class="usage-indicator"
>
<svg
class="dusk-icon dusk-icon--size--default usage-indicator__icon"
data-tooltip-id="main-tooltip"
data-tooltip-text="You have put 80% of your funds in your shielded account"
role="graphics-symbol"
viewBox="0 0 24 24"
>
<path
d="M12,1L3,5V11C3,16.55 6.84,21.74 12,23C17.16,21.74 21,16.55 21,11V5L12,1M12,7C13.4,7 14.8,8.1 14.8,9.5V11C15.4,11 16,11.6 16,12.3V15.8C16,16.4 15.4,17 14.7,17H9.2C8.6,17 8,16.4 8,15.7V12.2C8,11.6 8.6,11 9.2,11V9.5C9.2,8.1 10.6,7 12,7M12,8.2C11.2,8.2 10.5,8.7 10.5,9.5V11H13.5V9.5C13.5,8.7 12.8,8.2 12,8.2Z"
/>
</svg>
<div
aria-valuemax="100"
aria-valuemin="0"
aria-valuenow="80"
aria-valuetext="You have put 80% of your funds in your shielded account"
class="usage-indicator__meter"
role="meter"
>
<div
aria-hidden="true"
class="usage-indicator__meter-bar"
style="width: 80%;"
/>
</div>
<svg
class="dusk-icon dusk-icon--size--default usage-indicator__icon"
data-tooltip-id="main-tooltip"
data-tooltip-text="You have put 20% of your funds in your unshielded account"
role="graphics-symbol"
viewBox="0 0 24 24"
>
<path
d="M21 11C21 16.5 17.2 21.7 12 23C6.8 21.7 3 16.5 3 11V5L12 1L21 5V11M12 21C15.8 20 19 15.5 19 11.2V6.3L12 3.2L5 6.3V11.2C5 15.5 8.2 20 12 21M14.8 11H10.5V8.5C10.5 7.7 11.2 7.2 12 7.2S13.5 7.7 13.5 8.5V9H14.8V8.5C14.8 7.1 13.4 6 12 6S9.2 7.1 9.2 8.5V11C8.6 11 8 11.6 8 12.2V15.7C8 16.4 8.6 17 9.2 17H14.7C15.4 17 16 16.4 16 15.8V12.3C16 11.6 15.4 11 14.8 11Z"
/>
</svg>
</div>
`;
1 change: 1 addition & 0 deletions web-wallet/src/lib/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ export { default as Send } from "./Send/Send.svelte";
export { default as ScanQR } from "./ScanQR/ScanQR.svelte";
export { default as Stake } from "./Stake/Stake.svelte";
export { default as Transactions } from "./Transactions/Transactions.svelte";
export { default as UsageIndicator } from "./UsageIndicator/UsageIndicator.svelte";
2 changes: 2 additions & 0 deletions web-wallet/src/routes/components-showcase/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import Throbbers from "./Throbbers.svelte";
import Toasts from "./Toasts.svelte";
import Tooltips from "./Tooltips.svelte";
import UsageIndicators from "./UsageIndicators.svelte";
import Wizards from "./Wizards.svelte";
/** @type {Record<string, import("svelte").ComponentType>} */
Expand All @@ -35,6 +36,7 @@
Throbbers: Throbbers,
Toasts: Toasts,
Tooltips: Tooltips,
"Usage Indicators": UsageIndicators,
Wizards: Wizards,
};
Expand Down
11 changes: 11 additions & 0 deletions web-wallet/src/routes/components-showcase/UsageIndicators.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<svelte:options immutable={true} />

<script>
import { UsageIndicator } from "$lib/components";
</script>

<section>
<div style="width: 60%">
<UsageIndicator value={45} />
</div>
</section>
3 changes: 2 additions & 1 deletion web-wallet/src/style/dusk/colors.css
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@

/* Status */

--success: #16db93;
--success-500: #16db93;
--success-700: #0f9363;
--warning: #ffcf23;
--error: #ed254e;
--info: #71b1ff;
Expand Down
3 changes: 2 additions & 1 deletion web-wallet/src/style/dusk/language.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
--danger-color: var(--error);
--error-color: var(--error);
--info-color: var(--info);
--success-color: var(--success);
--success-color: var(--success-500);
--success-color-variant-dark: var(--success-700);
--warning-color: var(--warning);

--on-background-color: var(--smokey-black);
Expand Down

0 comments on commit 7b2cebf

Please sign in to comment.