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 Introduction

jsxstyle & friends

This repository is the monorepo for runtime versions jsxstyle as well as a few tools designed to be used with jsxstyle.

Package Description
jsxstyle stylable React/Preact components
jsxstyle/webpack-plugin webpack plugin that extracts static styles from jsxstyle components at build time

jsxstyle Sauce Test Status

jsxstyle is an inline style system for React and Preact. It provides a best-in-class developer experience without sacrificing performance.

Styles are written inline on a special set of components exported by jsxstyle. Inline styles on these components are converted to CSS rules and added to the document right as they’re needed.

With jsxstyle, your component code looks like this:

<Row padding={15}>
  <Block
    backgroundColor="#EEE"
    boxShadow="inset 0 0 0 1px rgba(0,0,0,0.15)"
    borderRadius={5}
    height={64}
    width={64}
    marginRight={15}
    backgroundSize="contain"
    backgroundImage="url(http://graph.facebook.com/justinbieber/picture?type=large)"
  />
  <Col fontFamily="sans-serif" fontSize={16} lineHeight="24px">
    <Block fontWeight={600}>Justin Bieber</Block>
    <Block fontStyle="italic">Canadian</Block>
  </Col>
</Row>

⚡️ Style as fast as you can think.

Jumping between JS and CSS in your editor is no longer necessary. Since style are inline, you can determine at a glance exactly how an element is styled. jsxstyle frees you up to do what you do best—write styles.

✅ Inline styles done right.

Just because styles are written inline doesn’t mean they stay inline. jsxstyle’s approach to inline styles ensures that a best-in-class developer experience comes with no performance cost.

😪 No more naming fatigue.

Naming components is hard enough, and there are only so many synonyms for “wrapper”. jsxstyle provides a set of stylable components, each with a few default styles set. These primitive stylable components form a set of building blocks that you can reuse throughout your application. You can still create named stylable components if you wish, by utilizing a paradigm you’re already familiar with: composition. No funky syntax necessary:

const RedBlock = (props) => <Block {...props} color="red" />;

🍱 Scoped styles right out the box.

Styles written on jsxstyle components are scoped to component instances instead of abstract reusable class names. That’s not to say we’ve abandoned class names, though; styles on jsxstyle components are extracted into CSS rules and assigned a hashed, content-based class name that is intentionally unlike a human-written name.

👯 Team friendly by design.

jsxstyle’s mental model is easy to teach and easy to learn, which means onboarding new frontend contributors takes seconds, not hours. Since styles applied by jsxstyle are scoped to component instances, frontend contributors don’t need a complete knowledge of the system in order to be 100% productive right from the start.

🛠 Powerful build-time optimizations.

Styles written inline on a set of components from a known source can very easily be statically analyzed, which opens up new possibilities for tooling and optimization. One such optimization is the built-in webpack-plugin that extracts static styles from jsxstyle components at build time. This plugin reduces and in some cases entirely removes the need for runtime jsxstyle.

Getting started

Install the jsxstyle package with your preferred node package manager. Components for React can be imported from jsxstyle, and components for Preact can be imported from jsxstyle/preact.

jsxstyle provides the following seven components:

Component Default styles
Block display: block;
Inline display: inline;
InlineBlock display: inline-block;
Row display: flex; flex-direction: row;
Col display: flex; flex-direction: column;
InlineRow display: inline-flex; flex-direction: row;
InlineCol display: inline-flex; flex-direction: column;
Grid display: grid;
Box No default styles

Most props passed to these components are assumed to be CSS properties. There are some exceptions to this rule:

  • component: the underlying HTML tag or component to render. Defaults to 'div'.
  • props: an object of props to pass directly to the underlying tag or component.
  • mediaQueries: an object of media query strings keyed by prefix. More on that below.

Additionally, the following component props can also be set at the top level if the component you specify supports these props:

  • checked
  • className
  • href
  • id
  • name
  • placeholder
  • style
  • type
  • value
  • Any event handler prop starting with on

This list is fairly arbitrary. If there’s a prop that you think is missing, feel free to request an addition to this list.

Features

Pseudoelements and pseudoclasses

To specify a pseudoelement or pseudoclass on a style property, prefix the prop with the name of the applicable pseudoelement or pseudoclass. If you’d like to specify a pseudoelement and a pseudoclass for a style prop, start with the pseudoclass—i.e., hoverPlaceholderColor, not placeholderHoverColor.

import { Block } from 'jsxstyle/preact';

<Block
  component="input"
  color="#888"
  activeColor="#333"
  placeholderColor="#BBB"
/>;
Supported Pseudoclasses Supported Pseudoelements
active, checked, disabled, empty, enabled, focus, hover, invalid, link, required, target, valid placeholder, selection, before, after

Media queries

Define a mediaQueries property with an object of media queries keyed by whatever prefixes you want to use. Prepend these media query keys to any style props that should be contained within media query blocks. Note that only one media query prefix can be applied at a time.

<Block
  mediaQueries={{
    sm: 'screen and (max-width: 640px)',
    lg: 'screen and (min-width: 1280px)',
  }}
  color="red"
  smColor="blue"
  lgColor="green"
/>

useMatchMedia hook

jsxstyle exports a hook, useMatchMedia, that enables the developer to subscribe to media query change events and react accordingly. Here’s the hook in action:

import { Block, useMatchMedia } from 'jsxstyle';

export const RedOrBlueComponent = ({ children }) => {
  const isSmallScreen = useMatchMedia('screen and (max-width: 800px)');

  // text color is red when viewport <= 800px, blue when viewport > 800px
  return <Block color={isSmallScreen ? 'red' : 'blue'}>{children}</Block>;
};

When this hook is used in combination with jsxstyle’s webpack plugin, prop values will be extracted if the prop passed to the component is a ternary and if the alternate and consequent values of the ternary are both static.


Convenient animation support

You can define an animation inline using object syntax, where the key is the specific keyframe name and the value is an object of styles:

<Block
  animation={{
    from: { opacity: 0 },
    to: { opacity: 1 },
  }}
  animationDuration="600ms"
  animationDirection="alternate"
/>

Shorthand properties for same-axis padding and margin

You can set margin or padding on the same axis—either horizontal or vertical—by setting marginH/marginV or paddingH/paddingV.

Note: shortcut props should not be used with in combination with -Top/Left/Bottom/Right variants. Prop names on jsxstyle components are sorted alphabetically before the styles are stringified, which means that styles will be applied alphabetically.


FAQs

Why write styles inline with jsxstyle?

Writing styles inline does away with name fatigue and constantly bouncing between CSS and component code in your editor, and jsxstyle’s approach to inline styles ensures that a best-in-class developer experience comes with no performance cost.
  1. Naming things is hard.

    jsxstyle manages CSS and corresponding generated class names, which means that what those class names actually are becomes unimportant. jsxstyle can generate short, production-optimized class names and retain a mapping of those class names to corresponding style objects. All you have to do is worry about actual style properties.

  2. Jumping between JS and CSS in your editor wastes time.

    There’s no need to constantly jump between components and the CSS file(s) that define how those components are styled because styles are defined right at the component level. CSS has always been a language that describes what HTML elements look like. With jsxstyle, those descriptions are right where you need them.

  3. Styles are… inline.

    With inline styles, any frontend contributor can look at an element and know in a matter of seconds exactly how it’s styled. Inline styles describe an element’s appearance better than CSS classes ever could, and because you don’t have to worry about the class abstraction, there’s no fear of you or another frontend contributor taking a pure CSS class (like .red { color: tomato }) and corrupting it by modifying its styles.

    Also, because styles are inline, when you delete a component, you delete its style properties along with it. Dead CSS is no longer a concern.

  4. Styles written inline don’t remain inline.

    jsxstyle is first and foremost syntax for styling components at a particular scope. The styles you specify on jsxstyle components are added to the document and a div or component you specify is output with a class name that points to the added styles.

  5. Building tooling around inline styles is simple and straightforward.

    Statically analyzing inline styles on known components is trivial. Most of the styles you’ll end up writing on jsxstyle primitive components are static. Once you’re done perusing this README, check out jsxstyle/webpack-plugin. It’s a webpack plugin that, at build time, extracts static styles defined on jsxstyle components into separate CSS files. This plugin reduces and in some cases entirely removes the need for runtime jsxstyle. jsxstyle becomes nothing more than syntactic sugar for styling components, much like how JSX itself is syntactic sugar for nested function calls. Dude, that’s next level!

Why use jsxstyle instead of BEM/SMACSS/OOCSS/etc.?

jsxstyle provides all the benefits of a CSS class naming/organization system, but without the system.

Writing CSS at scale is hard. Overly specific selectors cause specificity collisions. More generic selectors cause overstyling. Being a responsible frontend contributor in a shared codebase means you have to have a working knowledge of the system before you can contribute new code without introducing redundancies or errors.

Countless systems have been developed to either solve or circumvent inherent problems with writing CSS in a team environment. Most of these systems attempt to solve the complexity of writing CSS with even more complex systems. Once a system is implemented it has to be closely adhered to. CSS systems are fantastic in theory, but in practice, a CSS system is only as good as the most negligent frontend contributor on your team.

jsxstyle provides all the benefits of a good CSS class-naming system, with the added benefit of not having to learn or remember a CSS class-naming system.

  • No more specificity issues, collisions, accidental overstyling, or inscrutable class names.

    jsxstyle manages class names and generated styles, leaving you to do what you do best… write styles. Selector complexity is a thing of the past. Each jsxstyle component gets a single class name based on the inline styles specified on the component. The class name is reused when repeat instances of that set of style props are encountered.

  • No more bikeshedding!

    No more extended discussions about which CSS class naming strategy is best! I cannot emphasize enough how much time and mental energy this saves. Code review is simple as well. CSS-related nits only involve actual style properties. Conversations about how to style a thing begin and end with the actual CSS properties that need to be written.

  • Onboarding new frontend contributors takes seconds, not hours.

    A knowledge of existing styles is not required for a new frontend contributor to be 100% productive right from the start. In codebases without jsxstyle, in order for someone to be able to contribute, they usually have to know what styles to put where and where to look to put new styles. There are usually mixins and variables they don’t know exist because they don’t yet “know their way around the place”. With jsxstyle, you’re just writing styles on components.

Can I use jsxstyle with existing CSS?

Yes! jsxstyle is designed to work alongside existing styles and style systems. In order to avoid class name collisions, class names generated by jsxstyle are hashed names that are intentionally unlike class names that a human would write. As far as specificity is concerned, jsxstyle uses single class names as selectors, which makes overriding styles in your existing system easy (though not recommended).

Does jsxstyle support server rendering?

Yep!

jsxstyle exports a cache object with a few functions that make adding support for server rendering a breeze. Two things you need to know:

  1. In a server environment, the function that adds styles to the document is a noop, but it can be replaced with any arbitrary function. When server rendering, you can aggregate jsxstyle-injected styles when rendering your app to a string, and then add those styles to the response you send to the client.

  2. jsxstyle builds a cache of styles that have been added to the document to ensure they’re added exactly once. When server rendering, this cache will need to be reset between each render.

Here’s a minimal (untested!) example of jsxstyle server rendering with Koa:

import { cache } from 'jsxstyle';
import * as Koa from 'koa';
import * as React from 'react';
import { renderToString } from 'react-dom';

import App from './App';

// aggregate styles as they’re added to the document
let styles = '';
cache.injectOptions({
  onInsertRule(css) {
    styles += css;
  },
});

const app = new Koa();
app.use(async (ctx) => {
  // Reset cache and style string before each call to `renderToString`
  cache.reset();
  styles = '';
  const html = renderToString(<App path={ctx.request.path} />);

  ctx.body = `<!doctype html>
<style>${styles}</style>
<div id=".app-root">${html}</div>
<script src="/bundle.js"></script>
`;
});

Does jsxstyle support autoprefixing?

Runtime jsxstyle does not bundle an autoprefixer, but autoprefixing is easily doable if you use webpack. We recommend combining jsxstyle’s built-in webpack plugin with a CSS loader that handles provides autoprefixing. At Smyte, we use postcss-loader with postcss-cssnext. Not using webpack and you’d like to see runtime autoprefixing supported? Open an issue and let us know!

What about global styles?

jsxstyle only manages styles written on jsxstyle components. Where you put global styles is entirely up to you. At Smyte, we use a separate shared style sheet that contains a few reset styles.

Browser support

jsxstyle is tested on every push in a wide array of browsers, both old and new. Shout out to Sauce Labs for making cross browser testing free for open source projects. Sauce Labs is shockingly easy to integrate with other services. I’m not gonna say it’s simple to get set up, because it’s not, but once it’s up and running, damn, it’s easy. They even make an SVG test matrix you can drop into your README:

Sauce Test Status

Contributing

Got an idea for jsxstyle? Did you encounter a bug? Open an issue and let’s talk it through. PRs welcome too!

Alternatives

So you don’t think jsxstyle is the thing for you? That’s quite alright. It’s a good time to be picky about exactly how and where your styles are written. We’re in the golden age of component-based web frameworks, and a lot of ancient “best practices” that were set in place by the old guard are being rethought, to everyone’s benefit. It’s a weird and exciting time to be making stuff for the web.

Sorting through the myriad CSS-in-JS solutions out there can get tiring, but there are a few projects out there that have stuck out to me:

  • Tachyons by Adam Morse enables a lot of the the same benefits as jsxstyle but allows you to still use CSS classes. I love the “no new CSS” concept behind Tachyons. Tachyons elegantly solves the issues that Adam covers in his excellent blog post on scalable CSS.

  • Rebass by Brent Jackson is “a functional React UI component library, built with styled-components”. Rebass has similar API to jsxstyle, but is a bit more opinionated when it comes to separation of presentation and logic. Syntactically it’s more compact, and it has a few more tricks. We don’t like tricks over here at jsxstyle dot com but we do give Rebass two meaty thumbs up.

styled-components and (more recently) emotion have both gained serious traction in the frontend JS community. I can’t do either system justice in a single sentence and I’ve never used either system, but they both seem like reasonable jsxstyle alternatives that embrace the funky things you can do with tagged template literals.

jsxstyle's People

Contributors

7rulnik avatar antialias avatar appsforartists avatar artnez avatar chenxsan avatar danielberndt avatar github-actions[bot] avatar l42y avatar lettertwo avatar meyer avatar mjackson avatar petehunt avatar tannerwelsh avatar threepointone avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jsxstyle's Issues

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.

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?

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.

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?

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?

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.

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.

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.

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 ✌️

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!

@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

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.

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.

title attribute

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

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

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;
}

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.

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

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'; }

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
/>

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.

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.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.

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?

Media query support

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

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

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)

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.