Skip to content

Commit

Permalink
fix(tooltip): small tweaks to the tooltip state
Browse files Browse the repository at this point in the history
  • Loading branch information
cwoolum committed Jul 13, 2024
1 parent dd22ec2 commit 3a35a72
Show file tree
Hide file tree
Showing 11 changed files with 70 additions and 161 deletions.
5 changes: 5 additions & 0 deletions .changeset/tasty-pugs-decide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@qwik-ui/headless': minor
---

Implement a beta version of the Tooltip component
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { component$ } from '@builder.io/qwik';
import { Tooltip } from '@qwik-ui/headless';

import '../snippets/animation.css';

export default component$(() => {
return (
<Tooltip.Root gutter={4} flip>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,53 +1,14 @@
import { component$, useStyles$ } from '@builder.io/qwik';
import { component$ } from '@builder.io/qwik';
import { Tooltip } from '@qwik-ui/headless';

export default component$(() => {
useStyles$(`
.tooltip-panel {
background-color: #222;
color: #fff;
padding: 15px;
border-radius: 8px;
position: relative;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
transition: opacity 0.3s ease;
opacity: 0;
}
.tooltip-panel[data-state="open"] {
opacity: 1;
}
.tooltip-arrow {
position: absolute;
width: 20px;
height: 10px;
overflow: hidden;
}
.tooltip-arrow::before {
content: '';
position: absolute;
width: 10px;
height: 10px;
background-color: #222;
top: -5px;
left: calc(50% - 5px);
transform: rotate(45deg);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
transition: top 0.3s ease;
}
.tooltip-panel[data-state="open"] .tooltip-arrow::before {
top: -8px;
}
`);
import '../snippets/arrow-styling.css';

export default component$(() => {
return (
<Tooltip.Root gutter={4} flip>
<Tooltip.Trigger>Hover or Focus me</Tooltip.Trigger>
<Tooltip.Panel aria-label="Tooltip content" class="tooltip-panel">
<Tooltip.Arrow class="tooltip-arrow" width={20} height={10} />
<Tooltip.Panel aria-label="Tooltip content" class="tooltip-arrow-styled-panel">
<Tooltip.Arrow class="tooltip-arrow-styled-arrow" width={20} height={10} />
<div>
<h3 style="margin: 0 0 10px;">Tooltip Title</h3>
<p style="margin: 0;">This tooltip has a snazzy styled arrow!</p>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { component$ } from '@builder.io/qwik';
import { Tooltip } from '@qwik-ui/headless';

import '../snippets/transition.css';

export default component$(() => {
return (
<Tooltip.Root gutter={4} flip>
Expand Down
71 changes: 12 additions & 59 deletions apps/website/src/routes/docs/headless/tooltip/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -109,50 +109,20 @@ Tooltips are useful for displaying contextual information or additional details
### Styling open tooltips

```tsx
.tooltip-panel[data-state="open"] {
.tooltip-panel[data-open] {
background: lightblue;
}
```

Use the data-state attribute on the `<Tooltip.Panel>` component to specifically style the tooltip when it's open.
Use the `data-open` and `data-closed` attributes on the `<Tooltip.Panel>` component to specifically style the tooltip when it's open.

### Cross-browser Animations

Entry and exit animations have often been a frustrating experience in web development, especially trying to animate between `display: none`, a discrete property.

Luckily, the Qwik UI team has done an excellent job of managing animations on polyfill browsers for you using the `data-state` attributes.
Luckily, the Qwik UI team has done an excellent job of managing animations on polyfill browsers for you using the `data-*` attributes.

```css
.tooltip-animation {
transform: scale(0);
}

.tooltip-animation[data-state='open'] {
animation: tooltip-grow 0.5s ease-in-out forwards;
}

.tooltip-animation[data-state='closing'] {
animation: tooltip-shrink 0.4s ease-in-out forwards;
}

@keyframes tooltip-shrink {
from {
transform: scale(1);
}
to {
transform: scale(0);
}
}

@keyframes tooltip-grow {
from {
transform: scale(0);
}
to {
transform: scale(1);
}
}
```
<CodeSnippet name="animation.css" />

## Tooltip Behavior

Expand Down Expand Up @@ -206,42 +176,25 @@ If Tailwind is the framework of choice, then styles can be added using the [arbi

To use an animation, add the following CSS classes to the component.

- The `data-state="open"` attribute determines the animation that happens when it is first opened.
- The `data-open` attribute determines the animation that happens when it is first opened.

- The `data-state="closing"` class determines what class is added when the tooltip is **closed**.
- The `data-closed` class determines what class is added when the tooltip is **closed**.

Here's the CSS imported from the example:

<CodeSnippet name="animation.css" />

### Transition declarations

Transitions use the same classes for entry and exit animations. Those being `data-state="opening"` and `data-state="closing"`. They are explained more in the `Caveats` section.
Transitions use the same classes for entry and exit animations. Those being `data-open` and `data-closed`. They are explained more in the `Caveats` section.

<Showcase name="transition" />

> The [View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API) is another native solution that aims to solve animating between states. Support is currently in around **~71%** of browsers.
CSS from the example:

```css
.tooltip-transition {
opacity: 0;
transition:
opacity 0.5s,
display 0.5s,
overlay 0.5s;
transition-behavior: allow-discrete;
}

.tooltip-transition[data-state='open'] {
opacity: 1;
}

.tooltip-transition[data-state='closing'] {
opacity: 0;
}
```
<CodeSnippet name="transition.css" />

## Additional References

Expand Down Expand Up @@ -279,23 +232,23 @@ To read more about tooltips you can check it out on:
description: 'The space between the trigger element and the tooltip.',
},
{
name: 'data-state="closing"',
name: 'data-closing"',
type: 'selector',
description: 'Style the element when the tooltip is closing. This occurs when the popover has a delay set.',
},
{
name: 'data-state="closed"',
name: 'data-closed',
type: 'selector',
description: 'Style the element when the tooltip is closed.',
},

{
name: 'data-state="opening"',
name: 'data-opening',
type: 'selector',
description: 'Style the element when the tooltip is in the process of opening. This occurs when the popover has a delay set.',
},
{
name: 'data-state="open"',
name: 'data-open',
type: 'selector',
description: 'Style the element when the tooltip is open.',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
transform: scale(0);
}

.tooltip-animation[data-state='open'] {
.tooltip-animation[data-open] {
animation: tooltip-grow 0.5s ease-in-out forwards;
}

.tooltip-animation[data-state='closing'] {
.tooltip-animation[data-closing] {
animation: tooltip-shrink 0.4s ease-in-out forwards;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
.tooltip-arrow-styled-panel {
background-color: #222;
color: #fff;
padding: 15px;
border-radius: 8px;
position: relative;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
transition: opacity 0.3s ease;
opacity: 0;
}

.tooltip-arrow-styled-panel[data-open] {
opacity: 1;
}

.tooltip-arrow-styled-arrow {
position: absolute;
width: 20px;
height: 10px;
overflow: hidden;
}

.tooltip-arrow-styled-arrow::before {
content: '';
position: absolute;
width: 10px;
height: 10px;
background-color: #222;
top: -5px;
left: calc(50% - 5px);
transform: rotate(45deg);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
transition: top 0.3s ease;
}

.tooltip-arrow-styled-panel[data-open] .tooltip-arrow-styled-arrow::before {
top: -8px;
}
47 changes: 0 additions & 47 deletions apps/website/src/routes/docs/headless/tooltip/snippets/tooltip.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,50 +21,3 @@
0 4px 6px -1px rgba(0, 0, 0, 0.1),
0 2px 4px -1px rgba(0, 0, 0, 0.06);
}

.tooltip-animation {
transform: scale(0);
}

.tooltip-animation[data-state='open'] {
animation: tooltip-grow 0.5s ease-in-out forwards;
}

.tooltip-animation[data-state='closing'] {
animation: tooltip-shrink 0.4s ease-in-out forwards;
}

@keyframes tooltip-shrink {
from {
transform: scale(1);
}
to {
transform: scale(0);
}
}

@keyframes tooltip-grow {
from {
transform: scale(0);
}
to {
transform: scale(1);
}
}

.tooltip-transition {
opacity: 0;
transition:
opacity 0.5s,
display 0.5s,
overlay 0.5s;
transition-behavior: allow-discrete;
}

.tooltip-transition[data-state='open'] {
opacity: 1;
}

.tooltip-transition[data-state='closing'] {
opacity: 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
transition-behavior: allow-discrete;
}

.tooltip-transition[data-state='opening'] {
.tooltip-transition[data-open] {
opacity: 1;
}

.tooltip-transition[data-state='closing'] {
.tooltip-transition[data-closed] {
opacity: 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,7 @@ export const HTooltipPanel = component$((props: HTooltipPanelProps) => {
const context = useContext(TooltipContextId);

return (
<HPopoverPanel
{...props}
role="tooltip"
id={context.localId}
data-state={context.state.value}
>
<HPopoverPanel {...props} role="tooltip" id={context.localId}>
<Slot />
</HPopoverPanel>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export const HTooltipRoot = component$((props: TooltipProps) => {
return (
<HPopoverRoot
manual
hover={true}
hover
bind:anchor={triggerRef}
floating={placement}
id={localId}
Expand Down

0 comments on commit 3a35a72

Please sign in to comment.