diff --git a/.changeset/tasty-pugs-decide.md b/.changeset/tasty-pugs-decide.md new file mode 100644 index 000000000..5975c3b86 --- /dev/null +++ b/.changeset/tasty-pugs-decide.md @@ -0,0 +1,5 @@ +--- +'@qwik-ui/headless': minor +--- + +Implement a beta version of the Tooltip component diff --git a/apps/website/src/routes/docs/headless/tooltip/examples/animation.tsx b/apps/website/src/routes/docs/headless/tooltip/examples/animation.tsx index 94a17a8f3..45321b077 100644 --- a/apps/website/src/routes/docs/headless/tooltip/examples/animation.tsx +++ b/apps/website/src/routes/docs/headless/tooltip/examples/animation.tsx @@ -1,6 +1,8 @@ import { component$ } from '@builder.io/qwik'; import { Tooltip } from '@qwik-ui/headless'; +import '../snippets/animation.css'; + export default component$(() => { return ( diff --git a/apps/website/src/routes/docs/headless/tooltip/examples/arrow-styling.tsx b/apps/website/src/routes/docs/headless/tooltip/examples/arrow-styling.tsx index f653f2626..b9a88351d 100644 --- a/apps/website/src/routes/docs/headless/tooltip/examples/arrow-styling.tsx +++ b/apps/website/src/routes/docs/headless/tooltip/examples/arrow-styling.tsx @@ -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 ( Hover or Focus me - - + +

Tooltip Title

This tooltip has a snazzy styled arrow!

diff --git a/apps/website/src/routes/docs/headless/tooltip/examples/transition.tsx b/apps/website/src/routes/docs/headless/tooltip/examples/transition.tsx index ac88f3e92..3f7bf3fcc 100644 --- a/apps/website/src/routes/docs/headless/tooltip/examples/transition.tsx +++ b/apps/website/src/routes/docs/headless/tooltip/examples/transition.tsx @@ -1,6 +1,8 @@ import { component$ } from '@builder.io/qwik'; import { Tooltip } from '@qwik-ui/headless'; +import '../snippets/transition.css'; + export default component$(() => { return ( diff --git a/apps/website/src/routes/docs/headless/tooltip/index.mdx b/apps/website/src/routes/docs/headless/tooltip/index.mdx index 0b89dc17a..ec4b02ed8 100644 --- a/apps/website/src/routes/docs/headless/tooltip/index.mdx +++ b/apps/website/src/routes/docs/headless/tooltip/index.mdx @@ -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 `` component to specifically style the tooltip when it's open. +Use the `data-open` and `data-closed` attributes on the `` 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); - } -} -``` + ## Tooltip Behavior @@ -206,9 +176,9 @@ 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: @@ -216,7 +186,7 @@ Here's the CSS imported from the example: ### 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. @@ -224,24 +194,7 @@ Transitions use the same classes for entry and exit animations. Those being `dat 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; -} -``` + ## Additional References @@ -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.', }, diff --git a/apps/website/src/routes/docs/headless/tooltip/snippets/animation.css b/apps/website/src/routes/docs/headless/tooltip/snippets/animation.css index d450b4c2f..0ef140ab2 100644 --- a/apps/website/src/routes/docs/headless/tooltip/snippets/animation.css +++ b/apps/website/src/routes/docs/headless/tooltip/snippets/animation.css @@ -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; } diff --git a/apps/website/src/routes/docs/headless/tooltip/snippets/arrow-styling.css b/apps/website/src/routes/docs/headless/tooltip/snippets/arrow-styling.css new file mode 100644 index 000000000..a37f1313e --- /dev/null +++ b/apps/website/src/routes/docs/headless/tooltip/snippets/arrow-styling.css @@ -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; +} diff --git a/apps/website/src/routes/docs/headless/tooltip/snippets/tooltip.css b/apps/website/src/routes/docs/headless/tooltip/snippets/tooltip.css index ba53fa158..b0a6ae097 100644 --- a/apps/website/src/routes/docs/headless/tooltip/snippets/tooltip.css +++ b/apps/website/src/routes/docs/headless/tooltip/snippets/tooltip.css @@ -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; -} diff --git a/apps/website/src/routes/docs/headless/tooltip/snippets/transition.css b/apps/website/src/routes/docs/headless/tooltip/snippets/transition.css index 225be8bd1..7c7266a35 100644 --- a/apps/website/src/routes/docs/headless/tooltip/snippets/transition.css +++ b/apps/website/src/routes/docs/headless/tooltip/snippets/transition.css @@ -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; } diff --git a/packages/kit-headless/src/components/tooltip/tooltip-panel.tsx b/packages/kit-headless/src/components/tooltip/tooltip-panel.tsx index 9dad5d7d6..dbbc01d54 100644 --- a/packages/kit-headless/src/components/tooltip/tooltip-panel.tsx +++ b/packages/kit-headless/src/components/tooltip/tooltip-panel.tsx @@ -11,12 +11,7 @@ export const HTooltipPanel = component$((props: HTooltipPanelProps) => { const context = useContext(TooltipContextId); return ( - + ); diff --git a/packages/kit-headless/src/components/tooltip/tooltip-root.tsx b/packages/kit-headless/src/components/tooltip/tooltip-root.tsx index 738020dc0..b3affacce 100644 --- a/packages/kit-headless/src/components/tooltip/tooltip-root.tsx +++ b/packages/kit-headless/src/components/tooltip/tooltip-root.tsx @@ -81,7 +81,7 @@ export const HTooltipRoot = component$((props: TooltipProps) => { return (