@justeattakeaway/pie-icon-button 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,14 +1,14 @@
1
- [7:49:27 AM] @custom-elements-manifest/analyzer: Created new manifest.
1
+ [3:48:32 PM] @custom-elements-manifest/analyzer: Created new manifest.
2
2
  react wrapper has been added!
3
- vite v4.2.1 building for production...
3
+ vite v4.2.3 building for production...
4
4
  transforming...
5
- ✓ 19 modules transformed.
5
+ ✓ 28 modules transformed.
6
6
  rendering chunks...
7
7
  computing gzip size...
8
- dist/index.js  6.20 kB │ gzip: 1.70 kB
8
+ dist/index.js  7.93 kB │ gzip: 2.13 kB
9
9
  dist/react.js 59.14 kB │ gzip: 15.95 kB
10
10
  
11
11
  [vite:dts] Start generate declaration files...
12
- ✓ built in 14.76s
13
- [vite:dts] Declaration files built in 13749ms.
12
+ ✓ built in 30.04s
13
+ [vite:dts] Declaration files built in 27657ms.
14
14
  
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @justeattakeaway/pie-icon-button
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [Updated] - enum types to string union types to string union types ([#508](https://github.com/justeattakeaway/pie/pull/508)) by [@FayeCarter](https://github.com/FayeCarter)
8
+
9
+ ## 0.4.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [Changed] - Refactor visual tests to have labels showing props ([#519](https://github.com/justeattakeaway/pie/pull/519)) by [@jamieomaguire](https://github.com/jamieomaguire)
14
+
15
+ - [Added] - component and a11y browser tests ([#499](https://github.com/justeattakeaway/pie/pull/499)) by [@jamieomaguire](https://github.com/jamieomaguire)
16
+
17
+ - [Changed] - moved pie-webc-core dependency to devDependencies in each component ([#499](https://github.com/justeattakeaway/pie/pull/499)) by [@jamieomaguire](https://github.com/jamieomaguire)
18
+
19
+ - [Added] - percy visual tests ([#499](https://github.com/justeattakeaway/pie/pull/499)) by [@jamieomaguire](https://github.com/jamieomaguire)
20
+
21
+ - [Added] - Additional notes on visual tests and environment variables ([#525](https://github.com/justeattakeaway/pie/pull/525)) by [@jamieomaguire](https://github.com/jamieomaguire)
22
+
23
+ - [Added] Read me percy config examples ([#529](https://github.com/justeattakeaway/pie/pull/529)) by [@kevinrodrigues](https://github.com/kevinrodrigues)
24
+
25
+ ### Patch Changes
26
+
27
+ - [Changed] - Use `componentSelector` to define the custom element ([#530](https://github.com/justeattakeaway/pie/pull/530)) by [@raoufswe](https://github.com/raoufswe)
28
+
3
29
  ## 0.3.0
4
30
 
5
31
  ### Minor Changes
package/README.md CHANGED
@@ -11,3 +11,34 @@
11
11
  ## `pie-icon-button`
12
12
 
13
13
  `pie-icon-button` is a Web Component built using the Lit library. It offers a simple and accessible icon button component for web applications. This component can be easily integrated into various frontend frameworks and customized through a set of properties.
14
+
15
+ ## Testing
16
+
17
+ ### Browser tests
18
+
19
+ Run at the root of the monorepo:
20
+ ```
21
+ yarn test:browsers --filter=pie-icon-button
22
+ ```
23
+
24
+ ### Visual tests
25
+
26
+ Run at the root of the monorepo:
27
+ ```
28
+ yarn test:visual --filter=pie-icon-button
29
+ ```
30
+
31
+ Note: To run these locally, you will need to ensure that any environment variables required are set up on your machine to mirror those on CI (such as Percy tokens). How you achieve this will differ between operating systems.
32
+
33
+ Setup via bash:
34
+
35
+ ```
36
+ export PERCY_TOKEN_PIE_ICON_BUTTON=abcde
37
+ ```
38
+
39
+ Setup via package.json:
40
+
41
+ Under scripts `test:visual` replace the environment variable with the below:
42
+
43
+ ```
44
+ PERCY_TOKEN_PIE_ICON_BUTTON=abcde
package/dist/index.js CHANGED
@@ -1,59 +1,103 @@
1
- import { unsafeCSS as b, LitElement as h, html as u } from "lit";
1
+ import { unsafeCSS as b, LitElement as p, html as l } from "lit";
2
2
  import { property as d } from "lit/decorators.js";
3
3
  import "lit/decorators/property.js";
4
- const f = (o, r, e) => function(c, t) {
5
- const n = `#${t}`;
6
- Object.defineProperty(c, t, {
4
+ const g = (c, t, r) => function(n, o) {
5
+ const e = `#${o}`;
6
+ Object.defineProperty(n, o, {
7
7
  get() {
8
- return this[n];
8
+ return this[e];
9
9
  },
10
10
  set(a) {
11
- const v = this[n];
12
- r.includes(a) ? this[n] = a : (console.error(
13
- `<${o}> Invalid value "${a}" provided for property "${t}".`,
14
- `Must be one of: ${r.join(" | ")}.`,
15
- `Falling back to default value: "${e}"`
16
- ), this[n] = e), this.requestUpdate(t, v);
11
+ const f = this[e];
12
+ t.includes(a) ? this[e] = a : (console.error(
13
+ `<${c}> Invalid value "${a}" provided for property "${o}".`,
14
+ `Must be one of: ${t.join(" | ")}.`,
15
+ `Falling back to default value: "${r}"`
16
+ ), this[e] = r), this.requestUpdate(o, f);
17
17
  }
18
18
  });
19
- };
20
- var i = /* @__PURE__ */ ((o) => (o.PRIMARY = "primary", o.SECONDARY = "secondary", o.OUTLINE = "outline", o.GHOST = "ghost", o.GHOST_TERTIARY = "ghost-tertiary", o))(i || {});
21
- const g = `:host{--btn-border-radius: var(--dt-radius-rounded-e);--btn-height: 48px;--btn-width: var(--btn-height);--btn-bg-color: var(--dt-color-interactive-brand);--btn-icon-fill: var(--dt-color-content-interactive-primary);--btn-focus: var(--dt-color-focus-outer)}.o-iconBtn{min-block-size:var(--btn-height);aspect-ratio:1/1;border:none;border-radius:var(--btn-border-radius);outline:none;background-color:var(--btn-bg-color);cursor:pointer;user-select:none;display:flex;align-items:center;justify-content:center}@supports not (aspect-ratio: 1/1){.o-iconBtn{min-inline-size:var(--btn-width)}}.o-iconBtn:focus-visible{outline:2px solid var(--btn-focus)}.o-iconBtn svg{height:24.5px;width:24.5px}.o-iconBtn svg,.o-iconBtn path{fill:var(--btn-icon-fill)}:host([variant=primary]) .o-iconBtn:hover:not(:disabled){background-color:hsl(var(--dt-color-interactive-brand-h),var(--dt-color-interactive-brand-s),calc(var(--dt-color-interactive-brand-l) - var(--dt-color-hover-01)))}:host([variant=primary]) .o-iconBtn:active:not(:disabled){background-color:hsl(var(--dt-color-interactive-brand-h),var(--dt-color-interactive-brand-s),calc(var(--dt-color-interactive-brand-l) - var(--dt-color-active-01)))}:host([variant=secondary]){--btn-bg-color: var(--dt-color-interactive-secondary);--btn-icon-fill: var(--dt-color-content-interactive-secondary)}:host([variant=secondary]) .o-iconBtn:hover:not(:disabled){background-color:hsl(var(--dt-color-interactive-secondary-h),var(--dt-color-interactive-secondary-s),calc(var(--dt-color-interactive-secondary-l) - var(--dt-color-hover-01)))}:host([variant=secondary]) .o-iconBtn:active:not(:disabled){background-color:hsl(var(--dt-color-interactive-secondary-h),var(--dt-color-interactive-secondary-s),calc(var(--dt-color-interactive-secondary-l) - var(--dt-color-active-01)))}:host([variant=outline]){--btn-bg-color: var(--dt-color-container-default);--btn-icon-fill: var(--dt-color-content-interactive-brand)}:host([variant=outline]) .o-iconBtn{border:1px solid var(--dt-color-border-strong)}:host([variant=outline]) .o-iconBtn:hover:not(:disabled){background-color:hsl(var(--dt-color-container-default-h),var(--dt-color-container-default-s),calc(var(--dt-color-container-default-l) - var(--dt-color-hover-01)))}:host([variant=outline]) .o-iconBtn:active:not(:disabled){background-color:hsl(var(--dt-color-container-default-h),var(--dt-color-container-default-s),calc(var(--dt-color-container-default-l) - var(--dt-color-active-01)))}:host([variant=ghost]){--btn-bg-color: var(--dt-color-container-default);--btn-icon-fill: var(--dt-color-content-interactive-brand)}:host([variant=ghost]) .o-iconBtn:hover:not(:disabled){background-color:hsl(var(--dt-color-container-default-h),var(--dt-color-container-default-s),calc(var(--dt-color-container-default-l) - var(--dt-color-hover-01)))}:host([variant=ghost]) .o-iconBtn:active:not(:disabled){background-color:hsl(var(--dt-color-container-default-h),var(--dt-color-container-default-s),calc(var(--dt-color-container-default-l) - var(--dt-color-active-01)))}:host([variant=ghost-tertiary]){--btn-bg-color: var(--dt-color-container-default);--btn-icon-fill: var(--dt-color-content-interactive-tertiary)}:host([variant=ghost-tertiary]) .o-iconBtn:hover:not(:disabled){background-color:hsl(var(--dt-color-container-default-h),var(--dt-color-container-default-s),calc(var(--dt-color-container-default-l) - var(--dt-color-hover-01)))}:host([variant=ghost-tertiary]) .o-iconBtn:active:not(:disabled){background-color:hsl(var(--dt-color-container-default-h),var(--dt-color-container-default-s),calc(var(--dt-color-container-default-l) - var(--dt-color-active-01)))}:host([disabled]){--btn-bg-color: var(--dt-color-disabled-01);--btn-icon-fill: var(--dt-color-content-disabled)}:host([disabled]) .o-iconBtn{border:1px solid var(--dt-color-disabled-01);cursor:not-allowed}:host([disabled][variant=outline]) .o-iconBtn{outline:none}:host([disabled][variant=ghost]),:host([disabled][variant=ghost-tertiary]){--btn-bg-color: transparent;--btn-icon-fill: var(--dt-color-content-default)}:host([disabled][variant=ghost]) .o-iconBtn,:host([disabled][variant=ghost-tertiary]) .o-iconBtn{outline:none;border:none}
19
+ }, y = `.c-webComponentTestWrapper{padding-block:var(--dt-spacing-c);padding-inline:var(--dt-spacing-e);font-family:var(--dt-font-interactive-m-family);font-size:calc(var(--dt-font-size-20) * 1px);border:1px solid var(--dt-color-background-dark);display:grid;grid-template-columns:1fr 1fr}.c-webComponentTestWrapper-label{margin-block:var(--dt-spacing-c)}.c-webComponentTestWrapper-slot{padding:var(--dt-spacing-c);border:1px dashed var(--dt-color-background-dark);grid-column:1/3;margin-block-start:var(--dt-spacing-c)}
22
20
  `;
23
- var p = Object.defineProperty, y = Object.getOwnPropertyDescriptor, s = (o, r, e, c) => {
24
- for (var t = c > 1 ? void 0 : c ? y(r, e) : r, n = o.length - 1, a; n >= 0; n--)
25
- (a = o[n]) && (t = (c ? a(r, e, t) : a(t)) || t);
26
- return c && t && p(r, e, t), t;
21
+ var m = Object.defineProperty, B = Object.getOwnPropertyDescriptor, w = (c, t, r, n) => {
22
+ for (var o = n > 1 ? void 0 : n ? B(t, r) : t, e = c.length - 1, a; e >= 0; e--)
23
+ (a = c[e]) && (o = (n ? a(t, r, o) : a(o)) || o);
24
+ return n && o && m(t, r, o), o;
25
+ };
26
+ class s extends p {
27
+ constructor() {
28
+ super(...arguments), this.propKeyValues = "";
29
+ }
30
+ // Renders a string such as 'size: small, isFullWidth: true'
31
+ // as HTML such as:
32
+ // <p class="c-webComponentTestWrapper-label"><b>size</b>: <code>small</code></p>
33
+ // <p class="c-webComponentTestWrapper-label"><b>isFullWidth</b>: <code>true</code></p>
34
+ _renderPropKeyValues() {
35
+ return this.propKeyValues.split(",").map((t) => {
36
+ const [r, n] = t.split(":");
37
+ return l`<p class="c-webComponentTestWrapper-label"><b>${r}</b>: <code>${n}</code></p>`;
38
+ });
39
+ }
40
+ // eslint-disable-next-line class-methods-use-this
41
+ render() {
42
+ return l`
43
+ <div class="c-webComponentTestWrapper">
44
+ ${this._renderPropKeyValues()}
45
+ <div class="c-webComponentTestWrapper-slot">
46
+ <slot></slot>
47
+ </div>
48
+ </div>`;
49
+ }
50
+ }
51
+ s.styles = b(y);
52
+ w([
53
+ d({ type: String })
54
+ ], s.prototype, "propKeyValues", 2);
55
+ const v = "web-component-test-wrapper";
56
+ customElements.get(v) || customElements.define(v, s);
57
+ const $ = `.o-iconBtn{--btn-border-radius: var(--dt-radius-rounded-e);--btn-height: 48px;--btn-width: var(--btn-height);--btn-bg-color: var(--dt-color-interactive-brand);--btn-icon-fill: var(--dt-color-content-interactive-primary);--btn-focus: var(--dt-color-focus-outer);min-block-size:var(--btn-height);aspect-ratio:1/1;border:none;border-radius:var(--btn-border-radius);outline:none;background-color:var(--btn-bg-color);cursor:pointer;user-select:none;display:flex;align-items:center;justify-content:center}@supports not (aspect-ratio: 1/1){.o-iconBtn{min-inline-size:var(--btn-width)}}.o-iconBtn:focus-visible{outline:2px solid var(--btn-focus)}.o-iconBtn svg{height:24.5px;width:24.5px}.o-iconBtn svg,.o-iconBtn path{fill:var(--btn-icon-fill)}.o-iconBtn[variant=primary]:hover:not(:disabled){background-color:hsl(var(--dt-color-interactive-brand-h),var(--dt-color-interactive-brand-s),calc(var(--dt-color-interactive-brand-l) - var(--dt-color-hover-01)))}.o-iconBtn[variant=primary]:active:not(:disabled){background-color:hsl(var(--dt-color-interactive-brand-h),var(--dt-color-interactive-brand-s),calc(var(--dt-color-interactive-brand-l) - var(--dt-color-active-01)))}.o-iconBtn[variant=secondary]{--btn-bg-color: var(--dt-color-interactive-secondary);--btn-icon-fill: var(--dt-color-content-interactive-secondary)}.o-iconBtn[variant=secondary]:hover:not(:disabled){background-color:hsl(var(--dt-color-interactive-secondary-h),var(--dt-color-interactive-secondary-s),calc(var(--dt-color-interactive-secondary-l) - var(--dt-color-hover-01)))}.o-iconBtn[variant=secondary]:active:not(:disabled){background-color:hsl(var(--dt-color-interactive-secondary-h),var(--dt-color-interactive-secondary-s),calc(var(--dt-color-interactive-secondary-l) - var(--dt-color-active-01)))}.o-iconBtn[variant=outline]{--btn-bg-color: var(--dt-color-container-default);--btn-icon-fill: var(--dt-color-content-interactive-brand)}.o-iconBtn[variant=outline] .o-iconBtn{border:1px solid var(--dt-color-border-strong)}.o-iconBtn[variant=outline]:hover:not(:disabled){background-color:hsl(var(--dt-color-container-default-h),var(--dt-color-container-default-s),calc(var(--dt-color-container-default-l) - var(--dt-color-hover-01)))}.o-iconBtn[variant=outline]:active:not(:disabled){background-color:hsl(var(--dt-color-container-default-h),var(--dt-color-container-default-s),calc(var(--dt-color-container-default-l) - var(--dt-color-active-01)))}.o-iconBtn[variant=ghost]{--btn-bg-color: var(--dt-color-container-default);--btn-icon-fill: var(--dt-color-content-interactive-brand)}.o-iconBtn[variant=ghost]:hover:not(:disabled){background-color:hsl(var(--dt-color-container-default-h),var(--dt-color-container-default-s),calc(var(--dt-color-container-default-l) - var(--dt-color-hover-01)))}.o-iconBtn[variant=ghost]:active:not(:disabled){background-color:hsl(var(--dt-color-container-default-h),var(--dt-color-container-default-s),calc(var(--dt-color-container-default-l) - var(--dt-color-active-01)))}.o-iconBtn[variant=ghost-tertiary]{--btn-bg-color: var(--dt-color-container-default);--btn-icon-fill: var(--dt-color-content-interactive-tertiary)}.o-iconBtn[variant=ghost-tertiary]:hover:not(:disabled){background-color:hsl(var(--dt-color-container-default-h),var(--dt-color-container-default-s),calc(var(--dt-color-container-default-l) - var(--dt-color-hover-01)))}.o-iconBtn[variant=ghost-tertiary]:active:not(:disabled){background-color:hsl(var(--dt-color-container-default-h),var(--dt-color-container-default-s),calc(var(--dt-color-container-default-l) - var(--dt-color-active-01)))}.o-iconBtn[disabled]{--btn-bg-color: var(--dt-color-disabled-01);--btn-icon-fill: var(--dt-color-content-disabled)}.o-iconBtn[disabled] .o-iconBtn{border:1px solid var(--dt-color-disabled-01);cursor:not-allowed}.o-iconBtn[disabled][variant=outline] .o-iconBtn{outline:none}.o-iconBtn[disabled][variant=ghost],.o-iconBtn[disabled][variant=ghost-tertiary]{--btn-bg-color: transparent;--btn-icon-fill: var(--dt-color-content-default)}.o-iconBtn[disabled][variant=ghost] .o-iconBtn,.o-iconBtn[disabled][variant=ghost-tertiary] .o-iconBtn{outline:none;border:none}
58
+ `, x = [
59
+ "primary",
60
+ "secondary",
61
+ "outline",
62
+ "ghost",
63
+ "ghost-tertiary"
64
+ ];
65
+ var P = Object.defineProperty, _ = Object.getOwnPropertyDescriptor, u = (c, t, r, n) => {
66
+ for (var o = n > 1 ? void 0 : n ? _(t, r) : t, e = c.length - 1, a; e >= 0; e--)
67
+ (a = c[e]) && (o = (n ? a(t, r, o) : a(o)) || o);
68
+ return n && o && P(t, r, o), o;
27
69
  };
28
- const B = "pie-icon-button";
29
- class l extends h {
70
+ const h = "pie-icon-button";
71
+ class i extends p {
30
72
  constructor() {
31
- super(...arguments), this.variant = i.PRIMARY, this.disabled = !1;
73
+ super(...arguments), this.variant = "primary", this.disabled = !1;
32
74
  }
33
75
  render() {
34
76
  const {
35
- disabled: r
77
+ disabled: t,
78
+ variant: r
36
79
  } = this;
37
- return u`
80
+ return l`
38
81
  <button
39
82
  class="o-iconBtn"
40
- ?disabled=${r}>
83
+ variant=${r}
84
+ ?disabled=${t}>
41
85
  <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
42
86
  <path d="M11.8676 3.20496L8.0001 7.07248L4.13258 3.20496L3.20508 4.13246L7.0726 7.99998L3.20508 11.8675L4.13258 12.795L8.0001 8.92748L11.8676 12.795L12.7951 11.8675L8.92761 7.99998L12.7951 4.13246L11.8676 3.20496Z" fill="#242E30"/>
43
87
  </svg>
44
88
  </button>`;
45
89
  }
46
90
  }
47
- l.styles = b(g);
48
- s([
91
+ i.styles = b($);
92
+ u([
49
93
  d(),
50
- f(B, Object.values(i), i.PRIMARY)
51
- ], l.prototype, "variant", 2);
52
- s([
94
+ g(h, x, "primary")
95
+ ], i.prototype, "variant", 2);
96
+ u([
53
97
  d({ type: Boolean })
54
- ], l.prototype, "disabled", 2);
55
- customElements.define("pie-icon-button", l);
98
+ ], i.prototype, "disabled", 2);
99
+ customElements.define(h, i);
56
100
  export {
57
- i as ICON_BUTTON_VARIANT,
58
- l as PieIconButton
101
+ i as PieIconButton,
102
+ x as iconButtonVariants
59
103
  };
@@ -1,11 +1,8 @@
1
+ export interface IconButtonProps {
2
+ variant: 'primary' | 'secondary' | 'outline' | 'ghost' | 'ghost-tertiary';
3
+ }
1
4
  /**
2
5
  * Icon Button style variants
3
6
  */
4
- export declare enum ICON_BUTTON_VARIANT {
5
- PRIMARY = "primary",
6
- SECONDARY = "secondary",
7
- OUTLINE = "outline",
8
- GHOST = "ghost",
9
- GHOST_TERTIARY = "ghost-tertiary"
10
- }
7
+ export declare const iconButtonVariants: IconButtonProps['variant'][];
11
8
  //# sourceMappingURL=defs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"defs.d.ts","sourceRoot":"","sources":["../../../src/defs.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,oBAAY,mBAAmB;IAC3B,OAAO,YAAY;IACnB,SAAS,cAAc;IACvB,OAAO,YAAY;IACnB,KAAK,UAAU;IACf,cAAc,mBAAmB;CACpC"}
1
+ {"version":3,"file":"defs.d.ts","sourceRoot":"","sources":["../../../src/defs.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC5B,OAAO,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,GAAG,gBAAgB,CAAC;CAC7E;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,eAAe,CAAC,SAAS,CAAC,EAM1D,CAAC"}
@@ -1,9 +1,9 @@
1
1
  import { LitElement } from 'lit';
2
- import { ICON_BUTTON_VARIANT } from './defs';
3
- export { ICON_BUTTON_VARIANT };
2
+ import { IconButtonProps, iconButtonVariants } from './defs';
3
+ export { type IconButtonProps, iconButtonVariants };
4
4
  declare const componentSelector = "pie-icon-button";
5
5
  export declare class PieIconButton extends LitElement {
6
- variant: ICON_BUTTON_VARIANT;
6
+ variant: IconButtonProps['variant'];
7
7
  disabled: boolean;
8
8
  render(): import("lit-html").TemplateResult<1>;
9
9
  static styles: import("lit").CSSResult;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAmB,MAAM,KAAK,CAAC;AAGlD,OAAO,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAI7C,OAAO,EAAE,mBAAmB,EAAE,CAAC;AAE/B,QAAA,MAAM,iBAAiB,oBAAoB,CAAC;AAE5C,qBAAa,aAAc,SAAQ,UAAU;IAGrC,OAAO,EAAG,mBAAmB,CAA+B;IAG5D,QAAQ,UAAS;IAErB,MAAM;IAiBN,MAAM,CAAC,MAAM,0BAAqB;CACrC;AAID,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,qBAAqB;QAC3B,CAAC,iBAAiB,CAAC,EAAE,aAAa,CAAC;KACtC;CACJ"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAmB,MAAM,KAAK,CAAC;AAIlD,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAG7D,OAAO,EAAE,KAAK,eAAe,EAAE,kBAAkB,EAAE,CAAC;AAEpD,QAAA,MAAM,iBAAiB,oBAAoB,CAAC;AAE5C,qBAAa,aAAc,SAAQ,UAAU;IAGrC,OAAO,EAAE,eAAe,CAAC,SAAS,CAAC,CAAa;IAGhD,QAAQ,UAAS;IAErB,MAAM;IAkBN,MAAM,CAAC,MAAM,0BAAqB;CACrC;AAID,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,qBAAqB;QAC3B,CAAC,iBAAiB,CAAC,EAAE,aAAa,CAAC;KACtC;CACJ"}
package/package.json CHANGED
@@ -1,20 +1,21 @@
1
1
  {
2
2
  "name": "@justeattakeaway/pie-icon-button",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "PIE Design System Icon Button built using Web Components",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
8
8
  "types": "dist/types/index.d.ts",
9
9
  "scripts": {
10
- "build": "yarn build:wrapper pie-icon-button && run -T vite build --config ../../../configs/pie-components-config/vite.config.js",
11
- "watch": "run -T vite build --config ../../../configs/pie-components-config/vite.config.js --watch",
10
+ "build": "yarn build:wrapper pie-icon-button && run -T vite build",
11
+ "watch": "run -T vite build --watch",
12
12
  "test": "echo \"Error: no test specified\" && exit 0",
13
- "test:ci": "yarn test"
13
+ "test:visual": "run -T cross-env-shell PERCY_TOKEN=${PERCY_TOKEN_PIE_ICON_BUTTON} percy exec --allowed-hostname cloudfront.net -- npx playwright test -c ./playwright-lit-visual.config.ts",
14
+ "test:visual:ci": "yarn test:visual"
14
15
  },
15
16
  "author": "JustEatTakeaway - Design System Web Team",
16
17
  "license": "Apache-2.0",
17
- "dependencies": {
18
+ "devDependencies": {
18
19
  "@justeattakeaway/pie-webc-core": "workspace:*"
19
20
  },
20
21
  "volta": {
@@ -0,0 +1,56 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <link rel="preload" href="https://d30v2pzvrfyzpo.cloudfront.net/fonts/JETSansDigital-Regular-optimised.woff2" as="font" type="font/woff2" crossorigin>
7
+ <link rel="preload" href="https://d30v2pzvrfyzpo.cloudfront.net/fonts/JETSansDigital-Bold-optimised.woff2" as="font" type="font/woff2" crossorigin>
8
+ <link rel="preload" href="https://d30v2pzvrfyzpo.cloudfront.net/fonts/JETSansDigital-ExtraBold-optimised.woff2" as="font" type="font/woff2" crossorigin>
9
+ <style>
10
+ @font-face {
11
+ font-family: JETSansDigital;
12
+ src: url('https://d30v2pzvrfyzpo.cloudfront.net/fonts/JETSansDigital-Regular-optimised.woff2') format("woff2"),
13
+ url('https://d30v2pzvrfyzpo.cloudfront.net/fonts/JETSansDigital-Regular-optimised.woff') format("woff");
14
+ font-weight: 400;
15
+ font-display: swap;
16
+ }
17
+ @font-face {
18
+ font-family: JETSansDigital;
19
+ src: url('https://d30v2pzvrfyzpo.cloudfront.net/fonts/JETSansDigital-Bold-optimised.woff2') format("woff2"),
20
+ url('https://d30v2pzvrfyzpo.cloudfront.net/fonts/JETSansDigital-Bold-optimised.woff') format("woff");
21
+ font-weight: 700;
22
+ font-display: swap;
23
+ }
24
+ @font-face {
25
+ font-family: JETSansDigital;
26
+ src: url('https://d30v2pzvrfyzpo.cloudfront.net/fonts/JETSansDigital-ExtraBold-optimised.woff2') format("woff2"),
27
+ url('https://d30v2pzvrfyzpo.cloudfront.net/fonts/JETSansDigital-ExtraBold-optimised.woff') format("woff");
28
+ font-weight: 800;
29
+ font-display: swap;
30
+ }
31
+ body {
32
+ font-feature-settings: "tnum"; /* Enable tabular numbers */
33
+ }
34
+ /* basic styles to center align components and give them some spacing */
35
+ #root {
36
+ padding: 1em;
37
+ }
38
+
39
+ #root > * {
40
+ display: block;
41
+ margin-inline: auto;
42
+ }
43
+
44
+ #root > * + * {
45
+ margin-top: 1em;
46
+ }
47
+ </style>
48
+ <title>Testing Page</title>
49
+ <link rel="stylesheet" type="text/css" href="https://unpkg.com/@justeat/pie-design-tokens/dist/jet.css" />
50
+ <link rel="stylesheet" type="text/css" href="https://unpkg.com/@justeat/pie-design-tokens/dist/jet-hsl-colors.css" />
51
+ </head>
52
+ <body>
53
+ <div id="root"></div>
54
+ <script type="module" src="./index.ts"></script>
55
+ </body>
56
+ </html>
@@ -0,0 +1 @@
1
+ //Import common styles here
@@ -0,0 +1,5 @@
1
+ import { defineConfig } from '@sand4rt/experimental-ct-web';
2
+ import { getPlaywrightVisualConfig } from '@justeattakeaway/pie-components-config';
3
+
4
+ // @ts-ignore
5
+ export default defineConfig(getPlaywrightVisualConfig());
@@ -0,0 +1,5 @@
1
+ import { defineConfig } from '@sand4rt/experimental-ct-web';
2
+ import { getPlaywrightConfig } from '@justeattakeaway/pie-components-config';
3
+
4
+ // @ts-ignore
5
+ export default defineConfig(getPlaywrightConfig());
package/src/defs.ts CHANGED
@@ -1,10 +1,14 @@
1
+ export interface IconButtonProps {
2
+ variant: 'primary' | 'secondary' | 'outline' | 'ghost' | 'ghost-tertiary';
3
+ }
4
+
1
5
  /**
2
6
  * Icon Button style variants
3
7
  */
4
- export enum ICON_BUTTON_VARIANT {
5
- PRIMARY = 'primary',
6
- SECONDARY = 'secondary',
7
- OUTLINE = 'outline',
8
- GHOST = 'ghost',
9
- GHOST_TERTIARY = 'ghost-tertiary',
10
- }
8
+ export const iconButtonVariants: IconButtonProps['variant'][] = [
9
+ 'primary',
10
+ 'secondary',
11
+ 'outline',
12
+ 'ghost',
13
+ 'ghost-tertiary',
14
+ ];
@@ -1,4 +1,15 @@
1
- :host {
1
+ @mixin button-interactive-states($bg-color) {
2
+ &:hover:not(:disabled) {
3
+ background-color: hsl(var(#{$bg-color}-h), var(#{$bg-color}-s), calc(var(#{$bg-color}-l) - var(--dt-color-hover-01)));
4
+ }
5
+
6
+ &:active:not(:disabled) {
7
+ background-color: hsl(var(#{$bg-color}-h), var(#{$bg-color}-s), calc(var(#{$bg-color}-l) - var(--dt-color-active-01)));
8
+ }
9
+ }
10
+
11
+ // Base button styles
12
+ .o-iconBtn {
2
13
  --btn-border-radius: var(--dt-radius-rounded-e);
3
14
 
4
15
  // The base values are set to the size default, which is for the medium button size
@@ -10,20 +21,7 @@
10
21
  --btn-bg-color: var(--dt-color-interactive-brand);
11
22
  --btn-icon-fill: var(--dt-color-content-interactive-primary);
12
23
  --btn-focus: var(--dt-color-focus-outer);
13
- }
14
-
15
- @mixin button-interactive-states($bg-color) {
16
- & .o-iconBtn:hover:not(:disabled) {
17
- background-color: hsl(var(#{$bg-color}-h), var(#{$bg-color}-s), calc(var(#{$bg-color}-l) - var(--dt-color-hover-01)));
18
- }
19
-
20
- & .o-iconBtn:active:not(:disabled) {
21
- background-color: hsl(var(#{$bg-color}-h), var(#{$bg-color}-s), calc(var(#{$bg-color}-l) - var(--dt-color-active-01)));
22
- }
23
- }
24
24
 
25
- // Base button styles
26
- .o-iconBtn {
27
25
  min-block-size: var(--btn-height);
28
26
  aspect-ratio: 1 / 1;
29
27
 
@@ -55,68 +53,68 @@
55
53
  svg, path {
56
54
  fill: var(--btn-icon-fill);
57
55
  }
58
- }
59
56
 
60
- // Variants
61
- :host([variant='primary']) {
62
- @include button-interactive-states('--dt-color-interactive-brand');
63
- }
57
+ &[variant='primary'] {
58
+ @include button-interactive-states('--dt-color-interactive-brand');
59
+ }
64
60
 
65
- :host([variant='secondary']) {
66
- --btn-bg-color: var(--dt-color-interactive-secondary);
67
- --btn-icon-fill: var(--dt-color-content-interactive-secondary);
61
+ &[variant='secondary'] {
62
+ --btn-bg-color: var(--dt-color-interactive-secondary);
63
+ --btn-icon-fill: var(--dt-color-content-interactive-secondary);
68
64
 
69
- @include button-interactive-states('--dt-color-interactive-secondary');
70
- }
65
+ @include button-interactive-states('--dt-color-interactive-secondary');
66
+ }
71
67
 
72
- :host([variant='outline']) {
73
- --btn-bg-color: var(--dt-color-container-default);
74
- --btn-icon-fill: var(--dt-color-content-interactive-brand);
68
+ &[variant='outline'] {
69
+ --btn-bg-color: var(--dt-color-container-default);
70
+ --btn-icon-fill: var(--dt-color-content-interactive-brand);
75
71
 
76
- & .o-iconBtn {
77
- border: 1px solid var(--dt-color-border-strong);
78
- }
72
+ & .o-iconBtn {
73
+ border: 1px solid var(--dt-color-border-strong);
74
+ }
79
75
 
80
- @include button-interactive-states('--dt-color-container-default');
81
- }
76
+ @include button-interactive-states('--dt-color-container-default');
77
+ }
82
78
 
83
- :host([variant='ghost']) {
84
- --btn-bg-color: var(--dt-color-container-default);
85
- --btn-icon-fill: var(--dt-color-content-interactive-brand);
79
+ &[variant='ghost'] {
80
+ --btn-bg-color: var(--dt-color-container-default);
81
+ --btn-icon-fill: var(--dt-color-content-interactive-brand);
86
82
 
87
- @include button-interactive-states('--dt-color-container-default');
88
- }
83
+ @include button-interactive-states('--dt-color-container-default');
84
+ }
89
85
 
90
- :host([variant='ghost-tertiary']) {
91
- --btn-bg-color: var(--dt-color-container-default);
92
- --btn-icon-fill: var(--dt-color-content-interactive-tertiary);
86
+ &[variant='ghost-tertiary'] {
87
+ --btn-bg-color: var(--dt-color-container-default);
88
+ --btn-icon-fill: var(--dt-color-content-interactive-tertiary);
93
89
 
94
- @include button-interactive-states('--dt-color-container-default');
95
- }
90
+ @include button-interactive-states('--dt-color-container-default');
91
+ }
96
92
 
97
- :host([disabled]) {
98
- --btn-bg-color: var(--dt-color-disabled-01);
99
- --btn-icon-fill: var(--dt-color-content-disabled);
93
+ &[disabled] {
94
+ --btn-bg-color: var(--dt-color-disabled-01);
95
+ --btn-icon-fill: var(--dt-color-content-disabled);
100
96
 
101
- & .o-iconBtn {
102
- border: 1px solid var(--dt-color-disabled-01);
103
- cursor: not-allowed;
97
+ & .o-iconBtn {
98
+ border: 1px solid var(--dt-color-disabled-01);
99
+ cursor: not-allowed;
100
+ }
104
101
  }
105
- }
106
102
 
107
- :host([disabled][variant='outline']) {
108
- & .o-iconBtn {
109
- outline: none;
103
+ &[disabled][variant='outline'] {
104
+ & .o-iconBtn {
105
+ outline: none;
106
+ }
110
107
  }
111
- }
112
108
 
113
- :host([disabled][variant='ghost']),
114
- :host([disabled][variant='ghost-tertiary']) {
115
- --btn-bg-color: transparent;
116
- --btn-icon-fill: var(--dt-color-content-default);
109
+ &[disabled][variant='ghost'],
110
+ &[disabled][variant='ghost-tertiary'] {
111
+ --btn-bg-color: transparent;
112
+ --btn-icon-fill: var(--dt-color-content-default);
117
113
 
118
- & .o-iconBtn {
119
- outline: none;
120
- border: none;
114
+ & .o-iconBtn {
115
+ outline: none;
116
+ border: none;
117
+ }
121
118
  }
122
119
  }
120
+
package/src/index.ts CHANGED
@@ -1,31 +1,32 @@
1
1
  import { LitElement, html, unsafeCSS } from 'lit'; // eslint-disable-line import/no-extraneous-dependencies
2
2
  import { property } from 'lit/decorators.js'; // eslint-disable-line import/no-extraneous-dependencies
3
3
  import { validPropertyValues } from '@justeattakeaway/pie-webc-core';
4
- import { ICON_BUTTON_VARIANT } from './defs';
5
4
  import styles from './iconButton.scss?inline';
5
+ import { IconButtonProps, iconButtonVariants } from './defs';
6
6
 
7
7
  // Valid values available to consumers
8
- export { ICON_BUTTON_VARIANT };
8
+ export { type IconButtonProps, iconButtonVariants };
9
9
 
10
10
  const componentSelector = 'pie-icon-button';
11
11
 
12
12
  export class PieIconButton extends LitElement {
13
13
  @property()
14
- @validPropertyValues(componentSelector, Object.values(ICON_BUTTON_VARIANT), ICON_BUTTON_VARIANT.PRIMARY)
15
- variant : ICON_BUTTON_VARIANT = ICON_BUTTON_VARIANT.PRIMARY;
14
+ @validPropertyValues(componentSelector, iconButtonVariants, 'primary')
15
+ variant: IconButtonProps['variant'] = 'primary';
16
16
 
17
17
  @property({ type: Boolean })
18
18
  disabled = false;
19
19
 
20
20
  render () {
21
21
  const {
22
- disabled,
22
+ disabled, variant,
23
23
  } = this;
24
24
 
25
25
  // The inline SVG is temporary until we have a proper icon integration
26
26
  return html`
27
27
  <button
28
28
  class="o-iconBtn"
29
+ variant=${variant}
29
30
  ?disabled=${disabled}>
30
31
  <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
31
32
  <path d="M11.8676 3.20496L8.0001 7.07248L4.13258 3.20496L3.20508 4.13246L7.0726 7.99998L3.20508 11.8675L4.13258 12.795L8.0001 8.92748L11.8676 12.795L12.7951 11.8675L8.92761 7.99998L12.7951 4.13246L11.8676 3.20496Z" fill="#242E30"/>
@@ -37,7 +38,7 @@ export class PieIconButton extends LitElement {
37
38
  static styles = unsafeCSS(styles);
38
39
  }
39
40
 
40
- customElements.define('pie-icon-button', PieIconButton);
41
+ customElements.define(componentSelector, PieIconButton);
41
42
 
42
43
  declare global {
43
44
  interface HTMLElementTagNameMap {
@@ -0,0 +1,37 @@
1
+ import { test, expect } from '@sand4rt/experimental-ct-web';
2
+ import AxeBuilder from '@axe-core/playwright';
3
+ import {
4
+ PropObject, Combination, getAllPropCombinations, splitCombinationsByPropertyValue,
5
+ } from '@justeattakeaway/pie-webc-core/src/test-helpers/get-all-prop-combos.ts';
6
+ import { PieIconButton } from '@/index';
7
+ import { iconButtonVariants } from '@/defs';
8
+
9
+ const props: PropObject = {
10
+ variant: iconButtonVariants,
11
+ disabled: [true, false],
12
+ };
13
+
14
+ const componentPropsMatrix : Combination[] = getAllPropCombinations(props);
15
+ const componentPropsMatrixByVariant: Record<string, Combination[]> = splitCombinationsByPropertyValue(componentPropsMatrix, 'variant');
16
+ const componentVariants: string[] = Object.keys(componentPropsMatrixByVariant);
17
+
18
+ componentVariants.forEach((variant) => test(`Render all prop variations for Variant: ${variant}`, async ({ page, mount }) => {
19
+ await Promise.all(componentPropsMatrixByVariant[variant].map(async (combo: Combination) => {
20
+ await mount(
21
+ PieIconButton,
22
+ {
23
+ props: { ...combo },
24
+ slots: {
25
+ default: 'Hello world',
26
+ },
27
+ },
28
+ );
29
+ }));
30
+
31
+ const results = await new AxeBuilder.default({ page })
32
+ .withTags(['wcag21a', 'wcag21aa', 'wcag143', 'cat.color', 'cat.aria'])
33
+ .disableRules(['color-contrast', 'color-contrast-enhanced'])
34
+ .analyze();
35
+
36
+ expect(results.violations).toEqual([]);
37
+ }));
@@ -0,0 +1,24 @@
1
+ import { test, expect } from '@sand4rt/experimental-ct-web';
2
+ import { PieIconButton } from '@/index';
3
+
4
+ test('should correctly work with native click events', async ({ mount }) => {
5
+ const messages: string[] = [];
6
+ const expectedEventMessage = 'Native event dispatched';
7
+ const component = await mount(
8
+ PieIconButton,
9
+ {
10
+ props: {
11
+ variant: 'primary',
12
+ },
13
+ on: {
14
+ click: () => {
15
+ messages.push(expectedEventMessage);
16
+ },
17
+ },
18
+ },
19
+ );
20
+
21
+ await component.click();
22
+
23
+ expect(messages).toEqual([expectedEventMessage]);
24
+ });
@@ -0,0 +1,59 @@
1
+ import { test } from '@sand4rt/experimental-ct-web';
2
+ import percySnapshot from '@percy/playwright';
3
+ import { getLitPercyOptions } from '@justeattakeaway/pie-webc-core/src/test-helpers/percy-lit-options.ts';
4
+ import type {
5
+ PropObject, WebComponentPropValues, WebComponentTestInput,
6
+ } from '@justeattakeaway/pie-webc-core/src/test-helpers/defs.ts';
7
+ import {
8
+ getAllPropCombinations, splitCombinationsByPropertyValue,
9
+ } from '@justeattakeaway/pie-webc-core/src/test-helpers/get-all-prop-combos.ts';
10
+ import {
11
+ createTestWebComponent,
12
+ } from '@justeattakeaway/pie-webc-core/src/test-helpers/rendering.ts';
13
+ import {
14
+ WebComponentTestWrapper,
15
+ } from '@justeattakeaway/pie-webc-core/src/test-helpers/components/web-component-test-wrapper/WebComponentTestWrapper.ts';
16
+ import { PieIconButton } from '@/index';
17
+ import { iconButtonVariants } from '@/defs';
18
+
19
+ const props: PropObject = {
20
+ variant: iconButtonVariants,
21
+ disabled: [true, false],
22
+ };
23
+
24
+ // Renders a <pie-icon-button> HTML string with the given prop values
25
+ const renderTestPieIconButton = (propVals: WebComponentPropValues) => `<pie-icon-button variant="${propVals.variant}" ${propVals.disabled ? 'disabled' : ''}></pie-icon-button>`;
26
+
27
+ const componentPropsMatrix : WebComponentPropValues[] = getAllPropCombinations(props);
28
+ const componentPropsMatrixByVariant: Record<string, WebComponentPropValues[]> = splitCombinationsByPropertyValue(componentPropsMatrix, 'variant');
29
+ const componentVariants: string[] = Object.keys(componentPropsMatrixByVariant);
30
+
31
+ // This ensures the component is registered in the DOM for each test
32
+ // This is not required if your tests mount the web component directly in the tests
33
+ test('Component registered in the DOM', async ({ mount }) => {
34
+ await mount(
35
+ PieIconButton,
36
+ {
37
+ props: {},
38
+ },
39
+ );
40
+ });
41
+
42
+ componentVariants.forEach((variant) => test(`Render all prop variations for Variant: ${variant}`, async ({ page, mount }) => {
43
+ await Promise.all(componentPropsMatrixByVariant[variant].map(async (combo: WebComponentPropValues) => {
44
+ const testComponent: WebComponentTestInput = createTestWebComponent(combo, renderTestPieIconButton);
45
+ const propKeyValues = `disabled: ${testComponent.propValues.disabled}`;
46
+
47
+ await mount(
48
+ WebComponentTestWrapper,
49
+ {
50
+ props: { propKeyValues },
51
+ slots: {
52
+ default: testComponent.renderedString,
53
+ },
54
+ },
55
+ );
56
+ }));
57
+
58
+ await percySnapshot(page, `PIE Icon Button - Variant: ${variant}`, getLitPercyOptions());
59
+ }));
package/vite.config.js ADDED
@@ -0,0 +1,3 @@
1
+ import viteConfig from '@justeattakeaway/pie-components-config/vite.config'; // eslint-disable-line import/no-extraneous-dependencies
2
+
3
+ export default viteConfig;