Skip to content
Merged
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
10 changes: 5 additions & 5 deletions 2nd-gen/packages/core/components/tooltip/Tooltip.base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
*/
Expand All @@ -81,15 +81,15 @@ 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;

/**
* 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
*/
Expand All @@ -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.
*
Expand Down
20 changes: 19 additions & 1 deletion 2nd-gen/packages/swc/.storybook/preview-head.html
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 is nice, but I feel like our whole SB customization needs some love 😛 cc: @caseyisonit

Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion 2nd-gen/packages/swc/components/tooltip/Tooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
283 changes: 283 additions & 0 deletions 2nd-gen/packages/swc/components/tooltip/migration-guide.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
import { Meta } from '@storybook/addon-docs/blocks';

<Meta title="Tooltip/Migration guide" />

# Tooltip migration guide

Replace `<sp-tooltip>` with `<swc-tooltip>`, 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.

<div
style={{
borderLeft: '4px solid #2680eb',
background: 'rgba(38, 128, 235, 0.10)',
padding: '12px 16px',
margin: '16px 0',
borderRadius: '4px',
}}
>
<strong>ℹ️ Initial release scope.</strong> This release delivers the tag
rename, variant and event API changes, ARIA relationship wiring via{' '}
<code>for</code>, and native <code>{'popover="auto"'}</code> open/close
behavior.{' '}
<strong>
Automatic hover/focus trigger wiring and viewport-aware pixel positioning
are not yet available.
</strong>{' '}
They require <code>HoverController</code> and <code>PlacementController</code>
, which ship in a future release. Until then, control visibility via the{' '}
<code>open</code> property and position the tooltip with a helper library like
Floating UI.
</div>

## 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
<!-- Before -->
<sp-tooltip variant="info">Save your changes</sp-tooltip>
<sp-tooltip variant="positive">Upload complete</sp-tooltip>
<sp-tooltip>No changes yet</sp-tooltip>

<!-- After -->
<swc-tooltip variant="informative">Save your changes</swc-tooltip>
<!-- positive has no direct equivalent; choose based on content meaning -->
<swc-tooltip variant="informative">Upload complete</swc-tooltip>
<swc-tooltip>No changes yet</swc-tooltip>
```

### 3. Remove icon slot content

Spectrum 2 tooltip does not render icons. Remove all `slot="icon"` content.

```html
<!-- Before -->
<sp-tooltip variant="info">
<sp-icon-info slot="icon"></sp-icon-info>
Learn more
</sp-tooltip>

<!-- After -->
<swc-tooltip variant="informative">Learn more</swc-tooltip>
```

### 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, `<sp-tooltip>` 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
<!-- Before (Spectrum 1 pattern: tooltip nested inside trigger, self-managed) -->
<sp-action-button>
Save
<sp-tooltip self-managed placement="top">Save your changes</sp-tooltip>
</sp-action-button>

<!-- After (Spectrum 2 pattern: tooltip is a sibling; id + for wire the relationship) -->
<swc-action-button id="save-btn">Save</swc-action-button>
<swc-tooltip for="save-btn" placement="top">Save your changes</swc-tooltip>
```

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');
```

<div
style={{
borderLeft: '4px solid #2680eb',
background: 'rgba(38, 128, 235, 0.10)',
padding: '12px 16px',
margin: '16px 0',
borderRadius: '4px',
}}
>
<strong>
ℹ️ What <code>for</code> does in this release.
</strong>{' '}
Setting <code>{'for="[id]"'}</code> establishes the ARIA relationship between
the trigger and tooltip. It does <strong>not</strong> 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).
</div>

### 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
<!-- After (current release: manual event wiring required) -->
<button id="save-btn">Save</button>
<swc-tooltip for="save-btn" placement="top" id="save-tip">
Save your changes
</swc-tooltip>
<script>
const btn = document.querySelector('#save-btn');
const tip = document.querySelector('#save-tip');
btn.addEventListener('mouseenter', () => {
tip.open = true;
});
btn.addEventListener('mouseleave', () => {
tip.open = false;
});
btn.addEventListener('focusin', () => {
tip.open = true;
});
btn.addEventListener('focusout', () => {
tip.open = false;
});
</script>
```

## Accessibility

- **Trigger relationship:** Set `for="[trigger-id]"` on every `<swc-tooltip>`. 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 `<swc-popover>` 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:** `<swc-tooltip>` is hover/focus only. For touch-accessible disclosure, use `<swc-popover>` or contextual help.
- **`popover="auto"` auto-stack change:** Opening a `<swc-tooltip>` 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 `<swc-inline-alert>` once it is migrated to Spectrum 2. */}

<div
style={{
borderLeft: '4px solid #dba842',
background: 'rgba(219, 168, 66, 0.12)',
padding: '12px 16px',
margin: '16px 0',
borderRadius: '4px',
}}
>
<strong>⚠️ Breaking change.</strong> Spectrum 1{' '}
<code>{'--mod-tooltip-*'}</code> properties <strong>do not apply</strong> to{' '}
<code>{'<swc-tooltip>'}</code>. Remove every <code>{'--mod-tooltip-*'}</code>{' '}
override. The only public custom property in Spectrum 2 is listed below.
</div>

{/* @todo Replace the Description column with the `@cssproperty` JSDoc descriptions from `<swc-tooltip>`'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. |

<div
style={{
borderLeft: '4px solid #e34850',
background: 'rgba(227, 72, 80, 0.10)',
padding: '12px 16px',
margin: '16px 0',
borderRadius: '4px',
}}
>
<strong>🚫 Do not target internals.</strong> Internal classes,{' '}
<code>{'--_swc-tooltip-*'}</code> private properties, and shadow DOM are{' '}
<strong>not public API</strong>. Styling applied to them will break without
warning on minor releases.
</div>

## Checklist

- [ ] Update imports from `@spectrum-web-components/tooltip` to `@adobe/spectrum-wc`
- [ ] Rename all `<sp-tooltip>` to `<swc-tooltip>`
- [ ] 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
Loading
Loading