Skip to content
Open
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: 1 addition & 0 deletions second-gen/packages/core/shared/base/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ export {
type SizedElementInterface,
} from './sizedMixin';
export { defineElement } from './define-element';
export { version } from './version';
74 changes: 74 additions & 0 deletions second-gen/packages/swc/.storybook/guides/code_of_conduct.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Adobe Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to make participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment
include:

- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

- The use of sexualized language or imagery and unwelcome sexual attention or
advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic
address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise, unacceptable behavior may be
reported by contacting the project team at Grp-opensourceoffice@adobe.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality concerning the reporter of an incident.
Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]

[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
202 changes: 202 additions & 0 deletions second-gen/packages/swc/.storybook/guides/s2_migration.mdx
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is all useful and well-written!

The only thing I had in my notes that I didn't see mentioned was that in 2nd gen, components have a new naming convention (<swc-badge> instead of <sp-badge>), would that be useful to call out in here?

Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
# Migration guide

When migrating a component from the 1st generation to the 2nd generation, there are a few things to keep in mind.

## Component structure

Components in 1st and 2nd generation share a common base class. These base classes are located in the `second-gen/packages/core/components/` directory.

- 1st generation components are located in the `first-gen/packages/components/` directory.
- 2nd generation components are located in the `second-gen/packages/swc/components/` directory.

Keep in mind that all the code in the core package is shared between the 1st and 2nd generation components and should avoid any breaking changes being introduced here that could alter the 1st generation API.

Relevant files in the 1st generation components:

- `src/<component-name>-overrides.css` - Theme switching system; do not delete this file, even if it is empty
- `src/<component-name>.css` - Component styles; this file is used to import the styles from the Spectrum CSS project and the component styles and adds web component-specific styles
- `src/spectrum-<component-name>.css` - Styles imported and transformed by the build process from the Spectrum CSS project
- `src/<component-name>.ts` - Component implementation; this contains the attributes and properties for the component as well as the rendering logic
- `stories/` - Stories
- `test/` - Tests
- `README.md` - Component documentation

Relevant files in the 2nd generation components:

- `<component-name>.css` - Component styles; all styles should be added to this file
- `<component-name>.ts` - Component implementation; this contains the attributes and properties for the component as well as the rendering logic
- `stories/` - Stories will also serve as the documentation for the component; the story file should be named `<component-name>.stories.ts`. Use JSDoc to document a story in more detail.
- `test/` - Tests

## Getting started

### Create the base class

If the component folder does not yet exist in the core package, you will need to create it. It might be easiest to copy the existing component file from the 1st generation component and remove the render and styling logic as well as anything that is S1-specific.

For example, if you are migrating the `sp-accordion` component, you can copy the `first-gen/packages/accordion/src/Accordion.ts` to `second-gen/packages/core/components/accordion/Accordion.base.ts` and remove the render and styling logic as well as anything that is S1-specific.

### Implement the component class

Once the base class is created, you can start to implement the component in the `second-gen/packages/swc/components/` directory. The implementation file should be named `<component-name>.ts` and should extend the base class.

```ts
import { AccordionBase } from '@swc/core/components/accordion';

export class Accordion extends AccordionBase {
// ...
}
```

### Bring over styles from Spectrum CSS

Now we can bring over styles from the `spectrum-two` package in Spectrum CSS. Start by checking out the `@adobe/spectrum-css` repository and pulling down the `spectrum-two` branch.

Identify the component you need to migrate by searching the `components` directory for the component name.

Inside the CSS directory, you can expect to find the following files:

- `index.css` - This is the source of truth for the component Styles
- `dist/index.css` - This is the processed version of the component styles; for now, this is the best place to source styles for SWC. When copying files from Spectrum CSS into the 2nd-generation component, using this file will ensure you get the benefits of the CSS build tooling.
- `stories/<component-name>.stories.js` - This is a great source-of-truth for the SWC storybook. These stories are organized into logic groups with API defined in a customer-friendly fashion with typing and human-readable labels. These files also include migration notes and guidance specific to the S2-specific implementation of the component.
- `stories/template.js` - This is a great source-of-truth for the SWC render function; these templates already include property and class mappings. When bringing this file over to SWC, be sure to remove the `id` and `customStyles` attributes as they do not translate to the web component APIs.

Next, we need to copy the styles from the Spectrum CSS component to the 2nd-generation component.

```bash
cp -r spectrum-css/components/<component-name>/dist/index.css spectrum-web-components/second-gen/packages/swc/components/<component-name>/<component-name>.css
```

### Update styles in the 2nd-generation component

Now that we have the base styles in place, we need to check the first-gen implementation for any unique web component-specific styles that would not exist in the vanilla CSS implementation. This information will most likely be found in the `first-gen/packages/components/<component-name>/<component-name>.css` file.

For example, look for styles specific to slots, such as `::slotted([name="icon"]) {}`.

If these styles are found, we need to confirm if they are needed in the 2nd-generation component. Not all first-gen overrides or component-specific styles are needed in the 2nd-generation components and sometimes there are other ways to source those styles using the original classes provided by the Spectrum CSS asset.

It might be helpful, at this point, to define the render function for the second-gen component so you can spin up Storybook and start seeing these new styles in action. A quick way to kick this off is to copy the `spectrum-css/components/<component-name>/stories/template.js` file into a render function on your new 2nd-generation component.

Let's use the `Badge` component as an example. First, we need to add the styles to the component.

Start by importing the CSS file:

```ts
import styles from './badge.css';
```

Next, we import those styles into the component:

```ts
public static override get styles(): CSSResultArray {
return [styles];
}
```

Finally, we can start to implement the render function:

```ts
protected override render(): TemplateResult {
return html`
<div
class=${classMap({
['spectrum-Badge']: true,
[`spectrum-Badge--size${this.size?.toUpperCase()}`]: typeof this.size !== 'undefined',
[`spectrum-Badge--${this.variant}`]: typeof this.variant !== 'undefined',
[`spectrum-Badge--subtle`]: this.subtle,
[`spectrum-Badge--outline`]: this.outline,
[`spectrum-Badge--fixed-${this.fixed}`]: typeof this.fixed !== 'undefined',
})}
>
${when(
this.hasIcon,
() => html`
<div
class=${classMap({
[`spectrum-Badge-icon`]: true,
[`spectrum-Badge-icon--no-label`]:
!this.slotHasContent,
})}
>
<slot name="icon"></slot>
</div>
`
)}
<div class="spectrum-Badge-label">
<slot></slot>
</div>
</div>
`;
}
```

Let's compare this to the 1st-generation implementation:

```ts
protected override render(): TemplateResult {
return html`
${this.hasIcon
? html`
<slot
name="icon"
?icon-only=${!this.slotHasContent}
></slot>
`
: nothing}
<div class="label">
<slot></slot>
</div>
`;
}
```

As you can see, the 2nd-generation implementation leverages the `classMap` function to conditionally apply classes to the component based on the component's properties. This is a common pattern in the 2nd-generation components. This approach has several benefits:

- It separates the styling application from the properties and states of the component
- It creates a container inside the Shadow DOM which provides stronger encapsulation
- It allows for more efficient rendering by only applying the necessary classes to the component

In our 2nd-generation version, we will likely want to maintain any slots available in the 1st-generation component unless design changes from S2 provide a compelling reason to change or remove them.

Once your render function is in place, you can spin up Storybook and start seeing these new styles in action.

```bash
yarn workspace @swc/components storybook
```

_Note_: Run all commands provided in this guide from the root of the Spectrum Web Components monorepo.

_Tip_: If you want to run S1 Storybook alongside S2 Storybook, you can use the following command:

```bash
yarn start
```

## Implementing the API

Now that we have the base styles and render function in place, we can start to adjust styling and API to match the 2nd-generation design language.

Start by determining what display property your component's host should use. All components should have at least the following style added to the top of their 2nd-generation CSS.

```css
:host {
display: inline-flex;
}
```

Use the `display` property most aligned with the component's semantic role or purpose in the document.

### Properties

The 2nd-generation components may have changes to the properties and attributes of the component. These changes are typically due to design changes from S2 or to align with the 2nd-generation design language.

There are several resources you can use to help you understand the design changes from S2.

- [Migration roadmap](https://github.com/adobe/spectrum-web-components/tree/2nd-gen-component-analysis/migration-roadmap) - SWC branch name: `2nd-gen-component-analysis`
- [S2 design assets](https://www.figma.com/design/Mngz9H7WZLbrCvGQf3GnsY/S2---Desktop?m=auto) - Figma file

You can also use the `CHANGELOG.md` file in the Spectrum CSS repository to see the migration notes for the component.

```bash
cat spectrum-css/components/<component-name>/CHANGELOG.md
```
13 changes: 12 additions & 1 deletion second-gen/packages/swc/.storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,18 @@ import { resolve } from 'path';

/** @type { import('@storybook/web-components-vite').StorybookConfig } */
const config = {
stories: ['../components/**/*.stories.@(js|ts|md|mdx)'],
stories: [
{
directory: 'guides',
files: '*.@(md|mdx)',
titlePrefix: 'Guides',
},
{
directory: '../components',
files: '*/stories/*.stories.ts',
titlePrefix: 'Components',
},
],
framework: '@storybook/web-components-vite',
core: {
disableTelemetry: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import type { Meta, StoryObj } from '@storybook/web-components';
import '@swc/components/asset';

const meta: Meta = {
title: 'Components/Asset',
title: 'Asset',
component: 'swc-asset',
argTypes: {
variant: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ args['default-slot'] = 'Badge';
* Because outline and subtle fill styles draw a similar level of attention, choose only one to use consistently within a single product. Bold fill can be paired with either style, and is reserved for high-attention badging only.
*/
const meta: Meta = {
title: 'Components/Badge',
title: 'Badge',
component: 'swc-badge',
args,
argTypes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import type { Meta, StoryObj } from '@storybook/web-components';
import '@swc/components/divider';

const meta: Meta = {
title: 'Components/Divider',
title: 'Divider',
component: 'swc-divider',
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ argTypes['static-color'] = {
* Can be used in both determinate (with specific progress value) and indeterminate (loading) states.
*/
const meta: Meta = {
title: 'Components/Progress Circle',
title: 'Progress circle',
component: 'swc-progress-circle',
args,
argTypes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import '@swc/components/status-light';

export default {
component: 'swc-status-light',
title: 'Components/StatusLight',
title: 'Status light',
};

export const s = (): TemplateResult => html`
Expand Down
Loading