huww98 / TimeChart

An chart library specialized for large-scale time-series data, built on WebGL.
https://huww98.github.io/TimeChart
MIT License
358 stars 32 forks source link

Make tooltip `.name` and `.value` `max-width` configurable #80

Open leonard84 opened 2 months ago

leonard84 commented 2 months ago

Currently, the tooltip hardcodes the .name and .value classes to max-width: 100px. Its use of a shadowRoot exacerbates the problem, making an easy fix with CSS overrides impossible.

Please offer a way to increase the max sizes for both .name and .value.

huww98 commented 2 months ago

I've tried it once at https://github.com/huww98/TimeChart/issues/55#issuecomment-1273565906 . No satisfying interface found so far.

leonard84 commented 2 months ago

As I suggested back then, I would make it possible to pass in CSS styles in the tooltip config object, which you would then use to render the inner CSS.

tooltip: new TimeChart.plugins.TimeChartTooltipPlugin({
        enabled: true,
        style: {
          '.name': {
            'max-width': '50em'
          },
          '.value': {
          'max-width': '50em'
        }
      },
      xFormatter: (x) => new Date(x + baseTime).toLocaleString([], {
        // year: '2-digit',
        month: '2-digit',
        day: '2-digit',
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit',
        // fractionalSecondDigits: 3
      })
    })

This could be used something like this (code by Google Gemini).

function generateStyleSheet(config) {
  const defaultStyles = {
    ":host": {
      background: "var(--background-overlay, white)",
      border: "1px solid hsl(0, 0%, 80%)",
      "border-radius": "3px",
      padding: "2px 2px",
    },
    ".item": {
      "user-select": "none",
    },
    ".out-of-range.item": {
      display: "none",
    },
    td: {
      padding: "0px 5px",
    },
    ".name": {
      "margin-right": "10px",
      "max-width": "100px",
      "text-overflow": "ellipsis",
      overflow: "hidden",
      "white-space": "nowrap",
    },
    ".example": {
      width: "6px",
      height: "6px",
    },
    ".value": {
      "text-overflow": "ellipsis",
      overflow: "hidden",
      "white-space": "nowrap",
      "min-width": "100px",
      "max-width": "100px",
      "text-align": "right",
    },
    ".x-not-aligned .value": {
      opacity: "0.4",
    },
  };

  const mergedStyles = mergeStyles(defaultStyles, config?.style || {}); // Merge with configuration

  const style = document.createElement('style');
  style.textContent = Object.entries(mergedStyles)
    .map(([selector, properties]) => {
      const propertiesString = Object.entries(properties)
        .map(([prop, value]) => `${prop}: ${value};`)
        .join(" ");
      return `${selector} { ${propertiesString} }`;
    })
    .join("\n");

  return style;
}

// Helper to merge styles (deep merge for nested properties)
function mergeStyles(defaultStyles, customStyles) {
  const merged = { ...defaultStyles };
  for (const selector in customStyles) {
    if (merged[selector]) {
      merged[selector] = { ...merged[selector], ...customStyles[selector] }; // Deep merge
    } else {
      merged[selector] = customStyles[selector];
    }
  }
  return merged;
}

// Example Usage
const conf = {
  style: {
    ".name": {
      "max-width": "50em",
    },
    ".value": {
      "max-width": "50em",
    },
  },
};

const shadowRoot = document.createElement('div').attachShadow({ mode: 'open' });
shadowRoot.appendChild(generateStyleSheet(conf));
leonard84 commented 2 months ago

@huww98, what do you think of my suggestion?

huww98 commented 2 months ago

I actually don't like this idea. The best way I think would be using CSS to solve the styling issue, and just not put them in JS. But since we are not using web-component yet, maybe I can just take a large string consisting of a CSS fragment, and I just append it to the default style? Browser should do the merge itself.

leonard84 commented 1 month ago

Fine by me, as long as it works.

How would web-components change this?

leonard84 commented 3 weeks ago

Any chance to get this, or do you want a PR?