Skip to content

Commit 44dd28e

Browse files
annawen1kennylam
andauthored
feat(definition-tooltip): web components parity (#19135)
* feat(definition-tooltip): initial commit * chore: definition tooltip open logic * chore: definition tooltip styles * chore: remove unused imports * chore: clean up * chore: add storybook documentation * chore: generate component api table in docs --------- Co-authored-by: kennylam <[email protected]>
1 parent b0dd915 commit 44dd28e

File tree

7 files changed

+292
-2
lines changed

7 files changed

+292
-2
lines changed

packages/web-components/src/components/popover/popover-content.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,14 @@ class CDSPopoverContent extends LitElement {
6363
render() {
6464
if (this.autoalign) {
6565
return html`
66-
<span class="${prefix}--popover-content">
66+
<span class="${prefix}--popover-content" part="content">
6767
<slot> </slot>
6868
<span class="${prefix}--popover-caret"></span>
6969
</span>
7070
`;
7171
} else {
7272
return html`
73-
<span class="${prefix}--popover-content">
73+
<span class="${prefix}--popover-content" part="content">
7474
<slot> </slot>
7575
</span>
7676
<span class="${prefix}--popover-caret"></span>
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { Story, ArgTypes, Canvas, Meta } from '@storybook/blocks';
2+
import { cdnJs, cdnCss } from '../../globals/internal/storybook-cdn';
3+
import * as DefinitionTooltipStories from './definition-tooltip.stories';
4+
5+
<Meta of={DefinitionTooltipStories} />
6+
7+
# DefinitionTooltip
8+
9+
[Source code](https://github.com/carbon-design-system/carbon/tree/main/packages/web-components/src/components/tooltip)
10+
&nbsp;|&nbsp;
11+
[Usage guidelines](https://www.carbondesignsystem.com/components/tooltip/usage)
12+
&nbsp;|&nbsp;
13+
[Accessibility](https://www.carbondesignsystem.com/components/tooltip/accessibility)
14+
15+
{/* <!-- START doctoc generated TOC please keep comment here to allow auto update --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> */}
16+
17+
## Table of Contents
18+
19+
- [Overview](#overview)
20+
- [Customizing the content of a definition tooltip](#customizing-the-content-of-a-definition-tooltip)
21+
- [Tooltip alignment](#tooltip-alignment)
22+
- [Component API](#component-api)
23+
- [Feedback](#feedback)
24+
25+
{/* <!-- END doctoc generated TOC please keep comment here to allow auto update --> */}
26+
27+
## Overview
28+
29+
The `cds-definition-tooltip` component is used to provide additional information
30+
about a particular term or phrase in text content. It is similar to a `cds-tooltip`
31+
component but has fewer alignment options and has a slightly different
32+
interaction pattern.
33+
34+
The `cds-definition-tooltip` is made up of two parts: a term and the tooltip itself.
35+
You can customize the contents of the tooltip through the `definition` slot. You
36+
can customize the term by providing your own slotted content to this component.
37+
38+
<Canvas of={DefinitionTooltipStories.Default} />
39+
40+
### Customizing the content of a definition tooltip
41+
42+
You can customize the content of the tooltip through the `definition` slot. This
43+
slot allows you to provide text or your own custom elements to be rendered as a
44+
definition for your term.
45+
46+
Note: content passed into the `definition` slot must not contain any interactive
47+
content. If you pass in interactive content, it's semantics will not be
48+
available to users of screen reader software.
49+
50+
### Tooltip alignment
51+
52+
The `align` prop allows you to specify where your content should be placed
53+
relative to the tooltip. For example, if you provide `align="top"` to the
54+
`cds-definition-tooltip` component then the tooltip will render above your component.
55+
Similarly, if you provide `align="bottom"` then the tooltip will render below
56+
your component.
57+
58+
## Component API
59+
60+
<ArgTypes of="cds-definition-tooltip"/>
61+
62+
## Feedback
63+
64+
Help us improve this component by providing feedback, asking questions on Slack,
65+
or updating this file on
66+
[GitHub](https://github.com/carbon-design-system/carbon/edit/main/packages/web-components/src/components/tooltip/definition-tooltip.mdx).
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/**
2+
* Copyright IBM Corp. 2019, 2023
3+
*
4+
* This source code is licensed under the Apache-2.0 license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import { html } from 'lit';
9+
import './index';
10+
import styles from './tooltip-story.scss?lit';
11+
import { POPOVER_ALIGNMENT } from '../popover/defs';
12+
13+
const tooltipAlignments = {
14+
[`top`]: POPOVER_ALIGNMENT.TOP,
15+
[`top-left`]: POPOVER_ALIGNMENT.TOP_LEFT,
16+
[`top-right`]: POPOVER_ALIGNMENT.TOP_RIGHT,
17+
[`bottom`]: POPOVER_ALIGNMENT.BOTTOM,
18+
[`bottom-left`]: POPOVER_ALIGNMENT.BOTTOM_LEFT,
19+
[`bottom-right`]: POPOVER_ALIGNMENT.BOTTOM_RIGHT,
20+
[`left`]: POPOVER_ALIGNMENT.LEFT,
21+
[`left-bottom`]: POPOVER_ALIGNMENT.LEFT_BOTTOM,
22+
[`left-top`]: POPOVER_ALIGNMENT.LEFT_TOP,
23+
[`right`]: POPOVER_ALIGNMENT.RIGHT,
24+
[`right-bottom`]: POPOVER_ALIGNMENT.RIGHT_BOTTOM,
25+
[`right-top`]: POPOVER_ALIGNMENT.RIGHT_TOP,
26+
};
27+
28+
const defaultArgs = {
29+
align: POPOVER_ALIGNMENT.BOTTOM_LEFT,
30+
defaultOpen: false,
31+
definition: 'Example defintion',
32+
openOnHover: false,
33+
};
34+
35+
const controls = {
36+
align: {
37+
control: 'select',
38+
description: 'Specify how the trigger should align with the tooltip',
39+
options: tooltipAlignments,
40+
},
41+
openOnHover: {
42+
control: 'boolean',
43+
description:
44+
'Specifies whether the defintion tooltip should open on hover or not',
45+
},
46+
defaultOpen: {
47+
control: 'boolean',
48+
description:
49+
'Specify whether the tooltip should be open when it first renders',
50+
},
51+
definition: {
52+
control: 'text',
53+
description:
54+
'This is a slot where the applied the content inside of the tooltip that appears when a user interacts with the element rendered by the children prop',
55+
},
56+
};
57+
58+
export const Default = {
59+
argTypes: controls,
60+
args: defaultArgs,
61+
render: ({ align, defaultOpen, definition, openOnHover }) => html`
62+
<p>
63+
Custom domains direct requests for your apps in this Cloud Foundry
64+
organization to a
65+
<span style="display: inline-block;">
66+
<cds-definition-tooltip
67+
align=${align}
68+
?open-on-hover=${openOnHover}
69+
?default-open=${defaultOpen}>
70+
<span slot="definition">${definition}</span>
71+
URL
72+
</cds-definition-tooltip>
73+
</span>
74+
that you own. A custom domain can be a shared domain, a shared subdomain,
75+
or a shared domain and host.
76+
</p>
77+
`,
78+
};
79+
const meta = {
80+
title: 'Components/Defintion tooltip',
81+
decorators: [
82+
(story) =>
83+
html` <div class="sb-tooltip-story sb-definition-tooltip">
84+
<style>
85+
${styles}
86+
</style>
87+
${story()}
88+
</div>`,
89+
],
90+
};
91+
92+
export default meta;
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/**
2+
* Copyright IBM Corp. 2019, 2024
3+
*
4+
* This source code is licensed under the Apache-2.0 license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import { html, LitElement } from 'lit';
9+
import { property, state } from 'lit/decorators.js';
10+
import { prefix } from '../../globals/settings';
11+
import { POPOVER_ALIGNMENT } from '../popover/defs';
12+
import '../popover/index';
13+
import styles from './tooltip.scss?lit';
14+
import { carbonElement as customElement } from '../../globals/decorators/carbon-element';
15+
16+
/**
17+
* Definition tooltip.
18+
*
19+
* @element cds-definition-tooltip
20+
*/
21+
@customElement(`${prefix}-definition-tooltip`)
22+
class CDSDefinitionTooltip extends LitElement {
23+
/**
24+
* Specify how the trigger should align with the tooltip
25+
*/
26+
@property({ reflect: true, type: POPOVER_ALIGNMENT })
27+
align = 'bottom';
28+
29+
/**
30+
* Will auto-align Definition Tooltip. This prop is currently experimental and is subject to future changes.
31+
*/
32+
@property({ type: Boolean, reflect: true })
33+
autoalign = false;
34+
35+
/**
36+
* Specify whether the tooltip should be open when it first renders
37+
*/
38+
@property({ type: Boolean, reflect: true, attribute: 'default-open' })
39+
defaultOpen = false;
40+
41+
/**
42+
* Specifies whether the `DefinitionTooltip` should open on hover or not
43+
*/
44+
@property({ reflect: true, type: Boolean, attribute: 'open-on-hover' })
45+
openOnHover = false;
46+
47+
@state()
48+
open = false;
49+
50+
connectedCallback() {
51+
super.connectedCallback();
52+
53+
if (this.hasAttribute('default-open')) {
54+
this.open = true;
55+
}
56+
}
57+
58+
protected _handleBlur() {
59+
this.open = false;
60+
}
61+
62+
protected _handleMouseDown() {
63+
this.open = !this.open;
64+
}
65+
66+
protected _handleKeyDown(event: KeyboardEvent) {
67+
const { key } = event;
68+
69+
if (this.open && (key === 'Esc' || key === 'Escape')) {
70+
event.stopPropagation();
71+
this.open = false;
72+
}
73+
}
74+
75+
protected _handleHover() {
76+
if (this.openOnHover && !this.open) {
77+
this.open = true;
78+
} else {
79+
this.open = false;
80+
}
81+
}
82+
83+
protected _handleFocus() {
84+
this.open = true;
85+
}
86+
87+
render() {
88+
const { align, open } = this;
89+
90+
return html`
91+
<cds-popover
92+
@mouseenter=${this._handleHover}
93+
@mouseleave=${this._handleHover}
94+
highContrast
95+
dropShadow=${false}
96+
align=${align}
97+
.open=${open}>
98+
<button
99+
@focus=${this._handleFocus}
100+
@blur=${this._handleBlur}
101+
@mousedown=${this._handleMouseDown}
102+
@keydown=${this._handleKeyDown}
103+
aria-expanded=${open}
104+
class="${prefix}--definition-term">
105+
<slot></slot>
106+
</button>
107+
<cds-popover-content>
108+
<slot name="definition"></slot>
109+
</cds-popover-content>
110+
</cds-popover>
111+
`;
112+
}
113+
114+
static styles = styles;
115+
}
116+
117+
export default CDSDefinitionTooltip;

packages/web-components/src/components/tooltip/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77

88
import './tooltip';
99
import './tooltip-content';
10+
import './definition-tooltip';

packages/web-components/src/components/tooltip/tooltip-story.scss

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,12 @@
3535
.sb-tooltip-trigger svg {
3636
fill: theme.$background-inverse;
3737
}
38+
39+
// DefinitionTooltip
40+
.sb-definition-tooltip {
41+
max-inline-size: 60ch;
42+
}
43+
44+
.sb-definition-tooltip p {
45+
@include type.type-style('body-short-02');
46+
}

packages/web-components/src/components/tooltip/tooltip.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,8 @@
4444
@extend .#{$prefix}--tooltip-content;
4545
}
4646
}
47+
48+
// Definition tooltip
49+
:host(#{$prefix}-definition-tooltip) #{$prefix}-popover-content::part(content) {
50+
@extend .#{$prefix}--definition-tooltip;
51+
}

0 commit comments

Comments
 (0)