rewards-ds
TypeScript icon, indicating that this package has built-in type declarations

1.0.0 • Public • Published

Built With Stencil

Woolworths Atomic Design System

Welcome to the Woolworths Atomic Design System, an easy way to consume common reusable web components for use with various modern application frameworks (angular, vue, react).

Our design system is a collection of Web Components (using Stencil js by the lovely Ionic team), so they work in any major framework or with no framework at all.

QUICK START

  • The repository contains stencil, stoybook and gatsby
  • gatsby project has it's own package.json and build process - docs sub-directory

GATSBY

  • to run gasby you have to build static assets from stencil and storybook first
  • after npm install run npm run build:docs then npm run docs:start to start working with gatsby
  • in src/pages you’ll see the mdx files, basically add stencil components as regular html, except using the object spread method {...{ attributes here }} for attaching the attributes/props
  • to use react components in the mdx you’ll need to import them at the top
  • each page should be wrapped in <Layout></Layout>
  • navigation can be updated from gatsby-config.js inside of the siteMetaData -> navigation object. First level is a group of nav items, then nav items are added into the items array. Second level nesting is achieved by setting the parent value to the parent path. A parent path of / will indicate top level within the group. There is a group with top and example next level item to use as reference. Active state is not currently working.

When you’re ready to deploy, just commit and push changes, docs will be auto built and deployed to s3 under the branch name used. Root domain should be http://ww-rewards-ds.s3-website-ap-southeast-2.amazonaws.com/

STORYBOOK

Integration between storybook and stencil inspired by: https://andreaswissel.com/integrating-stencil-with-storybook

Getting Started

You can learn about and contribute to the Atomic Design System in a number of ways:

Browse our online documentation

Take a look at our Design System's online documentation, found at rewards-ds.netlify.com.

Build locally to push new components or to prototype

If you are looking to either extend the Reward Design System, by adding new elements, components, or views, OR are looking to create interactive coded prototypes using the Atomic Design System, simply follow these steps:

git clone https://github.com/mothershipvc/woolworths-rewards-ds.git rewards-ds
cd rewards-ds
git remote rm origin

and run:

npm install
npm start

Installing Reward DS packages in your app

You can use various Atomic Design System properties and components as packages via NPM, within your Angular, Vue, React, or Static apps!

Install NPM Packages into your app's repo

npm install rewards-ds

If you only want to use a specific collection or component, install it like so:

npm install rewards-ds@core OR
npm install rewards-ds@forms OR specific components, like
npm install rewards-ds@balance-panel

Using Reward DS packages in your app

Once you've installed the relevant Atomic Design System node packages into your repo, simply do one of the following (depending on what kind of app you're building):

Add the component(s) to the dependencies

Add the component to the app dependencies in package.json:

// package.json
 
"dependencies"{
  ...
  "@rewards-ds/core""^0.3.2",
  "@rewards-ds/forms""^0.3.2",
  "@rewards-ds/balance""^0.3.2"
}

Integration with Frameworks

Angular

Using a Stencil built web component collection within an Angular CLI project is a two-step process. We need to:

  1. Include the CUSTOM_ELEMENTS_SCHEMA in the modules that use the components.
  2. Call defineCustomElements(window) from main.ts (or some other appropriate place).

Including the Custom Elements Schema

Including the CUSTOM_ELEMENTS_SCHEMA in the module allows the use of the web components in the HTML markup without the compiler producing errors this code should be added into the AppModule and in every other modules that use your custom elements. Here is an example of adding it to AppModule:

import { BrowserModule } from '@angular/platform-browser';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
 
import { AppComponent } from './app.component';
 
@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, FormsModule],
  bootstrap: [AppComponent],
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}

The CUSTOM_ELEMENTS_SCHEMA needs to be included in any module that uses custom elements.

Calling defineCustomElements

A component collection built with Stencil includes a main function that is used to load the components in the collection. That function is called defineCustomElements() and it needs to be called once during the bootstrapping of your application. One convenient place to do this is in main.ts as such:

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
 
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
 
// Note: loader import location set using "esmLoaderPath" within the output target confg
import { defineCustomElements } from 'test-components/loader';
 
if (environment.production) {
  enableProdMode();
}
 
platformBrowserDynamic()
  .bootstrapModule(AppModule)
  .catch(err => console.log(err));
defineCustomElements(window);

Edge and IE11 polyfills

If you want your custom elements to be able to work on older browser, you should add the applyPolyfills() that surrond the defineCustomElements() function.

import { applyPolyfills, defineCustomElements } from 'rewards-ds/dist/loader';
...
applyPolyfills().then(() => {
  defineCustomElements(window)
})
 

Accessing components using ViewChild and ViewChildren

Once included, components could be referenced in your code using ViewChild and ViewChildren as in the following example:

import { Component, ElementRef, ViewChild } from '@angular/core';
 
import 'rewards-ds';
 
@Component({
  selector: 'app-home',
  template: `
    <test-components #test></test-components>
  `,
  styleUrls: ['./home.component.scss'],
})
export class HomeComponent {
  @ViewChild('test') myTestComponent: ElementRef<HTMLTestComponentElement>;
 
  async onAction() {
    await this.myTestComponent.nativeElement.testComponentMethod();
  }
}

React

With an application built using the create-react-app script the easiest way to include the component library is to call defineCustomElements(window) from the index.js file. Note that in this scenario applyPolyfills is needed if you are targeting Edge or IE11.

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
 
// test-component is the name of our made up Web Component that we have
// published to npm:
import { applyPolyfills, defineCustomElements } from 'test-components/loader';
 
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
 
applyPolyfills().then(() => {
  defineCustomElements(window);
});

Following the steps above will enable your web components to be used in React, however there are some additional complexities that must also be considered. https://custom-elements-everywhere.com/ describes them well.

Nuxt.js

Create a plugin, (e.g rewards.ts):

import Vue from 'vue';
 
import { defineCustomElements } from 'rewards-ds/dist/loader/index.cjs';
 
Vue.config.productionTip = false;
Vue.config.ignoredElements = [/rds-\w*/];
 
// Bind the custom elements to the window object
defineCustomElements(window);
// nuxt.config.ts
{
  plugins[
    { src: '~/plugins/rewards.ts', mode: 'client' },
  ],
}

Then, use it in any component!

<template>
  <div>
    <rds-barcode member-id="978020137962"></rds-barcode>
  </div>
</template>

Without a framework

Integrating a component built with Stencil to a project without a JavaScript framework is straight forward. If you're using a simple HTML page, you can add your component via a script tag. For example, if we published a component to npm, we could load the component through unpkg like this:

<!DOCTYPE html>
<html lang="en">
<head>
  <script src="https://unpkg.com/test-components/latest/dist/test-components.js"></script> 
</head>
<body>
  <test-component></test-component>
</body>
</html>

Alternatively, if you wanted to take advantage of ES Modules, you could include the components using an import statement. Note that in this scenario applyPolyfills is needed if you are targeting Edge or IE11.

<!DOCTYPE html>
<html lang="en">
<head>
  <script type="module">
    import { applyPolyfills, defineCustomElements } from 'https://unpkg.com/test-components/latest/dist/esm/es2017/test-components.define.js';
    applyPolyfills().then(() => {
      defineCustomElements(window);
    });
  </script> 
</head>
<body>
  <test-component></test-component>
</body>
</html>

Passing object props from a non-JSX element

Setting the prop manually

import { Prop } from '@stencil/core';
 
export class TodoList {
  @Prop() myObject: object;
  @Prop() myArray: Array<string>;
}
<todo-list></todo-list>
<script>
  const todoListElement = document.querySelector('todo-list');
  todoListElement.myObject = {};
  todoListElement.myArray = [];
</script>

Watching props changes

import { Prop, State, Watch } from '@stencil/core';
 
export class TodoList {
  @Prop() myObject: string;
  @Prop() myArray: string;
  @State() myInnerObject: object;
  @State() myInnerArray: Array<string>;
 
  componentWillLoad() {
    this.parseMyObjectProp(this.myObject);
    this.parseMyArrayProp(this.myArray);
  }
 
  @Watch('myObject')
  parseMyObjectProp(newValue: string) {
    if (newValue) this.myInnerObject = JSON.parse(newValue);
  }
 
  @Watch('myArray')
  parseMyArrayProp(newValue: string) {
    if (newValue) this.myInnerArray = JSON.parse(newValue);
  }
}
<todo-list my-object="{}" my-array="[]"></todo-list>

Readme

Keywords

none

Package Sidebar

Install

npm i rewards-ds

Weekly Downloads

28

Version

1.0.0

License

MIT

Unpacked Size

40.5 MB

Total Files

302

Last publish

Collaborators

  • granfar
  • diced-dev
  • kwooms
  • harrisonkhannah