Skip to content

Instantly share code, notes, and snippets.

@seanrankin
Last active January 20, 2021 20:46
Show Gist options
  • Save seanrankin/c697af6c7f70e8cdd987fc3268df9dfd to your computer and use it in GitHub Desktop.
Save seanrankin/c697af6c7f70e8cdd987fc3268df9dfd to your computer and use it in GitHub Desktop.
// Line-clampin is hard...
// Insert a 'see more' link at the end of x lines of text, hide the rest, and enable expansion
import React, { createRef, forwardRef, useLayoutEffect, useState } from 'react';
import { useGetBoundingClientRect } from '../../hooks';
import { Collapse } from './index';
import styles from './styles.scss';
const Word = forwardRef(({ word }, ref) => <span ref={ref}>{word} </span>);
Word.displayName = 'Word';
const LineClamp = ({ children = '', lines = 2, unclamp = false }) => {
const ellipsisRef = createRef();
const [wrapperBox, wrapperRef] = useGetBoundingClientRect();
const [open, setOpen] = useState(false);
const [intro, setIntro] = useState(null);
const [details, setDetails] = useState([]);
const text = children ? children.split(' ') : [];
const nodes = text.map((w, i) => {
const ref = createRef();
return <Word key={i} word={w} ref={ref} />;
});
useLayoutEffect(() => {
for (const [index, item] of nodes.entries()) {
const rec = item?.ref?.current?.getBoundingClientRect() ?? {};
if (rec.bottom > wrapperBox.bottom) {
const lastItem = index - 2;
setIntro(nodes.slice(0, lastItem));
setDetails(nodes.slice(lastItem));
break;
}
}
}, [wrapperBox.bottom]);
const style = open ? {} : { maxHeight: 24 * lines };
return (
<div
className={styles.lineClampLWrapper}
ref={wrapperRef}
style={style}
onClick={() => setOpen(!open)}
>
{intro || nodes}
<If condition={!open || !unclamp}>
<span
className={styles.lineClampLink}
onClick={() => (unclamp ? setOpen(!open) : null)}
ref={ellipsisRef}
>
{unclamp ? '... see more' : '...'}
</span>
</If>
<Collapse in={open} unmountOnExit={true}>
<div>{details}</div>
</Collapse>
</div>
);
};
export default LineClamp;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment