jsxstyle / jsxstyle Goto Github PK
View Code? Open in Web Editor NEWInline style system for JSX
Home Page: https://jsx.style/
License: Other
Inline style system for JSX
Home Page: https://jsx.style/
License: Other
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:
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.
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?
paddingVertical
, paddingHoriztonal
, marginVertical
, marginHorizontal
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;
}
Getting a strange error, any idea where this could be coming from? Super simple setup...
import React, {Component} from 'react'
import {Block} from 'jsxstyle'
class Detail extends Component {
render(){
return(
<Block>Content Test</Block>
)
}
}
export default DetailView
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 MeI figure if the show attribute is omitted, it defaults to true.
E.g. ul
, li
, etc.
We can convert expressions like this to media queries: <Block width={window.innerWidth > 640 ? '100%' : 320} />
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! :)
There’s nothing terribly React-specific in jsxstyle. Supporting other frameworks shouldn’t be too difficult.
Discovered that I can do this -
<Flex props={{onClick: ()=> alert('event handlers!') }}/>
Very cool! please add a line to the docs to let people know? Please and thanks!
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
The main pseudoclass I miss right now is :placeholder
, but there are quite a few more we don’t support: https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes
<Block
component="input"
props={{ type: 'text', placeholder: 'username' }}
color="#444"
placeholderColor="#AAA"
fontWeight={500}
placeholderFontWeight={600}
/>
I might be missing something but is this possible with jsxstyle?
In order to guarantee that jsxstyle works without issue in IE9 and better, we should test a small app built using jsxstyle in a real browser with one of these services.
{ Cannot find module 'react/lib/CSSPropertyOperations'
at $root/node_modules/jsxstyle/lib/createCSS.js:3:29 code: 'MODULE_NOT_FOUND' }
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?
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 :) )
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.
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?
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 !
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!
Would this work instead? https://github.com/postcss/postcss-js
If you haven't already considered this and it seems like something interesting and useful to you, I'm willing to test it and make a PR to include it.
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'; }
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.
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.
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
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)
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.
@meyer An idea for a more concise API for media queries:
<Block
mediaQueries={{ sm: '(min-width:700px)', lg: '(min-width: 1000px)' }}
color="red"
smColor="green"
lgColor="blue"
margin="2rem"
/>
<Block
mediaQueries={['(min-width: 400px)', '(min-width: 1000px)' ]}
color={['red', 'blue', 'green']}
margin="2rem" // strings are still the cool
/>
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.
It would be nice to do this:
<Block onClick={this.onRowClick}>Click Me</Block>
instead of this:
<Block props={{onClick: this.onRowClick }}>Click Me</Block>
I think we can get away with just Inline
, FlexRow
, and FlexCol
I’m a big fan of rebass’s fractional width feature.
// wired
<Block width={3 / 5} />
// tired
<Block width={3 / 5 * 100 + '%'} />
Pros:
Cons:
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)
If I put a title attribute on a Block tag, it doesn't show up:
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.
It’s a two part thing.
If…
jsxstyle
element is prefixed with a pseudoclass, and…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;
}
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"
/>
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.
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.
I saw an image showing this feature on Reddit, but it doesn't look like jsxstyle does this out of the box. How do I activate this?
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.
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.
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 ✌️
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.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.