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

Commit

Permalink
feat: ActionPad. Add same expand/collapse behavior as ActionBar (#690)
Browse files Browse the repository at this point in the history
* progress

* progress

* cleanup + Progress

* no message

* all setup

* slots const

* use storybook default values

* review fixes

* fix interface
  • Loading branch information
driskull authored Jan 7, 2020
1 parent 3882c76 commit 9f02abe
Show file tree
Hide file tree
Showing 20 changed files with 396 additions and 147 deletions.
20 changes: 19 additions & 1 deletion .storybook/resources.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CalciteTheme } from "../src/components/interfaces";
import { CalciteAppearance, CalciteLayout, CalciteScale, CalciteTheme } from "../src/components/interfaces";

type Direction = "ltr" | "rtl";

Expand All @@ -10,10 +10,16 @@ interface AttributeMetadata<T> {
interface CommonAttributes {
dir: AttributeMetadata<Direction>;
theme: AttributeMetadata<CalciteTheme>;
scale: AttributeMetadata<CalciteScale>;
layout: AttributeMetadata<CalciteLayout>;
appearance: AttributeMetadata<CalciteAppearance>;
}

const dirOptions: Direction[] = ["ltr", "rtl"];
const themeOptions: CalciteTheme[] = ["light", "dark"];
const layoutOptions: CalciteLayout[] = ["leading", "trailing"];
const scaleOptions: CalciteScale[] = ["s", "m", "l"];
const appearanceOptions: CalciteAppearance[] = ["solid", "clear"];

export const ATTRIBUTES: CommonAttributes = {
dir: {
Expand All @@ -23,5 +29,17 @@ export const ATTRIBUTES: CommonAttributes = {
theme: {
values: themeOptions,
defaultValue: themeOptions[0]
},
scale: {
values: scaleOptions,
defaultValue: scaleOptions[1]
},
layout: {
values: layoutOptions,
defaultValue: layoutOptions[0]
},
appearance: {
values: appearanceOptions,
defaultValue: appearanceOptions[0]
}
};
85 changes: 44 additions & 41 deletions src/components/calcite-action-bar/calcite-action-bar.e2e.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { newE2EPage } from "@stencil/core/testing";
import { accessible, hidden, renders } from "../../tests/commonTests";
import { setUpPage } from "../../tests/utils";
import { CSS } from "./resources";

describe("calcite-action-bar", () => {
it("renders", async () => renders("calcite-action-bar"));
Expand All @@ -16,76 +17,78 @@ describe("calcite-action-bar", () => {
expect(element.getAttribute("expanded")).toBeNull();
});

it("expand: true", async () => {
const page = await newE2EPage();
describe("expand functionality", () => {
it("should show expand by default", async () => {
const page = await newE2EPage();

await page.setContent("<calcite-action-bar></calcite-action-bar>");
await page.setContent("<calcite-action-bar></calcite-action-bar>");

await page.waitForChanges();
await page.waitForChanges();

const expandAction = await page.find("calcite-action-bar >>> calcite-action");
const expandAction = await page.find("calcite-action-bar >>> calcite-action");

expect(expandAction).not.toBeNull();
});

it("expand: false", async () => {
const page = await newE2EPage();
expect(expandAction).not.toBeNull();
});

await page.setContent('<calcite-action-bar expand="false"></calcite-action-bar>');
it("should not show expand when false", async () => {
const page = await newE2EPage();

await page.waitForChanges();
await page.setContent('<calcite-action-bar expand="false"></calcite-action-bar>');

const expandAction = await page.find("calcite-action-bar >>> calcite-action");
await page.waitForChanges();

expect(expandAction).toBeNull();
});
const expandAction = await page.find("calcite-action-bar >>> calcite-action");

it("expanded", async () => {
const page = await setUpPage("<calcite-action-bar></calcite-action-bar>", {
withPeerDependencies: true
expect(expandAction).toBeNull();
});

const bar = await page.find("calcite-action-bar");
it("should toggle expanded", async () => {
const page = await setUpPage("<calcite-action-bar></calcite-action-bar>", {
withPeerDependencies: true
});

const buttonGroup = await page.find("calcite-action-bar >>> .action-group--bottom");
const bar = await page.find("calcite-action-bar");

const button = await buttonGroup.find("calcite-action >>> .button");
const buttonGroup = await page.find(`calcite-action-bar >>> .${CSS.actionGroupBottom}`);

expect(button).not.toBeNull();
const button = await buttonGroup.find("calcite-action");

await button.click();
expect(button).not.toBeNull();

expect(bar).toHaveAttribute("expanded");
});
await button.click();

it("expanded change should fire event", async () => {
const page = await newE2EPage();
expect(bar).toHaveAttribute("expanded");
});

await page.setContent("<calcite-action-bar></calcite-action-bar>");
it("should fire expanded event", async () => {
const page = await newE2EPage();

const element = await page.find("calcite-action-bar");
await page.setContent("<calcite-action-bar></calcite-action-bar>");

const eventSpy = await page.spyOnEvent("calciteActionBarToggle", "window");
const element = await page.find("calcite-action-bar");

element.setProperty("expanded", true);
const eventSpy = await element.spyOnEvent("calciteActionBarToggle");

await page.waitForChanges();
element.setProperty("expanded", true);

expect(eventSpy).toHaveReceivedEvent();
});
await page.waitForChanges();

it("expanded by default", async () => {
const page = await newE2EPage();
expect(eventSpy).toHaveReceivedEvent();
});

await page.setContent("<calcite-action-bar expanded></calcite-action-bar>");
it("should have child actions be textEnabled when expanded is set", async () => {
const page = await newE2EPage();

const buttonGroup = await page.find("calcite-action-bar >>> .action-group--bottom");
await page.setContent("<calcite-action-bar expanded></calcite-action-bar>");

const button = await buttonGroup.find("calcite-action");
const buttonGroup = await page.find(`calcite-action-bar >>> .${CSS.actionGroupBottom}`);

const textEnabled = await button.getProperty("textEnabled");
const button = await buttonGroup.find("calcite-action");

expect(textEnabled).toBe(true);
const textEnabled = await button.getProperty("textEnabled");

expect(textEnabled).toBe(true);
});
});

it("should be accessible", async () =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ import {
} from "../../../.storybook/utils";
import readme from "./readme.md";
import { ATTRIBUTES } from "../../../.storybook/resources";
import { LAYOUT_VALUES } from "./resources";

const { dir, theme } = ATTRIBUTES;
const { dir, layout, theme } = ATTRIBUTES;

export default {
title: "components|calcite-action-bar",
Expand Down Expand Up @@ -47,7 +45,7 @@ const createAttributes: () => Attributes = () => [
},
{
name: "layout",
value: select("layout", LAYOUT_VALUES, "leading")
value: select("layout", layout.values, layout.defaultValue)
},
{
name: "theme",
Expand Down
71 changes: 22 additions & 49 deletions src/components/calcite-action-bar/calcite-action-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { Component, Element, Event, EventEmitter, Host, Prop, Watch, h } from "@

import { CalciteLayout, CalciteTheme } from "../interfaces";

import { getElementDir } from "../utils/dom";
import { CalciteExpandToggle, toggleChildActionText } from "../utils/CalciteExpandToggle";

import { CSS, ICONS } from "./resources";
import { CSS, SLOTS } from "./resources";

/**
* @slot bottom-actions - A slot for adding `calcite-action`s that will appear at the bottom of the action bar, above the collapse/expand button.
Expand Down Expand Up @@ -32,8 +32,8 @@ export class CalciteActionBar {
@Prop({ reflect: true }) expanded = false;

@Watch("expanded")
expandedHandler(newValue: boolean) {
this.setActionTextEnabled(newValue);
expandedHandler(expanded: boolean) {
toggleChildActionText({ parent: this.el, expanded });

this.calciteActionBarToggle.emit();
}
Expand Down Expand Up @@ -71,6 +71,8 @@ export class CalciteActionBar {
*/
@Event() calciteActionBarToggle: EventEmitter;

// --------------------------------------------------------------------------
//
// Private Properties
//
// --------------------------------------------------------------------------
Expand All @@ -84,7 +86,8 @@ export class CalciteActionBar {
// --------------------------------------------------------------------------

componentWillLoad() {
this.setActionTextEnabled(this.expanded);
const { el, expanded } = this;
toggleChildActionText({ parent: el, expanded });
}

// --------------------------------------------------------------------------
Expand All @@ -93,20 +96,6 @@ export class CalciteActionBar {
//
// --------------------------------------------------------------------------

getClosestShellLayout(): CalciteLayout {
const shellNode = this.el.closest("calcite-shell-panel");

if (!shellNode) {
return;
}

return shellNode.layout;
}

setActionTextEnabled(expanded: boolean): void {
this.el.querySelectorAll("calcite-action").forEach((action) => (action.textEnabled = expanded));
}

toggleExpand = (): void => {
this.expanded = !this.expanded;
};
Expand All @@ -117,39 +106,23 @@ export class CalciteActionBar {
//
// --------------------------------------------------------------------------

renderExpandToggle() {
const { expanded, expand, textExpand, textCollapse, el, layout } = this;

const rtl = getElementDir(el) === "rtl";

const expandText = expanded ? textCollapse : textExpand;
const icons = [ICONS.chevronsLeft, ICONS.chevronsRight];

if (rtl) {
icons.reverse();
}

const layoutFallback = layout || this.getClosestShellLayout() || "leading";

const trailing = layoutFallback === "trailing";
const expandIcon = trailing ? icons[1] : icons[0];
const collapseIcon = trailing ? icons[0] : icons[1];

return expand ? (
<calcite-action onClick={this.toggleExpand} textEnabled={expanded} text={expandText}>
<calcite-icon scale="s" icon={expanded ? expandIcon : collapseIcon} />
</calcite-action>
) : null;
}

renderBottomActionGroup() {
const expandToggleNode = this.renderExpandToggle();
const { expanded, expand, textExpand, textCollapse, el, layout, toggleExpand } = this;

const expandToggleNode = expand ? (
<CalciteExpandToggle
expanded={expanded}
textExpand={textExpand}
textCollapse={textCollapse}
el={el}
layout={layout}
toggleExpand={toggleExpand}
/>
) : null;

return this.el.querySelector("[slot=bottom-actions]") || expandToggleNode ? (
return this.el.querySelector(`[slot=${SLOTS.bottomActions}]`) || expandToggleNode ? (
<calcite-action-group class={CSS.actionGroupBottom}>
<div class={CSS.actionGroupBottomContainer}>
<slot name="bottom-actions" />
</div>
<slot name={SLOTS.bottomActions} />
{expandToggleNode}
</calcite-action-group>
) : null;
Expand Down
12 changes: 3 additions & 9 deletions src/components/calcite-action-bar/resources.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import { CalciteLayout } from "../interfaces";

export const CSS = {
actionGroupBottom: "action-group--bottom",
actionGroupBottomContainer: "action-group-bottom-container"
actionGroupBottom: "action-group--bottom"
};

export const LAYOUT_VALUES: CalciteLayout[] = ["leading", "trailing"];

export const ICONS = {
chevronsLeft: "chevrons-left",
chevronsRight: "chevrons-right"
export const SLOTS = {
bottomActions: "bottom-actions"
};
Loading

0 comments on commit 9f02abe

Please sign in to comment.