I wanted a way to allow people to select some text on my website and share it, specifically to Twitter. I chose to do this using Twitter intents which allow me to set up a link that can be clicked that will send someone to Twitter and open the compose Tweet dialog.
I implemented a single React (well, Preact) component with useState
to store the selected text and a fixed position area to display the text in when selected.
onselectionchange
fires way too much (for every character you select) to update the message all the time, so I debounced the listener with a 200ms delay. In the listener we toString()
the Selection
object, which turns the object into a string of the selected text. We apply the listener in a useEffect
and we're done.
const Tweetable = () => {const [tweetableText, setTweetableText] = useState();useEffect(() => {// event fires for every selection changedocument.onselectionchange = debounce(() => {// toString on the Selection object gives you the selected textconst text = document.getSelection().toString();setTweetableText(text);}, 200);},[]);return tweetableText ? (<divcss={{zIndex: 1,position: "fixed",top: "5px",display: "flex",flex: 1,width: "100%",background: "#10151e",justifyContent: "center",color: "#eef1f7",borderBottom: "1px solid rgba(51,183,255,.21)"}}><div css={{ maxWidth: 400, display: "flex", flexDirection: "column" }}><p css={{ paddingTop: "1rem" }}>{tweetableText}</p><ahref={"https://twitter.com/intent/tweet?text=" +encodeURI(tweetableText + " " + window.location.href)}css={{ color: "#1DA1F2", alignSelf: "flex-end", padding: "1rem" }}>Tweet this</a></div></div>) : null;};
and the debounce
function I used:
const debounce = (func, wait) => {let timeout;return function executedFunction(...args) {const later = () => {timeout = null;func(...args);};clearTimeout(timeout);timeout = setTimeout(later, wait);};};