Skip to content

Commit 54be0df

Browse files
authored
Merge pull request #226 from US-CBP/Tooltip
Tooltip
2 parents d8430e5 + 2a442b3 commit 54be0df

File tree

5 files changed

+526
-0
lines changed

5 files changed

+526
-0
lines changed

packages/web-components/assets/css/storybook-canvas.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ body:has(cbp-app[data-cbp-theme="dark"]) {
99
background-color: var(--cbp-color-branding-cbp-dark);
1010
}
1111

12+
.sb-main-centered cbp-app {
13+
min-height: unset;
14+
}
15+
1216

1317
/* Docs overrides */
1418
.sbdocs .sbdocs-content {
Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
/**
2+
* @Prop --cbp-tooltip-color: var(--cbp-color-text-lightest);
3+
* @Prop --cbp-tooltip-color-dark: var(--cbp-color-text-darkest);
4+
* @Prop --cbp-tooltip-color-bg: var(--cbp-color-gray-cool-80);
5+
* @Prop --cbp-tooltip-color-bg-dark: var(--cbp-color-gray-cool-5);
6+
* @Prop --cbp-tooltip-control-focus: 1px solid red;
7+
* @Prop --cbp-tooltip-control-focus-dark: 1px solid cyan;
8+
* @Prop --cbp-tooltip-padding: var(--cbp-space-inset-4x, 1rem);
9+
* @Prop --cbp-tooltip-gap: 0px;
10+
* @Prop --cbp-tooltip-offset: 0px;
11+
* @Prop --cbp-tooltip-caret-size: 15px;
12+
* @Prop --cbp-tooltip-caret-offset: calc(var(--cbp-tooltip-caret-size) / 2);
13+
* @Prop --cbp-tooltip-control-color-hover: var(--cbp-color-interactive-secondary-darker);
14+
* @Prop --cbp-tooltip-control-color-hover-dark: var(--cbp-color-interactive-secondary-lighter);
15+
* @Prop --cbp-tooltip-control-color-bg-hover: var(--cbp-color-interactive-secondary-lighter);
16+
* @Prop --cbp-tooltip-control-color-bg-hover-dark: var(--cbp-color-interactive-disabled-light);
17+
* @Prop --cbp-tooltip-control-color-focus: var(--cbp-color-text-lightest);
18+
* @Prop --cbp-tooltip-control-color-focus-dark: var(--cbp-color-text-darkest);
19+
* @Prop --cbp-tooltip-control-color-bg-focus: var(--cbp-color-interactive-focus-dark);
20+
* @Prop --cbp-tooltip-control-color-bg-focus-dark: var(--cbp-color-interactive-focus-light);
21+
*/
22+
:root{
23+
24+
--cbp-tooltip-color: var(--cbp-color-text-lightest);
25+
--cbp-tooltip-color-dark: var(--cbp-color-text-darkest);
26+
--cbp-tooltip-color-bg: var(--cbp-color-gray-cool-80);
27+
--cbp-tooltip-color-bg-dark: var(--cbp-color-gray-cool-5);
28+
--cbp-tooltip-gap: 0px;
29+
--cbp-tooltip-offset: 0px;
30+
--cbp-tooltip-caret-size: 15px;
31+
--cbp-tooltip-caret-offset: calc(var(--cbp-tooltip-caret-size) / 2);
32+
33+
34+
35+
--cbp-tooltip-control-height: 2.25rem;
36+
--cbp-tooltip-control-width: var(--cbp-tooltip-control-height);
37+
38+
--cbp-tooltip-control-color-hover: var(--cbp-color-interactive-secondary-darker);
39+
--cbp-tooltip-control-color-hover-dark: var(--cbp-color-text-darkest);
40+
--cbp-tooltip-control-color-bg-hover: var(--cbp-color-interactive-secondary-lighter);
41+
--cbp-tooltip-control-color-bg-hover-dark: var(--cbp-color-interactive-disabled-light);
42+
43+
--cbp-tooltip-control-color-focus: var(--cbp-color-text-lightest);
44+
--cbp-tooltip-control-color-focus-dark: var(--cbp-color-text-darkest);
45+
--cbp-tooltip-control-color-bg-focus: var(--cbp-color-interactive-focus-dark);
46+
--cbp-tooltip-control-color-bg-focus-dark: var(--cbp-color-interactive-focus-light);
47+
--cbp-tooltip-control-outline-focus: 2px solid var(--cbp-color-white);
48+
--cbp-tooltip-control-outline-focus-dark: 2px solid var(--cbp-color-black);
49+
50+
--cbp-tooltip-definition-color: var(--cbp-color-interactive-primary-dark);
51+
--cbp-tooltip-definition-color-dark: var(--cbp-color-interactive-primary-light);
52+
--cbp-tooltip-definition-color-hover: var(--cbp-color-interactive-primary-darker);
53+
--cbp-tooltip-definition-color-hover-dark: var(--cbp-color-interactive-primary-lighter);
54+
--cbp-tooltip-definition-color-focus: var(--cbp-color-interactive-focus-dark);
55+
--cbp-tooltip-definition-color-focus-dark: var(--cbp-color-interactive-focus-light);
56+
--cbp-tooltip-definition-outline-focus: 2px solid var(--cbp-color-interactive-focus-dark);
57+
--cbp-tooltip-definition-outline-focus-dark: 2px solid var(--cbp-color-interactive-focus-light);
58+
}
59+
60+
[data-cbp-theme=light] cbp-tooltip[context*=dark]:not([context=light-always]),
61+
[data-cbp-theme=dark] cbp-tooltip:not([context=dark-inverts]):not([context=light-always]) {
62+
63+
--cbp-tooltip-color-bg: var(--cbp-tooltip-color-bg-dark);
64+
--cbp-tooltip-color: var(--cbp-tooltip-color-dark);
65+
66+
--cbp-tooltip-control-color-hover: var(--cbp-tooltip-control-color-hover-dark);
67+
--cbp-tooltip-control-color-bg-hover: var(--cbp-tooltip-control-color-bg-hover-dark);
68+
69+
--cbp-tooltip-control-color-focus: var(--cbp-tooltip-control-color-focus-dark);
70+
--cbp-tooltip-control-color-bg-focus: var(--cbp-tooltip-control-color-bg-focus-dark);
71+
--cbp-tooltip-control-outline-focus: var(--cbp-tooltip-control-outline-focus-dark);
72+
73+
--cbp-tooltip-definition-color: var(--cbp-tooltip-definition-color-dark);
74+
--cbp-tooltip-definition-color-hover: var(--cbp-tooltip-definition-color-hover-dark);
75+
76+
--cbp-tooltip-definition-color-focus: var(--cbp-tooltip-definition-color-focus-dark);
77+
--cbp-tooltip-definition-outline-focus: var(--cbp-tooltip-definition-outline-focus-dark);
78+
}
79+
80+
cbp-tooltip {
81+
display: inline-flex;
82+
align-items: center;
83+
justify-content: center;
84+
position: relative;
85+
--cbp-tooltip-placement-gap: var(--cbp-tooltip-gap);
86+
--cbp-tooltip-placement-offset: var(--cbp-tooltip-offset);
87+
--cbp-tooltip-gap: var(--cbp-space-4x, 1rem);
88+
89+
&[open] [role='tooltip']{
90+
display: flex;
91+
}
92+
93+
&:hover{
94+
color: var(--cbp-tooltip-control-color-hover);
95+
background: var(--cbp-tooltip-control-color-bg-hover);
96+
}
97+
98+
&:focus-visible,
99+
&:focus-within{
100+
color: var(--cbp-tooltip-control-color-focus);
101+
background: var(--cbp-tooltip-control-color-bg-focus);
102+
outline:var(--cbp-tooltip-control-outline-focus);
103+
}
104+
105+
&[variant=default]{
106+
border-radius: var(--cbp-border-radius-soft);
107+
height: var(--cbp-tooltip-control-height);
108+
width: var(--cbp-tooltip-control-width);
109+
padding: var(--cbp-space-1x);
110+
outline-offset: calc(-1 * var(--cbp-space-1x));
111+
}
112+
113+
/** definition link*/
114+
&[variant=definition]{
115+
font-size: var(--cbp-font-size-body);
116+
color: var(--cbp-tooltip-definition-color);
117+
text-decoration: underline;
118+
text-decoration-style: dotted;
119+
cursor: pointer;
120+
121+
&:hover{
122+
color: var(--cbp-tooltip-definition-color-hover);
123+
background-color: transparent;
124+
}
125+
126+
&:focus,
127+
&:focus-visible,
128+
&:focus-within{
129+
color:var(--cbp-tooltip-definition-color-focus);
130+
background-color: transparent;
131+
outline:var(--cbp-tooltip-definition-outline-focus);
132+
}
133+
}
134+
135+
/** Alignment*/
136+
&[alignment='top-left'] div[role=tooltip]{
137+
--cbp-tooltip-placement-top: calc(0px - var(--cbp-tooltip-placement-gap, 5px));
138+
--cbp-tooltip-placement-left: calc(0px + var(--cbp-tooltip-placement-offset, 0px));
139+
--cbp-tooltip-placement-transform-x: 0;
140+
--cbp-tooltip-placement-transform-y: -100%;
141+
--cbp-tooltip-caret-rotation: 315deg;
142+
--cbp-tooltip-caret-top: calc(100% - var(--cbp-tooltip-caret-offset));
143+
--cbp-tooltip-caret-left: var(--cbp-tooltip-caret-offset)
144+
}
145+
146+
&[alignment='top-center'] div[role=tooltip]{
147+
--cbp-tooltip-placement-top: calc(0% - var(--cbp-tooltip-placement-gap, 5px));
148+
--cbp-tooltip-placement-left: 50%;
149+
--cbp-tooltip-placement-transform-x: -50%;
150+
--cbp-tooltip-placement-transform-y: -100%;
151+
--cbp-tooltip-caret-rotation: 315deg;
152+
--cbp-tooltip-caret-top: calc(100% - var(--cbp-tooltip-caret-offset));
153+
--cbp-tooltip-caret-left: calc(50% - var(--cbp-tooltip-caret-offset))
154+
}
155+
156+
&[alignment='top-right'] div[role=tooltip]{
157+
--cbp-tooltip-placement-top: calc(0px - var(--cbp-tooltip-placement-gap, 5px));
158+
--cbp-tooltip-placement-left: calc(100% + var(--cbp-tooltip-placement-offset, 0px));
159+
--cbp-tooltip-placement-transform-x: -100%;
160+
--cbp-tooltip-placement-transform-y: -100%;
161+
--cbp-tooltip-caret-rotation: 315deg;
162+
--cbp-tooltip-caret-top: calc(100% - var(--cbp-tooltip-caret-offset));
163+
--cbp-tooltip-caret-left: calc(100% - (var(--cbp-tooltip-caret-offset) * 3))
164+
}
165+
166+
&[alignment='right-top'] div[role=tooltip]{
167+
--cbp-tooltip-placement-top: calc(0px + var(--cbp-tooltip-placement-offset, 0px));
168+
--cbp-tooltip-placement-left: calc(100% + var(--cbp-tooltip-placement-gap, 5px));
169+
--cbp-tooltip-placement-transform-x: 0;
170+
--cbp-tooltip-placement-transform-y: 0%;
171+
--cbp-tooltip-caret-rotation: 45deg;
172+
--cbp-tooltip-caret-top: var(--cbp-tooltip-caret-offset);
173+
--cbp-tooltip-caret-left: calc(0% - var(--cbp-tooltip-caret-offset))
174+
}
175+
176+
&[alignment='right-center'] div[role=tooltip]{
177+
--cbp-tooltip-placement-top: 50%;
178+
--cbp-tooltip-placement-left: calc(100% + var(--cbp-tooltip-placement-gap, 5px));
179+
--cbp-tooltip-placement-transform-x: 0;
180+
--cbp-tooltip-placement-transform-y: -50%;
181+
--cbp-tooltip-caret-rotation: 45deg;
182+
--cbp-tooltip-caret-top: calc(50% - var(--cbp-tooltip-caret-offset));
183+
--cbp-tooltip-caret-left: calc(0% - var(--cbp-tooltip-caret-offset))
184+
}
185+
186+
&[alignment='right-bottom'] div[role=tooltip]{
187+
--cbp-tooltip-placement-top: calc(-150% + var(--cbp-tooltip-placement-offset, 0px));
188+
--cbp-tooltip-placement-left: calc(100% + var(--cbp-tooltip-placement-gap, 5px));
189+
--cbp-tooltip-placement-transform-x: 0;
190+
--cbp-tooltip-placement-transform-y: 0;
191+
--cbp-tooltip-caret-rotation: 45deg;
192+
--cbp-tooltip-caret-top: calc(75% - var(--cbp-tooltip-caret-offset));
193+
--cbp-tooltip-caret-left: calc(0% - var(--cbp-tooltip-caret-offset))
194+
}
195+
196+
&[alignment='bottom-left'] div[role=tooltip]{
197+
--cbp-tooltip-placement-top: calc(100% + var(--cbp-tooltip-placement-gap, 5px));
198+
--cbp-tooltip-placement-left: calc(0px + var(--cbp-tooltip-placement-offset, 0px));
199+
--cbp-tooltip-placement-transform-x: 0;
200+
--cbp-tooltip-placement-transform-y: 0;
201+
--cbp-tooltip-caret-rotation: 135deg;
202+
--cbp-tooltip-caret-left: var(--cbp-tooltip-caret-offset);
203+
--cbp-tooltip-caret-top: calc(0% - var(--cbp-tooltip-caret-offset))
204+
}
205+
206+
&[alignment='bottom-center'] div[role=tooltip]{
207+
--cbp-tooltip-placement-top: calc(100% + var(--cbp-tooltip-placement-gap, 5px));
208+
--cbp-tooltip-placement-left: 50%;
209+
--cbp-tooltip-placement-transform-x: -50%;
210+
--cbp-tooltip-placement-transform-y: 0;
211+
--cbp-tooltip-caret-rotation: 135deg;
212+
--cbp-tooltip-caret-left: calc(50% - var(--cbp-tooltip-caret-offset));
213+
--cbp-tooltip-caret-top: calc(0% - var(--cbp-tooltip-caret-offset))
214+
}
215+
216+
&[alignment='bottom-right'] div[role=tooltip]{
217+
--cbp-tooltip-placement-top: calc(100% + var(--cbp-tooltip-placement-gap, 5px));
218+
--cbp-tooltip-placement-left: calc(100% + var(--cbp-tooltip-placement-offset, 0px));
219+
--cbp-tooltip-placement-transform-x: -100%;
220+
--cbp-tooltip-placement-transform-y: 0;
221+
--cbp-tooltip-caret-rotation: 135deg;
222+
--cbp-tooltip-caret-left: calc(100% - (var(--cbp-tooltip-caret-offset) * 3));
223+
--cbp-tooltip-caret-top: calc(0% - var(--cbp-tooltip-caret-offset))
224+
}
225+
226+
&[alignment='left-top'] div[role=tooltip]{
227+
--cbp-tooltip-placement-top: calc(125% + var(--cbp-tooltip-placement-offset, 0px));
228+
--cbp-tooltip-placement-left: calc(0% - var(--cbp-tooltip-placement-gap, 5px));
229+
--cbp-tooltip-placement-transform-x: -100%;
230+
--cbp-tooltip-placement-transform-y: -50%;
231+
--cbp-tooltip-caret-rotation: 225deg;
232+
--cbp-tooltip-caret-top: calc(25% - var(--cbp-tooltip-caret-offset));
233+
--cbp-tooltip-caret-left: calc(100% - var(--cbp-tooltip-caret-offset))
234+
}
235+
236+
&[alignment='left-center'] div[role=tooltip]{
237+
--cbp-tooltip-placement-top: 50%;
238+
--cbp-tooltip-placement-left: calc(0% - var(--cbp-tooltip-placement-gap, 5px));
239+
--cbp-tooltip-placement-transform-x: -100%;
240+
--cbp-tooltip-placement-transform-y: -50%;
241+
--cbp-tooltip-caret-rotation: 225deg;
242+
--cbp-tooltip-caret-top: calc(50% - var(--cbp-tooltip-caret-offset));
243+
--cbp-tooltip-caret-left: calc(100% - var(--cbp-tooltip-caret-offset))
244+
}
245+
246+
&[alignment='left-bottom'] div[role=tooltip]{
247+
--cbp-tooltip-placement-top: calc(-150% + var(--cbp-tooltip-placement-offset, 0px));
248+
--cbp-tooltip-placement-left: calc(0% - var(--cbp-tooltip-placement-gap, 5px));
249+
--cbp-tooltip-placement-transform-x: -100%;
250+
--cbp-tooltip-placement-transform-y: 0%;
251+
--cbp-tooltip-caret-rotation: 225deg;
252+
--cbp-tooltip-caret-top: calc(75% - var(--cbp-tooltip-caret-offset));
253+
--cbp-tooltip-caret-left: calc(100% - var(--cbp-tooltip-caret-offset))
254+
}
255+
256+
257+
div[role=tooltip] {
258+
display: none;
259+
position: absolute;
260+
top: var(--cbp-tooltip-placement-top);
261+
left: var(--cbp-tooltip-placement-left);
262+
height: var(--tooltip-height, auto);
263+
padding: var(--cbp-space-1x);
264+
min-height: var(--cbp-space-11x);
265+
width: max-content;
266+
max-width: 33vw;
267+
transform: translate(var(--cbp-tooltip-placement-transform-x, 0), var(--cbp-tooltip-placement-transform-y, 0));
268+
border-style: solid;
269+
border-width: 0px;
270+
border-color: none;
271+
border-radius: var(--cbp-border-radius-softer);
272+
background-color: var(--cbp-tooltip-color-bg);
273+
color: var(--cbp-tooltip-color);
274+
font-size: var(--cbp-font-size-body);
275+
font-weight: var(--cbp-font-weight-regular);
276+
text-underline-offset: initial;
277+
box-shadow: var(--cbp-shadow-level-1-center);
278+
z-index: var(--cbp-z-index-level-1);
279+
280+
> div{
281+
padding: var(--cbp-space-1x);
282+
283+
[slot='cbp-tooltip-content']{
284+
line-height: var(--cbp-line-height-xs);
285+
}
286+
}
287+
}
288+
289+
290+
div[role=tooltip]::before {
291+
content: "";
292+
position: absolute;
293+
display: var(--cbp-caret-display, block);
294+
width: var(--cbp-tooltip-caret-size);
295+
height: var(--cbp-tooltip-caret-size);
296+
left: var(--cbp-tooltip-caret-left);
297+
top: var(--cbp-tooltip-caret-top);
298+
transform-origin: center;
299+
transform: rotate(var(--cbp-tooltip-caret-rotation));
300+
clip-path: polygon(8% 0, 100% 92%, 100% 100%, 0 100%, 0 0);
301+
border: inherit;
302+
background-color: inherit
303+
}
304+
305+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { Meta } from '@storybook/addon-docs';
2+
3+
<Meta title="Components/Tooltip/Specifications" />
4+
5+
# cbp-tooltip
6+
7+
## Purpose
8+
9+
* The tooltip component allows the development team to disclose supplemental, not essential or nessecary, information to a user via a
10+
triggering element. These should be used sparingly since hiding functionality should be avoided if at all possible. Historically,
11+
tooltips were accessible via hover but this does not conform to accessibility standards, and is completely invisible on touch-based
12+
devices. As such, tooltips are activated by focusing or clicking the triggering element
13+
14+
## Functional Requirements
15+
16+
* Tooltip is designed to wrap a slotted control, the control can be anything but the click and focus functionality will be impeded
17+
since they are used to launch the tooltip
18+
* Consumers will have to define the alignment of the tooltip. See the alignment prop for the defined options
19+
20+
## Technical Specifications
21+
22+
### User Interactions
23+
24+
* Focusing or clicking on the tooltip makes the tooltip visible
25+
* Once tooltip is open it will persist until the it is closed via clicking or focusing off of the close button in to left of content.
26+
Once closed the focus will return to the tooltip control
27+
28+
### Responsiveness
29+
30+
*
31+
32+
### Accessibility
33+
34+
* Tooltip is designed with keyboard navigation in mind, with the tooltip launching on focus & closing both via the escape key & focus
35+
leaving the close button
36+
* Tooltip has the roles semantically defined in HTML with the parent as role='button' and the tooltip container role='tooltip'
37+
* The tooltip root/parent has a tabindex of 0 to assist with Accessibility concerns with focus
38+
39+
### Additional Notes and Considerations

0 commit comments

Comments
 (0)