|
| 1 | +# Spectrum CSS Components |
| 2 | + |
| 3 | +The project is broken down into separate components for each component inside of the `components/` folder. |
| 4 | + |
| 5 | +Components are released on npm as `@spectrum-css/$COMPONENT`, where `$COMPONENT` corresponds to the folder name in this repository. |
| 6 | + |
| 7 | +## Component structure |
| 8 | + |
| 9 | +Each component has the following files: |
| 10 | + |
| 11 | +- `index.css` - The scale-specific styles for the component: dimensions, layout, etc (these change between scales) |
| 12 | +- `metadata/*.yml` - The markup examples and documentation for the component; also makes additional examples possible that appear separately in the site navigation. |
| 13 | +- `themes/*.css` - The theme-specific styles for the component. |
| 14 | +- `stories/*.stories.js` and `stories/template.js` - The storybook assets for rendering components in the Storybook tool and eventually to be used for visual regression testing. |
| 15 | + |
| 16 | +## Editing an existing component |
| 17 | + |
| 18 | +1. Run `gulp dev` in the root of the project to begin developing. |
| 19 | +2. Edit `components/$COMPONENT/index.css` with dimensions and color properties. The documentation will live reload with your changes. |
| 20 | +3. Edit the markup examples within `components/$COMPONENT/metadata/*.yml`. The documentation will live reload with your changes. |
| 21 | + |
| 22 | +## Adding a new component |
| 23 | + |
| 24 | +1. Generate a new component using the `yarn new component` command. The generator will prompt you to answer questions about your component. |
| 25 | +2. Edit the `dependencies` within the `package.json` file to use only the dependencies your component needs. All components rely on `@spectrum-css/tokens` and `@spectrum-css/component-builder-simple`, and most rely on `@spectrum-css/icon`. **Note: If you are working on a legacy component, it will dependend on `@spectrum-css/vars` and `@spectrum-css/component-builder` instead. This is expected.** |
| 26 | +3. Once your folder has been generated, you can run `yarn dev` in the root of the project to begin developing. |
| 27 | +4. The `index.css` file is where most of your styles will be added. |
| 28 | +5. Inside the `stories` directory you will find a `template.js` and an `*.stories.js` file. |
| 29 | + - In the `*.stories.js` file, define the available knobs and properties for your component, as well as any standard variations you want to surface in [Storybook](https://storybook.js.org/docs/react/writing-stories/introduction). |
| 30 | + - Update the `template.js` file with the markup, using [lit-html syntax](https://lit.dev/docs/templates/overview/) to adjust results based on the provided settings from the Storybook knobs. |
| 31 | +6. Edit your `metadata/*.yml` to add markup examples for each of the variants of your component. |
| 32 | + |
| 33 | +Because we use scoped packages, before it can be published with Lerna, you must manually publish the new component as public: |
| 34 | + |
| 35 | +```shell |
| 36 | +cd components/newcomponent |
| 37 | +npm publish --access=public |
| 38 | +``` |
| 39 | + |
| 40 | +## Component dependencies |
| 41 | + |
| 42 | +1. If your component requires another component in order to render, it should be declared in both `devDependencies` and `peerDependencies`. |
| 43 | + 1. The version range included in `peerDependencies` must satisfy the version included in `devDependencies`. |
| 44 | + 2. If a component appears in `peerDependencies`, it must also appear in `devDependencies`. |
| 45 | + 3. This goes for every class used to render the component; even if the class comes from a component that's a dependency of another component you already have a dependency on. |
| 46 | + 4. For instance, if your component requires a button with an icon inside of it, you must explicitly include both `icon` and `button` in both `devDependencies` and `peerDependencies`. |
| 47 | +2. If your component has an example that uses another component, but the component isn't required to render your component, it should be declared in `devDependencies` only. |
| 48 | + 1. For instance, if your component is commonly used with a table and includes an example where it is used with a table, but doesn't require table to render itself, you should declare `table` in `devDependencies` only. |
| 49 | + |
| 50 | +For example, `actionbar` gets its tokens from `vars`, and requires `button`, `checkbox`, `icon`, and `popover` to render, but also has an example where the component is used with a `table`. Its dependencies should be declared as follows: |
| 51 | + |
| 52 | +```json |
| 53 | +{ |
| 54 | + "name": "@spectrum-css/actionbar", |
| 55 | + "peerDependencies": { |
| 56 | + "@spectrum-css/button": ">=12, |
| 57 | + "@spectrum-css/checkbox": ">=8", |
| 58 | + "@spectrum-css/icon": ">=6", |
| 59 | + "@spectrum-css/popover": ">=6", |
| 60 | + "@spectrum-css/tokens": ">=14.0.0-next.3" |
| 61 | + } |
| 62 | +} |
| 63 | +``` |
| 64 | + |
| 65 | +The release will error out if: |
| 66 | + |
| 67 | +1. A package is specified in `peerDependencies` that does not appear in `devDependencies` |
| 68 | +2. The version of a package is specified in `devDependencies` satisfy the range defined for that package in `peerDependencies` |
| 69 | + |
| 70 | +## Releasing components |
| 71 | + |
| 72 | +Any change to a component or a component's dependencies will require a release of that component and all components that depend upon it. Component releases cannot be done ala carte and must be done from the top-level. |
| 73 | + |
| 74 | +See [Releasing](/README.md#Releasing) for more information. |
0 commit comments