danieldelcore / trousers

hooks-first CSS-in-JS library, focused on semantics and runtime performance
https://danieldelcore.github.io/trousers/
MIT License
302 stars 6 forks source link

Trousers v4 - An idea #83

Open danieldelcore opened 4 years ago

danieldelcore commented 4 years ago

Improvements ✅

Challenges ❌

- 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;
danieldelcore commented 4 years ago

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;
danieldelcore commented 3 years ago

Precursor integration notes:

danieldelcore commented 3 years ago

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')

danieldelcore commented 3 years ago

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%',
        })