Skip to content

Instantly share code, notes, and snippets.


Leesa Ward doubleedesign

View GitHub Profile
doubleedesign / ThemeUtils.ts
Last active April 7, 2023 01:33
Shortcut function for choosing text colour based on background colour using Styled Components + Polished
View ThemeUtils.ts
import { meetsContrastGuidelines } from 'polished';
import { ContrastScores } from 'polished/lib/types/color';
type WCAGLevel = keyof ContrastScores;
export function contrastTextColour(color: string, wcag: WCAGLevel = 'AA') {
const scores = meetsContrastGuidelines(color, '#fff');
if(scores[wcag]) {
return '#fff';
doubleedesign / ColorThemeTypedExample.styled.ts
Last active April 7, 2023 01:34
Typing styled-components props: Valid string values according to what's available in theme
View ColorThemeTypedExample.styled.ts
import styled from 'styled-components';
import { ThemeColor } from '../../types';
interface ButtonProps {
color: ThemeColor
export const StyledButton = styled.button<ButtonProps>`
background: ${({ theme, color }): string => theme.colors[color]};
// more styles
doubleedesign / Button.styled.ts
Created April 7, 2023 00:10
Extend a styled component as a different HTML element
View Button.styled.ts
import styled from 'styled-components';
interface ButtonProps {
// Props to be used for styling below
export const StyledButton = styled.button<ButtonProps>`
// Styles
&:hover, &:focus, &:active {
doubleedesign / useLocalStorage.ts
Created March 21, 2023 11:25
useLocalStorage React hook. Keep a state value in sync with one cached in the browser using local storage.
View useLocalStorage.ts
import { useState, useEffect, Dispatch, SetStateAction } from 'react';
export function useLocalStorage<T>(key: string, defaultValue: T): { value: T; setValue: Dispatch<SetStateAction<T>> } {
const [value, setValue] = useState(() => {
return localStorage?.getItem(key) ? JSON.parse(localStorage.getItem(key)) : defaultValue;
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
doubleedesign / _useResize.ts
Last active March 31, 2023 02:20
useResize React hook. Dynamically get height and width of an element when its size changes and store the values in state. Demo:
View _useResize.ts
import { MutableRefObject, useMemo, useEffect, useState } from 'react';
interface Dimensions {
width: number;
height: number;
export function useResize(ref: MutableRefObject<HTMLElement | undefined>, deps: unknown[]): Dimensions {
const [width, setWidth] = useState<number>(0);
const [height, setHeight] = useState<number>(0);
doubleedesign / _box.scss
Last active March 19, 2023 10:27
Vertically centred CSS arrow/triangle on side of box. Demo:
View _box.scss
$spacing: (
xs: 0.25rem,
sm: 0.5rem,
md: 0.75rem,
lg: 1rem,
xl: 1.5rem,
xxl: 2rem
$colours: (
doubleedesign / typechecker.test.ts
Last active February 5, 2023 11:30
Function to determine the TypeScript type of a given value using a predefined list of types
View typechecker.test.ts
import savedArtists from '../json-data/test/artists.json' assert { type: 'json'};
import { getType } from './typechecker';
// NOTE: These tests are a work in progress,
as I have so far only completed work with the "Artist" type on the project at the time of writing
describe('Typechecker', () => {
it('Correctly identifies and Artist', () => {
const item = savedArtists[0];
const type = getType(item);
doubleedesign / class-unhooky-plugin-custom-admin-stuff.php
Last active March 21, 2023 11:26
Unhook a Ninja Forms plugin action from within another plugin. The context for this example was using Ninja Forms for Expression of Interest forms associated with Jobs (a custom post type), and a customised admin screen for viewing submissions. (This isn't the whole plugin, it's just the parts required to show how to unhook a Ninja Forms functio…
View class-unhooky-plugin-custom-admin-stuff.php
* Job listings functionality for Client Website
* Note: Requires Ninja Forms plugin
* Note: Truncated for use in a gist to demonstrate unhooking a Ninja Forms function
* @since 1.0.0
* @package MyPlugin
* @subpackage MyPlugin/admin
class MyPlugin_Jobs extends MyPlugin_Settings {
doubleedesign / YearbookClasses.jsx
Last active November 23, 2022 15:49
InDesign Image Catalog for multiple folders at once (and multiple folders per page). Created for school yearbook projects (one folder per class, two classes per page) but could be adapted for other use cases where you want to lay out contact sheets of multiple folders automatically.
View YearbookClasses.jsx
* Custom Image Catalog script that runs for all subfolders in a selected folder.
* Lays out each folder of images in the specified number of rows and columns, 2 folders per page, shows an alert if there's more images than allowed for,
* labels each group with the folder name, creates paragraph styles for the captions and group headings, and saves the file.
* Based on the built-in Image Catalog script but modified and simplified (e.g. hard-coding the settings) for my use case.
* Could be modified to suit different numbers of folders per page, different image quantities etc by changing the settings at the top
* and making tweaks to other code as needed.
* Could also be extended to show one dialog for settings prior to the loop,
doubleedesign / cpt-case_study.php
Created June 28, 2021 09:43
Use a WooCommerce product attribute taxonomy for a custom post type
View cpt-case_study.php
// Register Custom Post Type
// Note: Using woocommerce_after_register_taxonomy hook instead of init because we're using a product attribute taxonomy with this CPT
function doublee_cpt_case_study() {
$labels = array(
'name' => _x('Case studies', 'Post Type General Name', 'doubleedesign'),
'singular_name' => _x('Case study', 'Post Type Singular Name', 'doubleedesign'),
'menu_name' => __('Case studies', 'doubleedesign'),
'name_admin_bar' => __('Case study', 'doubleedesign'),