Portrait of me in my natural habitat

Onion

For the last couple years I've been developing side projects, and I've been adding the same components to components/ over and over. At first I was copy+pasting them. At some point I made a template repo that I'd clone from, but that still had the problem of me needing to go back to copy+paste new stuff to it. Finally, in the middle of the summer of 2022, I sat down and resolved to make my own package.

The component library has taken a lot of inspiration from my work a Dropbox. The keystone of the system is the Block, and to call it CSS in JavaScript I feel would be misleading, but it's true the styles are added in the React components.

<Block color={color} colorTint="light" paddingTop="0.5">
    {children}
</Block>

If there was a goal for this project other than speeding up the MVP development on my side-projects, it'd be to push TypeScript to it's typing limimts. I'm constantly trying to make the props flexible while remaining typesafe. I feel like at this point I've used it all, from union types, to generics, to template strings; resulting in some nonsense like

export type Directions<T extends string, V> = Partial<
    Mapping<DirectionOptions<T>, V>
>;

export type ForBreakpoints<
    T,
    E extends keyof Breakpoints = 'mobile' | 'tablet' | 'wide' | 'desktop'
> = T | Partial<Pick<Record<keyof Breakpoints, T>, E>>;

export type SpacingPropsValue = ForBreakpoints<SpacingValues>;

export type PaddingProps = Directions<'padding', SpacingPropsValue>;

as a type-safe way of accomplishing

<Block paddingTop={{mobile: "1", tablet: "2"}} paddingBottom="2">
    Hello World
</Block>

annarborbus.info is a great example of a website I build using onion.

landing page of website using onion design system