Skip to content
Open
Show file tree
Hide file tree
Changes from 13 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
70 changes: 5 additions & 65 deletions 2nd-gen/packages/swc/.storybook/DocumentTemplate.mdx
Original file line number Diff line number Diff line change
@@ -1,22 +1,11 @@
import {
Meta,
Title,
Primary,
Controls,
Stories,
ArgTypes,
Description,
Subtitle,
HeaderMdx,
Meta,
Stories,
useOf,
} from '@storybook/addon-docs/blocks';
import {
ApiTable,
GettingStarted,
OverviewStory,
SpectrumStories,
StatusBadge,
} from './blocks';
import { DocsFooter, DocsHeader, SpectrumStories } from './blocks';

export const checkIsSingleStory = () => {
const resolvedOf = useOf('meta', ['meta']);
Expand Down Expand Up @@ -64,56 +53,12 @@ export const ConditionalSection = ({ tag, title, hideTitle = false }) => {
</div>
);

};
export const ConditionalAPISection = () => {
const resolvedOf = useOf('meta', ['meta']);
const tags = resolvedOf?.csfFile?.meta?.tags ?? [];
const hasCustomAPIDocs = tags.includes('api') || Object.values(resolvedOf.csfFile.stories).some(
(story) => story.tags?.includes('api')
);

if (!hasCustomAPIDocs) {
return (
<>
<HeaderMdx as="h2" id="api">API</HeaderMdx>

<Primary />
<Controls />
</>
);
}

return (
<>
<HeaderMdx as="h2" id="api">API</HeaderMdx>
<Primary />
<Controls />

<hr />
<SpectrumStories tag="api" hideTitle={true} />
</>
);

};

export const ConditionalGettingStarted = () => {
const resolvedOf = useOf('meta', ['meta']);

const tags = resolvedOf?.csfFile?.meta?.tags ?? [];

return <GettingStarted tags={tags} />;

};

<Meta isTemplate />

<Title />
<StatusBadge />
<Subtitle />
<Description />
<DocsHeader />
<SingleStoryDescription />
<OverviewStory />
<ConditionalGettingStarted />

<ConditionalSection tag="anatomy" title="Anatomy" hideTitle={true} />
<ConditionalSection tag="upcoming" title="Upcoming features" hideTitle={true} />
Expand All @@ -124,12 +69,7 @@ export const ConditionalGettingStarted = () => {
<ConditionalSection tag="a11y" title="Accessibility" hideTitle={true} />
<ConditionalSection tag="full-pattern" title="Full pattern" />

## API

<ApiTable />
<AdvancedExamplesStories />
<ConditionalSection tag="appendix" title="Appendix" hideTitle={true} />

## Feedback

Have feedback or questions? [Open an issue](https://github.com/adobe/spectrum-web-components/issues/new/choose).
<DocsFooter />
74 changes: 74 additions & 0 deletions 2nd-gen/packages/swc/.storybook/blocks/DocsFooter.tsx
Copy link
Copy Markdown
Contributor Author

@caseyisonit caseyisonit May 28, 2026

Choose a reason for hiding this comment

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

This and the DocsHeader blocks will be refined in a future PR but this reflects the current patterns that are consistent across all docs so far. Heavily based on DocumentTemplate.

Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* Copyright 2026 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

import {
Controls,
HeaderMdx,
Primary,
useOf,
} from '@storybook/addon-docs/blocks';
import React from 'react';

import { ApiTable } from './ApiTable';
import { SpectrumStories } from './SpectrumStories';

/**
* The standard bottom of a Storybook docs page: API table, primary story,
* controls, and the feedback link. Genre-aware via meta tags; controllers
* (tagged `controller`) skip the API table because they expose a TypeScript
* class rather than a custom element manifest.
*
* Authors compose a docs page as:
*
* <Meta of={Stories} />
* <DocsHeader />
* ...component-specific sections...
* <DocsFooter />
*/
export const DocsFooter = () => {
const resolvedOf = useOf('meta', ['meta']);
const tags: string[] = resolvedOf?.preparedMeta?.tags ?? [];
const isController = tags.includes('controller');

// Per-unit pages may flag custom API content by tagging stories with `api`.
const hasCustomApiStories = Object.values(
resolvedOf?.csfFile?.stories ?? {}
).some((story: any) => story.tags?.includes('api'));

return (
<>
<HeaderMdx as="h2" id="api">
API
</HeaderMdx>
{!isController && <ApiTable />}
<Primary />
<Controls />
{hasCustomApiStories && (
<>
<hr />
<SpectrumStories tag="api" hideTitle={true} />
</>
)}

<HeaderMdx as="h2" id="feedback">
Feedback
</HeaderMdx>
<p>
Have feedback or questions?{' '}
<a href="https://github.com/adobe/spectrum-web-components/issues/new/choose">
Open an issue
</a>
.
</p>
</>
);
};
52 changes: 52 additions & 0 deletions 2nd-gen/packages/swc/.storybook/blocks/DocsHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* Copyright 2026 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

import {
Description,
Subtitle,
Title,
useOf,
} from '@storybook/addon-docs/blocks';
import React from 'react';

import { GettingStarted } from './GettingStarted';
import { OverviewStory } from './OverviewStory';
import { StatusBadge } from './StatusBadge';

/**
* The standard top of a Storybook docs page: title, status badge, subtitle,
* description, overview story, and getting-started instructions. Genre-aware
* via meta tags (`migrated`, `controller`, `utility`); component, pattern,
* and controller pages all use this single block.
*
* Authors compose a docs page as:
*
* <Meta of={Stories} />
* <DocsHeader />
* ...component-specific sections...
* <DocsFooter />
*/
export const DocsHeader = () => {
const resolvedOf = useOf('meta', ['meta']);
const tags: string[] = resolvedOf?.preparedMeta?.tags ?? [];

return (
<>
<Title />
<StatusBadge />
<Subtitle />
<Description />
<OverviewStory />
<GettingStarted tags={tags} />
</>
);
};
2 changes: 2 additions & 0 deletions 2nd-gen/packages/swc/.storybook/blocks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
* governing permissions and limitations under the License.
*/
export * from './ApiTable';
export * from './DocsFooter';
export * from './DocsHeader';
export * from './GettingStarted';
export * from './OverviewStory';
export * from './SpectrumDocs';
Expand Down
25 changes: 22 additions & 3 deletions 2nd-gen/packages/swc/.storybook/preview.ts
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Auto generated from merges to main that werent picked up before

Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ const preview = {
'Tools vs packages',
'Writing migration guides',
'Focus management',
'Changelog strategy',
],
'Style guide',
[
Expand Down Expand Up @@ -330,7 +331,10 @@ const preview = {
'Rendering and styling migration analysis',
],
'Action button',
['Rendering and styling migration analysis'],
[
'Accessibility migration analysis',
'Rendering and styling migration analysis',
],
'Action group',
['Rendering and styling migration analysis'],
'Action menu',
Expand Down Expand Up @@ -360,9 +364,14 @@ const preview = {
'Rendering and styling migration analysis',
],
'Button group',
['Rendering and styling migration analysis'],
[
'Accessibility migration analysis',
'Rendering and styling migration analysis',
],
'Checkbox',
['Rendering and styling migration analysis'],
'Close button',
['Accessibility migration analysis'],
'Color field',
['Rendering and styling migration analysis'],
'Color loupe',
Expand All @@ -382,6 +391,11 @@ const preview = {
['Rendering and styling migration analysis'],
'Field label',
['Rendering and styling migration analysis'],
'Grid',
[
'Accessibility migration analysis',
'Rendering and styling migration analysis',
],
'Help text',
['Rendering and styling migration analysis'],
'Illustrated message',
Expand All @@ -391,12 +405,16 @@ const preview = {
'Rendering and styling migration analysis',
],
'Infield button',
['Rendering and styling migration analysis'],
[
'Accessibility migration analysis',
'Rendering and styling migration analysis',
],
'Infield progress circle',
['Rendering and styling migration analysis'],
'Link',
[
'Accessibility migration analysis',
'Migration plan',
'Rendering and styling migration analysis',
],
'Menu',
Expand Down Expand Up @@ -424,6 +442,7 @@ const preview = {
'Popover',
[
'Accessibility migration analysis',
'Migration plan',
'Rendering and styling migration analysis',
],
'Progress bar',
Expand Down
66 changes: 66 additions & 0 deletions 2nd-gen/packages/swc/components/asset/asset.internal.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { Canvas, Meta } from '@storybook/addon-docs/blocks';
import { DocsFooter, DocsHeader } from '../../.storybook/blocks';

import * as AssetStories from './stories/asset.internal.stories';

<Meta of={AssetStories} />

<DocsHeader />

## Anatomy

An asset consists of:

1. **Icon or image content**: either a file/folder icon or custom slotted content
2. **Accessible label**: provides context for assistive technologies

The asset automatically centers its content both horizontally and vertically within the available space.

### Content

- **Default slot**: custom content to display (typically an image) when variant is not set
- **Label**: accessible label for screen readers (used as `aria-label` on the icon SVGs)

<Canvas of={AssetStories.Anatomy} />

## Options

### Variants

Assets support two built-in icon variants for representing files and folders:

- **`file`**: displays a file icon, useful for representing documents, files, or file types
- **`folder`**: displays a folder icon, useful for representing directories or collections

When no variant is specified, the asset displays custom content provided via the default slot (typically an image).

<Canvas of={AssetStories.Variants} />

## Accessibility

### Features

The `<swc-asset>` element implements several accessibility features:

#### ARIA implementation

- **Icon labeling**: file and folder SVG icons automatically use the `label` property as `aria-label`
- **Non-interactive**: assets have no interactive behavior and are not focusable

#### Visual accessibility

- Icons use sufficient color contrast in both light and dark modes
- High contrast mode is supported with appropriate color overrides
- Content automatically centers for consistent layout and visual balance

### Best practices

- Always provide a descriptive `label` attribute for file and folder variants
- Use specific, meaningful labels or alt text (e.g., "Project proposal PDF", "projects/2025/proposal.pdf", or not just "File")
- The `label` on the asset itself should describe the asset's purpose or context
- For decorative images, use an empty `alt=""` attribute on the img tag
- Test with screen readers to verify assets are announced appropriately in context

<Canvas of={AssetStories.Accessibility} />

<DocsFooter />
Loading
Loading