GithubHelp home page GithubHelp logo

aphrodite-jss's Introduction

Aphrodite-like API on top of JSS.

This project is a merge of good ideas from aphrodite and JSS. It provides an API of aphrodite but fixes lots of limitations and caveats by using JSS as a rendering engine under the hood.

Good parts from aphrodite.

  • Pretty much like inline styles known from React, except it allows to use the entire CSS.
  • No CSS is generated until css() function invocation. Only the passed rules are converted to a CSS string and injected.
  • Theming is possible without any headache or framework integrations.

Benefits compared to aphrodite.

  • More powerfull rendering abstraction through JSS under the hood. You are using all it's plugins and JSON DSL. To name a few:
    • Children, siblings and any other kinds of selectors. (jss-nested)
    • Global styles, without auto namespacing (jss-global).
  • Immediate render upon css() call invocation. It gives you an access to computed styles right after render, no need to use setTimeout(). It also avoids additional recalcs and repaints, which can cause flickers and general performance overhead.
  • No auto "!important" insertion. You can write a plugin for this though.

Example

import {StyleSheet, css} from 'aphrodite-jss'

const sheet = StyleSheet.create({
  button: {
    border: '1px solid',
    borderRadius: 5,
    fontSize: 'inherit',
    lineHeight: '2.3em',
    padding: '0 1em',
    boxShadow: 'inset 0 1px 0 rgba(255, 255, 255, 0.1)',
    textShadow: '0 -1px 0 rgba(0, 0, 0, 0.25)',
    backgroundRepeat: 'repeat-x',
    color: '#fff',
    fontWeight: 400,
    '& span': {
      marginRight: 5,
      color: '#fff'
    }
  },
  primary: {
    borderColor: '#1177cd #0f6ab6 #0d5c9e',
    backgroundImage: 'linear-gradient(to bottom, #2591ed 0%, #1177cd 100%)',
    backgroundColor: '#1385e5',
    '&:hover': {
      backgroundImage: 'linear-gradient(to bottom, #3c9def 0%, #1385e5 100%)'
    }
  }
})

document.body.innerHTML = `
  <button class="${css(sheet.button, sheet.primary)}">
    <span>&#10004;</span>Primary
  </button>
`

API

Create style sheet.

StyleSheet.create(styles)

Create function doesn't render anything, it just registers your styles.

Returns an object, where key names correspond the original styles obejct.

Inject rules.

css(rule1, [rule2], [rule3], ...)

Injects a previously defined rule to the dom. This is done in sync, so the CSS rule is immediately available.

Returns a class name.

Styles format.

The format for styles is defined in jss. Aprodisiac uses jss-preset-default, so all default presets are already in place.

Customizing JSS.

aphroditeJss(jss, [options])

You can pass your own JSS instance with your custom setup.

Returns aphrodite's interface.

import aphroditeJss from 'aphrodite-jss'
import {create} from 'jss'

const {css, StyleSheet} = aphroditeJss(create())

Serverside Rendering.

There are 2 functions you need to know - toString() and reset(). As aphrodite-jss can not know that you are rendering a new response, you need to get the CSS (toString()) when you are processing the first request and call reset() to clean up the styles your current page has produced.

import {toString, reset} from 'aphrodite-jss'

function render() {
  const app = renderApp()
  const css = toString()
  reset()

  return `
    <head>
      <style>
        ${css}
      </style>
    <head>
    <body>
      ${app}
    </body>
  `
}

License

MIT

aphrodite-jss's People

Contributors

asvetliakov avatar jedwards1211 avatar kof avatar msnider avatar pyrrho avatar spadin avatar typical000 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aphrodite-jss's Issues

Add more tests

We need to add tests here to ensure JSS updates don't break this package. Anyone interested to help?

@keyframes don't work

Hello! I tried to add simple keyframes animation to my styles with aphrodite-jss.
I tried this:

StyleSheet.create((() => {
  ... ... ...
  '@keyframes anim': {
    from: {opacity: 0},
    to: {opacity: 1}
  },
  animationName: 'anim',
  animationDuration: '4s'
  ...

Also:

animation: anim 1s ease-out;

But it didn't work.
I'm using Chrome 60 and it doesn't need webkit prefix, for example.

Am I wrong with the syntax or this is a bug?

Suggested labels: question; example & if this is bug - bug

Alternate name for the project?

Hi,

Please don't take this the wrong way: as clever as "Aphrodisiac" is, the name is awkward at best. In particular, can be offputting to others when explaining the tool and its benefits. It's hard to credibly demonstrate this when the name is such a deterrent. (Yes, this actually happened in a meeting!)

May I suggest "Venus", the Roman goddess of love, or Aphrodite's counterpart? Thanks for your consideration.

Broken with new versions of JSS?

@phyllisstein commented on Thu May 04 2017

Hey there! I'm getting an error when calling aphrodite-jss's reset() function after server-side rendering:

TypeError: Cannot read property 'remove' of undefined
    at reset (/Users/daniel/Repos/Ignota/ignota1/node_modules/aphrodite-jss/lib/index.js:78:15)
    at module.exports../server.js.app.use.ctx (/Users/daniel/Repos/Ignota/ignota1/dist/app.js:11504:29)
    at dispatch (/Users/daniel/Repos/Ignota/ignota1/node_modules/koa-compose/index.js:44:32)
    at next (/Users/daniel/Repos/Ignota/ignota1/node_modules/koa-compose/index.js:45:18)
    at Object.<anonymous> (/Users/daniel/Repos/Ignota/ignota1/dist/app.js:11477:12)
    at boundThen (eval at processIncludes (/Users/daniel/Repos/Ignota/ignota1/node_modules/nodent-runtime/runtime.js:36:12), <anonymous>:3:4765)
From previous event:
    at module.exports../server.js.app.use (/Users/daniel/Repos/Ignota/ignota1/dist/app.js:11471:24)
    at dispatch (/Users/daniel/Repos/Ignota/ignota1/node_modules/koa-compose/index.js:44:32)
    at /Users/daniel/Repos/Ignota/ignota1/node_modules/koa-compose/index.js:36:12
    at Server.handleRequest (/Users/daniel/Repos/Ignota/ignota1/node_modules/koa/lib/application.js:136:14)
    at emitTwo (events.js:111:20)
    at Server.emit (events.js:194:7)
    at parserOnIncoming (_http_server.js:563:12)
    at HTTPParser.parserOnHeadersComplete (_http_common.js:99:23)

It seems like the JSS API might have changed and broken aphrodite-jss. I'm also seeing some strange stuff in the Web Inspector---empty <style> tags and grayed-out styles---that could conceivably be related:

screen shot 1

Are there any plans to update the package? I'm trying a switch to react-jss, but its story around merging styles at runtime---e.g., when a parent component wants to pass styles to a child---seems a little less clear-cut and more dependent on damnable specificity.

Thanks in advance for your help, and thanks for all your work on JSS!


@kof commented on Thu May 04 2017

Looks like a bug, do you like to try fixing it?


@phyllisstein commented on Fri May 05 2017

I managed to fix the server-side rendering API, which was a quick one-line change, in #12, but unfortunately don't have any insight yet into why styles are being rendered as null. I'll dig a little more but I'm not sure I even know where to start.


@kof commented on Fri May 12 2017

@phyllisstein any luck?


@phyllisstein commented on Fri May 12 2017

I think so? Left a note here: #12 (comment).

Unable to render media queries

Hey guys.

I'm not sure why but I'm unable to render media queries.

Can I not render my media queries like this?

css(StyleSheet.create({
  base: {
    '@media only screen and (min-width: 1024px)': {
      width: px(20),
    }
  }
}).base)

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on all branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.

Since we didn’t receive a CI status on the greenkeeper/initial branch, it’s possible that you don’t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/.

Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please delete the greenkeeper/initial branch in this repository, and then remove and re-add this repository to the Greenkeeper App’s white list on Github. You'll find this list on your repo or organization’s settings page, under Installed GitHub Apps.

Can't edit styles in Chrome

Just curious, is this avoidable?

image

I can't edit any JSS styles because they are greyed out for some reason.

merge is one-level

Given

const s = StyleSheet.create({                                                   
  red: { 
    '&.active': {                                                               
      width: '100px',                                                           
    }                                                                           
  },                                                                            
  blue: {
    '&.active': {                                                               
      height: '100px',                                                          
    }                                                                           
  },                                                                            
})  

<div className={cx(css(s.red, s.blue), 'active')}>                 

Got

.red-3089191041--blue-1941479325.active {
  height: 100px;
}

Expect

.red-3089191041--blue-1941479325.active {
  width: 100px;
  height: 100px;
}

Keyframes

Attempting to do a simple keyframe animation, just curious how this would work through aphrodite-jss.

Media queries

Hey I'm playing around with using this in a project (I replaced aphrodite because I wanted JSS plugins). I was hoping to start a discussion about media queries.

Do you have any ideas on how this would be done?

Also, somewhat related.. I've tweaked the css function a bit to allow something like css(styles.foo, css(styles.bar)), but it relies on an ugly hack which essentially caches the original object name and rule set. I'd love to submit a PR for something like that, but would be interested in hearing about the media query approach because it will most likely break my naive changes.

[bug?] Warning: [JSS] Could not find the referenced rule logoAndCopyright in aphrodite-jss.

I've got some styles using jss-nested with $classname syntax:

const style = StyleSheet.create({
  footer: {
    // ...

    '& $logoAndCopyright': {
      // ...
    },
  },

  logoAndCopyright: {},
})

then when I use it,

css(style.logoAndCopyright)

I get an error like

Warning: [JSS] Could not find the referenced rule logoAndCopyright in aphrodite-jss.

Full output:

Warning: [JSS] Could not find the referenced rule logoAndCopyright in aphrodite-jss.
  | warning | @ | _app.js:26063
-- | -- | -- | --
  | (anonymous) | @ | _app.js:1331
  | onProcessStyle | @ | _app.js:1393
  | onProcessStyle | @ | _app.js:3186
  | onProcessRule | @ | _app.js:3171
  | addRule | @ | _app.js:3759
  | css | @ | _app.js:211
  | render | @ | _app.js:26170
  | finishClassComponent | @ | main.js:24135
  | updateClassComponent | @ | main.js:24097
  | beginWork | @ | main.js:24766
  | performUnitOfWork | @ | main.js:26805
  | workLoop | @ | main.js:26844
  | renderRoot | @ | main.js:26884
  | performWorkOnRoot | @ | main.js:27502
  | performWork | @ | main.js:27424
  | performSyncWork | @ | main.js:27396
  | requestWork | @ | main.js:27296
  | scheduleWork$1 | @ | main.js:27160
  | scheduleRootUpdate | @ | main.js:27727
  | updateContainerAtExpirationTime | @ | main.js:27754
  | updateContainer | @ | main.js:27781
  | module.exports.webpackJsonp.../node_modules/react-dom/cjs/react-dom.development.js.ReactRoot.render | @ | main.js:28064
  | (anonymous) | @ | main.js:28204
  | unbatchedUpdates | @ | main.js:27621
  | legacyRenderSubtreeIntoContainer | @ | main.js:28200
  | hydrate | @ | main.js:28256
  | renderReactElement | @ | main.js:6559
  | _callee5$ | @ | main.js:6534
  | tryCatch | @ | main.js:30206
  | invoke | @ | main.js:30440
  | prototype.(anonymous function) | @ | main.js:30258
  | step | @ | main.js:166
  | _next | @ | main.js:181
  | (anonymous) | @ | main.js:188
  | F | @ | main.js:1500
  | (anonymous) | @ | main.js:161
  | _doRender | @ | main.js:6551
  | doRender | @ | main.js:6433
  | _callee2$ | @ | main.js:6339
  | tryCatch | @ | main.js:30206
  | invoke | @ | main.js:30440
  | prototype.(anonymous function) | @ | main.js:30258
  | step | @ | main.js:166
  | _next | @ | main.js:181
  | (anonymous) | @ | main.js:188
  | F | @ | main.js:1500
  | (anonymous) | @ | main.js:161
  | _render | @ | main.js:6369
  | render | @ | main.js:6311
  | _callee$ | @ | main.js:6290
  | tryCatch | @ | main.js:30206
  | invoke | @ | main.js:30440
  | prototype.(anonymous function) | @ | main.js:30258
  | step | @ | main.js:166
  | _next | @ | main.js:181
  | Promise.then (async) |   |  
  | step | @ | main.js:176
  | _next | @ | main.js:181
  | Promise.then (async) |   |  
  | step | @ | main.js:176
  | _next | @ | main.js:181
  | Promise.then (async) |   |  
  | step | @ | main.js:176
  | _next | @ | main.js:181
  | (anonymous) | @ | main.js:188
  | F | @ | main.js:1500
  | (anonymous) | @ | main.js:161
  | ../node_modules/next/dist/client/next-dev.js | @ | main.js:6592
  | __webpack_require__ | @ | manifest.js:715
  | fn | @ | manifest.js:118
  | 0 | @ | main.js:35329
  | __webpack_require__ | @ | manifest.js:715
  | webpackJsonpCallback | @ | manifest.js:26
  | (anonymous) | @ | main.js:2

Using with React

If we use this with React, the render() method may call css(rule1, rule2) multiple times. Is this okay?

How to Dynamically Theme Components

The docs say theming can be done without headaches but I am having trouble doing just that. What is the recommended approach to theming?

I am currently using jss and react and wrote some mods so I can do:

const styles = (theme) => ({
  button: {
    color: theme.palette.primary
  }
})

@injectSheet(styles)
class Button extends React.Component {
  render () {
    const { s, label } = this.props
    return (
      <button className={s.button}>
        <div>{ label }</div>
      </button>
    )
  }
}

This way I can also dynamically modify the theme and have changes instantly appear.
Change Theme -> HOC detects change -> HOC updates its WrappedComponent

Problem with this approach, this lib, and react, is that if the theme is changed then every style needs to be recalculated. In order to update react we could simply update the stylesheet, and the DOM would take care of everything. But this is only possible if the classnames have not changed. If they do change the react comps need updating.

My thoughts on how this could work with your lib and without integrating with React:
Change Theme -> Stylesheet.create (yours wrapped by my code) detects theme change -> triggers a stylesheet update -> DOM automatically updates everything

I believe that for this to work the classnames must remain the same.

If they can not, then I require an HOC to pass new classnames down as props which will trigger the React update. Of course if this is the only way then there is no place for this lib + react + dynamic theming. Correct?

Any ideas?

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.