-
Notifications
You must be signed in to change notification settings - Fork 250
feat(conversational-ai): deliver complete 2nd-gen conversational AI pattern with accessibility, docs, and test coverage #6170
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
Changes from all commits
464a674
1627a02
aa9de43
7aece43
e220a48
a2bc379
8cff96c
06cb9f1
631c11b
d57b02c
4ad12d1
4a301e4
0774ea8
6b56487
b7b7747
1f4e54c
38ba0ce
73530b0
d5d3926
b6e4a62
61b87b5
6bf33c3
f07bd52
d60862a
81edced
49aaa3f
8252d26
f5eab86
370cdf9
ee17aaa
06ab5c2
cce3926
a44c88b
d00ffb2
d2837f5
0683eec
f2ccc94
b06d790
e6ceeae
bf7584c
61ac670
0c49dc9
2f870f5
6575b34
a4f3f00
77ea520
75fc771
8adb5f5
489969f
a210822
67a2c7d
0546412
7f9e0e9
bf92916
908615d
b544180
b13b5a6
7862797
0bb00c4
546ea42
ef1e09c
e0c29f6
379d72d
3c7be38
7b2c596
c98fcb9
2b25f11
48de8e4
7d7325a
cb208ea
5c1f6c1
5592a07
d4405a9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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. |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This fallback
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; | ||
| } | ||
| } | ||
| 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. |
Uh oh!
There was an error while loading. Please reload this page.