diff --git a/packages/calcite-components/src/components.d.ts b/packages/calcite-components/src/components.d.ts index 8d2ead28b71..dbdc6085aa2 100644 --- a/packages/calcite-components/src/components.d.ts +++ b/packages/calcite-components/src/components.d.ts @@ -84,6 +84,7 @@ import { TableMessages } from "./components/table/assets/table/t9n"; import { TableCellMessages } from "./components/table-cell/assets/table-cell/t9n"; import { TableHeaderMessages } from "./components/table-header/assets/table-header/t9n"; import { TextAreaMessages } from "./components/text-area/assets/text-area/t9n"; +import { TileGroupLayout } from "./components/tile-group/interfaces"; import { TileSelectType } from "./components/tile-select/interfaces"; import { TileSelectGroupLayout } from "./components/tile-select-group/interfaces"; import { TipMessages } from "./components/tip/assets/tip/t9n"; @@ -170,6 +171,7 @@ export { TableMessages } from "./components/table/assets/table/t9n"; export { TableCellMessages } from "./components/table-cell/assets/table-cell/t9n"; export { TableHeaderMessages } from "./components/table-header/assets/table-header/t9n"; export { TextAreaMessages } from "./components/text-area/assets/text-area/t9n"; +export { TileGroupLayout } from "./components/tile-group/interfaces"; export { TileSelectType } from "./components/tile-select/interfaces"; export { TileSelectGroupLayout } from "./components/tile-select-group/interfaces"; export { TipMessages } from "./components/tip/assets/tip/t9n"; @@ -4985,6 +4987,20 @@ export namespace Components { */ "scale": Scale; } + interface CalciteTileGroup { + /** + * When `true`, interaction is prevented and the component is displayed with lower opacity. + */ + "disabled": boolean; + /** + * Defines the layout of the component. Use `"horizontal"` for rows, and `"vertical"` for a single column. + */ + "layout": TileGroupLayout; + /** + * Specifies the size of the component. + */ + "scale": Scale; + } interface CalciteTileSelect { /** * When `true`, the component is checked. @@ -7140,6 +7156,12 @@ declare global { prototype: HTMLCalciteTileElement; new (): HTMLCalciteTileElement; }; + interface HTMLCalciteTileGroupElement extends Components.CalciteTileGroup, HTMLStencilElement { + } + var HTMLCalciteTileGroupElement: { + prototype: HTMLCalciteTileGroupElement; + new (): HTMLCalciteTileGroupElement; + }; interface HTMLCalciteTileSelectElementEventMap { "calciteTileSelectChange": void; } @@ -7421,6 +7443,7 @@ declare global { "calcite-tabs": HTMLCalciteTabsElement; "calcite-text-area": HTMLCalciteTextAreaElement; "calcite-tile": HTMLCalciteTileElement; + "calcite-tile-group": HTMLCalciteTileGroupElement; "calcite-tile-select": HTMLCalciteTileSelectElement; "calcite-tile-select-group": HTMLCalciteTileSelectGroupElement; "calcite-time-picker": HTMLCalciteTimePickerElement; @@ -12490,6 +12513,20 @@ declare namespace LocalJSX { */ "scale"?: Scale; } + interface CalciteTileGroup { + /** + * When `true`, interaction is prevented and the component is displayed with lower opacity. + */ + "disabled"?: boolean; + /** + * Defines the layout of the component. Use `"horizontal"` for rows, and `"vertical"` for a single column. + */ + "layout"?: TileGroupLayout; + /** + * Specifies the size of the component. + */ + "scale"?: Scale; + } interface CalciteTileSelect { /** * When `true`, the component is checked. @@ -12992,6 +13029,7 @@ declare namespace LocalJSX { "calcite-tabs": CalciteTabs; "calcite-text-area": CalciteTextArea; "calcite-tile": CalciteTile; + "calcite-tile-group": CalciteTileGroup; "calcite-tile-select": CalciteTileSelect; "calcite-tile-select-group": CalciteTileSelectGroup; "calcite-time-picker": CalciteTimePicker; @@ -13116,6 +13154,7 @@ declare module "@stencil/core" { "calcite-tabs": LocalJSX.CalciteTabs & JSXBase.HTMLAttributes; "calcite-text-area": LocalJSX.CalciteTextArea & JSXBase.HTMLAttributes; "calcite-tile": LocalJSX.CalciteTile & JSXBase.HTMLAttributes; + "calcite-tile-group": LocalJSX.CalciteTileGroup & JSXBase.HTMLAttributes; "calcite-tile-select": LocalJSX.CalciteTileSelect & JSXBase.HTMLAttributes; "calcite-tile-select-group": LocalJSX.CalciteTileSelectGroup & JSXBase.HTMLAttributes; "calcite-time-picker": LocalJSX.CalciteTimePicker & JSXBase.HTMLAttributes; diff --git a/packages/calcite-components/src/components/tile-group/interfaces.ts b/packages/calcite-components/src/components/tile-group/interfaces.ts new file mode 100644 index 00000000000..16ac237b847 --- /dev/null +++ b/packages/calcite-components/src/components/tile-group/interfaces.ts @@ -0,0 +1 @@ +export type TileGroupLayout = "vertical" | "horizontal"; diff --git a/packages/calcite-components/src/components/tile-group/readme.md b/packages/calcite-components/src/components/tile-group/readme.md new file mode 100644 index 00000000000..904a43172c1 --- /dev/null +++ b/packages/calcite-components/src/components/tile-group/readme.md @@ -0,0 +1,21 @@ +# calcite-tile-group + + + +## Properties + +| Property | Attribute | Description | Type | Default | +| ---------- | ---------- | ------------------------------------------------------------------------------------------------------- | ---------------------------- | -------------- | +| `disabled` | `disabled` | When `true`, interaction is prevented and the component is displayed with lower opacity. | `boolean` | `false` | +| `layout` | `layout` | Defines the layout of the component. Use `"horizontal"` for rows, and `"vertical"` for a single column. | `"horizontal" \| "vertical"` | `"horizontal"` | +| `scale` | `scale` | Specifies the size of the component. | `"l" \| "m" \| "s"` | `"m"` | + +## Slots + +| Slot | Description | +| ---- | ------------------------------------------ | +| | A slot for adding `calcite-tile` elements. | + +--- + +*Built with [StencilJS](https://stenciljs.com/)* diff --git a/packages/calcite-components/src/components/tile-group/resources.ts b/packages/calcite-components/src/components/tile-group/resources.ts new file mode 100644 index 00000000000..71551c3c9c1 --- /dev/null +++ b/packages/calcite-components/src/components/tile-group/resources.ts @@ -0,0 +1,3 @@ +export const CSS = { + tileGroup: "tile-group", +}; diff --git a/packages/calcite-components/src/components/tile-group/tile-group.e2e.ts b/packages/calcite-components/src/components/tile-group/tile-group.e2e.ts new file mode 100644 index 00000000000..54b8899955c --- /dev/null +++ b/packages/calcite-components/src/components/tile-group/tile-group.e2e.ts @@ -0,0 +1,96 @@ +import { newE2EPage } from "@stencil/core/testing"; +import { accessible, defaults, disabled, reflects, renders, hidden } from "../../tests/commonTests"; +import { html } from "../../../support/formatting"; + +describe("calcite-tile-group", () => { + describe("renders", () => { + renders("calcite-tile-group", { display: "inline-block" }); + }); + + describe("honors hidden attribute.", () => { + hidden("calcite-tile-group"); + }); + + describe("accessible", () => { + accessible(``); + }); + + describe("defaults", () => { + defaults("calcite-tile-group", [ + { propertyName: "layout", defaultValue: "horizontal" }, + { propertyName: "scale", defaultValue: "m" }, + ]); + }); + + describe("reflects", () => { + reflects("calcite-tile-group", [ + { propertyName: "layout", value: "horizontal" }, + { propertyName: "scale", value: "m" }, + ]); + }); + + describe("disabled", () => { + disabled( + html` + + + + `, + { focusTarget: "none" }, + ); + }); + + describe("disabled with link tiles", () => { + disabled( + html` + + + + `, + { focusTarget: "child" }, + ); + }); + + describe("prop passing", () => { + it("tiles receive parent scale prop on initial load and when scale attribute is mutated", async () => { + const page = await newE2EPage(); + await page.setContent(html` + + + + + + `); + + let tiles = await page.findAll("calcite-tile"); + tiles.forEach((tile) => { + expect(tile.getAttribute("scale")).toBe("s"); + }); + + await page.$eval("calcite-tile-group", (element: HTMLCalciteTileGroupElement) => + element.setAttribute("scale", "l"), + ); + await page.waitForChanges(); + + tiles = await page.findAll("calcite-tile"); + tiles.forEach((tile) => { + expect(tile.getAttribute("scale")).toBe("l"); + }); + }); + }); +}); diff --git a/packages/calcite-components/src/components/tile-group/tile-group.scss b/packages/calcite-components/src/components/tile-group/tile-group.scss new file mode 100644 index 00000000000..7685f65c13b --- /dev/null +++ b/packages/calcite-components/src/components/tile-group/tile-group.scss @@ -0,0 +1,40 @@ +:host { + box-sizing: border-box; + display: inline-block; + + .tile-group { + display: grid; + grid-auto-rows: minmax(auto, 1fr); + } + + ::slotted(calcite-tile) { + margin-block-end: var(--calcite-spacing-px); + margin-inline-end: var(--calcite-spacing-px); + } +} + +:host([scale="s"]) { + .tile-group { + grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); + } +} +:host([scale="m"]) { + .tile-group { + grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); + } +} +:host([scale="l"]) { + .tile-group { + grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); + } +} + +:host([layout="vertical"]) { + .tile-group { + display: flex; + flex-direction: column; + } +} + +@include disabled(); +@include base-component(); diff --git a/packages/calcite-components/src/components/tile-group/tile-group.stories.ts b/packages/calcite-components/src/components/tile-group/tile-group.stories.ts new file mode 100644 index 00000000000..584f12da97b --- /dev/null +++ b/packages/calcite-components/src/components/tile-group/tile-group.stories.ts @@ -0,0 +1,964 @@ +import { select, boolean } from "@storybook/addon-knobs"; +import { html } from "../../../support/formatting"; +import readme from "./readme.md"; +import { storyFilters } from "../../../.storybook/helpers"; + +export default { + title: "Components/Tiles/Tile Group", + parameters: { + notes: readme, + chromatic: { delay: 10000 }, + }, + ...storyFilters(), +}; + +export const playground = (): string => html` + + + + + + +`; + +export const allVariants_NoTest = (): string => html` + + +
+

horizontal

+
+ +
+
+
small
+
medium
+
large
+
+ + +
+
icon, heading, description
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
icon, heading, description as link
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
icon, heading, description disabled
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
heading only
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
heading only as link
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
description only
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
description only as link
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
heading and description
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
heading and description as link
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
icon and heading (large visual)
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
icon and heading (large visual) as link
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+ + +
+

vertical

+
+ + +
+
heading only
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
heading only as link
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
description only
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
description only as link
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
heading and description
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
heading and description as link
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
icon, heading, description
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
icon, heading, description as link
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
icon and heading (large visual)
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
icon and heading (large visual) as link
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+`; diff --git a/packages/calcite-components/src/components/tile-group/tile-group.tsx b/packages/calcite-components/src/components/tile-group/tile-group.tsx new file mode 100644 index 00000000000..80d52d33f97 --- /dev/null +++ b/packages/calcite-components/src/components/tile-group/tile-group.tsx @@ -0,0 +1,94 @@ +import { Component, Element, h, Prop, VNode, Watch } from "@stencil/core"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + InteractiveContainer, + updateHostInteraction, +} from "../../utils/interactive"; +import { TileGroupLayout } from "./interfaces"; +import { Scale } from "../interfaces"; +import { CSS } from "./resources"; + +/** + * @slot - A slot for adding `calcite-tile` elements. + */ +@Component({ + tag: "calcite-tile-group", + styleUrl: "tile-group.scss", + shadow: true, +}) +export class TileGroup implements InteractiveComponent { + //-------------------------------------------------------------------------- + // + // Properties + // + //-------------------------------------------------------------------------- + + /** When `true`, interaction is prevented and the component is displayed with lower opacity. */ + @Prop({ reflect: true }) disabled = false; + + /** + * Defines the layout of the component. + * + * Use `"horizontal"` for rows, and `"vertical"` for a single column. + */ + @Prop({ reflect: true }) layout: TileGroupLayout = "horizontal"; + + /** + * Specifies the size of the component. + */ + @Prop({ reflect: true }) scale: Scale = "m"; + + @Watch("scale") + scaleWatcher(): void { + this.updateTiles(); + } + + //-------------------------------------------------------------------------- + // + // Private Properties + // + //-------------------------------------------------------------------------- + + @Element() el: HTMLCalciteTileGroupElement; + + //-------------------------------------------------------------------------- + // + // Private Methods + // + //-------------------------------------------------------------------------- + + private updateTiles = (): void => { + this.el.querySelectorAll("calcite-tile").forEach((item) => (item.scale = this.scale)); + }; + + //-------------------------------------------------------------------------- + // + // Lifecycle + // + //-------------------------------------------------------------------------- + + connectedCallback(): void { + connectInteractive(this); + this.updateTiles(); + } + + componentDidRender(): void { + updateHostInteraction(this); + } + + disconnectedCallback(): void { + disconnectInteractive(this); + } + + render(): VNode { + return ( + +
+ +
+
+ ); + } +} diff --git a/packages/calcite-components/src/components/tile/tile.scss b/packages/calcite-components/src/components/tile/tile.scss index dfc87da2ad8..c1324d4e007 100644 --- a/packages/calcite-components/src/components/tile/tile.scss +++ b/packages/calcite-components/src/components/tile/tile.scss @@ -150,11 +150,14 @@ padding: var(--calcite-spacing-xl); } } -:host(:not([embed])[href]:hover) { +:host(:not([embed])[href]:hover), +:host(:not([embed])[href]:focus) { --calcite-tile-border-color: var(--calcite-color-brand); .container { box-shadow: 0 0 0 2px var(--calcite-tile-border-color); cursor: pointer; + position: relative; + z-index: var(--calcite-z-index); } } :host(:not([embed])[href]:active) { diff --git a/packages/calcite-components/src/demos/tile-group.html b/packages/calcite-components/src/demos/tile-group.html new file mode 100644 index 00000000000..145e632be28 --- /dev/null +++ b/packages/calcite-components/src/demos/tile-group.html @@ -0,0 +1,934 @@ + + + + + + + Tile Group + + + + + + + + +
+

horizontal

+
+ +
+
+
small
+
medium
+
large
+
+ + +
+
icon, heading, description
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
icon, heading, description as link
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
icon, heading, description disabled
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
heading only
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
heading only as link
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
description only
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
description only as link
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
heading and description
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
heading and description as link
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
icon and heading (large visual)
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
icon and heading (large visual) as link
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+ + +
+

vertical

+
+ + +
+
heading only
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
heading only as link
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
description only
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
description only as link
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
heading and description
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
heading and description as link
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
icon, heading, description
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
icon, heading, description as link
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
icon and heading (large visual)
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
icon and heading (large visual) as link
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + + +
+
+
+ + diff --git a/packages/calcite-components/src/index.html b/packages/calcite-components/src/index.html index e8a0d4e3e1e..a1dfc41d1ae 100644 --- a/packages/calcite-components/src/index.html +++ b/packages/calcite-components/src/index.html @@ -196,10 +196,7 @@

Calcite demo

- - - + + - - + +