@justeattakeaway/pie-button 0.10.1 → 0.11.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.
@@ -0,0 +1,11 @@
1
+ vite v4.2.1 building for production...
2
+ transforming...
3
+ ✓ 4 modules transformed.
4
+ rendering chunks...
5
+ computing gzip size...
6
+ dist/index.js 4.12 kB │ gzip: 1.65 kB
7
+ 
8
+ [vite:dts] Start generate declaration files...
9
+ ✓ built in 8.92s
10
+ [vite:dts] Declaration files built in 8276ms.
11
+ 
package/CHANGELOG.md CHANGED
@@ -1,10 +1,32 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.11.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [Changed] - Improved readme files ([#418](https://github.com/justeattakeaway/pie/pull/418)) by [@jamieomaguire](https://github.com/jamieomaguire)
8
+
9
+ - [Changed] - Refactor SCSS to reduce duplication ([#416](https://github.com/justeattakeaway/pie/pull/416)) by [@jamieomaguire](https://github.com/jamieomaguire)
10
+
11
+ - [Changed] - Copy playwright projects from monorepo root ([#416](https://github.com/justeattakeaway/pie/pull/416)) by [@jamieomaguire](https://github.com/jamieomaguire)
12
+
13
+ - [Changed] - Split small size into expressive and productive ([#416](https://github.com/justeattakeaway/pie/pull/416)) by [@jamieomaguire](https://github.com/jamieomaguire)
14
+
15
+ ### Patch Changes
16
+
17
+ - [Removed] the custom decorator and uses the native `customElement` decorator instead ([#417](https://github.com/justeattakeaway/pie/pull/417)) by [@fernandofranca](https://github.com/fernandofranca)
18
+
19
+ ## 0.10.2
20
+
21
+ ### Patch Changes
22
+
23
+ - [Added] Declare global statement back in. ([#393](https://github.com/justeattakeaway/pie/pull/393)) by [@kevinrodrigues](https://github.com/kevinrodrigues)
24
+
3
25
  ## 0.10.1
4
26
 
5
27
  ### Patch Changes
6
28
 
7
- - [Fixed] - Added module entry for component
29
+ - [Fixed] - Added module entry for component ([#378](https://github.com/justeattakeaway/pie/pull/378)) by [@ashleynolan](https://github.com/ashleynolan)
8
30
 
9
31
  ## 0.10.0
10
32
 
package/README.md CHANGED
@@ -1,3 +1,13 @@
1
+ <p align="center">
2
+ <img align="center" src="../../../readme_image.png" height="200" alt="">
3
+ </p>
4
+
5
+ <p align="center">
6
+ <a href="https://www.npmjs.com/@justeattakeaway/pie-button">
7
+ <img alt="GitHub Workflow Status" src="https://img.shields.io/npm/v/@justeattakeaway/pie-button.svg">
8
+ </a>
9
+ </p>
10
+
1
11
  # pie-button
2
12
 
3
13
  This button is a Web Component built using Lit.
@@ -24,3 +34,23 @@ Local dev server using Vite (with hot module reloading)
24
34
  ```
25
35
  yarn dev
26
36
  ```
37
+
38
+
39
+ ## Running tests
40
+
41
+ ### Browser tests
42
+
43
+ Run at the root of the monorepo:
44
+ ```
45
+ yarn test:browsers --filter=pie-button
46
+ ```
47
+
48
+ ### Visual tests
49
+
50
+ Run at the root of the monorepo:
51
+ ```
52
+ yarn test:visual --filter=pie-button
53
+ ```
54
+
55
+
56
+
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
- import { unsafeCSS as f, LitElement as h, html as g } from "lit";
2
- import { classMap as m } from "lit/directives/class-map.js";
3
- import { property as u, customElement as v } from "lit/decorators.js";
4
- const x = `.o-btn{border-radius:50rem;border:none;font-family:JetSansDigital;font-weight:700;cursor:pointer;user-select:none;outline:none}.o-btn:focus-visible{outline:2px solid #4996fd}.o-btn--xsmall{padding:6px 8px;min-height:32px;font-size:14px;line-height:20px}.o-btn--small{padding:8px 16px;min-height:40px;font-size:19px;line-height:28px}.o-btn--medium{padding:10px 24px;min-height:48px;font-size:20px;line-height:28px}.o-btn--large{padding:14px 24px;min-height:56px;font-size:20px;line-height:28px}.o-btn--primary{background-color:#f36805;color:#fff}.o-btn--primary:hover{background-color:#df5f05}.o-btn--primary:active{background-color:#b74e04}.o-btn--secondary{background-color:#f5f3f1;color:#242e30}.o-btn--secondary:hover{background-color:#ede9e5}.o-btn--secondary:active{background-color:#dcd4cd}.o-btn--outline{outline:1px solid #dbd9d7;background-color:#fff;color:#303d3f}.o-btn--outline:hover{background-color:#f5f5f5}.o-btn--outline:active{background-color:#e0e0e0}.o-btn--ghost{background-color:#fff;color:#242e30}.o-btn--ghost:hover{background-color:#f5f5f5}.o-btn--ghost:active{background-color:#e0e0e0}.o-btn.o-btn--is-disabled{background-color:#efedea;color:#8c999b;outline:1px solid #efedea;cursor:default}.o-btn.o-btn--is-disabled.o-btn--ghost{background-color:#fff;outline:none}
5
- `, p = (o, n) => function(i, t) {
1
+ import { unsafeCSS as f, LitElement as g, html as h } from "lit";
2
+ import { classMap as v } from "lit/directives/class-map.js";
3
+ import { property as p, customElement as m } from "lit/decorators.js";
4
+ const x = `.o-btn{border-radius:50rem;border:none;font-family:JetSansDigital;cursor:pointer;user-select:none;outline:none}.o-btn:focus-visible{outline:2px solid #4996fd}.o-btn--xsmall{min-block-size:32px;padding:6px 8px;font-size:14px;font-weight:700;line-height:20px}.o-btn--small-productive{min-block-size:40px;padding:8px 16px;font-size:16px;font-weight:700;line-height:24px}.o-btn--small-expressive{min-block-size:40px;padding:6px 16px;font-size:20px;font-weight:700;line-height:28px}.o-btn--medium{min-block-size:48px;padding:10px 24px;font-size:20px;font-weight:700;line-height:28px}.o-btn--large{min-block-size:56px;padding:14px 24px;font-size:20px;font-weight:700;line-height:28px}.o-btn--primary{background-color:#f36805;color:#fff}.o-btn--primary:hover{background-color:#df5f05}.o-btn--primary:active{background-color:#b74e04}.o-btn--secondary{background-color:#f5f3f1;color:#242e30}.o-btn--secondary:hover{background-color:#ede9e5}.o-btn--secondary:active{background-color:#dcd4cd}.o-btn--outline{background-color:#fff;color:#303d3f;outline:1px solid #dbd9d7}.o-btn--outline:hover{background-color:#f5f5f5}.o-btn--outline:active{background-color:#e0e0e0}.o-btn--ghost{background-color:#fff;color:#242e30}.o-btn--ghost:hover{background-color:#f5f5f5}.o-btn--ghost:active{background-color:#e0e0e0}.o-btn.o-btn--is-disabled{background-color:#efedea;color:#8c999b;outline:1px solid #efedea;cursor:default}.o-btn.o-btn--is-disabled:hover{background-color:#e6e3de}.o-btn.o-btn--is-disabled:active{background-color:#d5cfc7}.o-btn.o-btn--is-disabled.o-btn--ghost{background-color:#fff;outline:none}
5
+ `, u = (o, n) => function(i, t) {
6
6
  const e = `#${t}`;
7
7
  Object.defineProperty(i, t, {
8
8
  get() {
@@ -18,18 +18,12 @@ const x = `.o-btn{border-radius:50rem;border:none;font-family:JetSansDigital;fon
18
18
  }
19
19
  });
20
20
  };
21
- var a = /* @__PURE__ */ ((o) => (o.XSMALL = "xsmall", o.SMALL = "small", o.MEDIUM = "medium", o.LARGE = "large", o))(a || {}), d = /* @__PURE__ */ ((o) => (o.SUBMIT = "submit", o.BUTTON = "button", o.RESET = "reset", o.MENU = "menu", o))(d || {}), b = /* @__PURE__ */ ((o) => (o.PRIMARY = "primary", o.SECONDARY = "secondary", o.OUTLINE = "outline", o.GHOST = "ghost", o))(b || {}), y = Object.defineProperty, M = Object.getOwnPropertyDescriptor, c = (o, n, i, t) => {
22
- for (var e = t > 1 ? void 0 : t ? M(n, i) : n, r = o.length - 1, s; r >= 0; r--)
21
+ var a = /* @__PURE__ */ ((o) => (o.XSMALL = "xsmall", o.SMALL_EXPRESSIVE = "small-expressive", o.SMALL_PRODUCTIVE = "small-productive", o.MEDIUM = "medium", o.LARGE = "large", o))(a || {}), d = /* @__PURE__ */ ((o) => (o.SUBMIT = "submit", o.BUTTON = "button", o.RESET = "reset", o.MENU = "menu", o))(d || {}), b = /* @__PURE__ */ ((o) => (o.PRIMARY = "primary", o.SECONDARY = "secondary", o.OUTLINE = "outline", o.GHOST = "ghost", o))(b || {}), y = Object.defineProperty, k = Object.getOwnPropertyDescriptor, c = (o, n, i, t) => {
22
+ for (var e = t > 1 ? void 0 : t ? k(n, i) : n, r = o.length - 1, s; r >= 0; r--)
23
23
  (s = o[r]) && (e = (t ? s(n, i, e) : s(e)) || e);
24
24
  return t && e && y(n, i, e), e;
25
25
  };
26
- function k(o) {
27
- return (n) => {
28
- if (!customElements.get(o))
29
- return v(o)(n);
30
- };
31
- }
32
- let l = class extends h {
26
+ let l = class extends g {
33
27
  constructor() {
34
28
  super(...arguments), this.size = a.MEDIUM, this.type = d.SUBMIT, this.variant = b.PRIMARY, this.disabled = !1;
35
29
  }
@@ -40,12 +34,12 @@ let l = class extends h {
40
34
  [`o-btn--${i}`]: i,
41
35
  "o-btn--is-disabled": t
42
36
  }, r = () => {
43
- const s = new Event("CustomEvent");
37
+ const s = new CustomEvent("CustomEvent", { detail: "WC event dispatched" });
44
38
  console.info("WC event dispatched"), this.dispatchEvent(s);
45
39
  };
46
- return g`
40
+ return h`
47
41
  <button
48
- class=${m(e)}
42
+ class=${v(e)}
49
43
  type=${n}
50
44
  ?disabled=${t}
51
45
  @click="${r}">
@@ -55,22 +49,22 @@ let l = class extends h {
55
49
  };
56
50
  l.styles = f(x);
57
51
  c([
58
- u(),
59
- p(Object.values(a), a.MEDIUM)
52
+ p(),
53
+ u(Object.values(a), a.MEDIUM)
60
54
  ], l.prototype, "size", 2);
61
55
  c([
62
- u(),
63
- p(Object.values(d), d.SUBMIT)
56
+ p(),
57
+ u(Object.values(d), d.SUBMIT)
64
58
  ], l.prototype, "type", 2);
65
59
  c([
66
- u(),
67
- p(Object.values(b), b.PRIMARY)
60
+ p(),
61
+ u(Object.values(b), b.PRIMARY)
68
62
  ], l.prototype, "variant", 2);
69
63
  c([
70
- u({ type: Boolean, reflect: !0 })
64
+ p({ type: Boolean, reflect: !0 })
71
65
  ], l.prototype, "disabled", 2);
72
66
  l = c([
73
- k("pie-button")
67
+ m("pie-button")
74
68
  ], l);
75
69
  export {
76
70
  a as BUTTON_SIZE,
@@ -3,7 +3,8 @@
3
3
  */
4
4
  export declare enum BUTTON_SIZE {
5
5
  XSMALL = "xsmall",
6
- SMALL = "small",
6
+ SMALL_EXPRESSIVE = "small-expressive",
7
+ SMALL_PRODUCTIVE = "small-productive",
7
8
  MEDIUM = "medium",
8
9
  LARGE = "large"
9
10
  }
@@ -1 +1 @@
1
- {"version":3,"file":"defs.d.ts","sourceRoot":"","sources":["../../../src/defs.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,oBAAY,WAAW;IACnB,MAAM,WAAW;IACjB,KAAK,UAAU;IACf,MAAM,WAAW;IACjB,KAAK,UAAU;CAClB;AAED;;GAEG;AACH,oBAAY,WAAW;IACnB,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,KAAK,UAAU;IACf,IAAI,SAAS;CAChB;AAED;;GAEG;AACH,oBAAY,cAAc;IACtB,OAAO,YAAY;IACnB,SAAS,cAAc;IACvB,OAAO,YAAY;IACnB,KAAK,UAAU;CAClB"}
1
+ {"version":3,"file":"defs.d.ts","sourceRoot":"","sources":["../../../src/defs.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,oBAAY,WAAW;IACnB,MAAM,WAAW;IACjB,gBAAgB,qBAAqB;IACrC,gBAAgB,qBAAqB;IACrC,MAAM,WAAW;IACjB,KAAK,UAAU;CAClB;AAED;;GAEG;AACH,oBAAY,WAAW;IACnB,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,KAAK,UAAU;IACf,IAAI,SAAS;CAChB;AAED;;GAEG;AACH,oBAAY,cAAc;IACtB,OAAO,YAAY;IACnB,SAAS,cAAc;IACvB,OAAO,YAAY;IACnB,KAAK,UAAU;CAClB"}
@@ -9,4 +9,9 @@ export declare class PieButton extends LitElement {
9
9
  render(): import("lit-html").TemplateResult<1>;
10
10
  static styles: import("lit").CSSResult;
11
11
  }
12
+ declare global {
13
+ interface HTMLElementTagNameMap {
14
+ 'pie-button': PieButton;
15
+ }
16
+ }
12
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAmB,MAAM,KAAK,CAAC;AAMlD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAGlE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC;AAWpD,qBACa,SAAU,SAAQ,UAAU;IAGrC,IAAI,EAAG,WAAW,CAAsB;IAIxC,IAAI,EAAG,WAAW,CAAsB;IAIxC,OAAO,EAAG,cAAc,CAA0B;IAGlD,QAAQ,EAAG,OAAO,CAAS;IAE3B,MAAM;IA2BN,MAAM,CAAC,MAAM,0BAAqB;CACrC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAmB,MAAM,KAAK,CAAC;AAMlD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAGlE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC;AAEpD,qBACa,SAAU,SAAQ,UAAU;IAGrC,IAAI,EAAG,WAAW,CAAsB;IAIxC,IAAI,EAAG,WAAW,CAAsB;IAIxC,OAAO,EAAG,cAAc,CAA0B;IAGlD,QAAQ,EAAG,OAAO,CAAS;IAE3B,MAAM;IA2BN,MAAM,CAAC,MAAM,0BAAqB;CACrC;AAED,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,qBAAqB;QAC3B,YAAY,EAAE,SAAS,CAAC;KAC3B;CACJ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@justeattakeaway/pie-button",
3
- "version": "0.10.1",
3
+ "version": "0.11.0",
4
4
  "description": "PIE design system button built using web components",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -10,7 +10,11 @@
10
10
  "build": "run -T vite build",
11
11
  "watch": "run -T vite build --watch",
12
12
  "dev": "run -T vite",
13
- "test": "echo \"Error: no test specified\" && exit 0"
13
+ "test": "echo \"Error: no test specified\" && exit 0",
14
+ "test:browsers": "npx playwright test -c ./playwright-lit.config.ts",
15
+ "test:browsers:ci": "yarn test:browsers",
16
+ "test:visual": "run -T cross-env-shell PERCY_TOKEN=${PERCY_TOKEN_PIE_BUTTON} percy exec --allowed-hostname cloudfront.net -- npx playwright test -c ./playwright-lit-visual.config.ts",
17
+ "test:visual:ci": "yarn test:visual"
14
18
  },
15
19
  "author": "JustEatTakeaway - Design System Web Team",
16
20
  "license": "Apache-2.0",
@@ -0,0 +1,49 @@
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
+ #root {
35
+ padding: 1.5em;
36
+ display: flex;
37
+ gap: 1em;
38
+ justify-content: center;
39
+ align-items: center;
40
+ flex-direction: column;
41
+ }
42
+ </style>
43
+ <title>Testing Page</title>
44
+ </head>
45
+ <body>
46
+ <div id="root"></div>
47
+ <script type="module" src="./index.ts"></script>
48
+ </body>
49
+ </html>
@@ -0,0 +1 @@
1
+ //Import common styles here
@@ -0,0 +1,52 @@
1
+ import { defineConfig, devices } from '@sand4rt/experimental-ct-web';
2
+ import { resolve } from 'path';
3
+
4
+ /**
5
+ * See https://playwright.dev/docs/test-configuration.
6
+ */
7
+ export default defineConfig({
8
+ /* Maximum time one test can run for. */
9
+ timeout: 10 * 1000,
10
+ /* Run tests in files in parallel */
11
+ fullyParallel: true,
12
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
13
+ forbidOnly: !!process.env.CI,
14
+ /* Retry on CI only */
15
+ retries: process.env.CI ? 2 : 0,
16
+ /* Opt out of parallel tests on CI. */
17
+ workers: '50%',
18
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
19
+ reporter: [['html', { outputFolder: 'lit-visual-report' }]],
20
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
21
+ use: {
22
+ ctViteConfig: {
23
+ resolve: {
24
+ alias: {
25
+ '@': resolve('./src'),
26
+ },
27
+ },
28
+ },
29
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
30
+ trace: 'on',
31
+ },
32
+
33
+ /* Configure projects for major browsers */
34
+ projects: [
35
+ {
36
+ name: 'visual:desktop',
37
+ grepInvert: /@mobile/,
38
+ use: {
39
+ ...devices['Desktop Chrome'],
40
+ },
41
+ testMatch: ['**/test/visual/*.spec.ts']
42
+ },
43
+ {
44
+ name: 'visual:mobile',
45
+ grep: /@mobile/,
46
+ use: {
47
+ ...devices['Pixel 5'],
48
+ },
49
+ testMatch: ['**/test/visual/*.spec.ts']
50
+ },
51
+ ],
52
+ });
@@ -0,0 +1,52 @@
1
+ import { defineConfig, devices } from '@sand4rt/experimental-ct-web';
2
+ import { resolve } from 'path';
3
+
4
+ /**
5
+ * See https://playwright.dev/docs/test-configuration.
6
+ */
7
+ export default defineConfig({
8
+ /* The base directory, relative to the config file, for snapshot files created with toMatchSnapshot and toHaveScreenshot. */
9
+ snapshotDir: './__snapshots__',
10
+ /* Maximum time one test can run for. */
11
+ timeout: 10 * 1000,
12
+ /* Run tests in files in parallel */
13
+ fullyParallel: true,
14
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
15
+ forbidOnly: !!process.env.CI,
16
+ /* Retry on CI only */
17
+ retries: process.env.CI ? 2 : 0,
18
+ /* Opt out of parallel tests on CI. */
19
+ workers: '50%',
20
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
21
+ reporter: [['html', { outputFolder: 'lit-browsers-report' }]],
22
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
23
+ use: {
24
+ ctViteConfig: {
25
+ resolve: {
26
+ alias: {
27
+ '@': resolve('./src'),
28
+ },
29
+ },
30
+ },
31
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
32
+ trace: 'on',
33
+ },
34
+
35
+ /* Configure projects for major browsers */
36
+ projects: [
37
+ {
38
+ name: 'component:chrome',
39
+ use: {
40
+ ...devices['Desktop Chrome'],
41
+ },
42
+ testMatch: ['**/test/component/*.spec.ts']
43
+ },
44
+ {
45
+ name: 'a11y:chrome',
46
+ use: {
47
+ ...devices['Desktop Chrome'],
48
+ },
49
+ testMatch: ['**/test/accessibility/*.spec.ts']
50
+ },
51
+ ],
52
+ });
package/src/button.scss CHANGED
@@ -1,110 +1,155 @@
1
1
  @use '@justeat/pie-design-tokens/dist/jet.scss' as dt;
2
2
 
3
+ $button-height-xs: 32px;
4
+ $button-height-s: 40px;
5
+ $button-height-m: 48px;
6
+ $button-height-l: 56px;
7
+
8
+ $button-border-radius: dt.$radius-rounded-e;
9
+ $button-font: dt.$font-interactive-m-family;
10
+ $button-focus: dt.$color-focus;
11
+
12
+ $button-bg-color-primary: dt.$color-interactive-brand;
13
+ $button-text-color-primary: dt.$color-content-interactive-primary;
14
+
15
+ $button-bg-color-secondary: dt.$color-interactive-secondary;
16
+ $button-text-color-secondary: dt.$color-content-interactive-secondary;
17
+
18
+ $button-bg-color-outline: dt.$color-container-default;
19
+ $button-text-color-outline: dt.$color-content-interactive-tertiary;
20
+ $button-outline-color-outline: dt.$color-border-strong;
21
+
22
+ $button-bg-color-ghost: dt.$color-container-default;
23
+ $button-text-color-ghost: dt.$color-content-link;
24
+ $button-disabled-bg-color-ghost: dt.$color-container-default;
25
+
26
+ $button-bg-color-disabled: dt.$color-disabled-01;
27
+ $button-text-color-disabled: dt.$color-content-disabled;
28
+ $button-outline-color-disabled: dt.$color-disabled-01;
29
+
30
+ // Sets up the size of a button such as xsmall or large
31
+ @mixin button-sizing($min-block-size, $padding-block, $padding-inline, $font-size, $font-weight, $line-height) {
32
+ min-block-size: $min-block-size;
33
+ padding: $padding-block $padding-inline;
34
+ font-size: $font-size * 1px;
35
+ font-weight: $font-weight;
36
+ line-height: $line-height * 1px;
37
+ }
38
+
39
+ // 'Themes' a button for it's particular variant, such as primary, secondary, outline, ghost
40
+ @mixin button-variant($bg-color, $text-color, $outline-color: null) {
41
+ background-color: $bg-color;
42
+ color: $text-color;
43
+
44
+ &:hover {
45
+ background-color: darken($bg-color, dt.$color-hover-01);
46
+ }
47
+
48
+ &:active {
49
+ background-color: darken($bg-color, dt.$color-active-01);
50
+ }
51
+
52
+ @if $outline-color != null {
53
+ outline: 1px solid $outline-color;
54
+ }
55
+ }
56
+
57
+ // Base button styles
3
58
  .o-btn {
4
- border-radius: dt.$radius-rounded-e;
59
+ border-radius: $button-border-radius;
5
60
  border: none;
6
- font-family: dt.$font-interactive-m-family;
7
- font-weight: dt.$font-interactive-m-weight;
61
+ font-family: $button-font;
8
62
 
9
63
  cursor: pointer;
10
64
  user-select: none;
11
65
  outline: none;
12
66
 
13
67
  &:focus-visible {
14
- outline: 2px solid dt.$color-focus;
68
+ outline: 2px solid $button-focus;
15
69
  }
16
70
  }
17
71
 
18
- .o-btn--xsmall {
19
- padding: 6px dt.$spacing-b;
20
- min-height: 32px;
21
- font-size: dt.$font-size-14 * 1px;
22
- line-height: dt.$font-size-14-line-height * 1px;
23
- }
24
-
25
- .o-btn--small {
26
- padding: 8px dt.$spacing-d;
27
- min-height: 40px;
28
- font-size: dt.$font-size-19 * 1px;
29
- line-height: dt.$font-size-19-line-height * 1px;
30
- }
31
-
32
- .o-btn--medium {
33
- padding: 10px dt.$spacing-e;
34
- min-height: 48px;
35
- font-size: dt.$font-size-20 * 1px;
36
- line-height: dt.$font-size-20-line-height * 1px;
37
- }
38
-
39
- .o-btn--large {
40
- padding: 14px dt.$spacing-e;
41
- min-height: 56px;
42
- font-size: dt.$font-size-20 * 1px;
43
- line-height: dt.$font-size-20-line-height * 1px;
72
+ // Sizes
73
+ $button-sizes: (
74
+ 'xsmall': (
75
+ 'min-block-size': $button-height-xs,
76
+ 'padding-block': 6px,
77
+ 'padding-inline': dt.$spacing-b,
78
+ 'font-size': dt.$font-interactive-xs-size,
79
+ 'font-weight': dt.$font-interactive-xs-weight,
80
+ 'line-height': dt.$font-interactive-xs-line-height
81
+ ),
82
+ 'small-productive': (
83
+ 'min-block-size': $button-height-s,
84
+ 'padding-block': dt.$spacing-b,
85
+ 'padding-inline': dt.$spacing-d,
86
+ 'font-size': dt.$font-interactive-s-size,
87
+ 'font-weight': dt.$font-interactive-s-weight,
88
+ 'line-height': dt.$font-interactive-s-line-height
89
+ ),
90
+ 'small-expressive': (
91
+ 'min-block-size': $button-height-s,
92
+ 'padding-block': 6px,
93
+ 'padding-inline': dt.$spacing-d,
94
+ 'font-size': dt.$font-interactive-l-size,
95
+ 'font-weight': dt.$font-interactive-l-weight,
96
+ 'line-height': dt.$font-interactive-l-line-height
97
+ ),
98
+ 'medium': (
99
+ 'min-block-size': $button-height-m,
100
+ 'padding-block': 10px,
101
+ 'padding-inline': dt.$spacing-e,
102
+ 'font-size': dt.$font-interactive-l-size,
103
+ 'font-weight': dt.$font-interactive-l-weight,
104
+ 'line-height': dt.$font-interactive-l-line-height
105
+ ),
106
+ 'large': (
107
+ 'min-block-size': $button-height-l,
108
+ 'padding-block': 14px,
109
+ 'padding-inline': dt.$spacing-e,
110
+ 'font-size': dt.$font-interactive-l-size,
111
+ 'font-weight': dt.$font-interactive-l-weight,
112
+ 'line-height': dt.$font-interactive-l-line-height
113
+ )
114
+ );
115
+
116
+ @each $size, $values in $button-sizes {
117
+ .o-btn--#{$size} {
118
+ @include button-sizing(
119
+ map-get($values, 'min-block-size'),
120
+ map-get($values, 'padding-block'),
121
+ map-get($values, 'padding-inline'),
122
+ map-get($values, 'font-size'),
123
+ map-get($values, 'font-weight'),
124
+ map-get($values, 'line-height')
125
+ );
126
+ }
44
127
  }
45
128
 
129
+ // Variants
46
130
  .o-btn--primary {
47
- background-color: dt.$color-interactive-brand;
48
- color: dt.$color-content-interactive-primary;
49
-
50
- &:hover {
51
- background-color: darken(dt.$color-interactive-brand, dt.$color-hover-01);
52
- }
53
-
54
- &:active {
55
- background-color: darken(dt.$color-interactive-brand, dt.$color-active-01);
56
- }
131
+ @include button-variant($button-bg-color-primary, $button-text-color-primary);
57
132
  }
58
133
 
59
134
  .o-btn--secondary {
60
- background-color: dt.$color-interactive-secondary;
61
- color: dt.$color-content-interactive-secondary;
62
-
63
- &:hover {
64
- background-color: darken(dt.$color-interactive-secondary, dt.$color-hover-01);
65
- }
66
-
67
- &:active {
68
- background-color: darken(dt.$color-interactive-secondary, dt.$color-active-01);
69
- }
135
+ @include button-variant($button-bg-color-secondary, $button-text-color-secondary);
70
136
  }
71
137
 
72
138
  .o-btn--outline {
73
- outline: 1px solid dt.$color-border-strong;
74
- background-color: dt.$color-container-default;
75
- color: dt.$color-content-interactive-tertiary;
76
-
77
- &:hover {
78
- background-color: darken(dt.$color-container-default, dt.$color-hover-01);
79
- }
80
-
81
- &:active {
82
- background-color: darken(dt.$color-container-default, dt.$color-active-01);
83
- }
139
+ @include button-variant($button-bg-color-outline, $button-text-color-outline, $button-outline-color-outline);
84
140
  }
85
141
 
86
142
  .o-btn--ghost {
87
- background-color: dt.$color-container-default;
88
- color: dt.$color-content-link;
89
-
90
- &:hover {
91
- background-color: darken(dt.$color-container-default, dt.$color-hover-01);
92
- }
93
-
94
- &:active {
95
- background-color: darken(dt.$color-container-default, dt.$color-active-01);
96
- }
143
+ @include button-variant($button-bg-color-ghost, $button-text-color-ghost);
97
144
  }
98
145
 
99
146
  .o-btn.o-btn--is-disabled {
100
- background-color: dt.$color-disabled-01;
101
- color: dt.$color-content-disabled;
102
- outline: 1px solid dt.$color-disabled-01;
147
+ @include button-variant($button-bg-color-disabled, $button-text-color-disabled, $button-outline-color-disabled);
103
148
 
104
149
  cursor: default;
105
150
 
106
151
  &.o-btn--ghost {
107
- background-color: dt.$color-container-default;
152
+ background-color: $button-disabled-bg-color-ghost;
108
153
  outline: none;
109
154
  }
110
- }
155
+ }
package/src/defs.ts CHANGED
@@ -3,7 +3,8 @@
3
3
  */
4
4
  export enum BUTTON_SIZE {
5
5
  XSMALL = 'xsmall',
6
- SMALL = 'small',
6
+ SMALL_EXPRESSIVE = 'small-expressive',
7
+ SMALL_PRODUCTIVE = 'small-productive',
7
8
  MEDIUM = 'medium',
8
9
  LARGE = 'large'
9
10
  }
package/src/index.ts CHANGED
@@ -9,16 +9,7 @@ import { BUTTON_SIZE, BUTTON_TYPE, BUTTON_VARIANT } from './defs';
9
9
  // Valid values available to consumers
10
10
  export { BUTTON_SIZE, BUTTON_TYPE, BUTTON_VARIANT };
11
11
 
12
- // TODO: Extract as a utility function in a shared package
13
- function defineCustomElement(elementName:string) {
14
- return (elementClass:typeof LitElement) => {
15
- if(customElements.get(elementName)) return;
16
-
17
- return customElement(elementName)(elementClass);
18
- }
19
- }
20
-
21
- @defineCustomElement('pie-button')
12
+ @customElement('pie-button')
22
13
  export class PieButton extends LitElement {
23
14
  @property()
24
15
  @validPropertyValues(Object.values(BUTTON_SIZE), BUTTON_SIZE.MEDIUM)
@@ -46,7 +37,7 @@ export class PieButton extends LitElement {
46
37
  };
47
38
 
48
39
  const raiseWCEvent = () => {
49
- const event = new Event('CustomEvent')
40
+ const event = new CustomEvent('CustomEvent', { detail: 'WC event dispatched' })
50
41
  console.info('WC event dispatched')
51
42
  this.dispatchEvent(event)
52
43
  }
@@ -64,3 +55,9 @@ export class PieButton extends LitElement {
64
55
  // Renders a `CSSResult` generated from SCSS by Vite
65
56
  static styles = unsafeCSS(styles);
66
57
  }
58
+
59
+ declare global {
60
+ interface HTMLElementTagNameMap {
61
+ 'pie-button': PieButton;
62
+ }
63
+ }
@@ -0,0 +1,36 @@
1
+ import { test, expect } from '@sand4rt/experimental-ct-web';
2
+ import { PieButton } from '@/index';
3
+ import { BUTTON_SIZE, BUTTON_VARIANT } from '@/defs';
4
+ import AxeBuilder from '@axe-core/playwright';
5
+
6
+ const sizes = Object.values(BUTTON_SIZE);
7
+ const variants = Object.values(BUTTON_VARIANT);
8
+ const disabledStates = [true, false];
9
+
10
+ variants.forEach(variant => {
11
+ test(`should render - ${variant}`, async ({ mount, page }) => {
12
+
13
+ for (const size of sizes) {
14
+ for (const isDisabled of disabledStates) {
15
+ const component = await mount(PieButton,
16
+ {
17
+ props: {
18
+ size,
19
+ variant,
20
+ disabled: isDisabled
21
+ },
22
+ slots: {
23
+ default: `Hello, ${size} ${variant} Button!`
24
+ },
25
+ });
26
+ }
27
+ }
28
+
29
+ const results = await new AxeBuilder.default({ page })
30
+ .withTags(['wcag21a', 'wcag21aa', 'wcag143', 'cat.color', 'cat.aria'])
31
+ .disableRules(['color-contrast', 'color-contrast-enhanced'])
32
+ .analyze();
33
+
34
+ expect(results.violations).toEqual([]);
35
+ });
36
+ })
@@ -0,0 +1,51 @@
1
+ import { test, expect } from '@sand4rt/experimental-ct-web';
2
+ import { PieButton } from '@/index';
3
+ import { BUTTON_SIZE, BUTTON_VARIANT } from '@/defs';
4
+
5
+ const sizes = Object.values(BUTTON_SIZE);
6
+ const variants = Object.values(BUTTON_VARIANT);
7
+ const disabledStates = [true, false];
8
+
9
+ variants.forEach(variant => {
10
+ test(`should render - ${variant}`, async ({ mount }) => {
11
+
12
+ for (const size of sizes) {
13
+ for (const isDisabled of disabledStates) {
14
+ const component = await mount(PieButton,
15
+ {
16
+ props: {
17
+ size,
18
+ variant,
19
+ disabled: isDisabled
20
+ },
21
+ slots: {
22
+ default: `Hello, ${size} ${variant} Button!`
23
+ },
24
+ });
25
+
26
+ await expect(component).toContainText(`Hello, ${size} ${variant} Button!`);
27
+ }
28
+ }
29
+ });
30
+ })
31
+
32
+ test('should emit an event when clicked', async ({ mount }) => {
33
+ const messages: string[] = [];
34
+ const component = await mount(PieButton,
35
+ {
36
+ props: {
37
+ size: BUTTON_SIZE.LARGE,
38
+ variant: BUTTON_VARIANT.PRIMARY
39
+ },
40
+ slots: {
41
+ default: 'Click me!'
42
+ },
43
+ on: {
44
+ CustomEvent: (data: string) => messages.push(data),
45
+ },
46
+ });
47
+
48
+ await component.click();
49
+
50
+ expect(messages).toEqual(['WC event dispatched'])
51
+ });
@@ -0,0 +1,31 @@
1
+ import { test } from '@sand4rt/experimental-ct-web';
2
+ import { PieButton } from '@/index';
3
+ import percySnapshot from '@percy/playwright'
4
+ import { BUTTON_SIZE, BUTTON_TYPE, BUTTON_VARIANT } from '@/defs';
5
+
6
+ const sizes = Object.values(BUTTON_SIZE);
7
+ const variants = Object.values(BUTTON_VARIANT);
8
+ const disabledStates = [true, false];
9
+
10
+ variants.forEach(variant => {
11
+ test(`should render - ${variant}`, async ({ page, mount }) => {
12
+
13
+ for (const size of sizes) {
14
+ for (const isDisabled of disabledStates) {
15
+ await mount(PieButton,
16
+ {
17
+ props: {
18
+ type: BUTTON_TYPE.BUTTON,
19
+ size,
20
+ variant,
21
+ disabled: isDisabled
22
+ },
23
+ slots: {
24
+ default: `Hello, ${size} ${variant} Button!`
25
+ },
26
+ });
27
+ }
28
+ }
29
+ await percySnapshot(page, `PIE Button - ${variant}`);
30
+ });
31
+ })
package/tsconfig.json CHANGED
@@ -1,26 +1,30 @@
1
1
  {
2
- "compilerOptions": {
3
- "target": "ES6",
4
- "module": "ES2022",
5
- "lib": ["es2020", "DOM", "DOM.Iterable"],
6
- "declaration": true,
7
- "declarationMap": true,
8
- "sourceMap": true,
9
- "inlineSources": true,
10
- "outDir": "./compiled",
11
- "rootDir": "./src",
12
- "strict": true,
13
- "noUnusedLocals": true,
14
- "noUnusedParameters": true,
15
- "noImplicitReturns": true,
16
- "noFallthroughCasesInSwitch": true,
17
- "noImplicitAny": true,
18
- "noImplicitThis": true,
19
- "moduleResolution": "node",
20
- "allowSyntheticDefaultImports": true,
21
- "experimentalDecorators": true,
22
- "forceConsistentCasingInFileNames": true
23
- },
24
- "include": ["src/**/*.ts","./declaration.d.ts"],
25
- "exclude": []
26
- }
2
+ "compilerOptions": {
3
+ "target": "ES6",
4
+ "module": "ES2022",
5
+ "lib": ["es2020", "DOM", "DOM.Iterable"],
6
+ "declaration": true,
7
+ "declarationMap": true,
8
+ "sourceMap": true,
9
+ "inlineSources": true,
10
+ "outDir": "./compiled",
11
+ "baseUrl": ".",
12
+ "paths": {
13
+ "@/*": ["./src/*"]
14
+ },
15
+ "rootDir": ".",
16
+ "strict": true,
17
+ "noUnusedLocals": true,
18
+ "noUnusedParameters": true,
19
+ "noImplicitReturns": true,
20
+ "noFallthroughCasesInSwitch": true,
21
+ "noImplicitAny": true,
22
+ "noImplicitThis": true,
23
+ "moduleResolution": "node",
24
+ "allowSyntheticDefaultImports": true,
25
+ "experimentalDecorators": true,
26
+ "forceConsistentCasingInFileNames": true
27
+ },
28
+ "include": ["src/**/*.ts","./declaration.d.ts", "test/**/*.ts"],
29
+ "exclude": []
30
+ }