diff --git a/2nd-gen/packages/core/components/tooltip/Tooltip.base.ts b/2nd-gen/packages/core/components/tooltip/Tooltip.base.ts
index 3cfd943481..44b6efcd39 100644
--- a/2nd-gen/packages/core/components/tooltip/Tooltip.base.ts
+++ b/2nd-gen/packages/core/components/tooltip/Tooltip.base.ts
@@ -63,7 +63,7 @@ export abstract class TooltipBase extends SpectrumElement {
/**
* The preferred placement of the tooltip relative to its trigger.
- * Applies a CSS class for tip direction; pixel positioning requires `PlacementController` (additive phase).
+ * Controls the tip direction via the reflected `placement` attribute; pixel positioning requires `PlacementController` (additive phase).
*
* @default 'top'
*/
@@ -81,7 +81,7 @@ export abstract class TooltipBase extends SpectrumElement {
/**
* The `id` of the trigger element in the same document tree root.
* Resolved via `getRootNode().getElementById(this.for)`.
- * Active from the initial release; drives ARIA relationship wiring on `open` change.
+ * Drives ARIA relationship wiring on `open` change.
*/
@property({ attribute: 'for', type: String })
public for: string | undefined;
@@ -89,7 +89,7 @@ export abstract class TooltipBase extends SpectrumElement {
/**
* Explicit trigger element reference. Overrides `for` when set.
* Use for cross-shadow-root triggers or programmatic insertion where `getElementById` is scoped to the wrong root.
- * Setter only — no HTML attribute.
+ * Setter only; no HTML attribute.
*
* @default null
*/
@@ -99,8 +99,8 @@ export abstract class TooltipBase extends SpectrumElement {
/**
* Duration in milliseconds of the warm-up delay before the tooltip shows on pointer hover.
* Set to `0` to show immediately on hover. Keyboard focus (`focusin` when `:focus-visible`)
- * always shows the tooltip immediately regardless of this value. The cooldown duration (before the next hover must wait again)
- * matches this value. Warm-up/cooldown state is shared across all tooltips in the same document,
+ * always shows the tooltip immediately regardless of this value. The cooldown duration after the
+ * pointer leaves the trigger matches this value. Warm-up/cooldown state is shared across all tooltips in the same document,
* so moving quickly between adjacent triggers (e.g. a toolbar) shows each subsequent tooltip
* immediately after the first warm-up elapses.
*
diff --git a/2nd-gen/packages/swc/.storybook/preview-head.html b/2nd-gen/packages/swc/.storybook/preview-head.html
index bfd12babc7..c61e8ffd0e 100644
--- a/2nd-gen/packages/swc/.storybook/preview-head.html
+++ b/2nd-gen/packages/swc/.storybook/preview-head.html
@@ -116,7 +116,25 @@
}
h4 {
- font-size: var(--swc-heading-size-s) !important;
+ font-size: var(--swc-heading-size-xs) !important;
+ }
+
+ kbd {
+ line-height: 1;
+ margin: 0px 2px;
+ padding: 3px 5px;
+ white-space: nowrap;
+ border-radius: 3px;
+ font-size: 12px;
+ border: 1px solid rgb(147, 158, 172);
+ border-inline-end-width: 2px;
+ border-block-end-width: 2px;
+ color: rgba(46, 51, 56, 0.9);
+ background-color: rgb(246, 249, 252);
+ font-family:
+ ui-monospace, Menlo, Monaco, 'Roboto Mono', 'Oxygen Mono',
+ 'Ubuntu Monospace', 'Source Code Pro', 'Droid Sans Mono', 'Courier New',
+ monospace !important;
}
:is(html, p, li, ul, ol) {
diff --git a/2nd-gen/packages/swc/components/tooltip/Tooltip.ts b/2nd-gen/packages/swc/components/tooltip/Tooltip.ts
index 9136027c9d..8e5e399d06 100644
--- a/2nd-gen/packages/swc/components/tooltip/Tooltip.ts
+++ b/2nd-gen/packages/swc/components/tooltip/Tooltip.ts
@@ -27,7 +27,7 @@ import styles from './tooltip.css';
*
* @slot - Text label displayed in the tooltip.
*
- * @cssprop --swc-tooltip-background-color - Background color of the tooltip bubble. Defaults to the neutral background color token.
+ * @cssprop --swc-tooltip-background-color - Background color of the tooltip bubble. Overrides the variant-specific background color.
*
* @fires swc-open - Dispatched when the tooltip begins to open, before the transition plays.
* @fires swc-close - Dispatched when the tooltip begins to close, before the transition plays.
diff --git a/2nd-gen/packages/swc/components/tooltip/migration-guide.mdx b/2nd-gen/packages/swc/components/tooltip/migration-guide.mdx
new file mode 100644
index 0000000000..6f797fb551
--- /dev/null
+++ b/2nd-gen/packages/swc/components/tooltip/migration-guide.mdx
@@ -0,0 +1,283 @@
+import { Meta } from '@storybook/addon-docs/blocks';
+
+
+
+# Tooltip migration guide
+
+Replace `` with ``, update the import, rename the tag, update event listeners, and change the authoring pattern so the tooltip is a sibling of the trigger rather than nested inside it.
+
+
+ ℹ️ Initial release scope. This release delivers the tag
+ rename, variant and event API changes, ARIA relationship wiring via{' '}
+ for, and native {'popover="auto"'} open/close
+ behavior.{' '}
+
+ Automatic hover/focus trigger wiring and viewport-aware pixel positioning
+ are not yet available.
+ {' '}
+ They require HoverController and PlacementController
+ , which ship in a future release. Until then, control visibility via the{' '}
+ open property and position the tooltip with a helper library like
+ Floating UI.
+
+
+## Installation
+
+```bash
+# Remove
+yarn remove @spectrum-web-components/tooltip
+
+# Add
+yarn add @adobe/spectrum-wc
+```
+
+Update your import:
+
+```js
+// Before
+import '@spectrum-web-components/tooltip/sp-tooltip.js';
+
+// After
+import '@adobe/spectrum-wc/components/tooltip/swc-tooltip.js';
+```
+
+> `@adobe/spectrum-wc` is a monolithic package. Importing via subpath (e.g. `@adobe/spectrum-wc/components/tooltip/swc-tooltip.js`) registers and loads only that component's bundle.
+
+## What changed
+
+### Renamed
+
+| Area | Spectrum 1 (`sp-tooltip`) | Spectrum 2 (`swc-tooltip`) |
+| ------------------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
+| Tag | `sp-tooltip` | `swc-tooltip` |
+| Import path | `@spectrum-web-components/tooltip/sp-tooltip.js` | `@adobe/spectrum-wc/components/tooltip/swc-tooltip.js` |
+| `variant` | `'info'` | `'informative'` |
+| `swc-open` / `swc-close` events | `sp-opened` / `sp-closed` | `swc-open`, `swc-after-open`, `swc-close`, `swc-after-close` |
+| Trigger wiring attribute | `self-managed` | `for="[id]"` declares the trigger relationship and wires ARIA now. Automatic hover/focus open/close ships in a future release. |
+
+### Added in Spectrum 2
+
+| Addition | Notes |
+| ------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
+| `for` attribute | Declares the trigger relationship by ID. Required for ARIA wiring and (in the additive phase) automatic hover/focus open/close. |
+| `manual` boolean attribute | Opt out of automatic controller wiring; consumer manages open/close via the `open` property. ARIA wiring still fires on `open` change. |
+| Logical placements: `start`, `end` | RTL-aware inline placement values; physical values (`top`, `bottom`, `left`, `right`) are unchanged. |
+| `delay` attribute | Warm-up/cooldown duration in ms (default 1500). `delay="0"` shows immediately. **Additive phase:** active when `HoverController` ships. |
+| `labeling` boolean attribute | Switches ARIA wiring to `ariaLabelledByElements` for icon-only triggers. **Additive phase.** |
+| `swc-after-open` / `swc-after-close` events | Fire after the open/close transition completes. |
+
+### Removed in Spectrum 2
+
+| Removed | Replacement |
+| --------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
+| `slot="icon"` | No replacement. Remove all icon content from tooltips; Spectrum 2 tooltip is text-only. |
+| `variant="positive"` | Use `variant="informative"`, `variant="neutral"`, or `variant="negative"` as content warrants. |
+| `variant="info"` | Renamed to `variant="informative"`. |
+| `self-managed` attribute | Removed. Automatic trigger wiring is the default. Add `for="[id]"` to the tooltip pointing to the trigger's `id`. |
+| `sp-opened` / `sp-closed` events | Replace with `swc-open` and `swc-close`. The timing also changes; see [step 4](#4-update-event-listeners). |
+| `--mod-tooltip-*` CSS custom properties | No `--mod-*` pass-through in Spectrum 2. See [Styling](#styling). |
+
+## Update your code
+
+### 1. Update the import
+
+```js
+// Before
+import '@spectrum-web-components/tooltip/sp-tooltip.js';
+
+// After
+import '@adobe/spectrum-wc/components/tooltip/swc-tooltip.js';
+```
+
+### 2. Rename the tag and fix variant values
+
+```html
+
+Save your changes
+Upload complete
+No changes yet
+
+
+Save your changes
+
+Upload complete
+No changes yet
+```
+
+### 3. Remove icon slot content
+
+Spectrum 2 tooltip does not render icons. Remove all `slot="icon"` content.
+
+```html
+
+
+
+ Learn more
+
+
+
+Learn more
+```
+
+### 4. Update event listeners
+
+Replace `sp-opened`/`sp-closed` with `swc-open` and `swc-close`. Use `swc-after-open` and `swc-after-close` when you need to act after the open or close transition completes.
+
+**Timing change:** In Spectrum 1, events fired from the internal overlay bridge. In Spectrum 2, they fire from native `popover` lifecycle hooks (`beforetoggle` / `transitionend`). Code that depended on the exact timing relative to DOM paint or transition frames may need adjustment.
+
+```js
+// Before
+tooltip.addEventListener('sp-opened', handleOpen);
+tooltip.addEventListener('sp-closed', handleClose);
+
+// After
+tooltip.addEventListener('swc-open', handleOpen); // fires before transition
+tooltip.addEventListener('swc-after-open', handleOpen); // fires after transition completes
+tooltip.addEventListener('swc-close', handleClose);
+tooltip.addEventListener('swc-after-close', handleClose);
+```
+
+### 5. Change the authoring pattern
+
+In Spectrum 1, `` was typically nested inside the trigger and required the `self-managed` attribute. In Spectrum 2, the tooltip is authored as a **sibling** of the trigger. Add an `id` to the trigger element and a `for` attribute on the tooltip referencing that `id`.
+
+```html
+
+
+ Save
+ Save your changes
+
+
+
+Save
+Save your changes
+```
+
+The tooltip may be placed anywhere in the same document tree root; it does not need to be immediately adjacent to the trigger.
+
+**For cross-shadow-root triggers** where `getElementById` cannot reach the trigger, set the `triggerElement` property directly instead of using `for`:
+
+```js
+const tooltip = document.querySelector('#my-tip');
+tooltip.triggerElement = shadowRoot.querySelector('#the-trigger');
+```
+
+
+
+ ℹ️ What for does in this release.
+ {' '}
+ Setting {'for="[id]"'} establishes the ARIA relationship between
+ the trigger and tooltip. It does not yet open or close the
+ tooltip automatically on hover or focus. Until automatic trigger wiring ships,
+ you must control visibility manually (see step 6 below).
+
+
+### 6. Manage open/close until automatic wiring ships
+
+In this release, automatic hover/focus open/close is not active. Implement `mouseenter`/`mouseleave` and `focusin`/`focusout` listeners yourself. Keep `for` set so the ARIA relationship is always established when the tooltip opens.
+
+When automatic wiring ships in a future release, remove these manual listeners; `for` will drive open/close automatically. Add `manual` to the tooltip only when you need to permanently opt out of automatic wiring at that point.
+
+```html
+
+
+
+ Save your changes
+
+
+```
+
+## Accessibility
+
+- **Trigger relationship:** Set `for="[trigger-id]"` on every ``. Without it, the ARIA relationship between the tooltip and its trigger is not established, and screen readers will not associate the tooltip text with the trigger. See [step 5](#5-change-the-authoring-pattern).
+- **Icon-only triggers:** Add `accessible-label` to the trigger (2nd-gen SWC components) or `aria-label` (native elements) so the trigger has an accessible name independent of the tooltip. The tooltip describes; it does not name. See [step 5](#5-change-the-authoring-pattern).
+- **No interactive content in tooltips:** `role="tooltip"` prohibits interactive elements (links, buttons, inputs) inside the tooltip. Refactor those patterns to `` or a dialog component.
+- **Non-interactive triggers:** Tooltips must be attached to focusable elements. Static text, decorative icons, and non-interactive elements are not valid tooltip triggers; use contextual help instead.
+- **Touch and mobile:** `` is hover/focus only. For touch-accessible disclosure, use `` or contextual help.
+- **`popover="auto"` auto-stack change:** Opening a `` closes other open `auto` popovers (menus, pickers). This differs from the Spectrum 1 `type="hint"` isolation behavior, which left menus and pickers open. This is expected behavior, not a bug.
+
+## Styling
+
+Spectrum 1 `--mod-tooltip-*` CSS custom properties are **not** supported in Spectrum 2. Spectrum 2 exposes one public custom property.
+
+{/* @todo Replace the inline-styled callouts in this section with `` once it is migrated to Spectrum 2. */}
+
+
+ ⚠️ Breaking change. Spectrum 1{' '}
+ {'--mod-tooltip-*'} properties do not apply to{' '}
+ {''}. Remove every {'--mod-tooltip-*'}{' '}
+ override. The only public custom property in Spectrum 2 is listed below.
+
+
+{/* @todo Replace the Description column with the `@cssproperty` JSDoc descriptions from ``'s CEM entry once they are added in a follow-up PR. */}
+
+| Custom property | Description |
+| -------------------------------- | ---------------------------------------------------------------------------------------- |
+| `--swc-tooltip-background-color` | Background color of the tooltip bubble. Overrides the variant-specific background color. |
+
+
+ 🚫 Do not target internals. Internal classes,{' '}
+ {'--_swc-tooltip-*'} private properties, and shadow DOM are{' '}
+ not public API. Styling applied to them will break without
+ warning on minor releases.
+
+
+## Checklist
+
+- [ ] Update imports from `@spectrum-web-components/tooltip` to `@adobe/spectrum-wc`
+- [ ] Rename all `` to ``
+- [ ] Replace `variant="info"` with `variant="informative"`
+- [ ] Replace `variant="positive"` with `variant="informative"`, `variant="neutral"`, or `variant="negative"` as appropriate
+- [ ] Remove all `slot="icon"` content from tooltips
+- [ ] Replace `sp-opened`/`sp-closed` event listeners with `swc-open`/`swc-close` (and `swc-after-open`/`swc-after-close` where needed)
+- [ ] Remove `self-managed` from all tooltips; add `id` to the trigger and `for="[id]"` to the tooltip
+- [ ] Confirm no tooltip is nested inside its trigger element
+- [ ] Add `mouseenter`/`mouseleave` and `focusin`/`focusout` listeners to control `open` until automatic wiring ships
+- [ ] Remove all `--mod-tooltip-*` CSS overrides
diff --git a/2nd-gen/packages/swc/components/tooltip/stories/tooltip.stories.ts b/2nd-gen/packages/swc/components/tooltip/stories/tooltip.stories.ts
index ef4da40b86..32d14dcc88 100644
--- a/2nd-gen/packages/swc/components/tooltip/stories/tooltip.stories.ts
+++ b/2nd-gen/packages/swc/components/tooltip/stories/tooltip.stories.ts
@@ -180,8 +180,16 @@ const triggered = (
};
/**
- * Each story renders one or more buttons that trigger associated tooltips when clicked.
- * These stories use a temporary click-to-toggle implementation until `HoverController` is available in the additive phase.
+ * A `` displays a brief, contextual message near a trigger element.
+ *
+ * Author `` as a sibling of the trigger element. Reference the trigger by its `id`
+ * using the `for` attribute; the tooltip can be placed anywhere in the same document tree root.
+ *
+ * For cross-shadow-root triggers where `getElementById` cannot reach the trigger, set the
+ * `triggerElement` property directly with an element reference.
+ *
+ * Each story in this document uses a temporary click-to-toggle interaction.
+ * Automatic hover and focus wiring is available in a future release.
*/
const meta: Meta = {
title: 'Tooltip',
@@ -242,8 +250,6 @@ export const Overview: Story = {
* 1. **Tooltip bubble**: Container with rounded corners and variant-specific background color
* 2. **Tip indicator**: Triangular arrow pointing toward the trigger element (placement-aware)
* 3. **Default slot**: Text content displayed inside the bubble
- *
- * Click each button below to toggle short and long text variants.
*/
export const Anatomy: Story = {
render: (args) => html`
@@ -269,6 +275,11 @@ export const Anatomy: Story = {
// ──────────────────────────
// OPTIONS STORIES
// ──────────────────────────
+
+/**
+ * Three semantic variants are available: `neutral` (default), `informative`, and `negative`.
+ * Each applies a distinct background color token.
+ */
export const Variants: Story = {
render: (args) => html`
${TOOLTIP_VARIANTS.map((variant) =>
@@ -285,7 +296,7 @@ export const Variants: Story = {
/**
* The `placement` attribute sets the preferred position of the tooltip relative to its trigger.
- * Pixel-accurate anchoring requires `PlacementController` (additive phase); these stories
+ * Pixel-accurate anchoring requires `PlacementController` (future release); these stories
* temporarily use Floating UI directly to verify visual appearance across placements.
*/
export const Placements: Story = {
@@ -348,11 +359,71 @@ export const Placements: Story = {
// STATES STORIES
// ──────────────────────────
-// TODO: will complete in separate documentation pass of phase 7
+/**
+ * The tooltip has two states: closed (default) and open.
+ *
+ * When open, the bubble and directional tip are visible. The `open` property reflects whether the
+ * tooltip is currently shown. Click the button below to toggle the open state.
+ */
+export const Open: Story = {
+ render: (args) => html`
+ ${triggered({ ...args }, 'tooltip-state-open', 'Action')}
+ `,
+ args: {
+ variant: 'neutral',
+ placement: 'top',
+ 'default-slot': 'Save your changes',
+ },
+ play: async ({ canvasElement }: { canvasElement: HTMLElement }) => {
+ const button = canvasElement.querySelector('swc-button') as HTMLElement;
+ button?.click();
+ },
+ tags: ['states'],
+};
-// ──────────────────────────────
+// ────────────────────────────────
// BEHAVIORS STORIES
-// ──────────────────────────────
+// ────────────────────────────────
+
+/**
+ * `` dispatches four lifecycle events as the tooltip opens and closes:
+ *
+ * - **`swc-open`**: Dispatched when the tooltip begins to open, before the enter transition plays.
+ * - **`swc-after-open`**: Dispatched after the enter transition completes.
+ * - **`swc-close`**: Dispatched when the tooltip begins to close, before the exit transition plays.
+ * - **`swc-after-close`**: Dispatched after the exit transition completes.
+ *
+ * When no CSS transition is active (for example, when `prefers-reduced-motion` removes it),
+ * `swc-after-open` and `swc-after-close` are dispatched synchronously on the same tick as
+ * `swc-open` and `swc-close`.
+ *
+ * Events fire regardless of what caused the state change: setting `open` directly, calling
+ * `showPopover()`/`hidePopover()`, pressing `Escape`, or a light-dismiss click.
+ */
+export const Events: Story = {
+ render: (args) => html`
+ ${triggered({ ...args }, 'tooltip-behavior-events', 'Open')}
+ `,
+ args: {
+ variant: 'neutral',
+ placement: 'top',
+ 'default-slot': 'Save your changes',
+ },
+ tags: ['behaviors'],
+};
+
+/**
+ * `` uses `popover="auto"`, which participates in the browser's auto popover stack.
+ * Opening a tooltip dismisses any other open `auto` popover in the document: other tooltips,
+ * menus, pickers, and selects.
+ *
+ * Set `manual` on the tooltip and manage the `open` property directly to opt out of automatic
+ * open and close behavior. ARIA relationship wiring still fires on `open` change when `for` or
+ * `triggerElement` is set.
+ */
+export const AutoStack: Story = {
+ tags: ['behaviors', 'description-only'],
+};
/**
* When a trigger has no visible text label and the tooltip text is its sole accessible name,
@@ -385,4 +456,95 @@ export const Labeling: Story = {
// ACCESSIBILITY STORIES
// ────────────────────────────────
-// TODO: will complete in separate documentation pass of phase 7
+/**
+ * ### Features
+ *
+ * The `` element implements the following accessibility features:
+ *
+ * #### ARIA role and relationship
+ *
+ * 1. **`role="tooltip"`**: Set on the host element via `connectedCallback`.
+ * 2. **`ariaDescribedByElements`**: When the tooltip opens, the SWC layer resolves the trigger
+ * via `for` or `triggerElement` and sets `Element.ariaDescribedByElements = [tooltipHost]`
+ * on the trigger's interactive surface. For 2nd-gen SWC components with an open shadow root,
+ * the inner `