Skip to content

Instantly share code, notes, and snippets.

View donaldpipowitch's full-sized avatar

Donald Pipowitch donaldpipowitch

View GitHub Profile
@donaldpipowitch
donaldpipowitch / README.md
Last active December 11, 2025 14:28
Use GitLab Pages to deploy a Storybook per branch

It's quite straightforward to use GitLab Pages to deploy a Storybook instance per branch (and remove it whenever the branch will be removed). And yeah, it's irony to document this in a GitHub Gist 😅

You just need a .gitlab-ci.yml like this one:

stages:
  - setup
  - build-and-test
  - deployment
  - pages
@donaldpipowitch
donaldpipowitch / .gitlab-ci.yml
Last active November 13, 2025 13:43
Visual Regression Testing with Storybook Test Runner
storybook:test-runner8:
image: mcr.microsoft.com/playwright:v1.39.0-jammy
stage: build-and-test
artifacts:
expire_in: 2 weeks
when: always
paths:
- .storybook-images/__diff_output__/
- .storybook-images/__received_output__/
before_script:
Name
Godzilla
Born
1952
Birthplace
Japan
Color
Green
@donaldpipowitch
donaldpipowitch / README.md
Last active December 30, 2024 14:31
Use @ts-check for custom ESLint rules

This is a very basic example which shows how you can create a simple ESLint rule with @ts-check support. This example features the rule and a test. The rule checks, if you pass an absolute URL to a history.push function or not.

If you want to use this rule in your ESLint configuration without publishing the rule there is a caveat. AFAIK you can't simply include the path to your rule in your .eslintrc.js (correct me if I'm wrong). You need to pass the directory of this rule to the CLI as --rulesdir "./path/to/rules" and if you use VS Code with the ESLint extension you need to set "eslint.options": { "rulePaths": ["./path/to/rules"] }, in your settings.json as well. Only then you can add the rule to your config:

module.exports = {
  // ...yourCurrentConfig,
  rules: {
    // ...yourCurrentConfig.rules,
 'some-rule': 'error'
@donaldpipowitch
donaldpipowitch / example.tsx
Created November 6, 2019 07:43
Mock Upload Progress with axios-mock-adapter
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
const mock = new MockAdapter(axios);
// this mocks a request which is always at 40% progress
mock.onPost('/upload-1').reply((config) => {
const total = 1024; // mocked file size
const progress = 0.4;
if (config.onUploadProgress) {
@donaldpipowitch
donaldpipowitch / README.md
Last active February 27, 2024 15:42
Type-safe query params in React with a "Hook Builder"

Everyone loves type-safe APIs nowadays, but as far as I can tell query parameters are a blind spot to most people right now.

I create a hook which uses a builder pattern a while ago, which allows you to create type-safe query parameters. It is not very polished and contains some specific use cases, that's why I hesitated to share it. But as I successfully use it for a couple of month already and (afaik) no one came up with something similar so far, I wanted to share it.

How does it look like?

import * as pp from './page-params';

type FavoriteFood = 'pizza' | 'noodles' | 'wraps' | 'hot-dogs';
@donaldpipowitch
donaldpipowitch / README.md
Last active February 18, 2024 09:43
Handle server errors in Formik

Whenever the server returns validation errors and we would set them with setFieldError they would be lost if any field would get a change or blur event. But we want to keep these kind of errors until the specific field changes. Additional we want to handle generic server errors (which are not specific to a field, but the whole form).

With these hooks field specific server side errors should be added like this:

const { setStatus } = useFormikContext();

const errors = {};
// adjust serverErrors to your own responses
// in this case they look like this: Array<{ name: string, error: string }>
@donaldpipowitch
donaldpipowitch / README.md
Last active November 13, 2023 22:08
Rewrite relative import paths with a codemod

⚠️ This is for an internal project, but shared publicly as a reference for myself.

If you want to have a general introduction how to write such a codemod have a look at this Gist from me.

What to do?

Place the usage.js and prettiermod.js in the root of the project. Run:

$ pnpm add globby@^11.0.0 @babel/traverse
@donaldpipowitch
donaldpipowitch / README.md
Created November 13, 2023 08:46
Custom ESLint Rules to support in migrating React Router v5 to v6

Use at your own risk! Feel free to modify. They were customized for our code base and help to automate 90% of the migration our big React Router v5 app.

You will notice some data-exact field on routes. Those are only needed while you have some merge requests still on v5 and some on v6. When your whole code base (including pending merge requests) is using v6 you can safely delete all those ESLint rules and you can just run a string-replace on your code base to remove data-exact="true" and data-exact="false".

My two biggest gotchas during the migration:

Regarding the first point we created this file src/components/root-routes that is also expected by one of the ESLint Rules:

@donaldpipowitch
donaldpipowitch / extension.ts
Created September 27, 2023 13:25
A VS Code extension which checks if a React component was created by styled-components.
import * as vscode from 'vscode';
import * as ts from 'typescript';
import * as path from 'path';
export function activate(context: vscode.ExtensionContext) {
const decorationType = vscode.window.createTextEditorDecorationType({
light: {
before: {
contentText: 'S.',
color: 'rgba(255, 0, 255, 0.7)',