GithubHelp home page GithubHelp logo

jsxstyle / jsxstyle Goto Github PK

View Code? Open in Web Editor NEW
2.1K 40.0 61.0 9.66 MB

Inline style system for JSX

Home Page: https://jsx.style/

License: Other

JavaScript 7.27% TypeScript 92.73%
css-in-js css inline-styles react jsxstyle

jsxstyle's Issues

Make style extraction - and thus `contextify` dependency - optional

Maybe that's too early an optimization for this awesome module right now, but contextify needs a compilation build step which renders the whole thing problematic in terms of xplat'ness.
As far as the core run-time functionality is pure JS, may be it would be better to have the rest fancy and dev-time stuff optional (I mean dev-time of the projects using this module, not this module dev time :) )

Expand on motivation / justification for jsxstyle

Regarding the section in the FAQ which states that:

jsxstyle is predicated on the idea that stylesheet rules are not a great way to reuse styles and that components are the correct abstraction.

Since believing in this opinion is vital to developers deciding whether to use this library, please can you expand the readme with more evidence on why you believe that components are the right abstraction.

Release to npm

Hi,

Could you consider releasing the current master as a new version on npm ? It block our migration to react 15.4 which fixes some important issues with jest.

Thanks !

Conditional rendering attribute

I know there is already a way to do this using javascript. But sometimes it would be just cleaner to do this:

Click Me Click Me Click Me Click Me

I figure if the show attribute is omitted, it defaults to true.

Flex component does not work

The Flex component fails at setting the css display property. In the autoprefix.js file, this code tries to set multiple values, which results in the value being ignored by the browser.

if (style.display === 'flex') { style.display = style.display + ';display:-webkit-flex;display:-ms-flexbox'; }

State of this project?

Even though jsxstyle is one of the "older" approaches for css-in-js, I still believe it's one of the most promising solutions out there right now. (Backed up quite nicely by @ryanflorence in this video)
Actually I'm using something similar (but crappier) for my current app: Components similar to yours for Layouting, css-files for making it look pretty.

I'm starting this issue to ask about your future plans with this project. I feel like this project has all the right ideas to become for css-in-js what redux has become for flux, but the infamous last 20% are still missing to make it more approachable to a wider audience.

I'm assuming you are a very busy person right now, doing great things with smyte. So I'm totally not expecting you to do it on your own. I was just curious if you had anything in mind, like calling for contributors, or whether you are happy to leave this project more or less as is and let it serve as inspiration for others to build upon. (which is perfectly acceptable too!)

In any case a big thank you for being a great inspiration for my work! :)

React 15 doesn't appear to work

In React 0.14:

import React from 'react'
import { render } from 'react-dom'
import { Flex, Block } from 'jsxstyle'

class App extends React.Component {
  render() {
    return (
      <Flex>
        <Block>One</Block>
        <Block>Main!</Block>
      </Flex>
    )
  }
}

render(<App/>, document.getElementById('app'))

Gives me this html output:

<div style="display:flex;display:-webkit-flex;display:-ms-flexbox;" data-reactid=".0">
  <div style="display:block;" data-reactid=".0.0">One</div>
  <div style="display:block;" data-reactid=".0.1">Two</div>
</div>

And displays in a row, as expected.

With React 15, I get this HTML:

<div data-reactroot="">
  <div style="display: block;">One</div>
  <div style="display: block;">Two</div>
</div>

And, as you can expect, it doesn't look correct because the top node doesn't get the style. I thought maybe something was up w/ the root node not working, but even deeper components still don't get the style applied.

Theming

React's context (ie. DI) can be used for theming ala https://twitter.com/floydophone/status/427697091377238016

Pseudocode for usage:

// SkinnedButton is a component that a bunch of other reusable components depend on. All
// it does is look in `this.context` for a component class that implements the `propTypes` it
// defines.
var jsxstyle = require('jsxstyle');

var SkinnedButton = jsxstyle.createSkinnableComponent({
  name: 'SkinnedButton',
  propTypes: {
    label: React.PropTypes.string.isRequired,
  },
});
module.exports = SkinnedButton;
var SkinnedButton = require('SkinnedButton');
// So if you build a reusable component and you want to allow someone to customize
// all buttons, just depend on this class.
var ReusableComponent = React.createClass({
  render: function() {
    return <div>Hello world! <SkinnedButton label="click me" /></div>;
  },
});
module.exports = ReusableComponent;
var Skin = require('jsxstyle').Skin;
// Skins let you inject your app-specific button as SkinnedButton for all children
// in the app by providing a child context:

var MyAppButton = require('./MyAppButton');
var ReusableComponent = require('ReusableComponent');
var MY_APP_SKIN = {
  SkinnedButton: MyAppButton,
}

var App = React.createClass({
  render: function() {
    return <Skin skin={MY_APP_SKIN}><ReusableComponent /></Skin>;
  },
});

This should be implemented.

React 15.5 deprecation warnings

Using jsxstyle with versions of React after v15.5.0 produce the following warning:

Warning: Block: React.createClass is deprecated and will be removed in 
version 16. Use plain JavaScript classes instead. If you're not yet ready 
to migrate, create-react-class is available on npm as a drop-in replacement.

Either src/makeStyleComponentClass.js needs to be rewritten or jsxstyle needs to add create-react-class as a dependency.

Flex components do not work in Safari

Safari currently only supports Flex with the -webkit- prefix. To get Flex components working in Safari you currently have to do the following:

<Flex
  display="-webkit-flex">
  I’m a Flexbox that works on Safari!
</Flex>

This doesn't fully solve the problem, as Flex related properties (eg. flexGrow) would need the same autoprefixing treatment that userSelect, transition, boxShadow and fontSmoothing currently get.

Edit: Actually, I'm a bit mystified as to what to do here because adding display="-webkit-flex" overrides the display property and breaks flex layouts for Firefox and others. In CSS you can declare multiple display properties, which is (sadly) a useful feature in this case. What's the best way to handle this? (related: this post on StackOverflow, see near the bottom of the original post)

Spread attributes and extractStyles.js

Seems like extractStyles.js isn't parsing JSX spread attributes.

// Center.js
import React, { Component, PropTypes } from 'react';
import { Flex } from 'jsxstyle';

const Center = ({ children, ...other }) =>
  <Flex alignItems='center'
    justifyContent='center'
    flexWrap='wrap'
    {...other}>
    {children}
  </Flex>;

export default Center;
// webpack.config.js
var path = require('path');
var webpack = require('webpack');

module.exports = {
  devtool: 'source-map',
  entry: [
    'webpack-hot-middleware/client',
    './src/index'
  ],
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, 'scripts'),
    publicPath: '/public/scripts/'
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin()
  ],
  module: {
    loaders: [{
      test: /\.js$/,
      loader: 'babel!' + path.join(__dirname, 'node_modules/jsxstyle/lib/webpackLoader.js') + '?LayoutConstants=' + path.join(__dirname, 'src', 'LayoutConstants.js'),
      include: path.join(__dirname, 'src')
    }]
  }
};
ERROR in ./src/Center.js
Module build failed: TypeError: Cannot read property 'name' of undefined
    at /Users/jaredpalmer/workspace/github/jaredpalmer/react-email-workflow/node_modules/jsxstyle/lib/extractStyles.js:67:34
    at Array.forEach (native)
    at transformOpeningElement (/Users/jaredpalmer/workspace/github/jaredpalmer/react-email-workflow/node_modules/jsxstyle/lib/extractStyles.js:66:23)
    at Context.recast.visit.visitJSXElement (/Users/jaredpalmer/workspace/github/jaredpalmer/react-email-workflow/node_modules/jsxstyle/lib/extractStyles.js:120:25)
    at Context.invokeVisitorMethod (/Users/jaredpalmer/workspace/github/jaredpalmer/react-email-workflow/node_modules/ast-types/lib/path-visitor.js:342:43)
    at Visitor.PVp.visitWithoutReset (/Users/jaredpalmer/workspace/github/jaredpalmer/react-email-workflow/node_modules/ast-types/lib/path-visitor.js:194:28)
    at visitChildren (/Users/jaredpalmer/workspace/github/jaredpalmer/react-email-workflow/node_modules/ast-types/lib/path-visitor.js:244:21)
    at Visitor.PVp.visitWithoutReset (/Users/jaredpalmer/workspace/github/jaredpalmer/react-email-workflow/node_modules/ast-types/lib/path-visitor.js:202:16)
    at visitChildren (/Users/jaredpalmer/workspace/github/jaredpalmer/react-email-workflow/node_modules/ast-types/lib/path-visitor.js:244:21)
    at Visitor.PVp.visitWithoutReset (/Users/jaredpalmer/workspace/github/jaredpalmer/react-email-workflow/node_modules/ast-types/lib/path-visitor.js:202:16)
 @ ./src/App.js 24:14-33

For "Open Areas of Work" are you planning updates?

The reference webpack loader is hacky, exposes internal paths, is not optimized for production, and doesn't work with extract-text-plugin.

Was just curious if you are currently planning on optimizing the loader for production? If so do you have an approx timeline.

Broken with [email protected]

Hey there. I was just about to test jsxstyle, but missing CSSPropertyOperations breaks the build. I see that you've already fixed this in the repo, but it doesn't seem to be on npm, so consider this a gentle nudge. :)

Thanks for an exciting looking library!

Jest snapshot serializer

If you're using jest snapshots with jsxstyle, this is the current output:

// Jest Snapshot v1, https://goo.gl/fbAQLP


exports[`<Page /> renders Page correctly 1`] = `
<div
      className=" jsxstyle1"
      style={undefined}
    >
      <h1
         className=" jsxstyle2"
         style={undefined}
      >
        Users
      </h1>
</div>
`

Would be helpful to get something like jest-styled-components or jest-glamor-react for jsxstyle.

Output would ideally look like:

.jsxstyle0 {
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
}

<h1
  class="jsxstyle0"
>
  Hello World
</h1>

We would need to write our own matcher and serializer, but then you could use it like so:

// src/setupTests.js
import {matcher, serializer} from 'jest-jsxstyle'

expect.addSnapshotSerializer(serializer)
expect.extend(matcher)
// Something.test.js

import React from 'react'
import renderer from 'react-test-renderer'

test('react-test-renderer', () => {
  const tree = renderer
    .create(
        <Title>Hello World, this is my first jsxstyle component!</Title>,
    )
    .toJSON()

  expect(tree).toMatchSnapshotWithJsxstyle()
})

Any thoughts? Would this help people out?

Pseudo Selector API Proposal

What if jsxstyle's CSS extractor looked out for special reserved prop prefixes such as hover, focus, active (for starters) and added the psuedo selector declaration accordingly. I'm aware that this would not bring jsxstyle to full parity with CSS pseudo-selectors, but it would solve ~80% the challenges with buttons and inputs.

// component.js
<Flex borderColor="red" hoverBorderColor="blue" />
/* extracted css */
.f12345_0 {
  border-color: red;
}
.f12345_0:hover {
  border-color: blue;
}

placeholder rule can cause error in specific browser

screen shot 2017-08-24 at 12 52 18 pm

error is caught in android webview which have user agent: Mozilla/5.0 (Linux; Android 5.1; m3 note Build/LMY47I) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/40.0.2214.127 Mobile Safari/537.36, guess it's chrome for android 40?

pass trough non css properties

I think non-css properties, like a onClick shouldn't be added to the style, but should be passed trough to be handled correctly.

When now declaring a component like:

<Block onClick={() => handleChange(tab)}>{tab}</Block>

You end up with:

image

I think it sucks to have a whitelist due to maintainability (what if the standard releases a new css property name?), but at the same time I think we cannot get around this.

Flex component doesn't get display:flex style

No matter what I try, the <Flex> component just doesn't ever have a display value of flex.

I dove into the source and in autoprefix.js the string display:-webkit-flex;display:-ms-flexbox is being added on to the style definition.

If you try:

<div style={{display: 'flex;display:-webkit-flex;display:-ms-flexbox'}} />

the styles never come through. However:

<div style={{display: 'flex'}} />

works as expected. Is this a react bug or what? Or am I being dumb and have missed something totally obvious?

CSS animation support

CSS animations are one of the last items on my list of reasons to use an external stylesheet.

We could add object property support to the animation shorthand property:

// numeric keys are assumed to be percentages
<Block
  animation={{
    0: { opacity: 0 },
    100: { opacity: 1 },
  }}
/>

// string keys and identifiers passed through as strings
<Block
  animation={{
    from: { opacity: 0 },
    to: { opacity: 1 },
  }}
  animationDuration="600ms"
/>

// string keys passed through as is
<Block
  animation={{
    '0%, 100%': { opacity: 0 },
    50: { opacity: 1 },
  }}
/>

Behind the scenes the animation object would get crunched into @keyframes with a content-hashed name, and the animation prop on the final style object would get replaced with that hashed name as the animationName property.

The only edge case I can think of right now is that the user specifies an animationName as well as an object animation, but that should be pretty easy to handle.

This feature shouldn’t affect perf at all since it’s just an object check for a known property.

Still thinking this over, and it’s not super high priority or launch-blocking for jsxstyle 2.0.

title attribute

If I put a title attribute on a Block tag, it doesn't show up:

will-change for inline styles

If you animate the value of a jsxstyle (e.g. change <Block transform = { someChangingValue } />), you end up with a new style node for every value of someChangingValue. I haven't done extensive performance testing, but my intuition says generating a new style sheet on every frame can't be good for performance; it's less work to set a single style than to instantiate some DOM, inject it into document.head, set the class, and let the browser find and update all the affected nodes. It's also less memory intensive, especially if the developer forgets to call value.toFixed and ends up with thousands of generated style nodes that will likely never be recycled.

Have you considered using willChange as a sentinel for animations? Perhaps willChange should take an array; any property name in that array will be set as an inline style rather than as a style sheet.

I hope I'm not prematurely optimizing; I know these assumptions should be backed up by data. Still, curious what your perspective is.

Jsxstyle plugin missing dependency

Hi,

I'm trying to use the JsxstylePlugin with webpack and it seems that it require the tmp dependency, which is not installed with jsxstyle.

Installing it manually solve the issue, but it should probably come with jsxstyle.

Thanks.

Theming component based on many props

Hi, first of all I would like to say I enjoy using jsxstyle, it has really opened my eyes regarding to styling in React, so thank you for this 👍 .

The problem is I don't know how to best theme a component based on many props.

Let's say we have a Button that I want to style based on 2 props: size and variant
And use it in this way:

<Button>Default</Button>
<Button variant="primary">Primary</Button>
<Button variant="ghost">Ghost</Button>

<Button size="small">Default small</Button>
<Button size="large">Default large</Button>
<Button variant="primary" size="small">Primary small</Button>
<Button variant="primary" size="large">Primary Large</Button>

I have come up with a solution but I would like feedback and if there is a better way.

import React, { PropTypes } from 'react';
import { InlineBlock } from 'jsxstyle';
import { colors } from '../styles';

const Button = ({ children, size, variant, ...props }) => {
  const styles = {
    backgroundColor: colors.gray,
    hoverBackgroundColor: colors.scorpion,
    color: colors.white,
    padding: "5px 15px",
    fontSize: 12
  };

  const variants = {
    primary: {
      backgroundColor: colors.accent,
      hoverBackgroundColor: 'red',
      color: colors.white
    },
    ghost: {
      backgroundColor: 'transparent',
      hoverBackgroundColor: 'transparent',
      color: colors.blue
    }
  };

  const sizes = {
    small: {
      padding: "2px 10px",
      fontSize: 10
    },
    large: {
      padding: "10px 30px",
      fontSize: 16
    }
  };

  if (variant) {
    Object.keys(variants[variant]).forEach(style => {
      styles[style] = variants[variant][style];
    });
  }

  if (size) {
    Object.keys(sizes[size]).forEach(style => {
      styles[style] = sizes[size][style];
    });
  }

  return (
    <InlineBlock
      component="button"
      padding={styles.padding}
      fontSize={styles.fontSize}
      textAlign="center"
      backgroundColor={styles.backgroundColor}
      hoverBackgroundColor={styles.hoverBackgroundColor}
      color={styles.color}
      borderRadius={4}
      border="none"
      props={props}
      children={children}
    />
  );
}

Button.propTypes = {
  children: PropTypes.node.isRequired,
  size: PropTypes.oneOf(['small', 'large']),
  variant: PropTypes.oneOf(['primary', 'ghost'])
};

export default Button;

Thanks ✌️

Comparison to ReactiveNative and React-Style

JSXStyle looks like an awesome solution for ReactJS.

But what is the story if I want to build a solution both for ReactJS and React Native?

There was a comment (twitter?) that if you wanted to reuse your styling information between react js and reactive native that you should use react-style.

What's the possibility of reuse of JSXStyle for React Native, if not in the immediate but at least in the intermediate future?

What problems does React-Style have that JSXStyle does not?

Hover bug: If you mouse in and out of element quickly hover appears but then doesn't go away

As said in the title, if you enter and then leave a component quickly the hover background will come up but then not go away. So only the 'handleMouseEnter' event will fire, and not the 'handleMouseLeave'. To trigger the 'handleMouseLeave' you have to mouse back over the component slowly and then mouse out. I've noticed the same thing if you do a handleMouseDown and handleMouseUp, and then do a fast click. Only the first event will register, and the mouseUp event won't be registered.

Pass non-CSS props as normal props

Since no styles start with on, seems like the API could pass along any props that start with on as normal event handlers, instead of the hacky props={}.

<Block onScroll={handleScroll}/>
// instead of
<Block props={{ onScroll: handleScroll }}/>

This would make wrapping these elements more flexible, like when you need to cloneElement(children)

Direct descendant selector support

Sometimes hovering on a thing or clicking on a thing should affect a child element. Creating a separate stylesheet just for this functionality seems a bit silly to me.

I think there’s a nice way we could expose very limited support for descendant selectors.

Proposal

It’s a two part thing.

Part 1: the parent

If…

  1. a style prop on a jsxstyle element is prefixed with a pseudoclass, and…
  2. said prop is also prefixed with something indicating that it’s styling a child element (Child in this case)…

then add an extra class that has the descendant style plus a unique descendant-y class name.

Code that looks like this:

<Block
  component="a"
  hoverChildColor="blue"
  props={{ href: 'https://google.com' }}>
  ...
</Block>

becomes this JS:

<a
  href="https://google.com"
  className="_jsxstyleClassName1">
   ...
</a>

and this CSS:

._jsxstyleClassName1 > ._childClassName {
  color: blue;
}

Part 2: the child

If a component has a prop that indicates it should be affected by descendant styles, then it receives the child className.

This code:

<Block
  component={SVGAsset}
  props={{ assetName: 'icon/disclosure-arrow-16' }}
  isChild
/>

becomes this JS:

<SVGAsset
  assetName="icon/disclosure-arrow-16"
  className="_jsxstyleClassName2 _childClassName"
/>

Why this sucks

  1. Only supports direct descendants. I haven’t thought of an ✨ elegant ✨ way to get around this yet but I think it is possible to support descendants. The user would have to specify a descendant key and keep track of it, though, and there’s the possibility of collisions if you’ve got more than one person writing component code. We could add utilities to generate a Symbol-like key though I guess. Hmmmmmm.
  2. people will write their code a bit differently so that the thing they want to style is a direct child of the thing they’re interacting with.

Basically, it’s sucks because it’s extremely limited, but that’s also why it’s good IMO.

🤔💡 Thought: we could also add adjacent sibling support this way, too.

Feedback welcome/appreciated.

RFC: Use arrays for media query values

@meyer An idea for a more concise API for media queries:

Current Behavior:

<Block
  mediaQueries={{ sm: '(min-width:700px)',  lg: '(min-width: 1000px)' }}
  color="red"
  smColor="green"
  lgColor="blue"
  margin="2rem"
/>

Desired Functionality:

<Block
  mediaQueries={['(min-width: 400px)', '(min-width: 1000px)' ]}
  color={['red', 'blue', 'green']}
  margin="2rem"     // strings are still the cool
/>

@petehunt

I know I am in the wrong place, but my son has a Masters degree in Education and is thinking of changing careers. He is interested in coding boot camp. He is 26 and very smart and is currently an AD of high school. I was wondering if this was worthwhile. @petehunt

Media query support

We can convert expressions like this to media queries: <Block width={window.innerWidth > 640 ? '100%' : 320} />

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.