Skip to content

chore: update styling guide #5437

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion PULL_REQUESTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ Incomplete templates may delay the review process.
- `breaking-change`: PR contains changes that break backward compatibility
- `help-wanted`: Extra attention is needed on this PR
- `on-hold`: PR needs more discussion.
- `Spectrum CSS`: An issue or pull request specific to the CSS being used by components.
- `Component: [Name]`: PR effects this component

Apply labels promptly to help maintainers prioritize and manage the review queue.
Expand Down
24 changes: 4 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,13 @@ Creating a new component from the command line can be done by running the follow
$ yarn new-package
```

This will scaffold your component's required architecture by prompting you for 2 data points - the desired name for your package and the name of the Spectrum CSS asset from which you will be building.
This will scaffold your component's required architecture by prompting you for the desired name for your package.

? **SWC package name (i.e. color-area)**

_Note_ that your component name should be provided in kebab case and should relate as closely as possible to the Spectrum core naming.

? **Spectrum CSS package name (i.e. colorarea)**

You can find this information in the [Spectrum CSS GitHub project](https://github.com/adobe/spectrum-css) by finding the component package.json (i.e., `components/accordion/package.json`)

For additional information, please see the [generating components documentation](https://opensource.adobe.com/spectrum-web-components/guides/generating-components) and capturing the value of the package name: `"name": "@spectrum-css/accordion"`. In this example, that name is `accordion`. _Note_ that the project scope `@spectrum-css` is stripped out of the response.
For additional information, please see the [generating components documentation](https://opensource.adobe.com/spectrum-web-components/guides/generating-components)

# Storybook

Expand Down Expand Up @@ -77,24 +73,11 @@ In the case that you'd like to serve and test a static build of the documentatio
yarn docs:build
```

# Updating Spectrum CSS

There are two mechanisms for broadly updating SWC's Spectrum CSS dependencies:

- `yarn update:spectrum-css` brings all Spectrum CSS dependencies to 'latest'
- `yarn update:spectrum-css:nonbreaking` brings them to the latest minor or patch version

We aim to keep Spectrum CSS as current as possible, to track the Spectrum design system closely.
The `:nonbreaking` variant lets us release patch updates quickly in cases where more work is required to be compatible with 'latest.'

# Advanced development

There are several commands that can be useful in specific scenarios:

- `yarn build:clear-cache` to remove previously created artifacts of the `tsc build` process.
- `yarn spectrum-vars` to ensure that theme files are up-to-date.
- `yarn process-icons` to make sure that the most recent icons are included.
- `yarn process-spectrum` to process the spectrum CSS style sources into the individual packages.
- `yarn build` to make sure the available JS has been built from the current TS source.

## Linting
Expand Down Expand Up @@ -151,7 +134,7 @@ Visual regression testing is done against screens derived from the exports of th

#### Keeping CI assets updated

If you find the `visual-*` jobs failing on CircleCI for reasons that you expect (you've updated the Spectrum CSS dependencies, you've added new tests, etc.) then you will need to update the golden images cache key before your build will pass. You can review and share the diffs for a test pass via a URL shaped like `vrt--spectrum-wc.netlify.app/${branchName}`. Before updating the cache key, be sure that the updated caches are both complete (there are times when process errors prevent images from being correctly created or when certain test passes take longer than others) and appear as expected. If you agree with the updated cache content, update the golden images cache key as follows.
If you find the `visual-*` jobs failing on CircleCI for reasons that you expect (you've updated components css, you've added new tests, etc.) then you will need to update the golden images cache key before your build will pass. You can review and share the diffs for a test pass via a URL shaped like `vrt--spectrum-wc.netlify.app/${branchName}`. Before updating the cache key, be sure that the updated caches are both complete (there are times when process errors prevent images from being correctly created or when certain test passes take longer than others) and appear as expected. If you agree with the updated cache content, update the golden images cache key as follows.

Your failing branch will have created a new cache with a key of `v1-golden-images-{{ .Revision }}-<< parameters.regression_color >>-<< parameters.regression_scale >>-<< parameters.dir >>-{{ epoch }}`. Here `{{ .Revision }}` outlines the git commit hash of the current CI pass. In `.circleci/config.yml`, you will use that to update the cache that is requested at the beginning of the `run-regressions` job. As part of the review site, the git commit hash will be listed in the side navigation UI for easy access, use this number to update the `current_golden_images_hash` paramater that appears as follows:

Expand Down Expand Up @@ -187,6 +170,7 @@ There is extended documentation on adding a new component to the library in the
- new-component-name.ts
- spectrum-config.js
- spectrum-new-component-name.css
- new-component-name-overrides.css
- stories
- new-component-name.stories.ts
- test
Expand Down
290 changes: 1 addition & 289 deletions projects/documentation/content/guides/adding-component.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@ slug: developing-component
This guide explains the techniques involved in the ongoing development a Spectrum control
as a <sp-link href="https://github.com/adobe/spectrum-web-components">spectrum-web-components</sp-link>.

The components in spectrum-web-components are based on the CSS definitions in
<sp-link href="https://github.com/adobe/spectrum-css">spectrum-css</sp-link>. Typically, component
implementations contain very little code. The CSS from the `spectrum-css`
project typically specifies most, if not all, of the presentation details.

## What is a web component?

According to <sp-link href="https://www.webcomponents.org/introduction">webcomponents.org</sp-link>,
Expand All @@ -29,7 +24,6 @@ web components are:
In order to add a new component to this library, you will need to develop a
working knowledge of the following technologies:

- <sp-link href="https://github.com/adobe/spectrum-css">Spectrum CSS</sp-link>: A CSS implementation of the Spectrum design language
- <sp-link href="https://developers.google.com/web/fundamentals/web-components/customelements">Web Components</sp-link>: Standards based method for adding new HTML tags to a browser
- <sp-link href="https://developers.google.com/web/fundamentals/web-components/shadowdom">Shadow DOM</sp-link>: The part of the Web Component spec that allows for encapsulation of component styles and child nodes
- <sp-link href="https://lit-element.polymer-project.org/guide">lit-element</sp-link>: A simple base class for creating fast, lightweight web components
Expand All @@ -45,81 +39,7 @@ the heart of a web component. It isolates the component from the styles and DOM
of the containing page. While this offers many benefits, it also means that we
must structure our CSS very differently.

The CSS from the <sp-link href="https://github.com/adobe/spectrum-css">spectrum-css</sp-link> project
is intended to be installed globally on a web page. Using it in the context of a
web component requires that we modify it. To facilitate that, this project comes
with a <sp-link href="https://github.com/adobe/spectrum-web-components/blob/master/tasks/process-spectrum.js">config-driven processor</sp-link> that can transform the Spectrum CSS into a format
that can be consumed in a web component.

The first step is to create a directory and a `spectrum-config.js` file for your
new component. This config file contains information about the structure of
the web component in relation to the Spectrum CSS classes.

Below is a fragment of the <sp-link href="https://github.com/adobe/spectrum-web-components/blob/master/src/button/spectrum-config.js">`spectrum-config.js` file for `sp-button`</sp-link>.

```javascript
const config = {
conversions: [
{
inPackage: '@spectrum-css/button',
outPackage: 'button',
fileName: 'button',
excludeByComponents: [builder.element('a')],
components: [
converter.classToHost(),
converter.classToAttribute('spectrum-Button--quiet'),
converter.classToAttribute('is-disabled', 'disabled'),
converter.pseudoToAttribute('disabled', 'disabled'),
...converter.enumerateAttributes(
[
['spectrum-Button--sizeS', 's'],
['spectrum-Button--sizeM', 'm'],
['spectrum-Button--sizeL', 'l'],
['spectrum-Button--sizeXL', 'xl'],
],
'size'
),
converter.classToId('spectrum-Button-label'),
converter.classToSlotted('spectrum-Icon', 'icon'),
{
find: [
builder.class('spectrum-Icon'),
builder.combinator('+'),
builder.class('spectrum-Button-label'),
],
replace: [
{
replace: builder.attribute('name', 'icon', 'equal'),
hoist: false,
},
builder.combinator('+'),
builder.id('label'),
],
},
{
hoist: false,
find: builder.pseudoClass('empty'),
replace: builder.attribute('hidden'),
},
],
},
],
};
```

If we wanted to create a button component using this config file, the steps would be as
follows:

1. Make the directory <sp-link href="https://github.com/adobe/spectrum-web-components/tree/master/src/button">`src/components/button`</sp-link>
2. In that new directory, create a <sp-link href="https://github.com/adobe/spectrum-web-components/blob/main/packages/button/src/spectrum-config.js">`spectrum-config.js`</sp-link>
file with the above contents
3. Run the command `yarn process-spectrum` to create the <sp-link href="https://github.com/adobe/spectrum-web-components/blob/main/packages/button/src/spectrum-button.css">CSS file</sp-link>

When you do the above, the <sp-link href="https://github.com/adobe/spectrum-web-components/blob/main/scripts/process-spectrum-postcss-plugin.js">config-driven processor</sp-link>
will look in the <sp-link href="https://github.com/adobe/spectrum-css">`spectrum-css`</sp-link> project
for the <sp-link href="https://unpkg.com/@spectrum-css/button/dist/index-vars.css">matching CSS file</sp-link>.
It will parse that file and restructure the CSS as per the configuration
instructions.
For more information on how to structure your CSS, see the [Styling](/guides/styling-components) guide.

## Structure of a Spectrum Web Component

Expand All @@ -143,214 +63,6 @@ structure that looks like this.
If anything here looks unfamiliar, it is probably a good time to do some reading
about <sp-link href="https://developers.google.com/web/fundamentals/web-components/customelements">web components</sp-link>.

You can compare this markup with the <sp-link href="http://opensource.adobe.com/spectrum-css/2.13.0/docs/#button---cta">reference markup in the `spectrum-css` documentation</sp-link>

### Host Class Mapping

We need to determine what the main CSS class is for our component in the
original `spectrum-css`. In the case of `sp-button`, we can see that the
top-level class is `.Spectrum-Button`. We then need to determine where we want
that CSS to be applied. In many cases, you will want that CSS to be applied to
the actual web component via the `:host` selector. That is the default behaviour
of the conversion script. In this case, we wanted to preserve all of the default
behaviour of the `button` element in HTML. So, we want the main CSS to be
applied to our `<button>` instead. If you look at the <sp-link href="https://github.com/adobe/spectrum-web-components/blob/main/packages/button/src/spectrum-config.js">`host` definition in
`spectrum-config.js`</sp-link>
you can see that we have supplied a `shadowSelector` option. That tells the
script to move all of the CSS for `.Spectrum-Button` to the `#button` element in
the shadow DOM.

```javascript
host: {
selector: '.spectrum-Button',
shadowSelector: '#button',
},
```

### Shadow DOM Structure

The next step is to fill out the remaining structure of the shadow DOM portion
of the component. Note that, in the shadow DOM, we are using ids instead of long
class names. We can do that because the namespace of each instance of our web
component has it's own DOM scope. So, there can never be an id name collision.

Typically, you will reference the <sp-link href="http://opensource.adobe.com/spectrum-css/2.13.0/docs/#checkbox">sample code from the
`spectrum-css`</sp-link>
documentation and <sp-link href="https://github.com/adobe/spectrum-web-components/blob/main/packages/checkbox/src/Checkbox.ts">recreate that structure in the shadow DOM of your
component</sp-link>.

In the case of `sp-checkbox`, we turn this sample DOM code:

```html-no-demo
<label class="spectrum-Checkbox">
<input type="checkbox" class="spectrum-Checkbox-input" id="checkbox-0">
<span class="spectrum-Checkbox-box">
<svg class="spectrum-Icon spectrum-UIIcon-CheckmarkSmall spectrum-Checkbox-checkmark" focusable="false" aria-hidden="true">
<use xlink:href="#spectrum-css-icon-CheckmarkSmall" />
</svg>
<svg class="spectrum-Icon spectrum-UIIcon-DashSmall spectrum-Checkbox-partialCheckmark" focusable="false" aria-hidden="true">
<use xlink:href="#spectrum-css-icon-DashSmall" />
</svg>
</span>
<span class="spectrum-Checkbox-label">Checkbox</span>
</label>
```

into this code in our component's render method (actually implementation is
slightly different):

```javascript
return html`
<label id="root">
<input
id="input"
type="checkbox"
?checked=${this.checked}
@change=${this.handleChange}
<span id="box">
<sp-icon
id="checkmark"
size="s"
name="ui:CheckmarkSmall"
aria-hidden="true"
></sp-icon>
<sp-icon
id="partialCheckmark"
size="s"
name="ui:DashSmall"
aria-hidden="true"
></sp-icon>
</span>
<span id="label"><slot></slot></span>
</label>
`;
```

You will notice that many of the `spectrum-css` classes are mapped to ids in the
web component. For example, `.spectrum-Checkbox-input` and
`.spectrum-Checkbox-box` become `#input` and `#box`. Those transformations are
described in the <sp-link href="https://github.com/adobe/spectrum-web-components/blob/main/packages/checkbox/src/spectrum-config.js">`ids` section of the `spectrum-config.js`
file</sp-link>.

```javascript
ids: [
{
selector: '.spectrum-Checkbox-input',
name: 'input',
},
{
selector: '.spectrum-Checkbox-box',
name: 'box',
},
{
selector: '.spectrum-Checkbox-checkmark',
name: 'checkmark',
},
{
selector: '.spectrum-Checkbox-partialCheckmark',
name: 'partialCheckmark',
},
{
selector: '.spectrum-Checkbox-label',
name: 'label',
},
],
```

### Properties and Attributes

Most of our controls have options that affect how they are rendered. For
example, Spectrum supports a number of different kinds of buttons (e.g primary,
secondary or call-to-action). `spectrum-css` supports these visual styles using
CSS classes. In web components, we typically support these options using
attributes/properties on the component. For example, here is a call-to-action
style button.

```html
<sp-button variant="accent">CTA</sp-button>
```

We could conditionally add CSS classes to the elements of the shadow DOM during
rendering, but it is much easier to just let the attributes on the DOM node
drive the styling directly. In order to facilitate that, the
<sp-link href="https://github.com/adobe/spectrum-web-components/blob/main/packages/button/src/spectrum-config.js">`spectrum-config.js` file lets you specify how to map the various
`spectrum-css` classes to CSS that is based on the attributes on the `:host` of
the web
component</sp-link>.

```javascript
attributes: [
{
type: 'boolean',
selector: '.spectrum-Button--quiet',
},
{
type: 'boolean',
selector: ':disabled',
},
{
type: 'enum',
name: 'variant',
values: [
'.spectrum-Button--cta',
'.spectrum-Button--primary',
'.spectrum-Button--secondary',
{
name: 'negative',
selector: '.spectrum-Button--warning',
},
'.spectrum-Button--overBackground',
'.spectrum-Button--secondary',
],
},
],
```

We support two different kinds of attributes, booleans and enums. Booleans are
turned on or off by the presence or absence of the attribute. Enum attributes
must be set to one of the allowed values. The <sp-link href="https://github.com/adobe/spectrum-web-components/blob/main/packages/button/src/spectrum-button.css">CSS generated will reference the
attributes on the `host:` element
directly</sp-link>.

### Class to Class Mapping

In some cases, you will need to retain the `spectrum-css` classes as classes. An
example of that is when you need to apply CSS rules to multiple items in the
shadow DOM. In that case, we simply map class names to shorter classnames. There
is an <sp-link href="https://github.com/adobe/spectrum-web-components/blob/main/packages/slider/src/spectrum-config.js">example of remapping classes in the slider
component</sp-link>.

```javascript
classes: [
{
selector: '.spectrum-Slider-track',
name: 'track',
},
],
```

### Slots

<sp-link href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot">Slot tags</sp-link> are
how we host our child content (light DOM) in our component's shadow DOM. The
`spectrum-css` for a component sometimes contains rules for laying out the child
content. There is a <sp-link href="https://github.com/adobe/spectrum-web-components/blob/main/packages/button/src/spectrum-config.js">`slots`
section</sp-link>
in the `spectrum-config.js` file for mapping those rules to the slotted content.

```javascript
slots: [
{
name: 'icon',
selector: '.spectrum-Icon',
},
],
```

The above section tells our CSS processor to map CSS for the `.spectrum-Icon`
class to the content that is being hosted in the <sp-link href="https://github.com/adobe/spectrum-web-components/blob/main/packages/button/src/spectrum-button.css">slot with the name
`icon`</sp-link>.

## Coding the Component

All of the `spectrum-web-components` are written using the
Expand Down
Loading
Loading