Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Word-wrap overflown X-axis labels #961

Closed
James2516 opened this issue Oct 22, 2017 · 10 comments
Closed

Word-wrap overflown X-axis labels #961

James2516 opened this issue Oct 22, 2017 · 10 comments

Comments

@James2516
Copy link

#198

This is supposedly fixed by #243 but it doesn't seem to work.

How do I use it? <XAxis dataKey="name" interval={0} width={30} label={<Text width={30} />} />?
@techniq

@techniq
Copy link
Contributor

techniq commented Oct 22, 2017

I haven't used recharts in a while, and have extracted out the <Text /> component to use in other projects (like vx) but all that is required to have <Text /> wrap is an explicit width like you have. I don't know how best to integrate Text with an axis but maybe you are supposed to pass props directly to it, such as:

<XAxis dataKey="name" interval={0} width={30} label={props => <Text width={30}>{props.text}</Text>} />

but I'm just guessing. I took a quick peak at the source of XAxis but didn't see how it uses the label prop.

@James2516
Copy link
Author

Doesn't work unfortunately...

@nogashimoni
Copy link

Any news ?

@havietduc91
Copy link

Doesn't work unfortunately...

Hi James2516, I just only use width param for XAxis or YAxis and it's working fine, maybe it helps you!
screenshot 3

Please click the bellow link to know more!
https://jsfiddle.net/vuh6cLyz/3/

@lisamartin00
Copy link

I was finally able to figure it out based on their Line Chart Example fiddle, which uses a custom component passed into the <XAxis> tick property.
https://jsfiddle.net/alidingling/5br7g9d6/

You can do something similar to what they've done and return the <Text> element
https://jsfiddle.net/lisamartin00/exasjofp/
Now you can set a fixed width and the text will wrap. You may still need to write some custom media queries to adjust the font-size for smaller screen widths, e.g.
@media screen and (max-width: 480px){ .recharts-cartesian-axis-ticks { font-size: 10.5px; }

@deadlyfingers
Copy link

deadlyfingers commented Dec 13, 2018

If you need word wrap on long string or word which has no spaces I have a fiddle which shows how to chunk long text strings and splits it up into multiple tspan elements. https://jsfiddle.net/deadlyfingers/jngsxqyo/85/

@xile611 xile611 closed this as completed Mar 17, 2020
@bertho-zero
Copy link
Contributor

bertho-zero commented Apr 23, 2020

I created a CustomizedAxisTick for that:

export default function EllipsisAxisTick({ maxLines = 3, payload, ...rest }) {
  const [text, setText] = useState(payload.value);
  const [suffix, setSuffix] = useState('');

  const measuredRef = useCallback(
    node => {
      if (node === null) {
        return;
      }
      let { wordsByLines } = node.state;
      let biggestLine = wordsByLines.reduce((a, b) => (a.width > b.width ? a : b));
      let tempText = text;
      const tempSuffix = wordsByLines.length > maxLines || biggestLine.width > rest.width ? '…' : '';

      while (wordsByLines.length > maxLines || biggestLine.width > rest.width) {
        tempText = tempText.slice(0, -1);
        wordsByLines = node.getWordsByLines(
          {
            ...rest,
            children: tempText + tempSuffix
          },
          true
        );
        biggestLine = wordsByLines.reduce((a, b) => (a.width > b.width ? a : b));
      }

      if (tempText !== text) {
        setText(tempText);
        setSuffix(tempSuffix);
      }
    },
    [maxLines, rest, text]
  );

  return (
    <g>
      <Text {...rest} ref={measuredRef}>
        {text + suffix}
      </Text>
      <title>{payload.value}</title>
    </g>
  );
}

// ...

  <YAxis
    dataKey="agenda.title"
    type="category"
    width={133}
    tick={<EllipsisAxisTick maxLines={3} />}
  />

Unlike the other solutions seen here, this is based on a maximum number of lines while respecting the width. If it goes beyond that adds an ellipsis and a title to the hover.

image

I noticed that getWordsByLines from Text does not cut long words that are longer than the width.

@Morantron
Copy link
Contributor

Morantron commented Jan 8, 2021

I created a CustomizedAxisTick for that:

export default function EllipsisAxisTick({ maxLines = 3, payload, ...rest }) {
  const [text, setText] = useState(payload.value);
  const [suffix, setSuffix] = useState('');

  const measuredRef = useCallback(
    node => {
      if (node === null) {
        return;
      }
      let { wordsByLines } = node.state;
      let biggestLine = wordsByLines.reduce((a, b) => (a.width > b.width ? a : b));
      let tempText = text;
      const tempSuffix = wordsByLines.length > maxLines || biggestLine.width > rest.width ? '…' : '';

      while (wordsByLines.length > maxLines || biggestLine.width > rest.width) {
        tempText = tempText.slice(0, -1);
        wordsByLines = node.getWordsByLines(
          {
            ...rest,
            children: tempText + tempSuffix
          },
          true
        );
        biggestLine = wordsByLines.reduce((a, b) => (a.width > b.width ? a : b));
      }

      if (tempText !== text) {
        setText(tempText);
        setSuffix(tempSuffix);
      }
    },
    [maxLines, rest, text]
  );

  return (
    <g>
      <Text {...rest} ref={measuredRef}>
        {text + suffix}
      </Text>
      <title>{payload.value}</title>
    </g>
  );
}

// ...

  <YAxis
    dataKey="agenda.title"
    type="category"
    width={133}
    tick={<EllipsisAxisTick maxLines={3} />}
  />

Unlike the other solutions seen here, this is based on a maximum number of lines while respecting the width. If it goes beyond that adds an ellipsis and a title to the hover.

image

I noticed that getWordsByLines from Text does not cut long words that are longer than the width.

This does no longer works in 2.0.0 because getWordsByLine is no longer accessible through the ref

I think it was introduced in this commit fc1669a

Would be cool to expose it again or maybe include this multiline ellipsis approach in the component itself, as it seems to work very well

cc @xile611 @bertho-zero

@Morantron
Copy link
Contributor

I've accidentally created a PR to include maxLines prop in the Text component itself

@ababos
Copy link

ababos commented Mar 30, 2021

Any solution to this? I have the "2.0.9", version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants