@simpleview/cms-component-library
v0.1.23
Published
Simpleview CMS Component Library
Downloads
183
Maintainers
Keywords
Readme
CMS Component Library
Simpleview CMS Component Library
Table of Contents
Quickstart - A guide to setting up the repo
NPM Scripts - A list of scripts available in the package.json
Repo Structure - An guided explanation of the repo stucture
Unit Testing Overview - Overview and example of unit testing with Jest
Storybook Stories Overview - Overview and example of stories in Storybook
NPM Package - Deploying the npm package
References - A list of useful links and resources, including snippet information
Quick Start
Install NodeJS
- For Powershell: Download the Windows installer (LTS version)
- For WSL/Ubuntu: Run the commands below in the terminal:
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash - sudo apt-get install -y nodejs
Clone this repository to your local machine
- Example using TortoiseGit:
- Navigate (or created as needed) to D:\cms30\ via File Explorer (this is the recommend folder location, but not required).
- Right click inside the folder and select "Git Clone..."
- Use
[email protected]:simpleviewinc/cms-component-library.git
for the URL. This will use your global GitHub user keys setup during the sv-kubernetes setup. - Click the button labeled "OK" and wait for the repo to checkout. This will create a folder called cms-component-library at D:\cms30\cms-component-library.
- Example using terminal or Windows CMD:
- In your terminal, navigate (or created as needed) to D:\cms30\ or ~/cms30 (this is the recommend folder location, but not required).
- Execute
git clone [email protected]:simpleviewinc/cms-component-library.git
cd D:/cms-30 # or whichever folder you are saving this in git clone [email protected]:simpleviewinc/cms-component-library.git
- Example using TortoiseGit:
Install Dependencies
- Open CMD Prompt (or your terminal of choice) and cd to D:\cms30\cms-component-library:
cd cms-component-library
- Execute
npm install
cd cms-component-library npm install
- Open CMD Prompt (or your terminal of choice) and cd to D:\cms30\cms-component-library:
Configure VS Code
Download the ESLint extension for VS Code.
Open your command palette (
Ctrl+Shift+P
on Windows andCmd+Shift+P
on Mac) and search for settings. Select the "Preferences: Open Settings (JSON)" option.Add the following JSON block to your settings.json file:
"eslint.validate": [ "javascript", "javascriptreact", "typescript", "typescriptreact", ], "editor.codeActionsOnSave": { "source.fixAll.eslint": true, },
Start Storybook
Storybook is the main method of local testing.- Open CMD Prompt (or your terminal of choice) and cd to D:\cms30\cms-component-library:
cd cms-component-library
- Execute
npm run storybook
- Visit
http://localhost:6006
on your local machine
cd cms-component-library npm run storybook
- Open CMD Prompt (or your terminal of choice) and cd to D:\cms30\cms-component-library:
NPM Scripts
A list of the scripts available via package.json
and their functions. Scripts are run via the command npm run [script]
storybook
: Starts up Storybookbuild-storybook
: Builds storybook for production (GitHub Pages)code-quality
: Run type-check, lint, and prettiertype-check
: Run TypeScript against all code to check for type errorslint
: Lint all code, fix anything that can be fixed byeslint
in the processprettier
: Format all code, overwrite filestest
: Run all testsbuild
: Build NPM Package todist
folderpublish
: Publish NPM release
Repo Structure
.storybook
: Configuration for Storybook.vscode
: Global snippets__MOCKS__
: Jest mocks, used to stub out API or filesystem calls - Learn Moresrc
: Main source code pathindex.tsx
: Main export for NPM package, if a component is not exported here, it won't be in the NPM package (More on NPM below)components
: React components and their corresponding CSS filesComponentName/ComponentName.tsx
: The component itselfComponentName/ComponetName.spec.tsx
: Tests forComponentName
component (More on tests below)ComponentName/ComponentName.stories.tsx
: Stories forComponentName
componet. (More on stories below)ComponentName.module.css
: CSS styles forComponentName
stories
: Storybook Introduction and stories not tied to a componentIntroduction.stories.mdx
: The intro page of storybook that outlines the storybook structureassets
: Assets for the introduction story and others not tied to specific componentsdocumentation
: Stories not tied to specific components, typically to display foundation styling
styles
: Global CSS filesglobal.css
: Globally scoped CSSnormalize.css
: Cross-browser default styles rebootfoundations.css
: Global CSS variables (will be replacingswatches.css
in the future)swatches.css
: Global CSS variables (formerlyvariables.css
)
hooks
: Path for all custom hookstypes
: Path for all shared typeslib
: Old SV libraries converted to TypeScriptutils
: Generic re-usable utilities
.eslintrc.yml
: ESLint configuration.prettierrc
: Prettier configurationjest.config.ts
: Jest configurationjest.setup.ts
: Jest setup (runs before all tests)
Unit Testing
We use Jest and React Testing Library to unit test every component. We also include jest-axe unit tests in every component test suite for basic accessibility coverage.
Unit tests are saved as ComponentName.spec.tsx
As an example of a basic test, here we are testing the Link component using the getByText query:
import React from 'react';
import { render } from '@testing-library/react'; // react-testing-library
// We do not need to import Jest, when we run tests
// it is Jest that runs these files, so all Jest
// functions are implicit
import Link from '../Link'; // This is the component we are testing
import { axe, toHaveNoViolations } from 'jest-axe'; // Jest-axe provides basic testing for common accessibility issues
expect.extend(toHaveNoViolations); // This adds the jest-axe custom Jest matcher to check for accessibility issues
// We start with `describe`, we are describing our Link component
describe('Link Component', () => {
// We expect that `it` `Renders Correctly`, you can have
// multiple `it` blocks if your component is more complex
// and requires testing different scenarios
it('Renders Correctly', () => {
// Here we are defining some variables to use as props
// for the component
const to = {
url: 'https://simplevieweinc.com/',
target: '_blank',
};
const childText = 'test text';
// This is an extra prop, we also want to make sure they are tested,
// check the Link component to see where the extra props are passed
const rel = 'noopener noreferrer';
// We get any queries we want to use (`getByText` here) from the
// `render` function of react-testing-library, and pass in our
// component with the mock data above, check the documentation
// for react-testing-library for more available queries
const { getByText } = render(
<Link
to={to}
rel={rel}
>
{childText}
</Link>,
);
// We should see the test within `childText` in the rendered component
const linkElement = getByText(childText);
// We expect to have found the element rendered by our component
expect(linkElement).toBeDefined();
// We expect the `target`, `href`, and `rel` attributes to be
// added to the element as defined by the Link component. Check
// the Jest documentation for more on `expect` Matchers.
expect(linkElement).toHaveProperty('target', to.target);
expect(linkElement).toHaveProperty('href', to.url);
expect(linkElement).toHaveProperty('rel', rel);
});
// A version of this test is added to every compoonent's unit tests
// to ensure that there are no testable accessibility (a11y) violations
// utilizing jest-axe's `.toHaveNoViolations()`.
it('should not have any testable a11y violations', async () => {
const { container } = render(
<WrapLink
link={{
url: '/',
}}
data-testid='wrap-link-test'
>
Test Text
</WrapLink>,
);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
});
Stories
Storybook is an open source tool for building UI components and pages in isolation. It streamlines UI development, testing, and documentation.
Storybook Documentation
We use Storybook to document our components. Storybook auto-generates documentation from comments in the component code, so it's crucial to add clear and contextual comments directly in the component files, not in the story files.
An example of the Docs page for the Link component
Here is an example showing the comments for the Link component's props that are automatically converted to Storybook Docs:
export type LinkProps = {
/**
* The `to` object specifies the URL to link to, and optionally a target that specifies where to open the linked document.
*/
to: LinkAsset;
/**
* The target attribute specifies where to open the linked document, overriding the `target` key in the `to` object.
*/
target?: '_self' | '_blank' | '_parent' | '_top';
}
In the above code example, the LinkProps
will automatically render like this:
NOTE: In the above code example the comment
/** **/
that is directly above the prop is used in Storybook as documentation for that prop. Storybook will be able to auto-detect the type and default (most of the time).
After the props are declared, the component description should be added that explains the general purpose or function of the component as well as any helpful clarifications. This will also display at the top of the Storybook Doc.
Here's an example below of the comments for the Link component. If you visit the Link component in Storybook you can see these comments translated into the Link description at the top of the page.
/**
* The Link component is used to trigger an action or event where the primary intention is navigation.
*
* The `target` property can be specified in two places, either as a property of the `to` object, or
* as a prop on the Link component itself. If both are specified, the `to` object is ignored.
* This way, you can override the target without modifing the `to` object.
*/
Storybook Story Example
Stories are saved as ComponentName.stories.tsx
Here is an example of a story for our Link component:
import React from 'react';
import { Link } from '../components';
// The title here translates to the story `Link` in the `UI Controls` folder
export default {
title: 'UI Controls/Link',
component: Link,
};
// Render the Link component
const Template: StoryFn<typeof Link> = (args) => {
const { children } = args;
return <Link {...args}>{children}</Link>;
};
// `Standard` is a layout displayed in Storybook,
// we can define multiple layouts if needed (e.g. `SecondStandard`).
// The args passed to primary are the props
// that the rendered component will receive.
export const Standard = Template.bind({});
Standard.args = {
to: {
url: '/',
target: '_self',
},
target: '_self',
variant: 'link',
children: 'I am a link',
};
// `SecondStandard` is an additional layout displayed
// in Storybook, that uses the same Template as `Standard`,
// but with it's own unique props.
export const SecondStandard= Template.bind({});
Standard.args = {
to: {
url: '/',
target: '_blank',
},
target: '_blank',
variant: 'link',
children: 'I am a second link',
};
NPM Package
See the NPM Release Documentation for instructions on deploying new versions to NPM.
References and Resources
Snippets
We have included some helpful boilerplate snippets for VSCode users.
There are currently the following named snippets:
svcomponent
- the boilerplate for a new componentsvtest
- the boilerplate for a new Jest test suitesvstory
- the boilerplate for a new Storybook story
To use these snippets:
- Create the folder for the new component and the relating file (
NewComponent.tsx
,NewComponent.spec.tsx
,NewComponent.stories.tsx
respectively) - Type the snippet name in the body of the file and press
Tab
- The boilerplate should render and allow you to change the
ComponentName
, if needed - Tab through to update the name of secondary parameters, if any.