3.0.16 • Published 3 months ago

g-nimbus-ui v3.0.16

Weekly downloads
-
License
MIT
Repository
github
Last release
3 months ago

Code style Built with Typescript Badge

Getting Started

  • create .npmrc file containing the following
registry=https://registry.npmjs.org/
scope=q4
@q4:registry=https://registry.npmjs.org/
//registry.npmjs.org/:_authToken=<NPM TOKEN>
  • add "@q4/nimbus-ui": "^X.X.X" to the package.json as a dependency

  • add css styles file to main tsx, ts, js, scss, or css file

// or main tsx/ts/js file
import "../node_modules/@q4/nimbus-ui/dist/_styles.css";
// main scss/css file
@import "../../node_modules/@q4/nimbus-ui/dist/styles";
  • add ConfigProvider to main tsx/ts file
import { ConfigProvider as NimbusConfigProvider } from "@q4/nimbus-ui";
...

// using styleguide v1
render(
  <NimbusConfigProvider styleGuide={StyleGuide.V1}>
    ...
  </NimbusConfigProvider>,
  document.getElementById("root")
);

// using styleguide v2
render(
  <NimbusConfigProvider>
    ...
  </NimbusConfigProvider>,
  document.getElementById("root")
);

// using v1ClassNames
render(
  <NimbusConfigProvider useV1ClassName>
    ...
  </NimbusConfigProvider>,
  document.getElementById("root")
);
  • add global variables to main scss file only when using v1 styles
// using styleguide v1
@import "node_modules/@q4/nimbus-ui/dist/v1/variables";

Changelog

View breaking changes here

Building New Components

If you would like to create a new component, start with plop. Our plop templates are designed to provide consistency in development, and here's how you can take advantage of that:

  1. Run npm run plop (if you have it installed globally, you can just run plop).
  2. You will be prompted to enter a name for your new component. Multi-worded components don't need to be entered as camelCase, but rather, in natural language (ex: dashboard card will automatically compile to DashboardCard in the respectively generated files).
  3. Don't forget to add your component to the list of exported definitions.
  4. Build!

Component Composition

Each component is built using typescript and comes with a set of expectations as outlined below. Note that each piece is covered (at least to a starting point) by the plop templates.

│ Nimbus UI src/components
├── ...
├── exampleComponent
│   ├── index.ts                             # Index file responsible for convinient export
│   ├── exampleComponent.component.tsx       # Core component
│   ├── exampleComponent.definition.ts       # Typescript definitions and markup models
│   ├── exampleComponent.spec.tsx            # Unit tests
│   ├── exampleComponent.style.tsx           # Styled Component
│   ├── exampleComponent.stories.tsx         # Storybook documentation
└── ...

Consider the following below items for each file within the composition.

Index / index.ts

Used to provide easy exporting of the component straight from the component directory. The default export should reference the memoized component.

Core Component / exampleComponent.component.tsx

  1. Components should be built as stateless functional components and leverage hooks to achieve any stateful results.
  2. Order of code should follow a consistent pattern. Take a look at the code block below for reference.
  3. className values should be referenced from an enum residing within the Typescript Definitions and Markup Models file. Read more about the ClassNames enum below.
  4. id values should be referenced from a declared idModel object powered by the IdModel residing within the Typescript Definitions and Markup Models file. Read more about the IdModel below.
  5. Components should be exported in two ways: memoized and not. The default export should be memoized. This is done to support React Docgen as memoized components cannot be used for prop type documentation generation.
│ Nimbus UI Component
├── imports
├── exported component declaration (appropriated documentation note above)
│   ├── prop declarations
│   ├── state or other hook declarations
│   ├── variable declarations, usually starting with the idModel and baseClassName
│   ├── useEffect declarations
│   ├── getter / setter functions
│   ├── handler functions
│   ├── supporting render functions
│   ├── returned JSX
├── default named export wrapped in memo
└──

Styles / exampleComponent.component.scss

V2 components should not use scss but should instead use styled compoents ( emotionJS )

  1. Components should follow the Q4 Design System
  2. If the component accepts a theme prop, a mixin should be created to fulfil the requirements of the themed paint-job
  3. Styling should be namespaced. Use the $namespace variable to ensure this.
  4. Order of styles should follow a consistent pattern. Take a look at the code block below for reference.
│ Nimbus UI Component Styles
├── imports
├── theme mixin
├── namespaced wrapping selector
│   ├── styles for elements ordered as they appear (varies)
│   ├── modifier styles
│   ├── theme styles
└──

Typescript Definitions and Markup Models / exampleComponent.definition.ts

  1. Component props should always start by extending either one of the BaseComponentProps general interfaces or a provided third-party library interface if you're looking to wrap a community component
  2. If an icon is used within the component, the consumer should always have the ability to overwrite the icon className via prop
  3. className values should be powered by an exported enum. This is done to provide an easy and scalable reference of selectors in automation tests.
  4. id values should be powered by an IdModel, which should start by extending the IdModelBase general class. This is done to support dynamic id generation, further providing easy and scalable references of selectors in automation tests. To read more about how the IdModel contributes to automation, take at a look at Getting Started with Nightwatch Automation. Additionally, the to get a better idea of effective tagging, take a look at Tagging of UI Element for Tracking and Automation.
export class CardListId extends AutomationListId<CardIdModel> {
  constructor(parentId: string) {
    const prefix = "Card-";
    super(parentId, prefix, CardIdModel);
  }
}

export class CardIdModel extends IdModelBase {
  title: string;
  spinner: string;

  constructor(id: string, index?: number | string) {
    super(id, index);
    if (isNullOrWhiteSpace(this.id)) return;

    this.title = `${this.id}Title`;
    this.spinner = `${this.id}Spinner`;
  }
}

export function generateCardClassName(className: string) {
  if (isNullOrWhiteSpace(className)) return {};

  return {
    Base: className,
    BaseWithLoadingModifier = `${className}--loading`,
    BaseWithAccentedModifier = "`${className}--accented`,
    Header = `${className}_header`,
    Title = `${className}_title`,
    HeaderChildren = `${className}_header-children`,
    Body = `${className}_body`,
    Spinner = `${className}_spinner`,
  };
}

export const CardBaseClassName = "nui-card";

export const CardClassNames = generateCardClassName(CardBaseClassName);

Unit Tests / exampleComponent.spec.tsx

Test coverage is a requirement for components to be pushed to production. The plop template will get you started, but additional coverage should be included based on our guidelines. To put it simply, unit tests should, at a minimum, cover functionality that the user expects when using the component.

Storybook Documentation / exampleComponent.stories.tsx

  1. Use the controls addon to provide a propConfig that the user can configure. Storybook customization of components should be strictly knob based, but if value can be found in interacting with the component, create a secondary Interactive story that controls the component through state to give users a more hands-on look.
  2. Use the actions addon to supplement the propConfig with callback listeners with the following format: [Component name] [callback prop name] has been triggered. If extending an existing component for a new use-case, specify the component that the callback is inherited from.
  3. Use the specifications addon to run unit tests within the Default story
  4. Use the a11y addon to ensure accessibility requirements are being met. Violations should be reported to the UI/UX Guild.
  5. If filler content can be used to provide additional documentation or usability insights, use the FillerBlock component

Additional Assets

External Dependancy Definitions

External Dependancy definitions are being exported so if you are using typescript there is no need to install them as dev dependancies in your project. Each external definition is in the dependancies folder inside /dist.

For example, they can be reference like this: import type { sampleGroup } from "@q4/nimbus-ui/dist/dependencies/sample";

Icons

Icons should be delivered from IcoMoon with the following format: [namespace]-[icon name]-[weight in pt]. The first portion of this format is already determined, as all Nimbus UI icons are namespaced with ni (ex: ni-plus-2pt). To update the icons, replace the files located in src/styles/nimbus with the new files generated by IcoMoon.

Using Your Local Version of Nimbus UI

If you are working on Nimbus UI and want to use the version you are developing (ie, your local version) in another project, follow these steps:

In nimbus-ui:

  1. Run npm run build-module.
  2. Run npm pack which will generate a .tbz file.

In the project you want to use your local version of nimbus-ui:

  1. Delete the package-lock.json.
  2. Delete the @q4/nimbus-ui folder.
  3. In your package.json point the @q4/nimbus-ui dependency to the generated .tbz file.
  4. Run npm i.