@justeattakeaway/pie-button 0.17.0 → 0.19.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
- [11:00:50 AM] @custom-elements-manifest/analyzer: Created new manifest.
1
+ [1:45:52 PM] @custom-elements-manifest/analyzer: Created new manifest.
2
2
  react wrapper has been added!
3
3
  vite v4.3.9 building for production...
4
4
  transforming...
5
5
  ✓ 22 modules transformed.
6
6
  rendering chunks...
7
7
  computing gzip size...
8
- dist/index.js  7.09 kB │ gzip: 1.77 kB
8
+ dist/index.js 11.55 kB │ gzip: 2.37 kB
9
9
  dist/react.js 59.01 kB │ gzip: 15.91 kB
10
10
  
11
11
  [vite:dts] Start generate declaration files...
12
- ✓ built in 13.54s
13
- [vite:dts] Declaration files built in 12277ms.
12
+ ✓ built in 10.50s
13
+ [vite:dts] Declaration files built in 9519ms.
14
14
  
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.19.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [Added] - pie-button loading state ([#603](https://github.com/justeattakeaway/pie/pull/603)) by [@jamieomaguire](https://github.com/jamieomaguire)
8
+
9
+ ## 0.18.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [Added] - inverse and ghost-inverse variants to pie-button ([#596](https://github.com/justeattakeaway/pie/pull/596)) by [@jamieomaguire](https://github.com/jamieomaguire)
14
+
15
+ - [Changed] - Set all component props to public ([#597](https://github.com/justeattakeaway/pie/pull/597)) by [@jamieomaguire](https://github.com/jamieomaguire)
16
+
3
17
  ## 0.17.0
4
18
 
5
19
  ### Minor Changes
package/README.md CHANGED
@@ -69,9 +69,10 @@ import { PieButton } from '@justeattakeaway/pie-button/dist/react';
69
69
  |-------------|-----------|-----------------|----------------------------------------------------------------------|
70
70
  | size | `String` | `medium` | Size of the button, one of `sizes` – `xsmall`, `small-expressive`, `small-productive`, `medium`, `large` |
71
71
  | type | `String` | `submit` | Type of the button, one of `types` – `submit`, `button`, `reset`, `menu` |
72
- | variant | `String` | `primary` | Variant of the button, one of `variants` – `primary`, `secondary`, `outline`, `ghost` |
72
+ | variant | `String` | `primary` | Variant of the button, one of `variants` – `primary`, `secondary`, `outline`, `ghost`, `inverse`, `ghost-inverse` |
73
73
  | disabled | `Boolean` | `false` | If `true`, disables the button. |
74
74
  | isFullWidth | `Boolean` | `false` | If `true`, sets the button width to 100% of it's container. |
75
+ | isLoading | `Boolean` | `false` | If `true`, displays a loading indicator inside the button.
75
76
 
76
77
  In your markup or JSX, you can then use these to set the properties for the `pie-button` component:
77
78
 
package/dist/index.js CHANGED
@@ -1,76 +1,85 @@
1
1
  import { unsafeCSS as h, LitElement as u, html as m } from "lit";
2
2
  import { property as c } from "lit/decorators.js";
3
3
  import "lit/decorators/property.js";
4
- const b = (l, o, a) => function(t, r) {
5
- const e = `#${r}`;
6
- Object.defineProperty(t, r, {
4
+ const b = (l, r, t) => function(o, e) {
5
+ const n = `#${e}`;
6
+ Object.defineProperty(o, e, {
7
7
  get() {
8
- return this[e];
8
+ return this[n];
9
9
  },
10
10
  set(v) {
11
- const p = this[e];
12
- o.includes(v) ? this[e] = v : (console.error(
13
- `<${l}> Invalid value "${v}" provided for property "${r}".`,
14
- `Must be one of: ${o.join(" | ")}.`,
15
- `Falling back to default value: "${a}"`
16
- ), this[e] = a), this.requestUpdate(r, p);
11
+ const p = this[n];
12
+ r.includes(v) ? this[n] = v : (console.error(
13
+ `<${l}> Invalid value "${v}" provided for property "${e}".`,
14
+ `Must be one of: ${r.join(" | ")}.`,
15
+ `Falling back to default value: "${t}"`
16
+ ), this[n] = t), this.requestUpdate(e, p);
17
17
  }
18
18
  });
19
- }, f = `.o-btn{--btn-border-radius: var(--dt-radius-rounded-e);--btn-font-family: var(--dt-font-interactive-m-family);--btn-font-weight: var(--dt-font-interactive-m-weight);--btn-padding: 10px var(--dt-spacing-e);--btn-min-height: 48px;--btn-font-size: calc(var(--dt-font-size-20) * 1px);--btn-line-height: calc(var(--dt-font-size-20-line-height) * 1px);--btn-bg-color: var(--dt-color-interactive-brand);--btn-text-color: var(--dt-color-content-interactive-primary);min-block-size:var(--btn-min-block-size);padding:var(--btn-padding);border:none;border-radius:var(--btn-border-radius);outline:none;background-color:var(--btn-bg-color);font-family:var(--btn-font-family);font-size:var(--btn-font-size);font-weight:var(--btn-font-weight);color:var(--btn-text-color);line-height:var(--btn-line-height);cursor:pointer;user-select:none}.o-btn:focus-visible{box-shadow:0 0 0 2px var(--dt-color-focus-inner);outline:none;position:relative}.o-btn:focus-visible:after{content:"";display:block;position:absolute;top:-3px;left:-3px;right:-3px;bottom:-3px;border-radius:var(--btn-border-radius);box-shadow:0 0 0 2px var(--dt-color-focus-outer)}.o-btn[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-btn[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-btn[variant=primary][size=xsmall],.o-btn[variant=primary][size=small-productive]{--btn-bg-color: var(--dt-color-interactive-primary)}.o-btn[variant=primary][size=xsmall]:hover:not(:disabled),.o-btn[variant=primary][size=small-productive]:hover:not(:disabled){background-color:hsl(var(--dt-color-interactive-primary-h),var(--dt-color-interactive-primary-s),calc(var(--dt-color-interactive-primary-l) - var(--dt-color-hover-01)))}.o-btn[variant=primary][size=xsmall]:active:not(:disabled),.o-btn[variant=primary][size=small-productive]:active:not(:disabled){background-color:hsl(var(--dt-color-interactive-primary-h),var(--dt-color-interactive-primary-s),calc(var(--dt-color-interactive-primary-l) - var(--dt-color-active-01)))}.o-btn[variant=secondary]{--btn-bg-color: var(--dt-color-interactive-secondary);--btn-text-color: var(--dt-color-content-interactive-secondary)}.o-btn[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-btn[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-btn[variant=outline]{--btn-bg-color: var(--dt-color-container-default);--btn-text-color: var(--dt-color-content-interactive-secondary);border:1px solid var(--dt-color-border-strong)}.o-btn[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-btn[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-btn[variant=ghost]{--btn-bg-color: transparent;--btn-text-color: var(--dt-color-content-link)}.o-btn[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-btn[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-btn[isFullWidth]{inline-size:100%}.o-btn[disabled]{--btn-text-color: var(--dt-color-content-disabled) !important;cursor:not-allowed}.o-btn[disabled]:not([variant=ghost]){--btn-bg-color: var(--dt-color-disabled-01) !important}.o-btn[disabled][variant=outline]{border-color:var(--dt-color-disabled-01)!important}.o-btn[size=xsmall]{--btn-padding: 6px var(--dt-spacing-b);--btn-font-size: calc(var(--dt-font-size-14) * 1px);--btn-line-height: calc(var(--dt-font-size-14-line-height) * 1px)}.o-btn[size=small-expressive]{--btn-padding: 6px var(--dt-spacing-d);--btn-font-size: calc(var(--dt-font-size-20) * 1px);--btn-line-height: calc(var(--dt-font-size-20-line-height) * 1px)}.o-btn[size=small-productive]{--btn-padding: 8px var(--dt-spacing-d);--btn-font-size: calc(var(--dt-font-size-16) * 1px);--btn-line-height: calc(var(--dt-font-size-16-line-height) * 1px)}.o-btn[size=large]{--btn-padding: 14px var(--dt-spacing-e);--btn-font-size: calc(var(--dt-font-size-20) * 1px);--btn-line-height: calc(var(--dt-font-size-20-line-height) * 1px)}
20
- `, g = ["xsmall", "small-productive", "small-expressive", "medium", "large"], y = ["submit", "button", "reset", "menu"], x = ["primary", "secondary", "outline", "ghost"];
21
- var z = Object.defineProperty, k = Object.getOwnPropertyDescriptor, d = (l, o, a, n) => {
22
- for (var t = n > 1 ? void 0 : n ? k(o, a) : o, r = l.length - 1, e; r >= 0; r--)
23
- (e = l[r]) && (t = (n ? e(o, a, t) : e(t)) || t);
24
- return n && t && z(o, a, t), t;
19
+ }, g = `*,*:before,*:after{box-sizing:border-box}@keyframes rotate360{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.o-btn{--btn-border-radius: var(--dt-radius-rounded-e);--btn-font-family: var(--dt-font-interactive-m-family);--btn-font-weight: var(--dt-font-interactive-m-weight);--btn-padding: 10px var(--dt-spacing-e);--btn-font-size: calc(var(--dt-font-size-20) * 1px);--btn-line-height: calc(var(--dt-font-size-20-line-height) * 1px);--btn-bg-color: var(--dt-color-interactive-brand);--btn-text-color: var(--dt-color-content-interactive-primary);--spinner-size-s: 20px;--spinner-size-m: 24px;--spinner-border-width-s: 2.5px;--spinner-border-width-m: 3px;--spinner-size: var(--spinner-size-m);--spinner-border-width: var(--spinner-border-width-m);--spinner-base-color-h: var(--dt-color-content-interactive-primary-h);--spinner-base-color-s: var(--dt-color-content-interactive-primary-s);--spinner-base-color-l: var(--dt-color-content-interactive-primary-l);--spinner-left-color-opacity: .35;--spinner-left-color: hsl(var(--spinner-base-color-h), var(--spinner-base-color-s), var(--spinner-base-color-l), var(--spinner-left-color-opacity));--spinner-right-color: hsl(var(--spinner-base-color-h), var(--spinner-base-color-s), var(--spinner-base-color-l), 1);--spinner-animation-duration: 1.15s;--spinner-animation-timing-function: linear;--spinner-animation-iteration-count: infinite;position:relative;box-sizing:border-box;padding:var(--btn-padding);border:none;border-radius:var(--btn-border-radius);outline:none;background-color:var(--btn-bg-color);font-family:var(--btn-font-family);font-size:var(--btn-font-size);font-weight:var(--btn-font-weight);color:var(--btn-text-color);line-height:var(--btn-line-height);cursor:pointer;user-select:none}.o-btn:focus-visible{box-shadow:0 0 0 2px var(--dt-color-focus-inner);outline:none;position:relative}.o-btn:focus-visible:after{content:"";display:block;position:absolute;top:-3px;left:-3px;right:-3px;bottom:-3px;border-radius:var(--btn-border-radius);box-shadow:0 0 0 2px var(--dt-color-focus-outer)}.o-btn[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-btn[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-btn[variant=primary][size=xsmall],.o-btn[variant=primary][size=small-productive]{--btn-bg-color: var(--dt-color-interactive-primary)}.o-btn[variant=primary][size=xsmall]:hover:not(:disabled),.o-btn[variant=primary][size=small-productive]:hover:not(:disabled){background-color:hsl(var(--dt-color-interactive-primary-h),var(--dt-color-interactive-primary-s),calc(var(--dt-color-interactive-primary-l) - var(--dt-color-hover-01)))}.o-btn[variant=primary][size=xsmall]:active:not(:disabled),.o-btn[variant=primary][size=small-productive]:active:not(:disabled){background-color:hsl(var(--dt-color-interactive-primary-h),var(--dt-color-interactive-primary-s),calc(var(--dt-color-interactive-primary-l) - var(--dt-color-active-01)))}.o-btn[variant=secondary]{--btn-bg-color: var(--dt-color-interactive-secondary);--btn-text-color: var(--dt-color-content-interactive-secondary);--spinner-base-color-h: var(--dt-color-content-interactive-secondary-h);--spinner-base-color-s: var(--dt-color-content-interactive-secondary-s);--spinner-base-color-l: var(--dt-color-content-interactive-secondary-l)}.o-btn[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-btn[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-btn[variant=outline]{--btn-bg-color: var(--dt-color-container-default);--btn-text-color: var(--dt-color-content-interactive-secondary);--spinner-base-color-h: var(--dt-color-content-interactive-secondary-h);--spinner-base-color-s: var(--dt-color-content-interactive-secondary-s);--spinner-base-color-l: var(--dt-color-content-interactive-secondary-l);border:1px solid var(--dt-color-border-strong)}.o-btn[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-btn[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-btn[variant=ghost]{--btn-bg-color: transparent;--btn-text-color: var(--dt-color-content-link);--spinner-base-color-h: var(--dt-color-content-interactive-secondary-h);--spinner-base-color-s: var(--dt-color-content-interactive-secondary-s);--spinner-base-color-l: var(--dt-color-content-interactive-secondary-l)}.o-btn[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-btn[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-btn[variant=inverse]{--btn-bg-color: var(--dt-color-interactive-inverse);--btn-text-color: var(--dt-color-content-interactive-secondary);--spinner-base-color-h: var(--dt-color-content-interactive-secondary-h);--spinner-base-color-s: var(--dt-color-content-interactive-secondary-s);--spinner-base-color-l: var(--dt-color-content-interactive-secondary-l)}.o-btn[variant=inverse]:hover:not(:disabled){background-color:hsl(var(--dt-color-interactive-inverse-h),var(--dt-color-interactive-inverse-s),calc(var(--dt-color-interactive-inverse-l) - var(--dt-color-hover-01)))}.o-btn[variant=inverse]:active:not(:disabled){background-color:hsl(var(--dt-color-interactive-inverse-h),var(--dt-color-interactive-inverse-s),calc(var(--dt-color-interactive-inverse-l) - var(--dt-color-active-01)))}.o-btn[variant=ghost-inverse]{--btn-bg-color: transparent;--btn-text-color: var(--dt-color-content-interactive-primary);--spinner-base-color-h: var(--dt-color-content-interactive-primary-h);--spinner-base-color-s: var(--dt-color-content-interactive-primary-s);--spinner-base-color-l: var(--dt-color-content-interactive-primary-l)}.o-btn[variant=ghost-inverse]:hover:not(:disabled){background-color:hsl(var(--dt-color-container-inverse-h),var(--dt-color-container-inverse-s),calc(var(--dt-color-container-inverse-l) - var(--dt-color-hover-01)))}.o-btn[variant=ghost-inverse]:active:not(:disabled){background-color:hsl(var(--dt-color-container-inverse-h),var(--dt-color-container-inverse-s),calc(var(--dt-color-container-inverse-l) - var(--dt-color-active-01)))}.o-btn[isFullWidth]{inline-size:100%}.o-btn[disabled]{--btn-text-color: var(--dt-color-content-disabled) !important;cursor:not-allowed}.o-btn[disabled]:not([variant=ghost],[variant=ghost-inverse]){--btn-bg-color: var(--dt-color-disabled-01) !important}.o-btn[disabled][variant=outline]{border-color:var(--dt-color-disabled-01)!important}.o-btn[size=xsmall]{--btn-padding: 6px var(--dt-spacing-b);--btn-font-size: calc(var(--dt-font-size-14) * 1px);--btn-line-height: calc(var(--dt-font-size-14-line-height) * 1px);--spinner-size: var(--spinner-size-s);--spinner-border-width: var(--spinner-border-width-s)}.o-btn[size=small-expressive]{--btn-padding: 6px var(--dt-spacing-d);--btn-font-size: calc(var(--dt-font-size-20) * 1px);--btn-line-height: calc(var(--dt-font-size-20-line-height) * 1px);--spinner-size: var(--spinner-size-s);--spinner-border-width: var(--spinner-border-width-s)}.o-btn[size=small-productive]{--btn-padding: 8px var(--dt-spacing-d);--btn-font-size: calc(var(--dt-font-size-16) * 1px);--btn-line-height: calc(var(--dt-font-size-16-line-height) * 1px);--spinner-size: var(--spinner-size-s);--spinner-border-width: var(--spinner-border-width-s)}.o-btn[size=large]{--btn-padding: 14px var(--dt-spacing-e);--btn-font-size: calc(var(--dt-font-size-20) * 1px);--btn-line-height: calc(var(--dt-font-size-20-line-height) * 1px);--spinner-size: var(--spinner-size-m);--spinner-border-width: var(--spinner-border-width-m)}.o-btn:before{content:"";position:absolute;left:50%;top:50%;translate:-50% -50%;height:var(--spinner-size);width:var(--spinner-size);display:block;background-color:transparent;border-radius:50%;border-color:var(--spinner-left-color) var(--spinner-right-color) var(--spinner-right-color) var(--spinner-left-color);border-width:var(--spinner-border-width);border-style:solid;will-change:transform;opacity:0}.o-btn[isLoading]:before{animation:rotate360 var(--spinner-animation-duration) var(--spinner-animation-timing-function) var(--spinner-animation-iteration-count);opacity:1}.o-btn[isLoading] .o-btn-text{opacity:0}
20
+ `, f = ["xsmall", "small-productive", "small-expressive", "medium", "large"], y = ["submit", "button", "reset", "menu"], x = ["primary", "secondary", "outline", "ghost", "inverse", "ghost-inverse"];
21
+ var z = Object.defineProperty, w = Object.getOwnPropertyDescriptor, s = (l, r, t, i) => {
22
+ for (var o = i > 1 ? void 0 : i ? w(r, t) : r, e = l.length - 1, n; e >= 0; e--)
23
+ (n = l[e]) && (o = (i ? n(r, t, o) : n(o)) || o);
24
+ return i && o && z(r, t, o), o;
25
25
  };
26
- const s = "pie-button";
27
- class i extends u {
26
+ const d = "pie-button";
27
+ class a extends u {
28
28
  constructor() {
29
- super(...arguments), this.size = "medium", this.type = "submit", this.variant = "primary", this.disabled = !1, this.isFullWidth = !1;
29
+ super(...arguments), this.size = "medium", this.type = "submit", this.variant = "primary", this.disabled = !1, this.isLoading = !1, this.isFullWidth = !1;
30
30
  }
31
31
  render() {
32
32
  const {
33
- type: o,
34
- disabled: a,
35
- isFullWidth: n,
36
- variant: t,
37
- size: r
33
+ type: r,
34
+ disabled: t,
35
+ isFullWidth: i,
36
+ variant: o,
37
+ size: e,
38
+ isLoading: n
38
39
  } = this;
39
40
  return m`
40
41
  <button
41
42
  class="o-btn"
42
- type=${o}
43
- variant=${t}
44
- size=${r}
45
- ?disabled=${a}
46
- ?isFullWidth=${n}>
47
- <slot></slot>
43
+ type=${r}
44
+ variant=${o}
45
+ size=${e}
46
+ ?disabled=${t}
47
+ ?isFullWidth=${i}
48
+ ?isLoading=${n}>
49
+ <span class="o-btn-text"><slot></slot></span>
48
50
  </button>`;
49
51
  }
52
+ focus() {
53
+ var r, t;
54
+ (t = (r = this.shadowRoot) == null ? void 0 : r.querySelector("button")) == null || t.focus();
55
+ }
50
56
  }
51
- i.styles = h(f);
52
- d([
57
+ a.styles = h(g);
58
+ s([
53
59
  c(),
54
- b(s, g, "medium")
55
- ], i.prototype, "size", 2);
56
- d([
60
+ b(d, f, "medium")
61
+ ], a.prototype, "size", 2);
62
+ s([
57
63
  c(),
58
- b(s, y, "submit")
59
- ], i.prototype, "type", 2);
60
- d([
64
+ b(d, y, "submit")
65
+ ], a.prototype, "type", 2);
66
+ s([
61
67
  c(),
62
- b(s, x, "primary")
63
- ], i.prototype, "variant", 2);
64
- d([
68
+ b(d, x, "primary")
69
+ ], a.prototype, "variant", 2);
70
+ s([
65
71
  c({ type: Boolean })
66
- ], i.prototype, "disabled", 2);
67
- d([
72
+ ], a.prototype, "disabled", 2);
73
+ s([
74
+ c({ type: Boolean, reflect: !0 })
75
+ ], a.prototype, "isLoading", 2);
76
+ s([
68
77
  c({ type: Boolean })
69
- ], i.prototype, "isFullWidth", 2);
70
- customElements.define(s, i);
78
+ ], a.prototype, "isFullWidth", 2);
79
+ customElements.define(d, a);
71
80
  export {
72
- i as PieButton,
73
- g as sizes,
81
+ a as PieButton,
82
+ f as sizes,
74
83
  y as types,
75
84
  x as variants
76
85
  };
@@ -1,31 +1,30 @@
1
1
  export declare const sizes: readonly ["xsmall", "small-productive", "small-expressive", "medium", "large"];
2
2
  export declare const types: readonly ["submit", "button", "reset", "menu"];
3
- export declare const variants: readonly ["primary", "secondary", "outline", "ghost"];
3
+ export declare const variants: readonly ["primary", "secondary", "outline", "ghost", "inverse", "ghost-inverse"];
4
4
  export interface ButtonProps {
5
5
  /**
6
- * (Optional) What size the button should be.
7
- * @default "medium"
6
+ * What size the button should be.
8
7
  */
9
8
  size: typeof sizes[number];
10
9
  /**
11
- * (Optional) What type attribute should be applied to the button. For example submit, button or menu.
12
- * @default "submit"
10
+ * What type attribute should be applied to the button. For example submit, button or menu.
13
11
  */
14
12
  type: typeof types[number];
15
13
  /**
16
- * (Optional) What style variant the button should be such as primary, outline or ghost.
17
- * @default "primary"
14
+ * What style variant the button should be such as primary, outline or ghost.
18
15
  */
19
16
  variant: typeof variants[number];
20
17
  /**
21
- * (Optional) When true, the button element is disabled.
22
- * @default false
18
+ * When true, the button element is disabled.
23
19
  */
24
20
  disabled: boolean;
25
21
  /**
26
- * (Optional) When true, the button element will occupy the full width of its container.
27
- * @default false
22
+ * When true, the button element will occupy the full width of its container.
28
23
  */
29
24
  isFullWidth: boolean;
25
+ /**
26
+ * When true, displays a loading indicator inside the button.
27
+ */
28
+ isLoading: boolean;
30
29
  }
31
30
  //# sourceMappingURL=defs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"defs.d.ts","sourceRoot":"","sources":["../../../src/defs.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,gFAAiF,CAAC;AACpG,eAAO,MAAM,KAAK,gDAAiD,CAAC;AACpE,eAAO,MAAM,QAAQ,uDAAwD,CAAC;AAE9E,MAAM,WAAW,WAAW;IACxB;;;OAGG;IACH,IAAI,EAAE,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3B;;;OAGG;IACH,IAAI,EAAE,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3B;;;OAGG;IACH,OAAO,EAAE,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC;IACjC;;;OAGG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,WAAW,EAAE,OAAO,CAAC;CACxB"}
1
+ {"version":3,"file":"defs.d.ts","sourceRoot":"","sources":["../../../src/defs.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,gFAAiF,CAAC;AACpG,eAAO,MAAM,KAAK,gDAAiD,CAAC;AACpE,eAAO,MAAM,QAAQ,mFAAoF,CAAC;AAE1G,MAAM,WAAW,WAAW;IACxB;;OAEG;IACH,IAAI,EAAE,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3B;;OAEG;IACH,IAAI,EAAE,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3B;;OAEG;IACH,OAAO,EAAE,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC;IACjC;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;CACtB"}
@@ -2,13 +2,15 @@ import { LitElement } from 'lit';
2
2
  import { ButtonProps, sizes, types, variants } from './defs';
3
3
  export { type ButtonProps, sizes, types, variants, };
4
4
  declare const componentSelector = "pie-button";
5
- export declare class PieButton extends LitElement {
5
+ export declare class PieButton extends LitElement implements ButtonProps {
6
6
  size: ButtonProps['size'];
7
7
  type: ButtonProps['type'];
8
8
  variant: ButtonProps['variant'];
9
9
  disabled: boolean;
10
+ isLoading: boolean;
10
11
  isFullWidth: boolean;
11
12
  render(): import("lit-html").TemplateResult<1>;
13
+ focus(): void;
12
14
  static styles: import("lit").CSSResult;
13
15
  }
14
16
  declare global {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAmB,MAAM,KAAK,CAAC;AAIlD,OAAO,EACH,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EACtC,MAAM,QAAQ,CAAC;AAGhB,OAAO,EACH,KAAK,WAAW,EAChB,KAAK,EACL,KAAK,EACL,QAAQ,GACX,CAAC;AAEF,QAAA,MAAM,iBAAiB,eAAe,CAAC;AAEvC,qBAAa,SAAU,SAAQ,UAAU;IAGjC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAY;IAIrC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAY;IAIrC,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,CAAa;IAG5C,QAAQ,UAAS;IAGjB,WAAW,UAAS;IAExB,MAAM;IAkBN,MAAM,CAAC,MAAM,0BAAqB;CACrC;AAID,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,qBAAqB;QAC3B,CAAC,iBAAiB,CAAC,EAAE,SAAS,CAAC;KAClC;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,EACH,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EACtC,MAAM,QAAQ,CAAC;AAGhB,OAAO,EACH,KAAK,WAAW,EAChB,KAAK,EACL,KAAK,EACL,QAAQ,GACX,CAAC;AAEF,QAAA,MAAM,iBAAiB,eAAe,CAAC;AAEvC,qBAAa,SAAU,SAAQ,UAAW,YAAW,WAAW;IAGrD,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAY;IAIrC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAY;IAIrC,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,CAAa;IAG5C,QAAQ,UAAS;IAGjB,SAAS,UAAS;IAGlB,WAAW,UAAS;IAE3B,MAAM;IAkBN,KAAK;IAKL,MAAM,CAAC,MAAM,0BAAqB;CACrC;AAID,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,qBAAqB;QAC3B,CAAC,iBAAiB,CAAC,EAAE,SAAS,CAAC;KAClC;CACJ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@justeattakeaway/pie-button",
3
- "version": "0.17.0",
3
+ "version": "0.19.0",
4
4
  "description": "PIE design system button built using web components",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/button.scss CHANGED
@@ -1,3 +1,9 @@
1
+ *,
2
+ *:before,
3
+ *:after {
4
+ box-sizing: border-box;
5
+ }
6
+
1
7
  // Defines button interactive states for hover and active using HSL & calc
2
8
  // Takes a color token name as an argument
3
9
  @mixin button-interactive-states($bg-color) {
@@ -10,6 +16,17 @@
10
16
  }
11
17
  }
12
18
 
19
+ // Spin animation for loading state
20
+ @keyframes rotate360 {
21
+ from {
22
+ transform: rotate(0deg);
23
+ }
24
+
25
+ to {
26
+ transform: rotate(360deg);
27
+ }
28
+ }
29
+
13
30
  // Base button styles
14
31
  .o-btn {
15
32
  // Custom Property Declarations
@@ -20,7 +37,6 @@
20
37
 
21
38
  // The base values are set to the size default, which is for the medium button size
22
39
  --btn-padding: 10px var(--dt-spacing-e);
23
- --btn-min-height: 48px;
24
40
  --btn-font-size: calc(var(--dt-font-size-20) * 1px);
25
41
  --btn-line-height: calc(var(--dt-font-size-20-line-height) * 1px);
26
42
 
@@ -29,7 +45,29 @@
29
45
  --btn-bg-color: var(--dt-color-interactive-brand);
30
46
  --btn-text-color: var(--dt-color-content-interactive-primary);
31
47
 
32
- min-block-size: var(--btn-min-block-size);
48
+ // Spinner sizes defaults - currently set for the medium button styles
49
+ --spinner-size-s: 20px;
50
+ --spinner-size-m: 24px;
51
+ --spinner-border-width-s: 2.5px;
52
+ --spinner-border-width-m: 3px;
53
+ --spinner-size: var(--spinner-size-m);
54
+ --spinner-border-width: var(--spinner-border-width-m);
55
+
56
+ // Spinner colors - currently set for the primary button styles
57
+ --spinner-base-color-h: var(--dt-color-content-interactive-primary-h);
58
+ --spinner-base-color-s: var(--dt-color-content-interactive-primary-s);
59
+ --spinner-base-color-l: var(--dt-color-content-interactive-primary-l);
60
+ --spinner-left-color-opacity: 0.35;
61
+ --spinner-left-color: hsl(var(--spinner-base-color-h), var(--spinner-base-color-s), var(--spinner-base-color-l), var(--spinner-left-color-opacity));
62
+ --spinner-right-color: hsl(var(--spinner-base-color-h), var(--spinner-base-color-s), var(--spinner-base-color-l), 1);
63
+
64
+ // Spinner animations
65
+ --spinner-animation-duration: 1.15s;
66
+ --spinner-animation-timing-function: linear;
67
+ --spinner-animation-iteration-count: infinite;
68
+
69
+ position: relative;
70
+ box-sizing: border-box;
33
71
  padding: var(--btn-padding);
34
72
  border: none;
35
73
  border-radius: var(--btn-border-radius);
@@ -102,6 +140,9 @@
102
140
  &[variant='secondary'] {
103
141
  --btn-bg-color: var(--dt-color-interactive-secondary);
104
142
  --btn-text-color: var(--dt-color-content-interactive-secondary);
143
+ --spinner-base-color-h: var(--dt-color-content-interactive-secondary-h);
144
+ --spinner-base-color-s: var(--dt-color-content-interactive-secondary-s);
145
+ --spinner-base-color-l: var(--dt-color-content-interactive-secondary-l);
105
146
 
106
147
  @include button-interactive-states('--dt-color-interactive-secondary');
107
148
  }
@@ -109,6 +150,9 @@
109
150
  &[variant='outline'] {
110
151
  --btn-bg-color: var(--dt-color-container-default);
111
152
  --btn-text-color: var(--dt-color-content-interactive-secondary);
153
+ --spinner-base-color-h: var(--dt-color-content-interactive-secondary-h);
154
+ --spinner-base-color-s: var(--dt-color-content-interactive-secondary-s);
155
+ --spinner-base-color-l: var(--dt-color-content-interactive-secondary-l);
112
156
 
113
157
  border: 1px solid var(--dt-color-border-strong);
114
158
 
@@ -118,10 +162,33 @@
118
162
  &[variant='ghost'] {
119
163
  --btn-bg-color: transparent;
120
164
  --btn-text-color: var(--dt-color-content-link);
165
+ --spinner-base-color-h: var(--dt-color-content-interactive-secondary-h);
166
+ --spinner-base-color-s: var(--dt-color-content-interactive-secondary-s);
167
+ --spinner-base-color-l: var(--dt-color-content-interactive-secondary-l);
121
168
 
122
169
  @include button-interactive-states('--dt-color-container-default');
123
170
  }
124
171
 
172
+ &[variant='inverse'] {
173
+ --btn-bg-color: var(--dt-color-interactive-inverse);
174
+ --btn-text-color: var(--dt-color-content-interactive-secondary);
175
+ --spinner-base-color-h: var(--dt-color-content-interactive-secondary-h);
176
+ --spinner-base-color-s: var(--dt-color-content-interactive-secondary-s);
177
+ --spinner-base-color-l: var(--dt-color-content-interactive-secondary-l);
178
+
179
+ @include button-interactive-states('--dt-color-interactive-inverse');
180
+ }
181
+
182
+ &[variant='ghost-inverse'] {
183
+ --btn-bg-color: transparent;
184
+ --btn-text-color: var(--dt-color-content-interactive-primary);
185
+ --spinner-base-color-h: var(--dt-color-content-interactive-primary-h);
186
+ --spinner-base-color-s: var(--dt-color-content-interactive-primary-s);
187
+ --spinner-base-color-l: var(--dt-color-content-interactive-primary-l);
188
+
189
+ @include button-interactive-states('--dt-color-container-inverse');
190
+ }
191
+
125
192
  // Additional modifiers
126
193
  &[isFullWidth] {
127
194
  inline-size: 100%;
@@ -132,8 +199,8 @@
132
199
 
133
200
  cursor: not-allowed;
134
201
 
135
- // For every variant except ghost, set the disabled background color
136
- &:not([variant='ghost']) {
202
+ // For every variant except ghost and ghost-inverse, set the disabled background color
203
+ &:not([variant='ghost'], [variant='ghost-inverse']) {
137
204
  --btn-bg-color: var(--dt-color-disabled-01) !important;
138
205
  }
139
206
 
@@ -147,18 +214,24 @@
147
214
  --btn-padding: 6px var(--dt-spacing-b);
148
215
  --btn-font-size: calc(var(--dt-font-size-14) * 1px);
149
216
  --btn-line-height: calc(var(--dt-font-size-14-line-height) * 1px);
217
+ --spinner-size: var(--spinner-size-s);
218
+ --spinner-border-width: var(--spinner-border-width-s);
150
219
  }
151
220
 
152
221
  &[size='small-expressive'] {
153
222
  --btn-padding: 6px var(--dt-spacing-d);
154
223
  --btn-font-size: calc(var(--dt-font-size-20) * 1px);
155
224
  --btn-line-height: calc(var(--dt-font-size-20-line-height) * 1px);
225
+ --spinner-size: var(--spinner-size-s);
226
+ --spinner-border-width: var(--spinner-border-width-s);
156
227
  }
157
228
 
158
229
  &[size='small-productive'] {
159
230
  --btn-padding: 8px var(--dt-spacing-d);
160
231
  --btn-font-size: calc(var(--dt-font-size-16) * 1px);
161
232
  --btn-line-height: calc(var(--dt-font-size-16-line-height) * 1px);
233
+ --spinner-size: var(--spinner-size-s);
234
+ --spinner-border-width: var(--spinner-border-width-s);
162
235
  }
163
236
 
164
237
  &[size='medium'] {
@@ -169,5 +242,39 @@
169
242
  --btn-padding: 14px var(--dt-spacing-e);
170
243
  --btn-font-size: calc(var(--dt-font-size-20) * 1px);
171
244
  --btn-line-height: calc(var(--dt-font-size-20-line-height) * 1px);
245
+ --spinner-size: var(--spinner-size-m);
246
+ --spinner-border-width: var(--spinner-border-width-m);
247
+ }
248
+
249
+ &:before {
250
+ content: '';
251
+
252
+ // Centre the spinner over the top of the button text
253
+ position: absolute;
254
+ left: 50%;
255
+ top: 50%;
256
+ translate: -50% -50%;
257
+
258
+ height: var(--spinner-size);
259
+ width: var(--spinner-size);
260
+ display: block;
261
+ background-color: transparent;
262
+ border-radius: 50%;
263
+ border-color: var(--spinner-left-color) var(--spinner-right-color) var(--spinner-right-color) var(--spinner-left-color);
264
+ border-width: var(--spinner-border-width);
265
+ border-style: solid;
266
+ will-change: transform;
267
+ opacity: 0;
268
+ }
269
+
270
+ &[isLoading] {
271
+ &:before {
272
+ animation: rotate360 var(--spinner-animation-duration) var(--spinner-animation-timing-function) var(--spinner-animation-iteration-count);
273
+ opacity: 1;
274
+ }
275
+
276
+ & .o-btn-text {
277
+ opacity: 0;
278
+ }
172
279
  }
173
280
  }
package/src/defs.ts CHANGED
@@ -1,31 +1,30 @@
1
1
  export const sizes = ['xsmall', 'small-productive', 'small-expressive', 'medium', 'large'] as const;
2
2
  export const types = ['submit', 'button', 'reset', 'menu'] as const;
3
- export const variants = ['primary', 'secondary', 'outline', 'ghost'] as const;
3
+ export const variants = ['primary', 'secondary', 'outline', 'ghost', 'inverse', 'ghost-inverse'] as const;
4
4
 
5
5
  export interface ButtonProps {
6
6
  /**
7
- * (Optional) What size the button should be.
8
- * @default "medium"
7
+ * What size the button should be.
9
8
  */
10
9
  size: typeof sizes[number];
11
10
  /**
12
- * (Optional) What type attribute should be applied to the button. For example submit, button or menu.
13
- * @default "submit"
11
+ * What type attribute should be applied to the button. For example submit, button or menu.
14
12
  */
15
13
  type: typeof types[number];
16
14
  /**
17
- * (Optional) What style variant the button should be such as primary, outline or ghost.
18
- * @default "primary"
15
+ * What style variant the button should be such as primary, outline or ghost.
19
16
  */
20
17
  variant: typeof variants[number];
21
18
  /**
22
- * (Optional) When true, the button element is disabled.
23
- * @default false
19
+ * When true, the button element is disabled.
24
20
  */
25
21
  disabled: boolean;
26
22
  /**
27
- * (Optional) When true, the button element will occupy the full width of its container.
28
- * @default false
23
+ * When true, the button element will occupy the full width of its container.
29
24
  */
30
25
  isFullWidth: boolean;
26
+ /**
27
+ * When true, displays a loading indicator inside the button.
28
+ */
29
+ isLoading: boolean;
31
30
  }
package/src/index.ts CHANGED
@@ -16,28 +16,31 @@ export {
16
16
 
17
17
  const componentSelector = 'pie-button';
18
18
 
19
- export class PieButton extends LitElement {
19
+ export class PieButton extends LitElement implements ButtonProps {
20
20
  @property()
21
21
  @validPropertyValues(componentSelector, sizes, 'medium')
22
- size: ButtonProps['size'] = 'medium';
22
+ public size: ButtonProps['size'] = 'medium';
23
23
 
24
24
  @property()
25
25
  @validPropertyValues(componentSelector, types, 'submit')
26
- type: ButtonProps['type'] = 'submit';
26
+ public type: ButtonProps['type'] = 'submit';
27
27
 
28
28
  @property()
29
29
  @validPropertyValues(componentSelector, variants, 'primary')
30
- variant: ButtonProps['variant'] = 'primary';
30
+ public variant: ButtonProps['variant'] = 'primary';
31
31
 
32
32
  @property({ type: Boolean })
33
- disabled = false;
33
+ public disabled = false;
34
+
35
+ @property({ type: Boolean, reflect: true })
36
+ public isLoading = false;
34
37
 
35
38
  @property({ type: Boolean })
36
- isFullWidth = false;
39
+ public isFullWidth = false;
37
40
 
38
41
  render () {
39
42
  const {
40
- type, disabled, isFullWidth, variant, size,
43
+ type, disabled, isFullWidth, variant, size, isLoading,
41
44
  } = this;
42
45
 
43
46
  return html`
@@ -47,11 +50,16 @@ export class PieButton extends LitElement {
47
50
  variant=${variant}
48
51
  size=${size}
49
52
  ?disabled=${disabled}
50
- ?isFullWidth=${isFullWidth}>
51
- <slot></slot>
53
+ ?isFullWidth=${isFullWidth}
54
+ ?isLoading=${isLoading}>
55
+ <span class="o-btn-text"><slot></slot></span>
52
56
  </button>`;
53
57
  }
54
58
 
59
+ focus () {
60
+ this.shadowRoot?.querySelector('button')?.focus();
61
+ }
62
+
55
63
  // Renders a `CSSResult` generated from SCSS by Vite
56
64
  static styles = unsafeCSS(styles);
57
65
  }
@@ -21,10 +21,11 @@ const props: PropObject = {
21
21
  type: 'button', // Changing the type does not affect the appearance of the button
22
22
  isFullWidth: [true, false],
23
23
  disabled: [true, false],
24
+ isLoading: [true, false],
24
25
  };
25
26
 
26
27
  // Renders a <pie-button> HTML string with the given prop values
27
- const renderTestPieButton = (propVals: WebComponentPropValues) => `<pie-button variant="${propVals.variant}" size="${propVals.size}" type="${propVals.type}" ${propVals.isFullWidth ? 'isFullWidth' : ''} ${propVals.disabled ? 'disabled' : ''}>Hello world</pie-button>`;
28
+ const renderTestPieButton = (propVals: WebComponentPropValues) => `<pie-button variant="${propVals.variant}" size="${propVals.size}" type="${propVals.type}" ${propVals.isFullWidth ? 'isFullWidth' : ''} ${propVals.disabled ? 'disabled' : ''} ${propVals.isLoading ? 'isLoading' : ''}>Hello world</pie-button>`;
28
29
 
29
30
  const componentPropsMatrix : WebComponentPropValues[] = getAllPropCombinations(props);
30
31
  const componentPropsMatrixByVariant: Record<string, WebComponentPropValues[]> = splitCombinationsByPropertyValue(componentPropsMatrix, 'variant');
@@ -48,12 +49,13 @@ test.beforeEach(async ({ page, mount }) => {
48
49
  componentVariants.forEach((variant) => test(`Render all prop variations for Variant: ${variant}`, async ({ page, mount }) => {
49
50
  await Promise.all(componentPropsMatrixByVariant[variant].map(async (combo: WebComponentPropValues) => {
50
51
  const testComponent: WebComponentTestInput = createTestWebComponent(combo, renderTestPieButton);
51
- const propKeyValues = `size: ${testComponent.propValues.size}, isFullWidth: ${testComponent.propValues.isFullWidth}, disabled: ${testComponent.propValues.disabled}`;
52
+ const propKeyValues = `size: ${testComponent.propValues.size}, isFullWidth: ${testComponent.propValues.isFullWidth}, disabled: ${testComponent.propValues.disabled}, isLoading: ${testComponent.propValues.isLoading}`;
53
+ const darkMode = variant === 'inverse' || variant === 'ghost-inverse';
52
54
 
53
55
  await mount(
54
56
  WebComponentTestWrapper,
55
57
  {
56
- props: { propKeyValues },
58
+ props: { propKeyValues, darkMode },
57
59
  slots: {
58
60
  component: testComponent.renderedString.trim(),
59
61
  },