New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add built in support for theming with React #414
Comments
For people searching Let's assume you already have a theme setup: interface Theme {
// Whatever you want
}
const theme: Theme = {
// blah blah blah
} as const; Then create a context: const ThemeContext = React.createContext<Theme>(theme); And here is the new // First let us import a pile of things
import { driver, getInitialStyle, type StyleObject } from 'styletron-standard';
import { createStyled, type StyletronComponent, type StyletronWrapper } from 'styletron-react';
const wrapper: StyletronWrapper = (StyledComponent) => React.forwardRef((props, ref) => (
<ThemeContext.Consumer>
{theme => <StyledComponent ref={ref} {...props} $theme={theme} />}
</ThemeContext.Consumer>
));
// And here comes the type, kaboom!
interface StyleFn {
<K extends keyof JSX.IntrinsicElements>(
component: K,
style: StyleObject | ((props: React.ComponentProps<K> & { $theme: Theme }) => StyleObject)
): StyletronComponent<JSX.IntrinsicElements[K]>;
<P extends React.ComponentType<any>>(
component: P,
style: StyleObject | ((props: React.ComponentProps<P> & { $theme: Theme }) => StyleObject)
): StyletronComponent<React.ComponentProps<P>>;
<EP extends object, K extends keyof JSX.IntrinsicElements>(
component: K,
style: StyleObject | ((props: React.ComponentProps<K> & { $theme: Theme } & EP) => StyleObject)
): StyletronComponent<JSX.IntrinsicElements[K] & EP>;
<EP extends object, P extends React.ComponentType<any>>(
component: P,
style: StyleObject | ((props: React.ComponentProps<P> & { $theme: Theme } & EP) => StyleObject)
): StyletronComponent<React.ComponentProps<P> & EP>;
}
// Finally, our new styled:
const styled: StyleFn = createStyled({
wrapper,
driver,
getInitialStyle
}); The new interface Theme {
background: '',
color: {
red: [''],
blue: ['', '']
}
}
const A = styled('a', {});
<A href="" />; // href can be validated
const B = styled('a', (props) => ({ color: props.$theme.color.red[0], background: props.href })); // Theme available via $theme
<B href="" />;
const C = styled<{ $isActive?: boolean }, 'a'>('a', (props) => ({ color: props.$isActive ? props.$theme.color.red[0] : props.href })); // You can pass $isActive here
<C $isActive />;
function Component(props: { myProps: number }) { return null }
const D = styled(Component, {});
<D myProps={1} />; // You can even validate myProps
const E = styled(Component, props => ({ background: String(props.myProps) }));
<E myProps={2} />;
const F = styled<{ $isActive?: boolean }, typeof Component>(Component, (props) => ({ color: props.$isActive ? props.$theme.color.red[0] : String(props.myProps) }));
<F $isActive myProps={1} />; // All $theme, $isActive and myProps can be validated
import { useStyletron as useStyletronFromStyletron } from 'styletron-react';
const useStyletron = () => {
const theme = React.useContext(ThemeContext);
const [css] = useStyletronFromStyletron();
return [css, theme] as const;
}; |
@SukkaW why should we add all these overload types for export type StyledFn = {
<T extends React.ElementType, Props>(
component: T,
style: StyleObject | ((props: Props) => StyleObject),
): StyletronComponent<T, Props>;
}; |
Although there is a guide on how to achieve theming with styletron-react, the guide doesn't work so well with typescript and it just gives you a headache.
The text was updated successfully, but these errors were encountered: