designsystemet icon indicating copy to clipboard operation
designsystemet copied to clipboard

Card component - Missing middle mouse button press

Open poi33 opened this issue 4 months ago • 2 comments

Version number

1.3.0

Description of the bug

Using the middle mouse button on a link opens it in a new tab.

When using the middle mouse button on the card component (Navigasjonskort) the middle mouse button does not.

Steps To Reproduce

  1. Go to the documentation page: https://storybook.designsystemet.no/iframe.html?viewMode=docs&id=komponenter-card--docs&globals=#1-kort-med-lenke-i-tittel
  2. Press the middle mouse button on the image part of the card
  3. No page opens

Additional Information

No response

poi33 avatar Sep 01 '25 13:09 poi33

Hi, thanks for the isse! When <a> is a child of a heading in our card, we add JS to make sure the whole card is clickale. We might be able to solve this with CSS, but we could potentially also solve this with JS. Either way, it is not something we will prioritize looking into right now

Barsnes avatar Sep 02 '25 09:09 Barsnes

The reason we can't use a pseudo element for the <a> is because we won't know for sure that .ds-card is the closest element with position: relative. Our .ds-card__block sets position: relative for example.

Barsnes avatar Sep 11 '25 12:09 Barsnes

This issue was mentioned while trying to figure out how to recreate the React logic with plain HTML + JS. The code below seems to work well and includes middle click handling.

Note that middle clicks don't trigger click but pointerup/down (or mouseup/down), so I had to fake the same behaviour as click to only trigger when down and up is on the same element.

Also @eirikbacker mentioned that the window.open should probably use link.rel instead of 'noreferrer' to respect the original intent in the HTML, so I did this too.

let pointerDownTarget = null;

/** @type {(e: PointerEvent) => void} */
const clickHandler = ({ type, ctrlKey, metaKey, button, target }) => {
  if (type === 'pointerdown') {
    pointerDownTarget = target;
    return;
  }
  // pointerup on different element than pointerdown
  if (type === 'pointerup' && target !== pointerDownTarget) {
    return;
  }
  if (!(target instanceof Element)) {
    return;
  }
  const middleMouseId = 1;
  const card = target.closest('.ds-card');
  if (card) {
    /** @type {HTMLAnchorElement | null} */
    const link = card?.querySelector(':is(h1,h2,h3,h4,h5,h6) a');

    if (!link || link?.contains(target)) return; // Let links handle their own clicks
    if (ctrlKey || metaKey || button === middleMouseId)
      window.open(link.href, '', link.rel);
    else link.click(); // Using link.click instead of window.location.href as this will trigger the browser's handling of rel=, target=, etc.
  }
};

document.addEventListener('pointerup', clickHandler);
document.addEventListener('pointerdown', clickHandler);

unekinn avatar Nov 25 '25 13:11 unekinn

See alternative solution with auxclick in https://github.com/digdir/designsystemet/pull/4335/changes#diff-1ff9f89903b47fd8243bdb7dbf43359df0baac7ab03f01ef61404aa6d35b1afc ☺️

eirikbacker avatar Dec 18 '25 07:12 eirikbacker