Skip to content
Merged
Show file tree
Hide file tree
Changes from 62 commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
464a674
feat: add new conversational-ai pattern
TarunAdobe Mar 18, 2026
1627a02
chore: add all conversation-ai components
TarunAdobe Mar 23, 2026
aa9de43
chore: update conversation ui component
TarunAdobe Apr 1, 2026
7aece43
chore: update conversation-turn component
TarunAdobe Apr 2, 2026
e220a48
feat(css): updating css for css and lint fixes
aramos-adobe Apr 5, 2026
a2bc379
Merge branch 'conversation-ai-pattern' of github.com:adobe/spectrum-w…
aramos-adobe Apr 5, 2026
8cff96c
feat(sources): add proper styling to links
aramos-adobe Apr 5, 2026
06cb9f1
chore: update api for conversation ai
TarunAdobe Apr 6, 2026
631c11b
chore: fix artifact media type
TarunAdobe Apr 6, 2026
d57b02c
chore: trigger preview deploy
TarunAdobe Apr 10, 2026
4ad12d1
chore: update demo
TarunAdobe Apr 13, 2026
4a301e4
chore: update conversation ai
TarunAdobe Apr 13, 2026
0774ea8
chore: trigger preview-docs workflow
TarunAdobe Apr 13, 2026
6b56487
chore: dummy commit
rubencarvalho Apr 13, 2026
b7b7747
feat(convoai): aligning with design annotations
aramos-adobe Apr 14, 2026
1f4e54c
Merge branch 'main' into ttomar/conversation-ai
TarunAdobe Apr 14, 2026
38ba0ce
chore: update conversation ai component
TarunAdobe Apr 14, 2026
73530b0
fix(css): adjusting user message corners and some focus states
aramos-adobe Apr 14, 2026
d5d3926
fix(css): suggestion item focus
aramos-adobe Apr 15, 2026
b6e4a62
chore: add mode to prompt field
TarunAdobe Apr 15, 2026
61b87b5
chore: fix upload artifact
TarunAdobe Apr 15, 2026
6bf33c3
fix(sources): adjust inline size
aramos-adobe Apr 15, 2026
f07bd52
fix(convoAi): running through tests via playwright and vite
aramos-adobe Apr 15, 2026
d60862a
fix(a11y): addressing Nikki comments on screen reader and keyboard
aramos-adobe Apr 17, 2026
81edced
Merge branch 'main' into ttomar/conversation-ai
TarunAdobe Apr 17, 2026
49aaa3f
chore: replaced incorrect focus group controller
TarunAdobe Apr 17, 2026
8252d26
chore: fix tests
TarunAdobe Apr 17, 2026
f5eab86
chore: separate upload artifact:
TarunAdobe Apr 17, 2026
370cdf9
Merge branch 'main' into ttomar/conversation-ai
TarunAdobe Apr 20, 2026
ee17aaa
chore: add event details
TarunAdobe Apr 20, 2026
06ab5c2
chore: add conversation thread component
TarunAdobe Apr 20, 2026
cce3926
chore: fix focus ring
TarunAdobe Apr 20, 2026
a44c88b
chore: use focus group controller
TarunAdobe Apr 20, 2026
d00ffb2
chore: review fixes
TarunAdobe Apr 20, 2026
d2837f5
chore: fix a11y tests
TarunAdobe Apr 20, 2026
0683eec
chore: update component name
TarunAdobe Apr 21, 2026
f2ccc94
chore: remove additional story block
TarunAdobe Apr 21, 2026
b06d790
chore: fix full pattern story
TarunAdobe Apr 21, 2026
e6ceeae
chore: review changes
TarunAdobe Apr 21, 2026
bf7584c
chore: fix focus ring on demo
TarunAdobe Apr 21, 2026
61ac670
Merge branch 'main' into ttomar/conversation-ai
TarunAdobe Apr 21, 2026
0c49dc9
fix(message): adjusting typography in system message
aramos-adobe Apr 21, 2026
2f870f5
Merge branch 'ttomar/conversation-ai' of github.com:adobe/spectrum-we…
aramos-adobe Apr 21, 2026
6575b34
chore: update focus ring behaviour
TarunAdobe Apr 21, 2026
a4f3f00
fix(feedback): focus state rings
aramos-adobe Apr 21, 2026
77ea520
Merge branch 'ttomar/conversation-ai' of github.com:adobe/spectrum-we…
aramos-adobe Apr 21, 2026
75fc771
fix(convoAi): fixing some css
aramos-adobe Apr 22, 2026
8adb5f5
chore: add changeset
TarunAdobe Apr 22, 2026
489969f
chore: update focus ring behaviour
TarunAdobe Apr 22, 2026
a210822
fix(css): removing some px based css values
aramos-adobe Apr 23, 2026
67a2c7d
fix(tests): addressing some test cases
aramos-adobe Apr 23, 2026
0546412
chore: fix blocking comments
TarunAdobe Apr 23, 2026
7f9e0e9
chore: review changes
TarunAdobe Apr 23, 2026
bf92916
Merge remote-tracking branch 'origin/main' into ttomar/conversation-ai
TarunAdobe Apr 23, 2026
908615d
Merge branch 'ttomar/conversation-ai' of github.com:adobe/spectrum-we…
aramos-adobe Apr 23, 2026
b544180
fix(css): making sure more tokens are used in css files and added som…
aramos-adobe Apr 24, 2026
b13b5a6
fix(css): changed background to use base app background for storybook
aramos-adobe Apr 24, 2026
7862797
chore: review comments
TarunAdobe Apr 24, 2026
0bb00c4
fix(css): adding more tokens where necessary
aramos-adobe Apr 24, 2026
546ea42
fix(css): focus indicator thickiness tokens
aramos-adobe Apr 24, 2026
ef1e09c
Merge branches 'ttomar/conversation-ai' and 'ttomar/conversation-ai' …
aramos-adobe Apr 27, 2026
e0c29f6
fix(css): addressing ue team css feedback
aramos-adobe Apr 28, 2026
379d72d
fix(tests): heading level adding some tests
aramos-adobe Apr 28, 2026
3c7be38
fix(promptfield): keyboard focus by tab but not click
aramos-adobe Apr 28, 2026
7b2c596
fix(css): adding accordion animation to the sources list
aramos-adobe Apr 28, 2026
c98fcb9
chore: review pass 1
TarunAdobe Apr 27, 2026
2b25f11
Merge branch 'main' into ttomar/conversation-ai
TarunAdobe Apr 28, 2026
48de8e4
fix(typography): adjust type settings
aramos-adobe Apr 29, 2026
7d7325a
chore: add accesible label and fix id
TarunAdobe Apr 29, 2026
cb208ea
chore: aligned stories, simplified slots and fixed prompt field
TarunAdobe Apr 29, 2026
5c1f6c1
chore: fix a11y tests
TarunAdobe Apr 29, 2026
5592a07
chore: add min max rows and a11y fix
TarunAdobe Apr 29, 2026
d4405a9
Merge branch 'main' into ttomar/conversation-ai
TarunAdobe Apr 29, 2026
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
5 changes: 5 additions & 0 deletions .changeset/solid-insects-fail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@adobe/spectrum-wc': minor
---

Add the new Conversational AI pattern and component set to @adobe/spectrum-wc with docs, stories, and test coverage.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ chromatic-diagnostics*.json
# Playwright test results (generated)
playwright-report/
test-results/
2nd-gen/test/playwright-a11y/results/

# local debug logs
debug-storybook.log

# yarn
.pnp.*
Expand Down
3 changes: 2 additions & 1 deletion 2nd-gen/packages/swc/.storybook/DocumentTemplate.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import {
import {
ApiTable,
GettingStarted,
SpectrumStories,
OverviewStory,
SpectrumStories,
StatusBadge,
} from './blocks';

Expand Down Expand Up @@ -114,6 +114,7 @@ export const ConditionalGettingStarted = () => {
<ConditionalSection tag="states" title="States" />
<ConditionalSection tag="behaviors" title="Behaviors" />
<ConditionalSection tag="a11y" title="Accessibility" hideTitle={true} />
<ConditionalSection tag="full-pattern" title="Full pattern" />

## API

Expand Down
42 changes: 32 additions & 10 deletions 2nd-gen/packages/swc/.storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,37 @@ const testStoryIndexer: Indexer = {
},
};

const COMPONENT_STORY_ROOT = {
directory: '../components',
titlePrefix: 'Components',
} as const;

const PATTERN_STORY_ROOT = {
directory: '../patterns',
titlePrefix: 'Patterns',
} as const;

const CORE_STORY_ROOT = {
directory: '../../core',
titlePrefix: 'Core',
} as const;

const stories: StorybookConfig['stories'] = [
{
directory: '../components',
...COMPONENT_STORY_ROOT,
// Production-style builds exclude internal-only stories; local/dev keeps the full set.
files:
storybookMode === 'build'
? '**/!(*.internal).stories.ts'
: '**/*.stories.ts',
titlePrefix: 'Components',
},
{
...PATTERN_STORY_ROOT,
files: '**/*.stories.ts',
},
{
...PATTERN_STORY_ROOT,
files: '**/*.mdx',
},
];

Expand All @@ -64,14 +86,12 @@ if (storybookMode !== 'ci-a11y') {
titlePrefix: 'Components',
},
{
directory: '../../core',
...CORE_STORY_ROOT,
files: '**/*.mdx',
titlePrefix: 'Core',
},
{
directory: '../../core',
...CORE_STORY_ROOT,
files: '**/stories/*.stories.ts',
titlePrefix: 'Core',
},
{
directory: 'learn-about-swc',
Expand All @@ -94,14 +114,16 @@ if (storybookMode !== 'ci-a11y') {
// Test stories are dev-only fixtures and should not ship in production Storybook.
if (storybookMode === 'dev') {
stories.push({
directory: '../components',
...COMPONENT_STORY_ROOT,
files: '**/*.test.ts',
});
stories.push({
...PATTERN_STORY_ROOT,
files: '**/*.test.ts',
titlePrefix: 'Components',
});
stories.push({
directory: '../../core',
...CORE_STORY_ROOT,
files: '**/stories/**/*.test.ts',
titlePrefix: 'Core',
});
}

Expand Down
47 changes: 19 additions & 28 deletions 2nd-gen/packages/swc/.storybook/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { withLanguageWrapper } from './decorators/language.js';
import { withStaticColorPlayground } from './decorators/static-color-playground.js';
import DocumentTemplate from './DocumentTemplate.mdx';
import { FontLoader } from './loaders/font-loader.js';
import { transformDocsSource } from './utils/docs-source-transform.js';

import '../stylesheets/swc.css';
import '../stylesheets/typography.css';
Expand Down Expand Up @@ -199,32 +200,7 @@ const preview = {
excludeDecorators: true,
type: 'auto',
language: 'html',
transform: async (source: string) => {
try {
const prettier = await import('prettier/standalone');
const prettierPluginHtml = await import('prettier/plugins/html');
const prettierPluginBabel = await import('prettier/plugins/babel');
const prettierPluginEstree =
await import('prettier/plugins/estree');

return prettier.format(source, {
parser: 'html',
plugins: [
prettierPluginHtml.default,
prettierPluginBabel.default,
prettierPluginEstree.default,
],
tabWidth: 2,
useTabs: false,
singleQuote: true,
printWidth: 80,
});
} catch (error) {
// If formatting fails, return the original source
console.error('Failed to format source code:', error);
return source;
}
},
transform: transformDocsSource,
},
},
options: {
Expand All @@ -236,6 +212,8 @@ const preview = {
'Core',
['Overview', 'Controllers'],
'Components',
'Patterns',
['Conversational AI', ['README', 'Prompt field', 'User message']],
Comment thread
TarunAdobe marked this conversation as resolved.
'Guides',
[
'Accessibility guides',
Expand Down Expand Up @@ -378,6 +356,8 @@ const preview = {
['Rendering and styling migration analysis'],
'Color field',
['Rendering and styling migration analysis'],
'Color loupe',
['Accessibility migration analysis'],
'Divider',
[
'Accessibility migration analysis',
Expand All @@ -392,7 +372,10 @@ const preview = {
'Help text',
['Rendering and styling migration analysis'],
'Illustrated message',
['Rendering and styling migration analysis'],
[
'Accessibility migration analysis',
'Rendering and styling migration analysis',
],
'Infield button',
['Rendering and styling migration analysis'],
'Infield progress circle',
Expand All @@ -408,7 +391,10 @@ const preview = {
'Picker button',
['Rendering and styling migration analysis'],
'Progress bar',
['Rendering and styling migration analysis'],
[
'Accessibility migration analysis',
'Rendering and styling migration analysis',
],
'Progress circle',
[
'Accessibility migration analysis',
Expand All @@ -431,6 +417,11 @@ const preview = {
['Rendering and styling migration analysis'],
'Switch',
['Rendering and styling migration analysis'],
'Tabs',
[
'Accessibility migration analysis',
'Rendering and styling migration analysis',
],
'Tag',
['Rendering and styling migration analysis'],
'Tags',
Expand Down
74 changes: 74 additions & 0 deletions 2nd-gen/packages/swc/.storybook/utils/docs-source-transform.ts
Copy link
Copy Markdown
Contributor

@rubencarvalho rubencarvalho Apr 22, 2026

Choose a reason for hiding this comment

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

Are we sure we need this? Is there a more Storybook idiomatic / automatic way of doing it: I'd start by trying this: https://storybook.js.org/docs/api/doc-blocks/doc-block-source#type (maybe try "dynamic"?). If it does not work then let's keep the transform, like you did.

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.

The transform is still needed for the Conversational AI pattern stories because many snippets come through as CSF/render wrapper code (or helper wrappers) rather than clean markup, and we want docs to show the <swc-...> HTML directly.

So we’re effectively already trying the Storybook-idiomatic path first (auto/dynamic), and only applying the transform as a fallback cleanup for those specific stories.

Also, we do have alternative if we want to avoid this transform for specific stories which is to show custom source instead of auto-generated sourceUse parameters.docs.source.code on the story (we already do this in some places with threadExampleSource). This lets us show curated code in docs regardless of how the story renders.. but I don't know which one to prefer

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 type { StoryContext } from '@storybook/web-components';

const PATTERN_TITLE_PREFIX = 'Patterns/Conversational AI/';

/**
* Format source snippets for Storybook code panel.
* For conversational AI pattern stories, this removes CSF wrapper noise and
* keeps only the `html\`...\`` content when possible.
*/
export async function transformDocsSource(
source: string,
storyContext?: StoryContext
): Promise<string> {
const normalizedSource = shouldNormalizePatternSource(storyContext)
? extractHtmlTemplate(source)
: source;

return formatHtml(normalizedSource);
}

function shouldNormalizePatternSource(storyContext?: StoryContext): boolean {
return storyContext?.title?.startsWith(PATTERN_TITLE_PREFIX) ?? false;
}

function extractHtmlTemplate(source: string): string {
const primaryMatch = source.match(
/\brender\s*:\s*\([^)]*\)\s*=>\s*html`([\s\S]*?)`\s*[},]/m
);
if (primaryMatch?.[1]) {
return primaryMatch[1].trim();
}

const fallbackMatch = source.match(/\bhtml`([\s\S]*?)`/m);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This fallback \bhtml\([\s\S]*?) matches the firsthtml— for patterns that definethreadExampleSourceandfullPatternSource as bare template tags before the render functions, any user copying source from the FullPattern story may get the wrong block.
How about you parse this with storybook's csf-tools ?

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.

let me think about this.

if (fallbackMatch?.[1]) {
return fallbackMatch[1].trim();
}

return source;
}

async function formatHtml(source: string): Promise<string> {
try {
const prettier = await import('prettier/standalone');
const prettierPluginHtml = await import('prettier/plugins/html');
const prettierPluginBabel = await import('prettier/plugins/babel');
const prettierPluginEstree = await import('prettier/plugins/estree');

return prettier.format(source, {
parser: 'html',
plugins: [
prettierPluginHtml.default,
prettierPluginBabel.default,
prettierPluginEstree.default,
],
tabWidth: 2,
useTabs: false,
singleQuote: true,
printWidth: 80,
});
} catch {
return source;
}
}
1 change: 1 addition & 0 deletions 2nd-gen/packages/swc/cem.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ function statusPlugin() {
export default {
globs: [
'components/**/*.ts',
'patterns/**/*.ts',
'../core/components/**/*.ts',
'../core/controllers/**/*.ts',
'../core/element/**/*.ts',
Expand Down
4 changes: 4 additions & 0 deletions 2nd-gen/packages/swc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
"./global-elements.css": {
"default": "./dist/global-elements.css"
},
"./patterns/*": {
"types": "./dist/patterns/*/index.d.ts",
"import": "./dist/patterns/*/index.js"
},
"./utils/*": {
"types": "./dist/utils/*.d.ts",
"import": "./dist/utils/*.js"
Expand Down
38 changes: 38 additions & 0 deletions 2nd-gen/packages/swc/patterns/conversational-ai/README.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Meta, Canvas } from '@storybook/addon-docs/blocks';
import * as ConversationThreadStories from './conversation-thread/stories/conversation-thread.stories';

<Meta title="Conversational AI/README" />

# Conversational AI

A complete set of building blocks for composing AI chat interfaces in 2nd-gen Spectrum Web Components. The pattern covers the full response lifecycle — from user input through AI generation, output, feedback, source attribution, and follow-up suggestions.

---

## Full example

<Canvas of={ConversationThreadStories.FullPattern} sourceState="none" />

---

## Components

| Element | Description |
| ------------------------- | ----------------------------------------------------------------------------------------------------- |
| `swc-prompt-field` | Text input surface for entering or refining a prompt |
| `swc-upload-artifact` | Shared upload artifact primitive with `card` and `media` types, used in prompt-field surfaces |
| `swc-conversation-thread` | Thread wrapper that stacks turns and enables ArrowUp/ArrowDown keyboard navigation between messages |
| `swc-conversation-turn` | Column alignment for one participant turn; stack consecutive messages in one turn for grouped spacing |
| `swc-user-message` | User message bubble with explicit `type="copy\|card\|media"` rendering |
| `swc-system-message` | System reply stack; **default slot** guidance is after the API table on the System message docs page |
| `swc-response-status` | Loading / generation-complete status indicator |
| `swc-message-feedback` | Positive / negative feedback control |
| `swc-message-sources` | Collapsible numbered list of response sources |
| `swc-suggestion-group` | Follow-up suggestion group with optional title and slotted suggestion items |
| `swc-suggestion-item` | Interactive chip action used inside `swc-suggestion-group`; emits bubbled selection event |

---

## Tokens

All components resolve styles through `token()` calls that map to `var(--swc-*)` custom properties. No hard-coded colours or sizes — set the standard Spectrum token layer to theme the pattern globally.
Loading
Loading