g-nimbus-ui v3.0.16
Getting Started
- create
.npmrcfile 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.jsonas adependencyadd
cssstyles 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 cardwill automatically compile toDashboardCardin 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 memoized 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.
classNamevalues should be referenced from anenumresiding within theTypescript Definitions and Markup Modelsfile. Read more about the ClassNamesenumbelow.idvalues should be referenced from a declaredidModelobject powered by theIdModelresiding within theTypescript Definitions and Markup Modelsfile. Read more about theIdModelbelow.- Components should be exported in two ways:
memoized and not. The default export should bememoized. This is done to support React Docgen asmemoized 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
themeprop, amixinshould be created to fulfil the requirements of the themed paint-job - Styling should be namespaced. Use the
$namespacevariable 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
BaseComponentPropsgeneral 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
classNamevia prop classNamevalues should be powered by an exportedenum. This is done to provide an easy and scalable reference of selectors in automation tests.idvalues should be powered by anIdModel, which should start by extending theIdModelBasegeneral class. This is done to support dynamicidgeneration, further providing easy and scalable references of selectors in automation tests. To read more about how theIdModelcontributes 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
propConfigthat 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 secondaryInteractivestory that controls the component through state to give users a more hands-on look. - Use the actions addon to supplement the
propConfigwith 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
Defaultstory - 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
FillerBlockcomponent
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 packwhich will generate a.tbzfile.
In the project you want to use your local version of nimbus-ui:
- Delete the
package-lock.json. - Delete the
@q4/nimbus-uifolder. - In your
package.jsonpoint the@q4/nimbus-uidependency to the generated.tbzfile. - Run
npm i.