Repository: sl-design-system/components
Pull request #1905: Feature/1839 refactoring popover
Author: login: Diaan
Created: 2025-03-26T15:51:37Z | Merged: 2025-03-28T12:51:02Z



Diff:
diff --git a/.changeset/rude-jobs-share.md b/.changeset/rude-jobs-share.md
new file mode 100644
index 0000000000..76164dd06a
--- /dev/null
+++ b/.changeset/rude-jobs-share.md
@@ -0,0 +1,20 @@
+---
+'@sl-design-system/sanoma-utbildning': patch
+'@sl-design-system/editorial-suite': patch
+'@sl-design-system/my-digital-book': patch
+'@sl-design-system/sanoma-learning': patch
+'@sl-design-system/myvanin': patch
+'@sl-design-system/popover': patch
+'@sl-design-system/tooltip': patch
+'@sl-design-system/itslearning': patch
+'@sl-design-system/bingel-int': patch
+'@sl-design-system/bingel-dc': patch
+'@sl-design-system/clickedu': patch
+'@sl-design-system/magister': patch
+'@sl-design-system/kampus': patch
+'@sl-design-system/neon': patch
+'@sl-design-system/teas': patch
+'@sl-design-system/max': patch
+---
+
+Refactored tooltip and popover to use new tokens
diff --git a/.changeset/rude-paths-roll.md b/.changeset/rude-paths-roll.md
new file mode 100644
index 0000000000..adbeb5e8aa
--- /dev/null
+++ b/.changeset/rude-paths-roll.md
@@ -0,0 +1,5 @@
+---
+'@sl-design-system/popover': patch
+---
+
+Fixed issue that caused text to flow out of the popover when it was too large
diff --git a/.changeset/upset-memes-give.md b/.changeset/upset-memes-give.md
new file mode 100644
index 0000000000..e965545064
--- /dev/null
+++ b/.changeset/upset-memes-give.md
@@ -0,0 +1,5 @@
+---
+'@sl-design-system/grid': patch
+---
+
+Improved styling of filter popovers
diff --git a/packages/components/grid/src/filter.scss b/packages/components/grid/src/filter.scss
index f36fd2ca6f..8eea4c2727 100644
--- a/packages/components/grid/src/filter.scss
+++ b/packages/components/grid/src/filter.scss
@@ -22,29 +22,33 @@
 sl-popover {
   --_padding: 0;
 
+  font-weight: var(
+    --sl-text-typeset-fontWeight-regular
+  ); // when using 'inherit' it inherits from the table header, which is bold
+
   padding: 0;
 }
 
 header {
   align-items: center;
+  background: var(--sl-elevation-surface-raised-default);
   border-block-end: 1px solid var(--sl-color-elevation-border-raised);
   display: flex;
-  gap: 0.5rem;
+  font-weight: var(--sl-font-weight-semibold);
+  gap: var(--sl-size-100);
+  inset-block-start: calc(var(--sl-size-300) * -1);
   justify-content: space-between;
-  padding-block: 0.25rem;
-  padding-inline: 0.5rem;
+  margin-block: calc(var(--sl-size-300) * -1) var(--sl-size-200);
+  padding-block-start: var(--sl-size-300);
+  position: sticky;
+  z-index: 1; // needed for the sticky positioning to work
 }
 
 h1 {
-  font: var(--sl-text-body-md-normal);
+  font: var(--sl-text-body-md-demibold);
   margin: 0;
 
   span {
     text-transform: lowercase;
   }
 }
-
-sl-checkbox-group,
-sl-text-field {
-  margin: 0.5rem;
-}
diff --git a/packages/components/grid/src/stories/filtering.stories.ts b/packages/components/grid/src/stories/filtering.stories.ts
index 75d689e55d..ec2c4fb466 100644
--- a/packages/components/grid/src/stories/filtering.stories.ts
+++ b/packages/components/grid/src/stories/filtering.stories.ts
@@ -27,7 +27,7 @@ export const Basic: Story = {
     <sl-grid .items=${people}>
       <sl-grid-column path="firstName"></sl-grid-column>
       <sl-grid-column path="lastName"></sl-grid-column>
-      <sl-grid-filter-column mode="text" path="profession"></sl-grid-filter-column>
+      <sl-grid-filter-column path="profession"></sl-grid-filter-column>
       <sl-grid-filter-column path="status"></sl-grid-filter-column>
       <sl-grid-filter-column path="membership"></sl-grid-filter-column>
     </sl-grid>
diff --git a/packages/components/popover/src/popover.scss b/packages/components/popover/src/popover.scss
index 986854ac37..2b37a8214a 100644
--- a/packages/components/popover/src/popover.scss
+++ b/packages/components/popover/src/popover.scss
@@ -1,18 +1,17 @@
 :host {
-  --_arrow-block-size: var(--sl-size-075);
-  --_arrow-inline-size: var(--sl-size-200);
+  --_arrow-block-size: var(--sl-size-125);
+  --_arrow-inline-size: var(--sl-size-250);
 
   background: var(--sl-elevation-surface-raised-default);
   border: var(--sl-size-borderWidth-default) solid var(--sl-color-border-plain);
   border-radius: var(--sl-size-borderRadius-default);
   box-shadow: var(--sl-elevation-shadow-overlay);
-  box-sizing: border-box;
   color: var(--sl-color-foreground-plain);
   margin: 0;
   max-inline-size: var(--sl-popover-max-inline-size, 80vw);
   opacity: 0;
   overflow: visible;
-  padding: var(--sl-size-100) var(--sl-size-150);
+  padding: 0;
 
   @media (prefers-reduced-motion: no-preference) {
     transition: opacity 0.2s cubic-bezier(0.25, 0, 0.3, 1);
@@ -36,6 +35,13 @@
   }
 }
 
+.container {
+  box-sizing: border-box;
+  max-block-size: inherit;
+  overflow: auto;
+  padding: var(--sl-size-300);
+}
+
 /* stylelint-disable-next-line selector-class-pattern */
 :host(:where(:popover-open, .\\:popover-open)) {
   /* stylelint-disable-next-line scss/at-rule-no-unknown */
@@ -53,22 +59,16 @@
 
 :host([actual-placement^='left']) .arrow {
   inset-inline-end: calc(var(--_arrow-inline-size) * -1);
-
-  svg {
-    rotate: 90deg;
-    transform-origin: left;
-    translate: calc(var(--_arrow-block-size) / 2) calc(var(--_arrow-inline-size) / -2);
-  }
+  rotate: 90deg;
+  transform-origin: left;
+  translate: calc(var(--_arrow-block-size) / 2) calc(var(--_arrow-inline-size) / -2);
 }
 
 :host([actual-placement^='right']) .arrow {
   inset-inline-start: calc(var(--_arrow-inline-size) * -1);
-
-  svg {
-    rotate: -90deg;
-    transform-origin: right;
-    translate: calc(var(--_arrow-block-size) / -2) calc(var(--_arrow-inline-size) / -2);
-  }
+  rotate: -90deg;
+  transform-origin: right;
+  translate: calc(var(--_arrow-block-size) / -2) calc(var(--_arrow-inline-size) / -2);
 }
 
 :host([actual-placement^='top']) .arrow {
@@ -83,4 +83,5 @@
   inline-size: var(--_arrow-inline-size);
   position: absolute;
   stroke: var(--sl-color-border-plain);
+  stroke-width: calc(var(--sl-size-borderWidth-default) * 2);
 }
diff --git a/packages/components/popover/src/popover.stories.ts b/packages/components/popover/src/popover.stories.ts
index 60d3e690fa..a2b821384d 100644
--- a/packages/components/popover/src/popover.stories.ts
+++ b/packages/components/popover/src/popover.stories.ts
@@ -10,6 +10,7 @@ import { type Popover } from './popover.js';
 type Props = Pick<Popover, 'position'> & {
   alignSelf: string;
   body: string | (() => TemplateResult);
+  maxWidth: number;
   noDescribedby: boolean;
   justifySelf: string;
 };
@@ -32,6 +33,9 @@ export default {
     body: {
       table: { disable: true }
     },
+    maxWidth: {
+      control: 'number'
+    },
     justifySelf: {
       control: 'inline-radio',
       options: ['start', 'center', 'end']
@@ -54,7 +58,7 @@ export default {
       ]
     }
   },
-  render: ({ alignSelf, justifySelf, body, position, noDescribedby }) => {
+  render: ({ alignSelf, justifySelf, body, maxWidth, position, noDescribedby }) => {
     const onClick = (): void => {
       const popover = document.querySelector('sl-popover') as HTMLElement;
       popover.togglePopover();
@@ -67,6 +71,9 @@ export default {
           height: calc(100dvh - 2rem);
           place-items: center;
         }
+        sl-popover {
+          --sl-popover-max-inline-size: ${maxWidth ? `${maxWidth}px` : 'none'};
+        }
       </style>
       <sl-button
         @click=${onClick}
@@ -82,7 +89,26 @@ export default {
   }
 } satisfies Meta<Props>;
 
-export const Basic: Story = {};
+export const Basic: Story = {
+  args: {
+    maxWidth: 400,
+    body: () => {
+      const onClick = (): void => {
+        return;
+      };
+      return html`
+        <header style="font:var(--sl-text-new-heading-sm);">Hello! I am a popover!</header>
+        <section>
+          <p>
+            I'm a lightweight and flexible UI element that appears on top of other content. I am often used to display
+            additional information, actions, or contextual content without disrupting the main flow of the interface.
+          </p>
+        </section>
+        <sl-button @click=${onClick} variant="primary">Button</sl-button>
+      `;
+    }
+  }
+};
 
 export const NoDescribedBy: Story = {
   args: {
@@ -95,6 +121,50 @@ export const NoDescribedBy: Story = {
   }
 };
 
+export const VerticalOverflow: Story = {
+  args: {
+    body: () => {
+      return html`Lorem<br />
+        ipsum<br />
+        dolor<br />
+        sit<br />
+        amet,<br />
+        qui<br />
+        deserunt<br />
+        esse<br />
+        minim<br />
+        cillum<br />
+        nostrud<br />
+        exercitation<br />
+        veniam<br />
+        consequat<br />
+        pariatur<br />
+        exercitation<br />
+        laborum<br />
+        nostrud<br />
+        culpa<br />
+        sunt<br />
+        exercitation<br />
+        pariatur.<br />
+        Nisi<br />
+        ipsum<br />
+        est<br />
+        ullamco<br />
+        nostrud<br />
+        sit<br />
+        pariatur.<br />
+        Ex<br />
+        nisi<br />
+        ipsum<br />
+        et<br />
+        est<br />
+        nulla<br />
+        ex<br />
+        ex.`;
+    }
+  }
+};
+
 export const RichContent: Story = {
   args: {
     body: () => {
@@ -158,7 +228,7 @@ export const All: Story = {
       </div>
 
       <div>
-        <sl-button id="anchor2" variant="primary" style="width: 72px">This is a popover anchor element (sl-button component) with all right and left popover allowed positions shown all examples at once</sl-button>
+        <sl-button id="anchor2" variant="primary" style="width: 72px; padding: 24px;">This is a popover anchor element (sl-button component) with all right and left popover allowed positions shown all examples at once</sl-button>
         <sl-popover anchor="anchor2" popover="manual" position="right">Right <br> example</sl-popover>
         <sl-popover anchor="anchor2" popover="manual" position="right-start">Right <br> start <br> example</sl-popover>
         <sl-popover anchor="anchor2" popover="manual" position="right-end">Right <br> end <br> example</sl-popover>
diff --git a/packages/components/popover/src/popover.ts b/packages/components/popover/src/popover.ts
index 734a843d7d..d7db673ba2 100644
--- a/packages/components/popover/src/popover.ts
+++ b/packages/components/popover/src/popover.ts
@@ -78,10 +78,8 @@ export class Popover extends LitElement {
         <slot></slot>
       </div>
       <div class="arrow" aria-hidden="true">
-        <svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" clip-rule="evenodd" viewBox="0 0 16 6">
-          <path
-            d="M14.48 5.911c.196.191.429.338.685.434.266.104.549.156.835.155H0c.424.002.841-.116 1.202-.339.114-.073.221-.156.317-.25l1.239-1.205L3.998 3.5l1.239-1.205 1.239-1.206c.202-.196.443-.343.703-.441C7.441.549 7.72.499 8 .5c.28 0 .56.049.82.148.261.098.501.245.703.441l1.239 1.206L12.001 3.5l1.239 1.206 1.24 1.205"
-          />
+        <svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" clip-rule="evenodd" viewBox="0 0 20 11">
+          <path d="M0 11 20 11 10 1 0 11" paint-order="stroke" />
         </svg>
       </div>
     `;
diff --git a/packages/components/tooltip/src/tooltip.scss b/packages/components/tooltip/src/tooltip.scss
index 05c6e4b80c..bf141034da 100644
--- a/packages/components/tooltip/src/tooltip.scss
+++ b/packages/components/tooltip/src/tooltip.scss
@@ -1,28 +1,21 @@
 :host {
-  --_arrow-block-size: 6px;
-  --_arrow-inline-size: 16px;
-  --_background: var(--sl-color-tooltip-background);
-  --_border-radius: var(--sl-border-radius-default);
-  --_border: 0;
-  --_color: var(--sl-color-tooltip-foreground);
-  --_font: var(--sl-text-tooltip-text-tip);
+  --_arrow-block-size: var(--sl-size-050);
+  --_arrow-inline-size: var(--sl-size-100);
   --_max-width: var(--sl-tooltip-max-width, auto);
-  --_padding-block: var(--sl-space-tooltip-block);
-  --_padding-inline: var(--sl-space-tooltip-inline);
 
-  background: var(--_background);
-  border: var(--_border);
-  border-radius: var(--_border-radius);
+  background: var(--sl-elevation-surface-raised-inverted);
+  border: 0;
+  border-radius: var(--sl-size-borderRadius-default);
   box-sizing: border-box;
-  color: var(--_color);
+  color: var(--sl-color-foreground-inverted-plain);
   font: var(--_font);
   margin: 0;
   max-inline-size: var(--_max-width);
   opacity: 0;
   overflow: visible;
   overflow-wrap: break-word;
-  padding-block: var(--_padding-block);
-  padding-inline: var(--_padding-inline);
+  padding-block: var(--sl-size-100);
+  padding-inline: var(--sl-size-150);
 
   @media (prefers-reduced-motion: no-preference) {
     transition: opacity 0.2s cubic-bezier(0.25, 0, 0.3, 1);
@@ -37,16 +30,26 @@
    */
   @supports not selector(:popover-open) {
     background: var(--_background) !important;
-    border: var(--_border) !important;
     color: var(--_color) !important;
     margin: 0 !important;
     overflow: visible !important;
-    padding-block: var(--_padding-block) !important;
-    padding-inline: var(--_padding-inline) !important;
+    padding-block: var(--sl-size-100) !important;
+    padding-inline: var(--sl-size-150) !important;
     position: fixed;
   }
 }
 
+.arrow {
+  background-color: inherit;
+  block-size: var(--_arrow-block-size);
+  clip-path: polygon(0 100%, 100% 100%, 50% 0);
+  display: flex;
+  inline-size: var(--_arrow-inline-size);
+  inset-block-end: calc(var(--_arrow-block-size) * -1);
+  position: absolute;
+  scale: 1 -1;
+}
+
 /* stylelint-disable-next-line selector-class-pattern */
 :host(:where(:popover-open, .\\:popover-open)) {
   /* stylelint-disable-next-line scss/at-rule-no-unknown */
@@ -59,38 +62,24 @@
 }
 
 :host([actual-placement^='bottom']) .arrow {
+  clip-path: polygon(50% 100%, 100% 0, 0 0);
   inset-block-start: calc(var(--_arrow-block-size) * -1);
 }
 
 :host([actual-placement^='left']) .arrow {
-  inset-inline-end: calc(var(--_arrow-inline-size) * -1);
-
-  svg {
-    rotate: 90deg;
-    transform-origin: left;
-    translate: calc(var(--_arrow-block-size) / 2) calc(var(--_arrow-inline-size) / -2);
-  }
+  block-size: var(--_arrow-inline-size);
+  clip-path: polygon(0 100%, 100% 50%, 0 0);
+  inline-size: var(--_arrow-block-size);
+  inset-inline-end: calc(var(--_arrow-block-size) * -1);
 }
 
 :host([actual-placement^='right']) .arrow {
-  inset-inline-start: calc(var(--_arrow-inline-size) * -1);
-
-  svg {
-    rotate: -90deg;
-    transform-origin: right;
-    translate: calc(var(--_arrow-block-size) / -2) calc(var(--_arrow-inline-size) / -2);
-  }
-}
-
-:host([actual-placement^='top']) .arrow {
-  inset-block-end: calc(var(--_arrow-block-size) * -1);
-  scale: 1 -1;
+  block-size: var(--_arrow-inline-size);
+  clip-path: polygon(100% 100%, 100% 0, 0 50%);
+  inline-size: var(--_arrow-block-size);
+  inset-inline-start: calc(var(--_arrow-block-size) * -1);
 }
 
-.arrow {
-  block-size: var(--_arrow-block-size);
-  display: flex;
-  fill: var(--_background);
-  inline-size: var(--_arrow-inline-size);
-  position: absolute;
+.safe-triangle {
+  position: fixed;
 }
diff --git a/packages/components/tooltip/src/tooltip.ts b/packages/components/tooltip/src/tooltip.ts
index e90844b87a..3e7fea1d3b 100644
--- a/packages/components/tooltip/src/tooltip.ts
+++ b/packages/components/tooltip/src/tooltip.ts
@@ -118,8 +118,15 @@ export class Tooltip extends LitElement {
     );
   };
 
-  #onHide = ({ target }: Event): void => {
-    if (this.#matchesAnchor(target as Element)) {
+  #onHide = (event: Event): void => {
+    let toTooltip = false;
+    let fromTooltip = false;
+    if (event instanceof PointerEvent) {
+      toTooltip = (event.relatedTarget as Element)?.nodeName === 'SL-TOOLTIP';
+      fromTooltip =
+        (event.target as Element)?.nodeName === 'SL-TOOLTIP' && !this.#matchesAnchor(event.relatedTarget as Element);
+    }
+    if ((this.#matchesAnchor(event.target as Element) && !toTooltip) || fromTooltip) {
       this.hidePopover();
     }
   };
@@ -127,7 +134,12 @@ export class Tooltip extends LitElement {
   #onShow = ({ target }: Event): void => {
     if (this.#matchesAnchor(target as HTMLElement)) {
       this.anchorElement = target as HTMLElement;
+
       this.showPopover();
+      requestAnimationFrame(() => {
+        //timeout is needed because otherwise the actualPlacement is not set yet
+        this.#calculateSafeTriangle();
+      });
     }
   };
 
@@ -151,6 +163,7 @@ export class Tooltip extends LitElement {
 
     this.setAttribute('popover', 'manual');
     this.setAttribute('role', 'tooltip');
+    this.setAttribute('aria-hidden', 'true'); // Prevent the tooltip from being read by screen readers multiple times
 
     const root = this.getRootNode() as HTMLElement;
 
@@ -177,13 +190,79 @@ export class Tooltip extends LitElement {
   override render(): TemplateResult {
     return html`
       <slot></slot>
-      <div class="arrow">
-        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="6">
-          <path
-            d="M14.48 5.411c.384.374.938.588 1.52.589H0c.582-.001 1.136-.215 1.52-.589L6.475.59c.807-.785 2.241-.785 3.048 0L14.48 5.41Z"
-          />
-        </svg>
-      </div>
+      <div class="arrow"></div>
+      <div class="safe-triangle"></div>
     `;
   }
+
+  /**
+   * Calculate a "safe triangle" for the submenu to a user can safely move his cursor
+   * from the trigger to the submenu without the submenu closing.
+   * See https://www.smashingmagazine.com/2023/08/better-context-menus-safe-triangles
+   */
+  #calculateSafeTriangle(): void {
+    const actualPlacement = this.getAttribute('actual-placement');
+
+    if (!actualPlacement || !this.anchorElement) {
+      return;
+    }
+
+    const tooltipRect = this.getBoundingClientRect(),
+      anchorRect = this.anchorElement.getBoundingClientRect();
+    let insetBlockStart,
+      blockSize,
+      inlineSize,
+      polygon,
+      anchorInsetBlockStart = 0,
+      insetInlineStart,
+      anchorSideBlockStart = 0,
+      tootltipSideBlockStart = 0;
+
+    if (actualPlacement.startsWith('top') || actualPlacement.startsWith('bottom')) {
+      anchorInsetBlockStart = Math.floor(anchorRect.left - tooltipRect.left);
+      inlineSize = Math.ceil(Math.max(tooltipRect.width, anchorRect.width));
+      insetInlineStart = Math.ceil(Math.min(tooltipRect.left, anchorRect.left));
+    }
+
+    if (actualPlacement.startsWith('top')) {
+      blockSize = Math.ceil(anchorRect.top - tooltipRect.bottom) + 2;
+      insetBlockStart = tooltipRect.bottom - 1;
+      polygon = `0% 0%, 100% 0, ${anchorInsetBlockStart + anchorRect.width}px 100%, ${anchorInsetBlockStart}px 100%`;
+    }
+
+    if (actualPlacement.startsWith('bottom')) {
+      blockSize = Math.ceil(tooltipRect.top - anchorRect.bottom) + 2;
+      insetBlockStart = anchorRect.bottom - 1;
+      polygon = `${anchorInsetBlockStart}px 0, ${anchorInsetBlockStart + anchorRect.width}px 0, 100% 100%, 0 100%`;
+    }
+
+    if (actualPlacement.startsWith('left') || actualPlacement.startsWith('right')) {
+      blockSize = Math.ceil(Math.max(tooltipRect.height, anchorRect.height)) + 2;
+      insetBlockStart = Math.min(anchorRect.top, tooltipRect.top) - 1;
+      anchorInsetBlockStart = anchorRect.top;
+      anchorSideBlockStart = Math.max(anchorRect.top - tooltipRect.top, 0);
+      tootltipSideBlockStart = Math.max(tooltipRect.top - anchorRect.top, 0);
+    }
+
+    if (actualPlacement.startsWith('right')) {
+      insetInlineStart = Math.ceil(Math.min(tooltipRect.left, anchorRect.right)) - 1;
+      inlineSize = Math.ceil(tooltipRect.left - anchorRect.right) + 2;
+      polygon = `0 ${anchorSideBlockStart}px , 100% ${tootltipSideBlockStart}px,
+                 100% ${tootltipSideBlockStart + tooltipRect.height + 2}px, 0 ${anchorSideBlockStart + anchorRect.height + 2}px`;
+    }
+
+    if (actualPlacement.startsWith('left')) {
+      insetInlineStart = Math.ceil(Math.min(tooltipRect.right, anchorRect.left)) - 1;
+      inlineSize = Math.ceil(anchorRect.left - tooltipRect.right) + 2;
+      polygon = `0 ${tootltipSideBlockStart}px , 100% ${anchorSideBlockStart}px,
+                 100% ${anchorSideBlockStart + anchorRect.height + 2}px, 0 ${tootltipSideBlockStart + tooltipRect.height + 2}px`;
+    }
+
+    const inset = `${insetBlockStart}px auto auto ${insetInlineStart}px`;
+    const safeTriangle = this.renderRoot.querySelector<HTMLElement>('.safe-triangle')!;
+    safeTriangle.style.blockSize = `${blockSize}px`;
+    safeTriangle.style.clipPath = `polygon(${polygon})`;
+    safeTriangle.style.inlineSize = `${inlineSize}px`;
+    safeTriangle.style.inset = inset;
+  }
 }


Reviews:
user: login: anna-lach
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-28T07:23:26Z
user: login: Diaan
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-28T09:20:40Z
user: login: anna-lach
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-28T09:30:41Z
user: login: jpzwarte
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-28T09:33:51Z
user: login: Diaan
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-28T09:49:14Z
user: login: anna-lach
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-28T10:12:01Z

Review comments:
diff_hunk: @@ -4,6 +4,7 @@
   --_icon-color: currentcolor;
 
   display: block;
+  font-weight: normal; // when using 'inherit' it inherits from the table header, which is bold
path: packages/components/grid/src/filter.scss
user: login: anna-lach
body: Maybe it should be a token `--sl-text-typeset-fontWeight-regular`?
created_at: 2025-03-28T07:13:24Z
author_association: COLLABORATOR
diff_hunk: @@ -83,4 +84,5 @@
   inline-size: var(--_arrow-inline-size);
   position: absolute;
   stroke: var(--sl-color-border-plain);
+  stroke-width: 2px;
path: packages/components/popover/src/popover.scss
user: login: anna-lach
body: Can you please use a token?
created_at: 2025-03-28T07:14:55Z
author_association: COLLABORATOR
diff_hunk: @@ -1,28 +1,21 @@
 :host {
-  --_arrow-block-size: 6px;
-  --_arrow-inline-size: 16px;
-  --_background: var(--sl-color-tooltip-background);
-  --_border-radius: var(--sl-border-radius-default);
-  --_border: 0;
-  --_color: var(--sl-color-tooltip-foreground);
-  --_font: var(--sl-text-tooltip-text-tip);
+  --_arrow-block-size: 5px;
path: packages/components/tooltip/src/tooltip.scss
user: login: anna-lach
body: Can you please use a token? :)
created_at: 2025-03-28T07:18:03Z
author_association: COLLABORATOR
diff_hunk: @@ -1,28 +1,21 @@
 :host {
-  --_arrow-block-size: 6px;
-  --_arrow-inline-size: 16px;
-  --_background: var(--sl-color-tooltip-background);
-  --_border-radius: var(--sl-border-radius-default);
-  --_border: 0;
-  --_color: var(--sl-color-tooltip-foreground);
-  --_font: var(--sl-text-tooltip-text-tip);
+  --_arrow-block-size: 5px;
+  --_arrow-inline-size: 10px;
path: packages/components/tooltip/src/tooltip.scss
user: login: anna-lach
body: Can you please use a token?
created_at: 2025-03-28T07:18:08Z
author_association: COLLABORATOR
diff_hunk: @@ -1,28 +1,21 @@
 :host {
-  --_arrow-block-size: 6px;
-  --_arrow-inline-size: 16px;
-  --_background: var(--sl-color-tooltip-background);
-  --_border-radius: var(--sl-border-radius-default);
-  --_border: 0;
-  --_color: var(--sl-color-tooltip-foreground);
-  --_font: var(--sl-text-tooltip-text-tip);
+  --_arrow-block-size: 5px;
path: packages/components/tooltip/src/tooltip.scss
user: login: Diaan
body: There is no token for 5px 🤷
created_at: 2025-03-28T09:20:39Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,21 @@
+---
+'@sl-design-system/sanoma-utbildning': patch
+'@sl-design-system/editorial-suite': patch
+'@sl-design-system/my-digital-book': patch
+'@sl-design-system/sanoma-learning': patch
+'@sl-design-system/myvanin': patch
+'@sl-design-system/popover': patch
+'@sl-design-system/tooltip': patch
+'@sl-design-system/itslearning': patch
+'@sl-design-system/bingel-int': patch
+'@sl-design-system/bingel-dc': patch
+'@sl-design-system/grid': patch
path: .changeset/rude-jobs-share.md
user: login: jpzwarte
body: Grid should be excluded here? Since it has its own changeset?
created_at: 2025-03-28T09:27:02Z
author_association: MEMBER
diff_hunk: @@ -4,6 +4,7 @@
   --_icon-color: currentcolor;
 
   display: block;
+  font-weight: normal; // when using 'inherit' it inherits from the table header, which is bold
path: packages/components/grid/src/filter.scss
user: login: jpzwarte
body: Perhaps use `initial` instead of `normal`? (not 100% sure that is correct)
created_at: 2025-03-28T09:29:04Z
author_association: MEMBER
diff_hunk: @@ -27,24 +28,24 @@ sl-popover {
 
 header {
   align-items: center;
+  background: var(--sl-elevation-surface-raised-default);
   border-block-end: 1px solid var(--sl-color-elevation-border-raised);
   display: flex;
+  font-weight: var(--sl-font-weight-semibold);
   gap: 0.5rem;
path: packages/components/grid/src/filter.scss
user: login: jpzwarte
body: Please use `var(--sl-size-100)`
created_at: 2025-03-28T09:29:59Z
author_association: MEMBER
diff_hunk: @@ -27,24 +28,24 @@ sl-popover {
 
 header {
   align-items: center;
+  background: var(--sl-elevation-surface-raised-default);
   border-block-end: 1px solid var(--sl-color-elevation-border-raised);
   display: flex;
+  font-weight: var(--sl-font-weight-semibold);
   gap: 0.5rem;
+  inset-block-start: calc(var(--sl-size-300) * -1);
   justify-content: space-between;
-  padding-block: 0.25rem;
-  padding-inline: 0.5rem;
+  margin-block: calc(var(--sl-size-300) * -1) var(--sl-size-200);
+  padding-block-start: var(--sl-size-300);
+  position: sticky;
+  z-index: 1;
path: packages/components/grid/src/filter.scss
user: login: jpzwarte
body: I've started documenting the value of `z-index`, so it's clear why it is a certain value.
created_at: 2025-03-28T09:30:30Z
author_association: MEMBER
diff_hunk: @@ -1,28 +1,21 @@
 :host {
-  --_arrow-block-size: 6px;
-  --_arrow-inline-size: 16px;
-  --_background: var(--sl-color-tooltip-background);
-  --_border-radius: var(--sl-border-radius-default);
-  --_border: 0;
-  --_color: var(--sl-color-tooltip-foreground);
-  --_font: var(--sl-text-tooltip-text-tip);
+  --_arrow-block-size: 5px;
path: packages/components/tooltip/src/tooltip.scss
user: login: anna-lach
body: Maybe it would be helpful to have such?
created_at: 2025-03-28T09:30:41Z
author_association: COLLABORATOR
diff_hunk: @@ -1,18 +1,18 @@
 :host {
-  --_arrow-block-size: var(--sl-size-075);
-  --_arrow-inline-size: var(--sl-size-200);
+  --_arrow-block-size: var(--sl-size-125);
+  --_arrow-inline-size: var(--sl-size-250);
 
   background: var(--sl-elevation-surface-raised-default);
   border: var(--sl-size-borderWidth-default) solid var(--sl-color-border-plain);
   border-radius: var(--sl-size-borderRadius-default);
   box-shadow: var(--sl-elevation-shadow-overlay);
-  box-sizing: border-box;
+  box-sizing: content-box;
path: packages/components/popover/src/popover.scss
user: login: jpzwarte
body: Isn't `content-box` the default?
created_at: 2025-03-28T09:30:57Z
author_association: MEMBER
diff_hunk: @@ -1,18 +1,18 @@
 :host {
-  --_arrow-block-size: var(--sl-size-075);
-  --_arrow-inline-size: var(--sl-size-200);
+  --_arrow-block-size: var(--sl-size-125);
+  --_arrow-inline-size: var(--sl-size-250);
 
   background: var(--sl-elevation-surface-raised-default);
   border: var(--sl-size-borderWidth-default) solid var(--sl-color-border-plain);
   border-radius: var(--sl-size-borderRadius-default);
   box-shadow: var(--sl-elevation-shadow-overlay);
-  box-sizing: border-box;
+  box-sizing: content-box;
   color: var(--sl-color-foreground-plain);
   margin: 0;
   max-inline-size: var(--sl-popover-max-inline-size, 80vw);
   opacity: 0;
   overflow: visible;
-  padding: var(--sl-size-100) var(--sl-size-150);
+  padding: 0;
path: packages/components/popover/src/popover.scss
user: login: jpzwarte
body: Isn't this the default?
created_at: 2025-03-28T09:31:10Z
author_association: MEMBER
diff_hunk: @@ -83,4 +84,5 @@
   inline-size: var(--_arrow-inline-size);
   position: absolute;
   stroke: var(--sl-color-border-plain);
+  stroke-width: 2px;
path: packages/components/popover/src/popover.scss
user: login: jpzwarte
body: `var(--sl-size-025)`
created_at: 2025-03-28T09:31:44Z
author_association: MEMBER
diff_hunk: @@ -118,16 +118,28 @@ export class Tooltip extends LitElement {
     );
   };
 
-  #onHide = ({ target }: Event): void => {
-    if (this.#matchesAnchor(target as Element)) {
+  #onHide = (event: Event): void => {
+    let toTooltip = false;
+    let fromTooltip = false;
+    if (event instanceof PointerEvent) {
+      toTooltip = (event.relatedTarget as Element)?.nodeName === 'SL-TOOLTIP';
+      fromTooltip =
+        (event.target as Element)?.nodeName === 'SL-TOOLTIP' && !this.#matchesAnchor(event.relatedTarget as Element);
+    }
+    if ((this.#matchesAnchor(event.target as Element) && !toTooltip) || fromTooltip) {
       this.hidePopover();
     }
   };
 
   #onShow = ({ target }: Event): void => {
     if (this.#matchesAnchor(target as HTMLElement)) {
       this.anchorElement = target as HTMLElement;
+
       this.showPopover();
+      setTimeout(() => {
path: packages/components/tooltip/src/tooltip.ts
user: login: jpzwarte
body: Since this is only `10ms`, is `requestAnimationFrame()` also an option?
created_at: 2025-03-28T09:33:18Z
author_association: MEMBER
diff_hunk: @@ -1,18 +1,18 @@
 :host {
-  --_arrow-block-size: var(--sl-size-075);
-  --_arrow-inline-size: var(--sl-size-200);
+  --_arrow-block-size: var(--sl-size-125);
+  --_arrow-inline-size: var(--sl-size-250);
 
   background: var(--sl-elevation-surface-raised-default);
   border: var(--sl-size-borderWidth-default) solid var(--sl-color-border-plain);
   border-radius: var(--sl-size-borderRadius-default);
   box-shadow: var(--sl-elevation-shadow-overlay);
-  box-sizing: border-box;
+  box-sizing: content-box;
   color: var(--sl-color-foreground-plain);
   margin: 0;
   max-inline-size: var(--sl-popover-max-inline-size, 80vw);
   opacity: 0;
   overflow: visible;
-  padding: var(--sl-size-100) var(--sl-size-150);
+  padding: 0;
path: packages/components/popover/src/popover.scss
user: login: Diaan
body: It appears there is a default padding on popovers from the user agent stylesheet:
<img width="554" alt="image" src="https://github.com/user-attachments/assets/cde68a6c-c641-4702-af6a-e3ce4a0389f1" />

created_at: 2025-03-28T09:49:14Z
author_association: COLLABORATOR

PR comments:
user: login: changeset-bot[bot]
created_at: 2025-03-26T15:51:41Z
body: ###  🦋  Changeset detected

Latest commit: 9bf6c504ff10a02db740550be8c287d7b4d8b86e

**The changes in this PR will be included in the next version bump.**

<details><summary>This PR includes changesets to release 17 packages</summary>

  | Name                                | Type  |
| ----------------------------------- | ----- |
| @sl-design-system/sanoma-utbildning | Patch |
| @sl-design-system/editorial-suite   | Patch |
| @sl-design-system/my-digital-book   | Patch |
| @sl-design-system/sanoma-learning   | Patch |
| @sl-design-system/myvanin           | Patch |
| @sl-design-system/popover           | Patch |
| @sl-design-system/tooltip           | Patch |
| @sl-design-system/itslearning       | Patch |
| @sl-design-system/bingel-int        | Patch |
| @sl-design-system/bingel-dc         | Patch |
| @sl-design-system/clickedu          | Patch |
| @sl-design-system/magister          | Patch |
| @sl-design-system/kampus            | Patch |
| @sl-design-system/neon              | Patch |
| @sl-design-system/teas              | Patch |
| @sl-design-system/max               | Patch |
| @sl-design-system/grid              | Patch |

</details>

Not sure what this means? [Click here  to learn what changesets are](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add another changeset to this PR](https://github.com/sl-design-system/components/new/feature/1839-refactoring-popover?filename=.changeset/dry-lions-behave.md&value=---%0A%22%40sl-design-system%2Fgrid%22%3A%20patch%0A%22%40sl-design-system%2Fpopover%22%3A%20patch%0A%22%40sl-design-system%2Ftooltip%22%3A%20patch%0A---%0A%0AFeature%2F1839%20refactoring%20popover%0A)


author_association: NONE
user: login: github-actions[bot]
created_at: 2025-03-26T15:53:48Z
body: ### 🕸 Website preview
You can view a preview [here](https://proud-water-0d02ee203-1905.westeurope.2.azurestaticapps.net) (commit [`9bf6c504ff10a02db740550be8c287d7b4d8b86e`](https://github.com/sl-design-system/components/commit/9bf6c504ff10a02db740550be8c287d7b4d8b86e)).
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-26T15:55:54Z
body: ### 🕸 Storybook preview
You can view a preview [here](https://kind-plant-088739303-1905.westeurope.1.azurestaticapps.net) (commit [`9bf6c504ff10a02db740550be8c287d7b4d8b86e`](https://github.com/sl-design-system/components/commit/9bf6c504ff10a02db740550be8c287d7b4d8b86e)).
author_association: CONTRIBUTOR