styletron / styletron

:zap: Toolkit for component-oriented styling
https://www.styletron.org
MIT License
3.32k stars 101 forks source link

Compose classes from external css frameworks #43

Closed zerkalica closed 5 years ago

zerkalica commented 7 years ago

How to compose class names, like in jss-compose plugin, https://github.com/cssinjs/jss/issues/265

muratgozel commented 7 years ago

i dont know if there is such feature but i prefer extending classes like this:

const Icon = styled('svg', (props) => ({
  width: '1.4rem',
  height: '1.4rem',
  fill: !props.hover ? 'white' : app.branding.colors[0],
  marginRight: '0.3rem'
}))

const MessengerIcon = styled(Icon, (props) => ({
  fill: !props.hover ? 'white' : app.style.socialMediaColors.messenger
}))
zerkalica commented 7 years ago

No, i talking about external class names, such as 'btn', 'btn-primary', not variables in styles. How to combine existing bootstrap/material css class names in styletron style definitions?

scott113341 commented 7 years ago

Reading through the source of styletron-react#styled, it looks like you can pass in a className property that will get merged with all of the Styletron atomic class games. @zerkalica, is that the behavior you are asking about?

zerkalica commented 7 years ago

No.

  1. It's only for react: package is styletron-react.
  2. This not give me abstraction on top of styletron classes, see https://github.com/cssinjs/jss/issues/247 Jss like styletron - abstraction layer between any css-framework and application code. Placing string className in my component breaks this abstraction.
scott113341 commented 7 years ago

Ok, I think I see what you are saying. Right now, this is how you'd compose a Styletron styled component with css framework classes:

const btnStyles = {
  color: 'red',
  fontSize: '18px'
};

const MyButton = styled('button', btnStyles);

<MyButton className="btn btn-primary">Click</MyButton>
// renders as: <button class="btn btn-primary a b">Click</button>

Where a and b classes contain the color and fontSize properties as declared in btnStyles.

BUT, you are looking to do something like this:

const btnStyles = {
  className: 'btn btn-primary',
  color: 'red',
  fontSize: '18px'
};

const MyButton = styled(Button, btnStyles);

<MyButton>Click</MyButton>
// renders as: <button class="btn btn-primary a b">Click</button>

Do I understand correctly?

zerkalica commented 7 years ago

Yes, looks like jss composed.

scott113341 commented 7 years ago

Well, there's no way to that right now as written. I'm not sure if this is something @rtsao would want a PR for. I could see something like this being nice to have:

const Button = styled('button', { className: 'btn' });
const ButtonPrimary = styled(Button, { className: 'btn-primary' });
const MyPrimaryButton = styled(ButtonPrimary, { color: 'red' });

<MyPrimaryButton>Click</MyPrimaryButton>
// renders as: <button class="btn btn-primary a">Click</button>

However, it may not be worth adding to Styletron, especially since Styletron's main selling point is its performance, which relies on NOT using huge global css stylesheets.

Here's how you could abstract this with constants in a file:

/* buttons.js */
export const buttonClasses = 'btn';
export const buttonPrimaryClasses = 'btn btn-primary';

export const Button = styled('button', { className: buttonClasses });
export const ButtonPrimary = styled('button', { className: buttonPrimaryClasses });

/* app.js */
import { buttonPrimaryClasses } from './buttons.js';
const MyPrimaryButton = styled('button', { className: buttonPrimaryClasses, color: 'red' });

<MyPrimaryButton>Click</MyPrimaryButton>
// renders as: <button class="btn btn-primary a">Click</button>

Or you could do it with some simple factories:

/* buttons.js */
export const buttonClasses = 'btn';
export const buttonPrimaryClasses = 'btn btn-primary';

export const Button = props => styled('button', { className: buttonClasses, ...props });
export const ButtonPrimary = props => styled('button', { className: buttonPrimaryClasses, ...props });

/* app.js */
import { ButtonPrimary } from './buttons.js';
const MyPrimaryButton = ButtonPrimary({ color: 'red' });

<MyPrimaryButton>Click</MyPrimaryButton>
// renders as: <button class="btn btn-primary a">Click</button>
zerkalica commented 7 years ago

My be better to use composes: ['btn', 'btn-primary'], instead of className: 'btn btn-primary' ? More compatible with jss.

rtsao commented 5 years ago

Closing for inactivity. Feel free to re-open if this is still an issue. Thanks!