diegohaz / diegohaz/styled-tools

Needles should be recursively resolved

Open
#55 9 comments 0 reactions 0 assignees View on GitHub
enhancement PR welcome
Dominant language
JavaScript
Stars
799
Forks
24
PR merge metrics
No merged PRs in 30d

Description

I ended up finding a solution to my problem while writing this issue, but I believe it's something that styled-tools should handle by default. I'm working with the sample below which a reakit theme, and the issue is in `contrastText`. What ends up happening is that `bg` resolves to a prop-getter function instead of a string. The reason being that `bgNeedle` is a prop-getter that resolves to a prop-getter which is not supported by `withProp`. What I ended up doing is writing a custom implementation of `withProp` (below the example) that recursively resolves prop-getter functions. It would be useful if this was either the default behavior of `withProp` or was exposed as a separate function.

```ts
// utils.ts

import { range } from 'lodash-es';
import { getLuminance, lighten } from 'polished';
import { Needle, palette as p, withProp } from 'styled-tools';

export const contrastText = (bgNeedle: Needle) =>
withProp(
[bgNeedle, p('black'), p('white')] as any,
(bg: string, black: string, white: string) => {
// bg ends up being a prop getter function here instead of a string.
return getLuminance(bg) > 0.179 ? black : white;
},
);

export const contrastPalette = (palette: string, tone?: number) =>
contrastText(p(palette, tone));

export const lightenPalette = (
amount: number,
palette: string,
tone?: number,
) =>
withProp([p(palette, tone)] as any, (color: string) =>
lighten(amount, color),
);

export const tonePalette = (palette: string) => [
p(palette),
...range(0.1, 0.5, 0.1).map(i => lightenPalette(i, palette)),
];

export const tonePaletteText = (palette: string) =>
range(5).map(i => contrastPalette(palette, i));

export const tonePaletteWithText = (name: string, palette: string) => ({
[name]: tonePalette(palette),
[`${name}Text`]: tonePaletteText(name)
});
```

```ts
// index.ts

import { tonePaletteWithText } from './utils';

export const palette = {
white: '#fff',
black: '#000',

astronautBlue: '#003a5d',

...tonePaletteWithText('primary', 'astronautBlue'),
};
```

## Solution

```ts
// simple deepWithProp

const deepWithProp = (
needle: Needle | Needle[],
fn: (...args: any[]) => T
) => (props = {}): T => {
if (Array.isArray(needle)) {
const needles = needle.map(arg => deepWithProp(arg, x => x)(props));
return fn(...needles);
}
if (typeof needle === "function") {
return fn(deepWithProp(needle(props as Props), x => x)(props));
}
return fn(prop(needle, needle)(props));
};
```

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.