Skip to content

Instantly share code, notes, and snippets.

@reecelucas
reecelucas / useScrollBlock.js
Last active April 5, 2024 09:12
React hook to enable/disable page scroll
import { useRef } from 'react';
const safeDocument = typeof document !== 'undefined' ? document : {};
/**
* Usage:
* const [blockScroll, allowScroll] = useScrollBlock();
*/
export default () => {
const scrollBlocked = useRef();
@reecelucas
reecelucas / preventOrphanedWord.js
Last active May 25, 2023 15:21
Prevent orphaned word in string
export const preventOrphanWord = (string) => {
const words = string.trim().split(' ');
// Only proceed if we've got at least 3 words
if (words.length < 3) {
return string;
}
const [nextToLastWord, lastWord] = words.slice(-2);
const precedingWords = words.slice(0, words.length - 2);
@reecelucas
reecelucas / Tab.js
Last active December 3, 2021 09:50
React version of Heydon Pickering's "Tabbed Interface" inclusive component. https://inclusive-components.design/tabbed-interfaces/.
import React, { useContext, useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import TabContext from './TabContext';
import getAttributeProps from './getAttributeProps';
const propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]).isRequired,
@reecelucas
reecelucas / useScrollDirection.js
Last active September 8, 2021 20:07
React hook to detect scroll direction, based on the API of https://github.com/dollarshaveclub/scrolldir
const SCROLL_UP = "up";
const SCROLL_DOWN = "down";
const useScrollDirection = ({
initialDirection,
thresholdPixels,
off
} = {}) => {
const [scrollDir, setScrollDir] = useState(initialDirection);
@reecelucas
reecelucas / FileInput.tsx
Created July 11, 2019 11:19
Custom React file select component
import * as React from 'react';
interface Props extends React.HTMLProps<HTMLInputElement> {
onFileSelect: (file: File) => void;
}
const FileInput = ({ onFileSelect, ...props }: Props) => {
const inputRef = React.useRef<HTMLInputElement>();
const onChange = (event: React.ChangeEvent) => {
@reecelucas
reecelucas / scroll-progress.js
Created September 27, 2018 09:50
Scroll progress indicator in native JS
import debounce from "lodash/debounce";
const getPageHeight = () =>
Math.max(
document.body.scrollHeight,
document.body.offsetHeight,
document.documentElement.clientHeight,
document.documentElement.scrollHeight,
document.documentElement.offsetHeight
);
@reecelucas
reecelucas / fetchGraphQL.js
Last active April 29, 2020 09:52
Simple util for querying a GraphQL service using the fetch API
const fetchGraphQL = async ({ url, query, variables, headers }) => {
const response = await fetch(url, {
method: "POST",
headers: {
...headers,
"Content-Type": "application/json"
},
body: JSON.stringify({ query, variables })
});
@reecelucas
reecelucas / scroll-utils.js
Last active April 23, 2020 08:45
Utility functions to toggle page scroll
let bodyBlocked = false;
const { body, documentElement: html } = document;
export const blockScroll = () => {
if (bodyBlocked) {
return;
}
const scrollBarWidth = window.innerWidth - html.clientWidth;
@reecelucas
reecelucas / useWebSocket.js
Last active April 17, 2020 09:05
React hook to provide a declarative wrapper around the WebSockets API
import { useEffect, useRef } from 'react'
const isFunction = fn => typeof fn === 'function';
const connectionIsOpen = ws => ws && ws.readyState === WebSocket.OPEN;
/**
* Usage:
* const { webSocket, sendMessage, closeConnection } = useWebSocket({
* url: 'wss://echo.websocket.org/',
* onOpen: useCallback(event => {
@reecelucas
reecelucas / usePrevious.js
Last active March 30, 2020 18:06
React hook to get a previous prop/state value
import { useEffect, useRef } from 'react';
/**
* Usage:
* const [count, setCount] = useState(0);
* const prevCount = usePrevious(count);
*/
export default value => {
const ref = useRef();