g-nimbus-ui
v3.0.16
Published
A shared UI library for React.js
Downloads
7
Readme
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 thepackage.json
as adependency
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:
- Run
npm run plop
(if you have it installed globally, you can just runplop
). - 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 toDashboardCard
in the respectively generated files). - Don't forget to add your component to the list of exported
definitions
. - 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 memo
ized component.
Core Component / exampleComponent.component.tsx
- Components should be built as stateless functional components and leverage hooks to achieve any stateful results.
- Order of code should follow a consistent pattern. Take a look at the code block below for reference.
className
values should be referenced from anenum
residing within theTypescript Definitions and Markup Models
file. Read more about the ClassNamesenum
below.id
values should be referenced from a declaredidModel
object powered by theIdModel
residing within theTypescript Definitions and Markup Models
file. Read more about theIdModel
below.- Components should be exported in two ways:
memo
ized and not. The default export should bememo
ized. This is done to support React Docgen asmemo
ized 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 )
- Components should follow the Q4 Design System
- If the component accepts a
theme
prop, amixin
should be created to fulfil the requirements of the themed paint-job - Styling should be namespaced. Use the
$namespace
variable to ensure this. - 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
- 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 - If an icon is used within the component, the consumer should always have the ability to overwrite the icon
className
via prop className
values should be powered by an exportedenum
. This is done to provide an easy and scalable reference of selectors in automation tests.id
values should be powered by anIdModel
, which should start by extending theIdModelBase
general class. This is done to support dynamicid
generation, further providing easy and scalable references of selectors in automation tests. To read more about how theIdModel
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
- 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 secondaryInteractive
story that controls the component through state to give users a more hands-on look. - 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. - Use the specifications addon to run unit tests within the
Default
story - Use the a11y addon to ensure accessibility requirements are being met. Violations should be reported to the UI/UX Guild.
- 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
:
- Run
npm run build-module
. - Run
npm pack
which will generate a.tbz
file.
In the project you want to use your local version of nimbus-ui
:
- Delete the
package-lock.json
. - Delete the
@q4/nimbus-ui
folder. - In your
package.json
point the@q4/nimbus-ui
dependency to the generated.tbz
file. - Run
npm i
.