Skip to content
This repository has been archived by the owner on Jun 29, 2023. It is now read-only.

feat(action): Add icon property to display calcite-icon. #837

Merged
merged 11 commits into from
Feb 27, 2020
29 changes: 19 additions & 10 deletions src/components/calcite-action/calcite-action.e2e.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { newE2EPage } from "@stencil/core/testing";
import { accessible, hidden, renders } from "../../tests/commonTests";
import { CSS } from "./resources";

describe("calcite-action", () => {
it("renders", async () => renders("calcite-action"));
Expand All @@ -10,7 +11,7 @@ describe("calcite-action", () => {
const page = await newE2EPage();
await page.setContent(`<calcite-action text="hello world" text-enabled></calcite-action>`);

const textContainer = await page.find("calcite-action >>> .text-container");
const textContainer = await page.find(`calcite-action >>> .${CSS.textContainer}`);
const isVisible = await textContainer.isVisible();

expect(isVisible).toBe(true);
Expand All @@ -20,49 +21,57 @@ describe("calcite-action", () => {
const page = await newE2EPage();
await page.setContent(`<calcite-action text="hello world"></calcite-action>`);

const textContainer = await page.find("calcite-action >>> .text-container");
const textContainer = await page.find(`calcite-action >>> .${CSS.textContainer}`);
const isVisible = await textContainer.isVisible();

expect(isVisible).toBe(false);
});

it("should have icon container with icon prop", async () => {
const page = await newE2EPage();
await page.setContent(`<calcite-action icon="hamburger"></calcite-action>`);

const iconContainer = await page.find(`calcite-action >>> .${CSS.iconContainer}`);
expect(iconContainer).not.toBeNull();
});

it("should have icon container with calcite-icon", async () => {
const page = await newE2EPage();
await page.setContent(`<calcite-action><calcite-icon icon="hamburger" scale="s"></calcite-icon></calcite-action>`);

const iconContainer = await page.find("calcite-action >>> .icon-container");
const iconContainer = await page.find(`calcite-action >>> .${CSS.iconContainer}`);
expect(iconContainer).not.toBeNull();
});

it("should have icon container with svg", async () => {
const page = await newE2EPage();
await page.setContent(`<calcite-action><svg></svg></calcite-icon></calcite-action>`);

const iconContainer = await page.find("calcite-action >>> .icon-container");
const iconContainer = await page.find(`calcite-action >>> .${CSS.iconContainer}`);
expect(iconContainer).not.toBeNull();
});

it("should not have icon container if no calcite-icon present", async () => {
it("should not have icon container if no icon present", async () => {
const page = await newE2EPage();
await page.setContent(`<calcite-action></calcite-action>`);

const iconContainer = await page.find("calcite-action >>> .icon-container");
const iconContainer = await page.find(`calcite-action >>> .${CSS.iconContainer}`);
expect(iconContainer).toBeNull();
});

it("should have icon container if loading", async () => {
const page = await newE2EPage();
await page.setContent(`<calcite-action loading></calcite-action>`);

const iconContainer = await page.find("calcite-action >>> .icon-container");
const iconContainer = await page.find(`calcite-action >>> .${CSS.iconContainer}`);
expect(iconContainer).not.toBeNull();
});

it("should use text prop for a11y attributes when text is not enabled", async () => {
const page = await newE2EPage();
await page.setContent(`<calcite-action text="hello world"></calcite-action>`);

const button = await page.find("calcite-action >>> .button");
const button = await page.find(`calcite-action >>> .${CSS.button}`);
expect(button.getAttribute("title")).toBe("hello world");
expect(button.getAttribute("aria-label")).toBe("hello world");
});
Expand All @@ -71,7 +80,7 @@ describe("calcite-action", () => {
const page = await newE2EPage();
await page.setContent(`<calcite-action text="hello world" label="hi"></calcite-action>`);

const button = await page.find("calcite-action >>> .button");
const button = await page.find(`calcite-action >>> .${CSS.button}`);
expect(button.getAttribute("title")).toBe("hi");
expect(button.getAttribute("aria-label")).toBe("hi");
});
Expand All @@ -80,7 +89,7 @@ describe("calcite-action", () => {
const page = await newE2EPage();
await page.setContent(`<calcite-action disabled></calcite-action>`);

const button = await page.find("calcite-action >>> .button");
const button = await page.find(`calcite-action >>> .${CSS.button}`);
expect(button).toHaveAttribute("disabled");
});

Expand Down
7 changes: 5 additions & 2 deletions src/components/calcite-action/calcite-action.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ const createAttributes: () => Attributes = () => [
name: "disabled",
value: boolean("disabled", false)
},
{
name: "icon",
value: text("icon", "beaker")
},
{
name: "indicator",
value: boolean("indicator", false)
Expand Down Expand Up @@ -60,5 +64,4 @@ const createAttributes: () => Attributes = () => [
}
];

export const basic = () =>
create("calcite-action", createAttributes(), `<calcite-icon scale="s" icon="beaker"></calcite-icon>`);
export const basic = () => create("calcite-action", createAttributes(), "");
23 changes: 13 additions & 10 deletions src/components/calcite-action/calcite-action.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ export class CalciteAction {
*/
@Prop({ reflect: true }) disabled = false;

/**
* The name of the icon to display. The value of this property must match the icon name from https://esri.github.io/calcite-ui-icons/.
*/
@Prop() icon?: string;

/**
* Indicates unread changes.
*/
Expand Down Expand Up @@ -120,9 +125,12 @@ export class CalciteAction {
}

renderIconContainer(): VNode {
const { loading } = this;

const calciteLoaderNode = <calcite-loader is-active inline></calcite-loader>;
const { el, loading, icon, scale } = this;
const iconScale = scale === "l" ? "m" : "s";
const calciteLoaderNode = loading ? <calcite-loader is-active inline /> : null;
const calciteIconNode = icon ? <calcite-icon icon={icon} scale={iconScale} /> : null;
const iconNode = calciteLoaderNode || calciteIconNode;
const hasIconToDisplay = iconNode || el.querySelector("calcite-icon, svg");

const slotContainerNode = (
<div
Expand All @@ -134,15 +142,10 @@ export class CalciteAction {
</div>
);

const iconNode = loading
? calciteLoaderNode
: this.el.querySelector("calcite-icon, svg")
? slotContainerNode
: null;

return iconNode ? (
return hasIconToDisplay ? (
<div key="icon-container" aria-hidden="true" class={CSS.iconContainer}>
{iconNode}
{slotContainerNode}
</div>
) : null;
}
Expand Down