trousers
trousers copied to clipboard
Trousers v4 - An idea
Improvements ✅
- Leaning into the CSS prop
- Zero config SSR becomes possible
- Modifier predicates are passed into the underlying element
- No longer dependant on hooks
- Dynamic properties can be applied to css vars to avoid remounting styles
- Less dependency on React
Challenges ❌
- Extending proptypes in typescript for basic elements
- import { useStyles } from '@trousers/core';
- import styleCollector from '@trousers/collector';
+ /** @jsx jsx */
+ import css from '@trousers/core';
+ import jsx from '@trousers/react';
- const styles = props => styleCollector('button')
- .element`
- background-color: ${theme => theme.backgroundColor};
- `
- .modifier('primary', props.primary)`
- background-color: #f95b5b;
- `;
+ const styles = css('button', `
+ background-color: ${theme => theme.backgroundColor};
+ `)
+ .modifier('primary')`
+ background-color: #f95b5b;
+ `
+ .modifier('disabled')`
+ background-color: red;
+ `;
const Button = props => {
- const buttonClassNames = useStyles(styles(props));
return <button
- className={buttonClassNames}
+ css={styles}
+ primary={props.primary}
>
{props.children}
</button>;
};
export default Button;
Themes should now be mounted as classnames of css vars. Rather than depending on costly react context, we'll apply themes via a classname and css vars. The themes will be mounted to the head just like any other style.
For example:
const theme = {
primary: 'red',
secondary: 'blue,
};
is mounted as:
.theme-somehash {
--primary: red;
--secondary: blue;
}
which is applied to a button like so:
/** @jsx jsx */
import css from '@trousers/core';
import jsx from '@trousers/react';
import createTheme from '@trousers/theme';
+ const theme = createTheme({
+ primary: 'red',
+ secondary: 'blue,
+});
const styles = css('button', `
- background-color: ${theme => theme.backgroundColor};
+ background-color: var(--theme-secondary);
`)
.modifier('primary')`
+ background-color: var(--theme-primary);
`;
const Button = props => {
return <button
css={styles}
primary={props.primary}
+ theme={theme}
>
{props.children}
</button>;
};
export default Button;
Complete example:
/** @jsx jsx */
import css from '@trousers/core';
import jsx from '@trousers/react';
import createTheme from '@trousers/theme';
const theme = createTheme({
default: 'blue,
primary: 'red',
});
const styles = css('button', `
background-color: var(--theme-default);
`)
.modifier('primary')`
background-color: var(--theme-primary);
`;
const Button = props => {
return <button
css={styles}
primary={props.primary}
theme={theme}
>
{props.children}
</button>;
};
export default Button;
Precursor integration notes:
- Themes feel a bit disconnected from each other.
- Where are themes coming from? How is a global theme different to a local theme?
- Maybe we can prefix themes some how? Or use a $ similar to stitches
- Can we potentially provide a helper that allows us to do typechecking + default values?
Could the macro support this?
const styles: CSSProperties = {};
if (start) {
styles.gridColumnStart = start;
}
if (end) {
styles.gridColumnEnd = end;
}
if (span) {
styles.gridColumnEnd = `span ${span}`;
}
return <div css={styles}>{children}</div>;
It could, potentially with an additive API. styles.append('element', 'gridColumnEnd', 'span 5')
Macro dynamic interpolation edge case:
css('Stack', {
display: 'grid',
gridTemplateColumns: 'repeat(1, 1fr)',
gap: `var(--space-${gap})`, // We need to be able to detect this
width: '100%',
})