Skip to content

Commit

Permalink
feat(meter): Add Meter component (#7401)
Browse files Browse the repository at this point in the history
**Related Issue:** #2249 

## Summary
Adds new Meter component with a variety of display capabilities.


https://github.com/Esri/calcite-design-system/assets/4733155/dfca6fa0-ebb9-45d4-b97d-f749270559b4
  • Loading branch information
macandcheese authored Aug 22, 2023
1 parent e94e200 commit 47163ed
Show file tree
Hide file tree
Showing 13 changed files with 2,052 additions and 0 deletions.
5 changes: 5 additions & 0 deletions packages/calcite-components/.storybook/preview-head.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
max-width: 100%;
}

calcite-meter {
width: 450px;
max-width: 100%;
}

calcite-tabs,
calcite-progress {
width: 900px;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type MeterLabelType = "percent" | "units";
166 changes: 166 additions & 0 deletions packages/calcite-components/src/components/meter/meter.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import { newE2EPage } from "@stencil/core/testing";
import { html } from "../../../support/formatting";
import { accessible, renders, hidden, defaults, reflects } from "../../tests/commonTests";

describe("calcite-meter", () => {
describe("renders", () => {
renders("calcite-meter", { display: "flex" });
});

describe("defaults", () => {
defaults("calcite-meter", [
{
propertyName: "appearance",
defaultValue: "outline-fill",
},
{
propertyName: "disabled",
defaultValue: false,
},
{
propertyName: "fillType",
defaultValue: "range",
},
{
propertyName: "groupSeparator",
defaultValue: false,
},
{
propertyName: "max",
defaultValue: 100,
},
{
propertyName: "min",
defaultValue: 0,
},
{
propertyName: "rangeLabelType",
defaultValue: "percent",
},
{
propertyName: "scale",
defaultValue: "m",
},
{
propertyName: "unitLabel",
defaultValue: "",
},
{
propertyName: "valueLabel",
defaultValue: false,
},
{
propertyName: "valueLabelType",
defaultValue: "percent",
},
]);
});

describe("reflects", () => {
reflects("calcite-meter", [
{
propertyName: "appearance",
value: "outline-fill",
},
{
propertyName: "fillType",
value: "range",
},
{
propertyName: "max",
value: 100,
},
{
propertyName: "min",
value: 0,
},
{
propertyName: "rangeLabelType",
value: "percent",
},
{
propertyName: "scale",
value: "m",
},
{
propertyName: "valueLabelType",
value: "percent",
},
]);
});

describe("hidden", () => {
hidden("calcite-meter");
});

describe("accessible", () => {
accessible(`<calcite-meter label="A great meter"></calcite-meter>`);
});

describe("correctly sets range and value properties", () => {
it("correctly sets range and value properties if not present", async () => {
const page = await newE2EPage({
html: html`<calcite-meter />`,
});
const meter = await page.find(`calcite-meter`);
page.waitForChanges();
expect(await meter.getProperty("min")).toBe(0);
expect(await meter.getProperty("max")).toBe(100);
expect(await meter.getProperty("low")).toBe(0);
expect(await meter.getProperty("high")).toBe(100);
expect(await meter.getProperty("value")).toBe(0);
});

it("correctly sets range and value properties if not present and non-default min / max set", async () => {
const page = await newE2EPage({
html: html`<calcite-meter min="2000" max="10000" />`,
});
const meter = await page.find(`calcite-meter`);
page.waitForChanges();
expect(await meter.getProperty("min")).toBe(2000);
expect(await meter.getProperty("max")).toBe(10000);
expect(await meter.getProperty("low")).toBe(2000);
expect(await meter.getProperty("high")).toBe(10000);
expect(await meter.getProperty("value")).toBe(2000);
});

it("correctly adjusts out of range low and high", async () => {
const page = await newE2EPage({
html: html`<calcite-meter min="10" low="200" high="30" max="25" />`,
});
const meter = await page.find(`calcite-meter`);
page.waitForChanges();
expect(await meter.getProperty("min")).toBe(10);
expect(await meter.getProperty("max")).toBe(25);
expect(await meter.getProperty("low")).toBe(10);
expect(await meter.getProperty("high")).toBe(25);
expect(await meter.getProperty("value")).toBe(10);
});

it("correctly adjusts out of range low and high - b", async () => {
const page = await newE2EPage({
html: html`<calcite-meter min="10" low="15" high="5" max="25" />`,
});
const meter = await page.find(`calcite-meter`);
page.waitForChanges();
expect(await meter.getProperty("min")).toBe(10);
expect(await meter.getProperty("max")).toBe(25);
expect(await meter.getProperty("low")).toBe(10);
expect(await meter.getProperty("high")).toBe(25);
expect(await meter.getProperty("value")).toBe(10);
});

it("correctly leaves out of range value", async () => {
const page = await newE2EPage({
html: html`<calcite-meter value="210" min="10" low="200" high="30" max="25" />`,
});
const meter = await page.find(`calcite-meter`);
page.waitForChanges();
expect(await meter.getProperty("min")).toBe(10);
expect(await meter.getProperty("max")).toBe(25);
expect(await meter.getProperty("low")).toBe(10);
expect(await meter.getProperty("high")).toBe(25);
expect(await meter.getProperty("value")).toBe(210);
});
});
});
120 changes: 120 additions & 0 deletions packages/calcite-components/src/components/meter/meter.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
@include base-component();
@include disabled();

:host {
@apply flex;
--calcite-meter-space-internal: theme("spacing[0.5]");
--calcite-meter-height-internal: theme("spacing.4");
--calcite-meter-font-size-internal: var(--calcite-font-size--1);
}

:host([scale="s"]) {
--calcite-meter-height-internal: theme("spacing.3");
--calcite-meter-font-size-internal: var(--calcite-font-size--2);
}

:host([scale="l"]) {
--calcite-meter-height-internal: theme("spacing.6");
--calcite-meter-font-size-internal: var(--calcite-font-size-0);
}

.container {
@apply flex relative items-center w-full m-0;
block-size: var(--calcite-meter-height-internal);
background-color: var(--calcite-ui-foreground-2);
border: 1px solid var(--calcite-ui-border-3);
border-radius: var(--calcite-meter-height-internal);
}

.solid {
border: 1px solid var(--calcite-ui-foreground-3);
background-color: var(--calcite-ui-foreground-3);
}

.outline {
@apply bg-transparent;
}

.value-visible {
margin-block-start: theme("spacing.6");
}

.steps-visible {
margin-block-end: theme("spacing.6");
}

.step-line {
@apply block absolute inset-y-0;
inline-size: var(--calcite-meter-space-internal);
background-color: var(--calcite-ui-border-3);
}

.label {
@apply absolute;
font-size: var(--calcite-meter-font-size-internal);
}

.label-hidden {
@apply invisible opacity-0;
}

.label-value {
inset-block-end: calc(100% + 0.5em);
font-weight: var(--calcite-font-weight-bold);
color: var(--calcite-ui-text-1);
}

.label-range {
@apply text-color-3;
inset-block-start: calc(100% + 0.5em);
}

.unit-label {
@apply text-color-3 font-medium;
}

.label-value .unit-label {
@apply text-color-2 font-bold;
}

.fill {
@apply block absolute duration-150 ease-in-out bg-brand z-default;
inset-inline-start: var(--calcite-meter-space-internal);
inset-block: var(--calcite-meter-space-internal);
border-radius: var(--calcite-meter-height-internal);
max-inline-size: calc(100% - (var(--calcite-meter-space-internal) * 2));
min-inline-size: calc(var(--calcite-meter-height-internal) - (var(--calcite-meter-space-internal) * 2));
transition-property: inline-size, background-color, box-shadow;
}

.fill-danger {
background-color: var(--calcite-ui-danger);
}

.fill-success {
background-color: var(--calcite-ui-success);
}

.fill-warning {
background-color: var(--calcite-ui-warning);
}

.solid .fill {
inset-block: 0;
inset-inline-start: 0;
max-inline-size: 100%;
min-inline-size: calc(var(--calcite-meter-height-internal));
box-shadow: 0 0 0 1px var(--calcite-ui-brand);
}

.solid .fill-danger {
box-shadow: 0 0 0 1px var(--calcite-ui-danger);
}

.solid .fill-success {
box-shadow: 0 0 0 1px var(--calcite-ui-success);
}

.solid .fill-warning {
box-shadow: 0 0 0 1px var(--calcite-ui-warning);
}
Loading

0 comments on commit 47163ed

Please sign in to comment.