@justeattakeaway/pie-button 0.26.0 → 0.28.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.
package/README.md CHANGED
@@ -83,6 +83,7 @@ import { PieButton } from '@justeattakeaway/pie-button/dist/react';
83
83
  | disabled | `Boolean` | `false` | If `true`, disables the button. |
84
84
  | isFullWidth | `Boolean` | `false` | If `true`, sets the button width to 100% of its container. |
85
85
  | isLoading | `Boolean` | `false` | If `true`, displays a loading indicator inside the button. |
86
+ | iconPlacement | `String` | `leading` | Icon placements of the icon slot, if provided, one of `iconPlacements` - `leading`, `trailing` |
86
87
 
87
88
  In your markup or JSX, you can then use these to set the properties for the `pie-button` component:
88
89
 
@@ -99,22 +100,20 @@ In your markup or JSX, you can then use these to set the properties for the `pie
99
100
  | Slot | Description |
100
101
  |---------------|------------------------------------------------------------------------------------------------------------------------------------|
101
102
  | Default slot | The default slot is used to pass text into the button component. |
102
- | icon-leading | Used to pass in a leading icon. We recommend using `pie-icons-webc` for defining this icon, but this can also accept an SVG icon. |
103
- | icon-trailing | Used to pass in a trailing icon. We recommend using `pie-icons-webc` for defining this icon, but this can also accept an SVG icon. |
103
+ | icon | Used to pass in an icon to the button component. The icon placement can be controlled via the `iconPlacement` prop and we recommend using `pie-icons-webc` for defining this icon, but this can also accept an SVG icon. |
104
104
 
105
- ### Using `pie-icons-webc` with `pie-button`icon slots
105
+ ### Using `pie-icons-webc` with `pie-button` icon slot
106
106
 
107
- We recommend using `pie-icons-webc` when using the `icon-leading` and `icon-trailing` slots. Here is an example of how you would do this:
107
+ We recommend using `pie-icons-webc` when using the `icon` slot. Here is an example of how you would do this:
108
108
 
109
109
  ```html
110
110
  <!--
111
- Note that pie-button and the icons that you want to use will need to be imported as components into your application.
111
+ Note that pie-button and the icon that you want to use will need to be imported as components into your application.
112
112
  See the `pie-icons-webc` README for more info on importing these icons.
113
113
  -->
114
114
  <pie-button>
115
- <icon-plus-circle slot="icon-leading"></icon-plus-circle>
115
+ <icon-plus-circle slot="icon"></icon-plus-circle>
116
116
  Search
117
- <icon-chevron-down slot="icon-trailing"></icon-chevron-down>
118
117
  </pie-button>
119
118
  ```
120
119
 
package/dist/index.d.ts CHANGED
@@ -15,6 +15,10 @@ export declare interface ButtonProps {
15
15
  * What style variant the button should be such as primary, outline or ghost.
16
16
  */
17
17
  variant: Variant;
18
+ /**
19
+ * The placement of the icon slot, if provided, such as leading or trailing
20
+ */
21
+ iconPlacement?: typeof iconPlacements[number];
18
22
  /**
19
23
  * When true, the button element is disabled.
20
24
  */
@@ -29,15 +33,17 @@ export declare interface ButtonProps {
29
33
  isLoading: boolean;
30
34
  }
31
35
 
36
+ export declare const iconPlacements: readonly ["leading", "trailing"];
37
+
32
38
  /**
33
- * @slot icon-leading - Leading icon
34
- * @slot icon-trailing - Trailing icon
39
+ * @slot icon - The icon slot
35
40
  * @slot - Default slot
36
41
  */
37
42
  export declare class PieButton extends LitElement implements ButtonProps {
38
43
  size: ButtonProps['size'];
39
44
  type: ButtonProps['type'];
40
45
  variant: ButtonProps['variant'];
46
+ iconPlacement: ButtonProps['iconPlacement'];
41
47
  disabled: boolean;
42
48
  isLoading: boolean;
43
49
  isFullWidth: boolean;
package/dist/index.js CHANGED
@@ -1,23 +1,23 @@
1
- import { unsafeCSS as h, LitElement as m, html as f } from "lit";
1
+ import { unsafeCSS as g, LitElement as f, html as p, nothing as h } from "lit";
2
2
  import { property as c } from "lit/decorators.js";
3
3
  import "lit/decorators/property.js";
4
- const b = (l, r, t) => function(o, e) {
4
+ const b = (d, r, t) => function(o, e) {
5
5
  const i = `#${e}`;
6
6
  Object.defineProperty(o, e, {
7
7
  get() {
8
8
  return this[i];
9
9
  },
10
- set(v) {
11
- const p = this[i];
12
- r.includes(v) ? this[i] = v : (console.error(
13
- `<${l}> Invalid value "${v}" provided for property "${e}".`,
10
+ set(l) {
11
+ const m = this[i];
12
+ r.includes(l) ? this[i] = l : (console.error(
13
+ `<${d}> Invalid value "${l}" provided for property "${e}".`,
14
14
  `Must be one of: ${r.join(" | ")}.`,
15
15
  `Falling back to default value: "${t}"`
16
- ), this[i] = t), this.requestUpdate(e, p);
16
+ ), this[i] = t), this.requestUpdate(e, m);
17
17
  }
18
18
  });
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);--btn-icon-size: 24px;--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;display:flex;gap:var(--dt-spacing-b);align-items:center;justify-content:center;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;inline-size:var(--btn-inline-size);text-rendering:optimizelegibility;-webkit-font-smoothing:antialiased;-moz-font-smoothing:antialiased}.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){--hover-modifier: calc(-1 * var(--dt-color-hover-01));--btn-bg-color: hsl(var(--dt-color-interactive-brand-h), var(--dt-color-interactive-brand-s), calc(var(--dt-color-interactive-brand-l) + var(--hover-modifier)))}.o-btn[variant=primary]:active:not(:disabled),.o-btn[variant=primary][isLoading]:not(:disabled){--active-modifier: calc(-1 * var(--dt-color-active-01));--btn-bg-color: hsl(var(--dt-color-interactive-brand-h), var(--dt-color-interactive-brand-s), calc(var(--dt-color-interactive-brand-l) + var(--active-modifier)))}.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){--hover-modifier: calc(-1 * var(--dt-color-hover-01));--btn-bg-color: hsl(var(--dt-color-interactive-primary-h), var(--dt-color-interactive-primary-s), calc(var(--dt-color-interactive-primary-l) + var(--hover-modifier)))}.o-btn[variant=primary][size=xsmall]:active:not(:disabled),.o-btn[variant=primary][size=xsmall][isLoading]:not(:disabled),.o-btn[variant=primary][size=small-productive]:active:not(:disabled),.o-btn[variant=primary][size=small-productive][isLoading]:not(:disabled){--active-modifier: calc(-1 * var(--dt-color-active-01));--btn-bg-color: hsl(var(--dt-color-interactive-primary-h), var(--dt-color-interactive-primary-s), calc(var(--dt-color-interactive-primary-l) + var(--active-modifier)))}.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){--hover-modifier: calc(-1 * var(--dt-color-hover-01));--btn-bg-color: hsl(var(--dt-color-interactive-secondary-h), var(--dt-color-interactive-secondary-s), calc(var(--dt-color-interactive-secondary-l) + var(--hover-modifier)))}.o-btn[variant=secondary]:active:not(:disabled),.o-btn[variant=secondary][isLoading]:not(:disabled){--active-modifier: calc(-1 * var(--dt-color-active-01));--btn-bg-color: hsl(var(--dt-color-interactive-secondary-h), var(--dt-color-interactive-secondary-s), calc(var(--dt-color-interactive-secondary-l) + var(--active-modifier)))}.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);--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=outline]:hover:not(:disabled){--hover-modifier: calc(-1 * var(--dt-color-hover-01));--btn-bg-color: hsl(var(--dt-color-container-default-h), var(--dt-color-container-default-s), calc(var(--dt-color-container-default-l) + var(--hover-modifier)))}.o-btn[variant=outline]:active:not(:disabled),.o-btn[variant=outline][isLoading]:not(:disabled){--active-modifier: calc(-1 * var(--dt-color-active-01));--btn-bg-color: hsl(var(--dt-color-container-default-h), var(--dt-color-container-default-s), calc(var(--dt-color-container-default-l) + var(--active-modifier)))}.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){--hover-modifier: calc(-1 * var(--dt-color-hover-01));--btn-bg-color: hsl(var(--dt-color-container-default-h), var(--dt-color-container-default-s), calc(var(--dt-color-container-default-l) + var(--hover-modifier)))}.o-btn[variant=ghost]:active:not(:disabled),.o-btn[variant=ghost][isLoading]:not(:disabled){--active-modifier: calc(-1 * var(--dt-color-active-01));--btn-bg-color: hsl(var(--dt-color-container-default-h), var(--dt-color-container-default-s), calc(var(--dt-color-container-default-l) + var(--active-modifier)))}.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){--hover-modifier: calc(-1 * var(--dt-color-hover-01));--btn-bg-color: hsl(var(--dt-color-interactive-inverse-h), var(--dt-color-interactive-inverse-s), calc(var(--dt-color-interactive-inverse-l) + var(--hover-modifier)))}.o-btn[variant=inverse]:active:not(:disabled),.o-btn[variant=inverse][isLoading]:not(:disabled){--active-modifier: calc(-1 * var(--dt-color-active-01));--btn-bg-color: hsl(var(--dt-color-interactive-inverse-h), var(--dt-color-interactive-inverse-s), calc(var(--dt-color-interactive-inverse-l) + var(--active-modifier)))}.o-btn[variant=ghost-inverse],.o-btn[variant=outline-inverse]{--btn-bg-color: transparent;--btn-text-color: var(--dt-color-content-interactive-primary)}.o-btn[variant=ghost-inverse]:hover:not(:disabled),.o-btn[variant=outline-inverse]:hover:not(:disabled){--hover-modifier: calc(-1 * var(--dt-color-hover-01));--hover-modifier: var(--dt-color-hover-02);--btn-bg-color: hsl(var(--dt-color-container-inverse-h), var(--dt-color-container-inverse-s), calc(var(--dt-color-container-inverse-l) + var(--hover-modifier)))}.o-btn[variant=ghost-inverse]:active:not(:disabled),.o-btn[variant=ghost-inverse][isLoading]:not(:disabled),.o-btn[variant=outline-inverse]:active:not(:disabled),.o-btn[variant=outline-inverse][isLoading]:not(:disabled){--active-modifier: calc(-1 * var(--dt-color-active-01));--active-modifier: var(--dt-color-active-02);--btn-bg-color: hsl(var(--dt-color-container-inverse-h), var(--dt-color-container-inverse-s), calc(var(--dt-color-container-inverse-l) + var(--active-modifier)))}.o-btn[variant=outline-inverse]{border:1px solid var(--dt-color-border-strong)}.o-btn[variant=destructive]{--btn-bg-color: var(--dt-color-support-error)}.o-btn[variant=destructive]:hover:not(:disabled){--hover-modifier: calc(-1 * var(--dt-color-hover-01));--btn-bg-color: hsl(var(--dt-color-support-error-h), var(--dt-color-support-error-s), calc(var(--dt-color-support-error-l) + var(--hover-modifier)))}.o-btn[variant=destructive]:active:not(:disabled),.o-btn[variant=destructive][isLoading]:not(:disabled){--active-modifier: calc(-1 * var(--dt-color-active-01));--btn-bg-color: hsl(var(--dt-color-support-error-h), var(--dt-color-support-error-s), calc(var(--dt-color-support-error-l) + var(--active-modifier)))}.o-btn[variant=destructive-ghost]{--btn-bg-color: transparent;--btn-text-color: var(--dt-color-content-interactive-error);--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=destructive-ghost]:hover:not(:disabled){--hover-modifier: calc(-1 * var(--dt-color-hover-01));--btn-bg-color: hsl(var(--dt-color-container-default-h), var(--dt-color-container-default-s), calc(var(--dt-color-container-default-l) + var(--hover-modifier)))}.o-btn[variant=destructive-ghost]:active:not(:disabled),.o-btn[variant=destructive-ghost][isLoading]:not(:disabled){--active-modifier: calc(-1 * var(--dt-color-active-01));--btn-bg-color: hsl(var(--dt-color-container-default-h), var(--dt-color-container-default-s), calc(var(--dt-color-container-default-l) + var(--active-modifier)))}.o-btn[isFullWidth]{--btn-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],[variant=destructive-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);--btn-icon-size: 16px;--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);--btn-icon-size: 20px;--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);--btn-icon-size: 20px;--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 .o-btn-text{flex-grow:1}.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}::slotted(svg){height:var(--btn-icon-size);width:var(--btn-icon-size)}
20
- `, u = ["xsmall", "small-productive", "small-expressive", "medium", "large"], y = ["submit", "button", "reset", "menu"], x = [
19
+ }, u = `*,*: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);--btn-icon-size: 24px;--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;display:flex;gap:var(--dt-spacing-b);align-items:center;justify-content:center;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;inline-size:var(--btn-inline-size);text-rendering:optimizelegibility;-webkit-font-smoothing:antialiased;-moz-font-smoothing:antialiased}.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){--hover-modifier: calc(-1 * var(--dt-color-hover-01));--btn-bg-color: hsl(var(--dt-color-interactive-brand-h), var(--dt-color-interactive-brand-s), calc(var(--dt-color-interactive-brand-l) + var(--hover-modifier)))}.o-btn[variant=primary]:active:not(:disabled),.o-btn[variant=primary][isLoading]:not(:disabled){--active-modifier: calc(-1 * var(--dt-color-active-01));--btn-bg-color: hsl(var(--dt-color-interactive-brand-h), var(--dt-color-interactive-brand-s), calc(var(--dt-color-interactive-brand-l) + var(--active-modifier)))}.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){--hover-modifier: calc(-1 * var(--dt-color-hover-01));--btn-bg-color: hsl(var(--dt-color-interactive-primary-h), var(--dt-color-interactive-primary-s), calc(var(--dt-color-interactive-primary-l) + var(--hover-modifier)))}.o-btn[variant=primary][size=xsmall]:active:not(:disabled),.o-btn[variant=primary][size=xsmall][isLoading]:not(:disabled),.o-btn[variant=primary][size=small-productive]:active:not(:disabled),.o-btn[variant=primary][size=small-productive][isLoading]:not(:disabled){--active-modifier: calc(-1 * var(--dt-color-active-01));--btn-bg-color: hsl(var(--dt-color-interactive-primary-h), var(--dt-color-interactive-primary-s), calc(var(--dt-color-interactive-primary-l) + var(--active-modifier)))}.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){--hover-modifier: calc(-1 * var(--dt-color-hover-01));--btn-bg-color: hsl(var(--dt-color-interactive-secondary-h), var(--dt-color-interactive-secondary-s), calc(var(--dt-color-interactive-secondary-l) + var(--hover-modifier)))}.o-btn[variant=secondary]:active:not(:disabled),.o-btn[variant=secondary][isLoading]:not(:disabled){--active-modifier: calc(-1 * var(--dt-color-active-01));--btn-bg-color: hsl(var(--dt-color-interactive-secondary-h), var(--dt-color-interactive-secondary-s), calc(var(--dt-color-interactive-secondary-l) + var(--active-modifier)))}.o-btn[variant=outline]{--btn-bg-color: transparent;--btn-text-color: var(--dt-color-content-interactive-secondary);border:1px solid var(--dt-color-border-strong);--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=outline]:hover:not(:disabled){--hover-modifier: calc(-1 * var(--dt-color-hover-01));--hover-modifier: var(--dt-color-hover-01);--btn-bg-color: hsl(var(--dt-color-black-h), var(--dt-color-black-s), var(--dt-color-black-l), var(--hover-modifier))}.o-btn[variant=outline]:active:not(:disabled),.o-btn[variant=outline][isLoading]:not(:disabled){--active-modifier: calc(-1 * var(--dt-color-active-01));--active-modifier: var(--dt-color-active-01);--btn-bg-color: hsl(var(--dt-color-black-h), var(--dt-color-black-s), var(--dt-color-black-l), var(--active-modifier))}.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){--hover-modifier: calc(-1 * var(--dt-color-hover-01));--hover-modifier: var(--dt-color-hover-01);--btn-bg-color: hsl(var(--dt-color-black-h), var(--dt-color-black-s), var(--dt-color-black-l), var(--hover-modifier))}.o-btn[variant=ghost]:active:not(:disabled),.o-btn[variant=ghost][isLoading]:not(:disabled){--active-modifier: calc(-1 * var(--dt-color-active-01));--active-modifier: var(--dt-color-active-01);--btn-bg-color: hsl(var(--dt-color-black-h), var(--dt-color-black-s), var(--dt-color-black-l), var(--active-modifier))}.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){--hover-modifier: calc(-1 * var(--dt-color-hover-01));--btn-bg-color: hsl(var(--dt-color-interactive-inverse-h), var(--dt-color-interactive-inverse-s), calc(var(--dt-color-interactive-inverse-l) + var(--hover-modifier)))}.o-btn[variant=inverse]:active:not(:disabled),.o-btn[variant=inverse][isLoading]:not(:disabled){--active-modifier: calc(-1 * var(--dt-color-active-01));--btn-bg-color: hsl(var(--dt-color-interactive-inverse-h), var(--dt-color-interactive-inverse-s), calc(var(--dt-color-interactive-inverse-l) + var(--active-modifier)))}.o-btn[variant=ghost-inverse],.o-btn[variant=outline-inverse]{--btn-bg-color: transparent;--btn-text-color: var(--dt-color-content-interactive-primary)}.o-btn[variant=ghost-inverse]:hover:not(:disabled),.o-btn[variant=outline-inverse]:hover:not(:disabled){--hover-modifier: calc(-1 * var(--dt-color-hover-01));--hover-modifier: var(--dt-color-hover-01);--btn-bg-color: hsl(var(--dt-color-container-default-h), var(--dt-color-container-default-s), var(--dt-color-container-default-l), var(--hover-modifier))}.o-btn[variant=ghost-inverse]:active:not(:disabled),.o-btn[variant=ghost-inverse][isLoading]:not(:disabled),.o-btn[variant=outline-inverse]:active:not(:disabled),.o-btn[variant=outline-inverse][isLoading]:not(:disabled){--active-modifier: calc(-1 * var(--dt-color-active-01));--active-modifier: var(--dt-color-active-01);--btn-bg-color: hsl(var(--dt-color-container-default-h), var(--dt-color-container-default-s), var(--dt-color-container-default-l), var(--active-modifier))}.o-btn[variant=outline-inverse]{border:1px solid var(--dt-color-border-strong)}.o-btn[variant=destructive]{--btn-bg-color: var(--dt-color-support-error)}.o-btn[variant=destructive]:hover:not(:disabled){--hover-modifier: calc(-1 * var(--dt-color-hover-01));--btn-bg-color: hsl(var(--dt-color-support-error-h), var(--dt-color-support-error-s), calc(var(--dt-color-support-error-l) + var(--hover-modifier)))}.o-btn[variant=destructive]:active:not(:disabled),.o-btn[variant=destructive][isLoading]:not(:disabled){--active-modifier: calc(-1 * var(--dt-color-active-01));--btn-bg-color: hsl(var(--dt-color-support-error-h), var(--dt-color-support-error-s), calc(var(--dt-color-support-error-l) + var(--active-modifier)))}.o-btn[variant=destructive-ghost]{--btn-bg-color: transparent;--btn-text-color: var(--dt-color-content-interactive-error);--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=destructive-ghost]:hover:not(:disabled){--hover-modifier: calc(-1 * var(--dt-color-hover-01));--hover-modifier: var(--dt-color-hover-01);--btn-bg-color: hsl(var(--dt-color-black-h), var(--dt-color-black-s), var(--dt-color-black-l), var(--hover-modifier))}.o-btn[variant=destructive-ghost]:active:not(:disabled),.o-btn[variant=destructive-ghost][isLoading]:not(:disabled){--active-modifier: calc(-1 * var(--dt-color-active-01));--active-modifier: var(--dt-color-active-01);--btn-bg-color: hsl(var(--dt-color-black-h), var(--dt-color-black-s), var(--dt-color-black-l), var(--active-modifier))}.o-btn[isFullWidth]{--btn-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],[variant=destructive-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);--btn-icon-size: 16px;--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);--btn-icon-size: 20px;--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);--btn-icon-size: 20px;--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[isLoading]: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;animation:rotate360 var(--spinner-animation-duration) var(--spinner-animation-timing-function) var(--spinner-animation-iteration-count)}.o-btn[isLoading]>*{visibility:hidden}::slotted(svg){height:var(--btn-icon-size);width:var(--btn-icon-size)}
20
+ `, y = ["xsmall", "small-productive", "small-expressive", "medium", "large"], z = ["submit", "button", "reset", "menu"], x = [
21
21
  "primary",
22
22
  "secondary",
23
23
  "outline",
@@ -27,16 +27,16 @@ const b = (l, r, t) => function(o, e) {
27
27
  "ghost-inverse",
28
28
  "destructive",
29
29
  "destructive-ghost"
30
- ];
31
- var z = Object.defineProperty, w = Object.getOwnPropertyDescriptor, s = (l, r, t, a) => {
32
- for (var o = a > 1 ? void 0 : a ? w(r, t) : r, e = l.length - 1, i; e >= 0; e--)
33
- (i = l[e]) && (o = (a ? i(r, t, o) : i(o)) || o);
34
- return a && o && z(r, t, o), o;
30
+ ], w = ["leading", "trailing"];
31
+ var k = Object.defineProperty, L = Object.getOwnPropertyDescriptor, s = (d, r, t, a) => {
32
+ for (var o = a > 1 ? void 0 : a ? L(r, t) : r, e = d.length - 1, i; e >= 0; e--)
33
+ (i = d[e]) && (o = (a ? i(r, t, o) : i(o)) || o);
34
+ return a && o && k(r, t, o), o;
35
35
  };
36
- const d = "pie-button";
37
- class n extends m {
36
+ const v = "pie-button";
37
+ class n extends f {
38
38
  constructor() {
39
- super(...arguments), this.size = "medium", this.type = "submit", this.variant = "primary", this.disabled = !1, this.isLoading = !1, this.isFullWidth = !1;
39
+ super(...arguments), this.size = "medium", this.type = "submit", this.variant = "primary", this.iconPlacement = "leading", this.disabled = !1, this.isLoading = !1, this.isFullWidth = !1;
40
40
  }
41
41
  render() {
42
42
  const {
@@ -45,9 +45,10 @@ class n extends m {
45
45
  isFullWidth: a,
46
46
  variant: o,
47
47
  size: e,
48
- isLoading: i
48
+ isLoading: i,
49
+ iconPlacement: l
49
50
  } = this;
50
- return f`
51
+ return p`
51
52
  <button
52
53
  class="o-btn"
53
54
  type=${r}
@@ -56,9 +57,9 @@ class n extends m {
56
57
  ?disabled=${t}
57
58
  ?isFullWidth=${a}
58
59
  ?isLoading=${i}>
59
- <slot name="icon-leading"></slot>
60
- <span class="o-btn-text"><slot></slot></span>
61
- <slot name="icon-trailing"></slot>
60
+ ${l === "leading" ? p`<slot name="icon"></slot>` : h}
61
+ <slot></slot>
62
+ ${l === "trailing" ? p`<slot name="icon"></slot>` : h}
62
63
  </button>`;
63
64
  }
64
65
  focus() {
@@ -66,19 +67,23 @@ class n extends m {
66
67
  (t = (r = this.shadowRoot) == null ? void 0 : r.querySelector("button")) == null || t.focus();
67
68
  }
68
69
  }
69
- n.styles = h(g);
70
+ n.styles = g(u);
70
71
  s([
71
72
  c(),
72
- b(d, u, "medium")
73
+ b(v, y, "medium")
73
74
  ], n.prototype, "size", 2);
74
75
  s([
75
76
  c(),
76
- b(d, y, "submit")
77
+ b(v, z, "submit")
77
78
  ], n.prototype, "type", 2);
78
79
  s([
79
80
  c(),
80
- b(d, x, "primary")
81
+ b(v, x, "primary")
81
82
  ], n.prototype, "variant", 2);
83
+ s([
84
+ c({ type: String }),
85
+ b(v, w, "leading")
86
+ ], n.prototype, "iconPlacement", 2);
82
87
  s([
83
88
  c({ type: Boolean })
84
89
  ], n.prototype, "disabled", 2);
@@ -88,10 +93,11 @@ s([
88
93
  s([
89
94
  c({ type: Boolean })
90
95
  ], n.prototype, "isFullWidth", 2);
91
- customElements.define(d, n);
96
+ customElements.define(v, n);
92
97
  export {
93
98
  n as PieButton,
94
- u as sizes,
95
- y as types,
99
+ w as iconPlacements,
100
+ y as sizes,
101
+ z as types,
96
102
  x as variants
97
103
  };
package/dist/react.d.ts CHANGED
@@ -16,6 +16,10 @@ export declare interface ButtonProps {
16
16
  * What style variant the button should be such as primary, outline or ghost.
17
17
  */
18
18
  variant: Variant;
19
+ /**
20
+ * The placement of the icon slot, if provided, such as leading or trailing
21
+ */
22
+ iconPlacement?: typeof iconPlacements[number];
19
23
  /**
20
24
  * When true, the button element is disabled.
21
25
  */
@@ -30,17 +34,19 @@ export declare interface ButtonProps {
30
34
  isLoading: boolean;
31
35
  }
32
36
 
37
+ export declare const iconPlacements: readonly ["leading", "trailing"];
38
+
33
39
  export declare const PieButton: ReactWebComponent<PieButton_2, {}>;
34
40
 
35
41
  /**
36
- * @slot icon-leading - Leading icon
37
- * @slot icon-trailing - Trailing icon
42
+ * @slot icon - The icon slot
38
43
  * @slot - Default slot
39
44
  */
40
45
  declare class PieButton_2 extends LitElement implements ButtonProps {
41
46
  size: ButtonProps['size'];
42
47
  type: ButtonProps['type'];
43
48
  variant: ButtonProps['variant'];
49
+ iconPlacement: ButtonProps['iconPlacement'];
44
50
  disabled: boolean;
45
51
  isLoading: boolean;
46
52
  isFullWidth: boolean;
package/dist/react.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as g from "react";
2
- import { PieButton as b } from "./index.js";
3
- import { sizes as D, types as G, variants as O } from "./index.js";
2
+ import { PieButton as P } from "./index.js";
3
+ import { iconPlacements as D, sizes as G, types as O, variants as S } from "./index.js";
4
4
  import "lit";
5
5
  import "lit/decorators.js";
6
6
  import "lit/decorators/property.js";
@@ -9,23 +9,23 @@ import "lit/decorators/property.js";
9
9
  * Copyright 2018 Google LLC
10
10
  * SPDX-License-Identifier: BSD-3-Clause
11
11
  */
12
- const B = /* @__PURE__ */ new Set(["children", "localName", "ref", "style", "className"]), E = /* @__PURE__ */ new WeakMap(), M = (p, r, d, m, u) => {
13
- const i = u == null ? void 0 : u[r];
14
- i === void 0 || d === m ? d == null && r in HTMLElement.prototype ? p.removeAttribute(r) : p[r] = d : ((s, t, h) => {
12
+ const b = /* @__PURE__ */ new Set(["children", "localName", "ref", "style", "className"]), E = /* @__PURE__ */ new WeakMap(), B = (m, l, p, d, u) => {
13
+ const i = u == null ? void 0 : u[l];
14
+ i === void 0 || p === d ? p == null && l in HTMLElement.prototype ? m.removeAttribute(l) : m[l] = p : ((s, t, h) => {
15
15
  let o = E.get(s);
16
16
  o === void 0 && E.set(s, o = /* @__PURE__ */ new Map());
17
17
  let a = o.get(t);
18
18
  h !== void 0 ? a === void 0 ? (o.set(t, a = { handleEvent: h }), s.addEventListener(t, a)) : a.handleEvent = h : a !== void 0 && (o.delete(t), s.removeEventListener(t, a));
19
- })(p, i, d);
19
+ })(m, i, p);
20
20
  };
21
- function P(p = window.React, r, d, m, u) {
21
+ function M(m = window.React, l, p, d, u) {
22
22
  let i, s, t;
23
- if (r === void 0) {
24
- const l = p;
25
- ({ tagName: s, elementClass: t, events: m, displayName: u } = l), i = l.react;
23
+ if (l === void 0) {
24
+ const r = m;
25
+ ({ tagName: s, elementClass: t, events: d, displayName: u } = r), i = r.react;
26
26
  } else
27
- i = p, t = d, s = r;
28
- const h = i.Component, o = i.createElement, a = new Set(Object.keys(m ?? {}));
27
+ i = m, t = p, s = l;
28
+ const h = i.Component, o = i.createElement, a = new Set(Object.keys(d ?? {}));
29
29
  class f extends h {
30
30
  constructor() {
31
31
  super(...arguments), this.o = null;
@@ -33,7 +33,7 @@ function P(p = window.React, r, d, m, u) {
33
33
  t(e) {
34
34
  if (this.o !== null)
35
35
  for (const v in this.i)
36
- M(this.o, v, this.props[v], e ? e[v] : void 0, m);
36
+ B(this.o, v, this.props[v], e ? e[v] : void 0, d);
37
37
  }
38
38
  componentDidMount() {
39
39
  this.t();
@@ -50,24 +50,25 @@ function P(p = window.React, r, d, m, u) {
50
50
  }), this.i = {};
51
51
  const y = { ref: this.u };
52
52
  for (const [n, c] of Object.entries(v))
53
- B.has(n) ? y[n === "className" ? "class" : n] = c : a.has(n) || n in t.prototype ? this.i[n] = c : y[n] = c;
53
+ b.has(n) ? y[n === "className" ? "class" : n] = c : a.has(n) || n in t.prototype ? this.i[n] = c : y[n] = c;
54
54
  return o(s, y);
55
55
  }
56
56
  }
57
57
  f.displayName = u ?? t.name;
58
- const N = i.forwardRef((l, e) => o(f, { ...l, _$Gl: e }, l == null ? void 0 : l.children));
58
+ const N = i.forwardRef((r, e) => o(f, { ...r, _$Gl: e }, r == null ? void 0 : r.children));
59
59
  return N.displayName = f.displayName, N;
60
60
  }
61
- const $ = P({
61
+ const $ = M({
62
62
  displayName: "PieButton",
63
- elementClass: b,
63
+ elementClass: P,
64
64
  react: g,
65
65
  tagName: "pie-button",
66
66
  events: {}
67
67
  });
68
68
  export {
69
69
  $ as PieButton,
70
- D as sizes,
71
- G as types,
72
- O as variants
70
+ D as iconPlacements,
71
+ G as sizes,
72
+ O as types,
73
+ S as variants
73
74
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@justeattakeaway/pie-button",
3
- "version": "0.26.0",
3
+ "version": "0.28.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
@@ -8,29 +8,33 @@
8
8
 
9
9
  /**
10
10
  * Defines button interactive states for hover, active and loading.
11
- * Takes the interactive color name as an argument, and whether the color
12
- * should be lightened or darkened.
11
+ * $bg-color: design token name to be used for the states
12
+ * $mode: 'default': apply the default lighten/darken to the color via hsl
13
+ * 'transparent': uses hsla syntax to make the color semi-opaque (used for ghost and outline button variants)
13
14
  */
14
- @mixin button-interactive-states($bg-color, $lighten: false) {
15
+ @mixin button-interactive-states($bg-color, $mode: 'default') {
15
16
  &:hover:not(:disabled) {
16
17
  --hover-modifier: calc(-1 * var(--dt-color-hover-01));
17
18
 
18
- @if $lighten {
19
- --hover-modifier: var(--dt-color-hover-02);
19
+ // for mode=transparent, use the hsla syntax to make the button background opaque by a set percentage
20
+ @if $mode == 'transparent' {
21
+ --hover-modifier: var(--dt-color-hover-01);
22
+ --btn-bg-color: hsl(var(#{$bg-color}-h), var(#{$bg-color}-s), var(#{$bg-color}-l), var(--hover-modifier));
23
+ } @else {
24
+ --btn-bg-color: hsl(var(#{$bg-color}-h), var(#{$bg-color}-s), calc(var(#{$bg-color}-l) + var(--hover-modifier)));
20
25
  }
21
-
22
- --btn-bg-color: hsl(var(#{$bg-color}-h), var(#{$bg-color}-s), calc(var(#{$bg-color}-l) + var(--hover-modifier)));
23
26
  }
24
27
 
25
28
  &:active:not(:disabled),
26
29
  &[isLoading]:not(:disabled) {
27
30
  --active-modifier: calc(-1 * var(--dt-color-active-01));
28
31
 
29
- @if $lighten {
30
- --active-modifier: var(--dt-color-active-02);
32
+ @if $mode == 'transparent' {
33
+ --active-modifier: var(--dt-color-active-01);
34
+ --btn-bg-color: hsl(var(#{$bg-color}-h), var(#{$bg-color}-s), var(#{$bg-color}-l), var(--active-modifier));
35
+ } @else {
36
+ --btn-bg-color: hsl(var(#{$bg-color}-h), var(#{$bg-color}-s), calc(var(#{$bg-color}-l) + var(--active-modifier)));
31
37
  }
32
-
33
- --btn-bg-color: hsl(var(#{$bg-color}-h), var(#{$bg-color}-s), calc(var(#{$bg-color}-l) + var(--active-modifier)));
34
38
  }
35
39
  }
36
40
 
@@ -189,12 +193,14 @@
189
193
  }
190
194
 
191
195
  &[variant='outline'] {
192
- --btn-bg-color: var(--dt-color-container-default);
196
+ --btn-bg-color: transparent;
193
197
  --btn-text-color: var(--dt-color-content-interactive-secondary);
194
198
 
195
199
  border: 1px solid var(--dt-color-border-strong);
196
200
 
197
- @include button-interactive-states('--dt-color-container-default');
201
+ // use black as the background color for hover and inverse,
202
+ // as this variant uses a shade of transparent black showing through the container background
203
+ @include button-interactive-states('--dt-color-black', 'transparent');
198
204
  @include spinner-base-colors('--dt-color-content-interactive-secondary');
199
205
  }
200
206
 
@@ -202,7 +208,9 @@
202
208
  --btn-bg-color: transparent;
203
209
  --btn-text-color: var(--dt-color-content-link);
204
210
 
205
- @include button-interactive-states('--dt-color-container-default');
211
+ // use black as the background color for hover and inverse,
212
+ // as this variant uses a shade of transparent black showing through the container background
213
+ @include button-interactive-states('--dt-color-black', 'transparent');
206
214
  @include spinner-base-colors('--dt-color-content-interactive-secondary');
207
215
  }
208
216
 
@@ -219,7 +227,9 @@
219
227
  --btn-bg-color: transparent;
220
228
  --btn-text-color: var(--dt-color-content-interactive-primary);
221
229
 
222
- @include button-interactive-states('--dt-color-container-inverse', true);
230
+ // use white as the background color for hover and inverse,
231
+ // as these variants use a shade of transparent white showing through the container background
232
+ @include button-interactive-states('--dt-color-container-default', 'transparent');
223
233
  }
224
234
 
225
235
  &[variant='outline-inverse'] {
@@ -236,7 +246,9 @@
236
246
  --btn-bg-color: transparent;
237
247
  --btn-text-color: var(--dt-color-content-interactive-error);
238
248
 
239
- @include button-interactive-states('--dt-color-container-default');
249
+ // use black as the background color for hover and inverse,
250
+ // as this variant uses a shade of transparent black showing through the container background
251
+ @include button-interactive-states('--dt-color-black', 'transparent');
240
252
  @include spinner-base-colors('--dt-color-content-interactive-secondary');
241
253
  }
242
254
 
@@ -300,39 +312,30 @@
300
312
  --spinner-border-width: var(--spinner-border-width-m);
301
313
  }
302
314
 
303
- &:before {
304
- content: '';
305
-
306
- // Centre the spinner over the top of the button text
307
- position: absolute;
308
- left: 50%;
309
- top: 50%;
310
- translate: -50% -50%;
311
-
312
- height: var(--spinner-size);
313
- width: var(--spinner-size);
314
- display: block;
315
- background-color: transparent;
316
- border-radius: 50%;
317
- border-color: var(--spinner-left-color) var(--spinner-right-color) var(--spinner-right-color) var(--spinner-left-color);
318
- border-width: var(--spinner-border-width);
319
- border-style: solid;
320
- will-change: transform;
321
- opacity: 0;
322
- }
323
-
324
- .o-btn-text {
325
- flex-grow: 1;
326
- }
327
-
328
315
  &[isLoading] {
329
316
  &:before {
317
+ content: '';
318
+
319
+ // Centre the spinner over the top of the button text
320
+ position: absolute;
321
+ left: 50%;
322
+ top: 50%;
323
+ translate: -50% -50%;
324
+
325
+ height: var(--spinner-size);
326
+ width: var(--spinner-size);
327
+ display: block;
328
+ background-color: transparent;
329
+ border-radius: 50%;
330
+ border-color: var(--spinner-left-color) var(--spinner-right-color) var(--spinner-right-color) var(--spinner-left-color);
331
+ border-width: var(--spinner-border-width);
332
+ border-style: solid;
333
+ will-change: transform;
330
334
  animation: rotate360 var(--spinner-animation-duration) var(--spinner-animation-timing-function) var(--spinner-animation-iteration-count);
331
- opacity: 1;
332
335
  }
333
336
 
334
- & .o-btn-text {
335
- opacity: 0;
337
+ & > * {
338
+ visibility: hidden;
336
339
  }
337
340
  }
338
341
  }
package/src/defs.ts CHANGED
@@ -4,6 +4,7 @@ export const variants = [
4
4
  'primary', 'secondary', 'outline', 'outline-inverse', 'ghost',
5
5
  'inverse', 'ghost-inverse', 'destructive', 'destructive-ghost',
6
6
  ] as const;
7
+ export const iconPlacements = ['leading', 'trailing'] as const;
7
8
 
8
9
  export type Variant = typeof variants[number];
9
10
 
@@ -20,6 +21,10 @@ export interface ButtonProps {
20
21
  * What style variant the button should be such as primary, outline or ghost.
21
22
  */
22
23
  variant: Variant;
24
+ /**
25
+ * The placement of the icon slot, if provided, such as leading or trailing
26
+ */
27
+ iconPlacement?: typeof iconPlacements[number];
23
28
  /**
24
29
  * When true, the button element is disabled.
25
30
  */
package/src/index.ts CHANGED
@@ -1,9 +1,11 @@
1
- import { LitElement, html, unsafeCSS } from 'lit';
1
+ import {
2
+ LitElement, html, unsafeCSS, nothing,
3
+ } from 'lit';
2
4
  import { property } from 'lit/decorators.js';
3
5
  import { validPropertyValues } from '@justeattakeaway/pie-webc-core';
4
6
  import styles from './button.scss?inline';
5
7
  import {
6
- ButtonProps, sizes, types, variants,
8
+ ButtonProps, sizes, types, variants, iconPlacements,
7
9
  } from './defs';
8
10
 
9
11
  // Valid values available to consumers
@@ -12,8 +14,7 @@ export * from './defs';
12
14
  const componentSelector = 'pie-button';
13
15
 
14
16
  /**
15
- * @slot icon-leading - Leading icon
16
- * @slot icon-trailing - Trailing icon
17
+ * @slot icon - The icon slot
17
18
  * @slot - Default slot
18
19
  */
19
20
  export class PieButton extends LitElement implements ButtonProps {
@@ -29,6 +30,10 @@ export class PieButton extends LitElement implements ButtonProps {
29
30
  @validPropertyValues(componentSelector, variants, 'primary')
30
31
  public variant: ButtonProps['variant'] = 'primary';
31
32
 
33
+ @property({ type: String })
34
+ @validPropertyValues(componentSelector, iconPlacements, 'leading')
35
+ public iconPlacement: ButtonProps['iconPlacement'] = 'leading';
36
+
32
37
  @property({ type: Boolean })
33
38
  public disabled = false;
34
39
 
@@ -40,7 +45,13 @@ export class PieButton extends LitElement implements ButtonProps {
40
45
 
41
46
  render () {
42
47
  const {
43
- type, disabled, isFullWidth, variant, size, isLoading,
48
+ type,
49
+ disabled,
50
+ isFullWidth,
51
+ variant,
52
+ size,
53
+ isLoading,
54
+ iconPlacement,
44
55
  } = this;
45
56
 
46
57
  return html`
@@ -52,9 +63,9 @@ export class PieButton extends LitElement implements ButtonProps {
52
63
  ?disabled=${disabled}
53
64
  ?isFullWidth=${isFullWidth}
54
65
  ?isLoading=${isLoading}>
55
- <slot name="icon-leading"></slot>
56
- <span class="o-btn-text"><slot></slot></span>
57
- <slot name="icon-trailing"></slot>
66
+ ${iconPlacement === 'leading' ? html`<slot name="icon"></slot>` : nothing}
67
+ <slot></slot>
68
+ ${iconPlacement === 'trailing' ? html`<slot name="icon"></slot>` : nothing}
58
69
  </button>`;
59
70
  }
60
71