reshadow icon indicating copy to clipboard operation
reshadow copied to clipboard

reshadow beta roadmap

Open lttb opened this issue 5 years ago • 10 comments

The roadmap:

  • [ ] finalize the API (almost done)
  • [ ] complete the docs
    • [ ] describe the usage with different frameworks and libraries
      • [ ] React
      • [ ] Preact
      • [ ] Vue
      • [ ] Svelte
      • [ ] htm
      • [ ] styled-components API
    • [ ] describe the runtime usage and usage with plugins:
      • [ ] reshadow/babel
      • [ ] reshadow/macro
      • [ ] reshadow/postcss
      • [ ] reshadow/webpack
      • [ ] reshadow/prettier
      • [ ] reshadow/eslint
    • [ ] describe the common use cases
    • [x] the transition from styled-components
  • [ ] provide more examples and tutorials
  • [ ] provide some benchmarks

lttb avatar Jun 02 '19 15:06 lttb

@lttb Hello, This project is very interesting! I have a question regarding use:size={size}. Is it supported in Svelte? Or React only?

s0kil avatar Jun 03 '19 05:06 s0kil

Hi @s0kil, thank you for the feedback!

svelte has its own use directive, but with reshadow it is possible to omit the namespace to set the modifier :name={value} or with shorthand :{name} like {value} that svelte has for attributes.

For example,

<button :size="s" :{variant}>click</button>

this is the same as in React

<button use:size="s" use:variant={variant}>click</button>

I made an example with reshadow, svelte and modifiers here: https://codesandbox.io/s/reshadowsvelte-bup1c

At this moment this is an undocumented reshadow feature and I'm still thinking about the syntax, if you have any other ideas and proposals, I'll be glad for the feedback 🙂

lttb avatar Jun 03 '19 09:06 lttb

@lttb I'm currently working on a project that requires very dynamic components, and using directives makes it so much easier.

s0kil avatar Jun 03 '19 10:06 s0kil

@lttb Instead of providing a CSS file, are you planning to support component styles?

<style>
  /* Styles go here */
  button {
    padding: 5px 10px;
    border-radius: 5px;
    font-size: 16px;
  }

  button[|size="s"] {
    font-size: 14px;
  }

  button[|size="m"] {
    font-size: 16px;
  }
</style>

<button :size="s">Button</button>

It's also possible to add a lang attribute to <style> similar to what svelte-preprocess works:

<style lang="reshadow">
  /* Styles go here */
  button {
    padding: 5px 10px;
    border-radius: 5px;
    font-size: 16px;
  }

  button[|size="s"] {
    font-size: 14px;
  }

  button[|size="m"] {
    font-size: 16px;
  }
</style>

<button :size="s">Button</button>

s0kil avatar Jun 03 '19 12:06 s0kil

@s0kil

yeah, it is already possible with reshadow, you can even use your own language to preprocess before reshadow, for example:

<style reshadow lang="scss">
  button {
    padding: 5px 10px;
    border-radius: 5px;
    font-size: 16px;
  }
</style>

<button>Button</button>

Moreover, it is possible to use runtime js values in styles with reshadow by string interpolation:

<script>
  import { randomColor } from "./randomColor";

  let color = randomColor();
</script>

<style reshadow>
    h1 {
        color: ${color};
    }
</style>

<h1>title</h1>

And you can also use reshadow css function val to achieve that too:

<script>
  import { randomColor } from "./randomColor";

  let color = randomColor();
</script>

<style reshadow>
    h1 {
        color: val(color);
    }
</style>

<h1>title</h1>

The API is still WIP, but you can play with it here: https://codesandbox.io/s/reshadowsvelte-5wzt1

lttb avatar Jun 03 '19 12:06 lttb

And I did not mention, that another one way to use reshadow with svelte is styled function (https://codesandbox.io/s/bup1c):

<script>
  import styled from "reshadow";

  /* import just css file, reshadow will process it */
  import styles from "./styles.css";
  /* css-in-js is available too */
  import * as themes from "./themes";
  import { randomColor } from "./randomColor";

  export let theme = "light";

  let color = randomColor();

  styled(styles, themes[theme])`
    h1 {
      color: ${color};
    }
  `;
</script>

<h1>hello world</h1>

the cool thing about this function is that it is possible to compose different styles together, which is useful for CSS code splitting, styles injection via DI and so on

lttb avatar Jun 03 '19 12:06 lttb

@lttb Thank you for your quick and detailed response.

s0kil avatar Jun 03 '19 13:06 s0kil

I've come across a funny case. If you use css-in-js approach w/ babel plugin assets' paths won't be parsed

example

import styled from 'reshadow';

const Comp = props => styled`
  @font-face {
    font-family: custom-font;
    src: url('../fonts/custom-font.woff2') type('woff2');
  }
`(
  <name {...props} />
)

If you use this approach the file ../fonts/custom-font.woff2 will not be recognised as a dependency and wont be passed to webpack or whatever bundler you happen to use. This is kind of a corner case. Yet it will also work with background images and other assets you happen to require from your css. I think this should end up somewhere in the docs.

antonk52 avatar Jun 05 '19 22:06 antonk52

I came across two more cases which eventually should end up in either/or FAQ/gotchas sections on the website

  • class name extraction
  • workaround for components using React Portal

Class name extraction

Essentially when you use third party libs that provide components which can accept class names in object format. I am aware of two options we can do it

// option one
import React from 'react'
import styled from 'reshadow'
import Comp from 'third-party'

// both our styles and styles for third party components are located together
// in out component
const MyComp = () => styled`
  container {/* container styles */}
  .wrapper {/* .wrapper styles */}
  .inner {/* .inner styles */}
`(
  <wrapper>
    <Comp classes={{compWrapper: styled.styles.wrapper, compInner: styled.styles.inner}} />
  </wrapper>
);
// option two
import React from 'react'
import styled, {css} from 'reshadow'
import Comp from 'third-party'

// our styles and styles for third party components are separated
const style = css`
  .wrapper {/* .wrapper styles */}
  .inner {/* .inner styles */}
`;

const MyComp = () => styled`
  container {/* container styles */}
`(
  <wrapper>
    <Comp classes={{compWrapper: style.wrapper, compInner: style.inner}} />
  </wrapper>
);

React Portal workaround

If you use dynamic values which fallback into css custom properties

import React from 'react'
import styled, {css} from 'reshadow'
import ReactModal from 'react-modal'

const MyComp = ({color, ...props}) => styled`
  wrapper {
    color: ${color}
  }
`(
  <wrapper {...props}>
    <ReactModal>
      <p>lorem ipsum</p>
    </ReactModal>
  </wrapper>
)

if I did not know how reshadow works I would expect the text inside modal to be the same color as I pass in the component. Since these values are set as css custom properties on the wrapper element and React modal are rendered in a different place in the DOM the css custom property for color will not be accessible inside react modal. To fix it I was suggested a work around which assumes that the component using portal accepts style prop. It goes smth like so

<ReactModal style={styled.$$style}>

If I have time I am happy with doing a PR for both of the above.

antonk52 avatar Jun 14 '19 17:06 antonk52

It's been a while, since most work is done in the next branch and what is left is the documentation I would like to propose a way to tackle it. I've copied over the points from the initial issue and commented on each below. I'd like to get some feedback on this idea before getting to work on it.

  • [ ] complete the docs
    • needs clarification on what is lacking
  • [ ] describe the usage with different frameworks and libraries
    • let's return the example directory and set up example for reshadow usage with each framework/lib
    • [ ] React
    • [ ] Preact
    • [ ] Vue
    • [ ] Svelte
    • [ ] htm
    • [ ] styled-components API
  • [ ] describe the runtime usage and usage with plugins:
    • Each package should have a separate section on a Packages page on the docs website
    • [ ] reshadow/babel
    • [ ] reshadow/macro
    • [ ] reshadow/postcss
    • [ ] reshadow/webpack
    • [ ] reshadow/prettier
    • [ ] reshadow/eslint

antonk52 avatar Apr 14 '20 14:04 antonk52