-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Emotion Native #759
Emotion Native #759
Conversation
Almost done! Just need some work on flow types. |
I don't know why there are some flow types error in other packages (I haven't touch any). Plus, typescript tests seems to be broken. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking great!!
package.json
Outdated
"version": "7.0.13", | ||
"scripts": { | ||
"build:watch": "node scripts/build/watch", | ||
"build": "node scripts/build", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you be able to revert these formatting changes in the package.jsons?
@@ -0,0 +1,26 @@ | |||
{ | |||
"name": "primitives-core", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be @emotion/primitives-core
and it should be imported as @emotion/primitives-core
packages/primitives/package.json
Outdated
"babel-plugin-emotion": "^9.2.5", | ||
"css-to-react-native": "^2.2.0" | ||
"primitives-core": "1.0.0-beta" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@emotion/primitives-core
packages/primitives/test/css.test.js
Outdated
@@ -1,5 +1,5 @@ | |||
// @flow | |||
import { css } from '@emotion/primitives' | |||
import { css } from '../src' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be @emotion/primitives
, all package names are aliased to their src.
@@ -8,7 +8,7 @@ import reactPrimitives from 'react-primitives' | |||
import { ThemeProvider } from 'emotion-theming' | |||
import { render, unmountComponentAtNode } from 'react-dom' | |||
|
|||
import styled from '@emotion/primitives' | |||
import styled from '../src' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above
@@ -1,7 +1,7 @@ | |||
// @flow | |||
import '../mock-primitives' | |||
import * as React from 'react' | |||
import styled, { css } from '@emotion/primitives' | |||
import styled, { css } from '../../src' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above
packages/native/package.json
Outdated
@@ -0,0 +1,23 @@ | |||
{ | |||
"name": "emotion-native", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@emotion/native
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉
packages/native/src/index.js
Outdated
|
||
const css = createCss(reactNative.StyleSheet) | ||
|
||
const components = `ActivityIndicator ActivityIndicatorIOS ART Button DatePickerIOS DrawerLayoutAndroid |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you make this into an array since it's easier to read and there's no need to split
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure! No issues.
|
||
let returnArguments = (...args) => args | ||
|
||
describe('Emotion native css', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not really sure if we need all these tests duplicated, maybe it could just be a small smoke test to make sure css works
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking of this too! I'll need some help over here so will ping you later when I comeback to this after fixing basic stuff.
packages/primitives-core/README.md
Outdated
|
||
## Introduction | ||
|
||
This package contains some shared utilities which are consumed by `@emotion/primitives` and `@emotion/native` for styling and rendering components. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a note saying that most people won't need this package and should use @emotion/primitives
and @emotion/native
?
|
||
export function createStyled( | ||
StyleSheet: Object, | ||
getShouldForwardProp: Function = (cmp: React.ElementType): Function => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be getShouldForwardProp: (cmp: React.ElementType) => (prop: string) => boolean = () => defaultPickTest
and could you make this argument into an object so that if there needs to be more options in the future it's easier?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup! I'll fix it
packages/primitives/src/styled.js
Outdated
|
||
function isPrimitiveComponent(component: React.ElementType) { | ||
function shouldForwardProp(component: React.ElementType) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be called getShouldForwardProp
// render(<Text innerRef={ref} id="something" />, rootNode) | ||
// expect(ref.current).toBe(rootNode.querySelector('#something')) | ||
// unmountComponentAtNode(rootNode) | ||
// }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason this was commented out?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm.. can't recall may be its related to emotion primitives PR work. Anyway, I'll uncomment and update the test.
packages/primitives-core/README.md
Outdated
|
||
### `createStyled(StyleSheet)` | ||
|
||
`createStyled` also accepts a platform specific `StyleSheet` method for creating styles, and returns a styled component. You can assign primitives to it for example - `View` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"returns a styled component", createStyled returns a function that returns a function that returns a styled component right?
packages/native/README.md
Outdated
|
||
## Theming | ||
|
||
Use `emotion-theming` for theming support. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An example maybe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm... That'd be great! I'll add it
packages/native/README.md
Outdated
AppRegistry.registerComponent('ExampleApp', () => App); | ||
``` | ||
|
||
The API surface remains same for `@emotion/native` which means you can use all the API methods similar to `emotion`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reading this is confusing, the same as what? emotion? or @emotion/primitives
? and you can't use everything that emotion
has, e.g. keyframes
and injectGlobal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops! I missed those parts of emotion API. I'll fix it.
I also noticed some flow types errors for CreateStyled in @emotion on running yarn flow. |
if you merge from master, those flow errors should be fixed. |
I pulled latest changes from master and now getting this error on running
Any ideas ? Except this, all tests are updated and are passing. |
@nitin42 run |
Still no luck! Getting that same error on running |
Thanks @tkh44 for the review! |
"dependencies": { | ||
"@emotion/primitives-core": "1.0.0" | ||
}, | ||
"peerDependencies": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldnt a peer on react be here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops! Done ✅
color: hotpink; | ||
`; | ||
|
||
export default class App extends React.Component { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indentation is different here than in other examples (in this file), this could be enforced with prettier + lint-staged on precommit hook (with husky) as it can handle .md
too, cc @mitchellhamilton
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That'd be great. This will also resolve all the formatting issues!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Andarist If you could submit a PR for it, that would be great!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll try to remember to do that later :)
packages/native/src/index.js
Outdated
|
||
export { css } | ||
|
||
export default /* #__PURE__ */ styled |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this doesnt make much sense here, #__PURE__
comments are useful for call expressions, this is just exported identifier
Not sure what actual value it gives in context of react-native (it's not that much bytes-constrained as web), it certainly won't hurt, but would have to be used differently.
I would convert this to:
export default components.reduce((acc, comp) =>
Object.defineProperty(acc, comp, {
enumerable: true,
configurable: false,
get() {
return styled(reactNative[comp])
}
})
, styled)
This would make it self contained expression that can be more safely annotated with PURE.
You could also use my plugin to insert those PURE annotations automatically - https://github.com/Andarist/babel-plugin-annotate-pure-calls , but ofc that's not obligatory 😉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense. I'll refactor the code to use your solution.
|
||
import { styled } from './styled' | ||
|
||
const css = createCss(reactNative.StyleSheet) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this could be annotated with PURE
/** | ||
* a function that returns a styled component which render styles in React Native | ||
*/ | ||
let styled = createStyled(StyleSheet) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is also a good candidate for PURE
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are there any side-effects of using PURE here ?
packages/primitives-core/README.md
Outdated
|
||
### `createStyled(StyleSheet)` | ||
|
||
`createStyled` also accepts a platform specific `StyleSheet` method for creating styles, and returns a function that returns a function that returns a styled component. You can assign primitives to it for example - `View` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and returns a function that returns a function that returns a styled component
while this is technically correct, it sounds like a gibberish 😅 could we rephrase it ?
|
||
export function createStyled( | ||
StyleSheet: Object, | ||
{ getShouldForwardProp = () => defaultPickTest }: options = {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've noticed that this API differs from web one. Regular emotion accepts shouldForwardProp
- is there any reason why this is different here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the whole createStyled
also differs from regular create-emotion-styled
API which accepts whole emotion (created upfront with create-emotion
). It seems to me that react-native equivalent would be
const css = createCss(StyleSheet)
const styled = createStyled(css)
or
const css = createCss(StyleSheet)
const styled = createStyled({ css })
I'm not sure if native version has some other API than css
/styled
(web one has), so I'm not sure which one would be more appropriate here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
regarding shouldForwardProp
- I think I've found the answer, this is used at 1 layer above than regular shouldForwardProp
, right? would be good to support normal shouldForwardProp
, but it can also be added later (maybe create some kind of TODO list of things that could be added to achieve parity with regular emotion
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The API here differs because, we may add some more options along with getShouldForwardProp
in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The API here differs because, we may add some more options along with getShouldForwardProp in the future.
Making it an object is ofc preferrable, but that was not the question. Normal emotion
also accepts configuration objects - my question was about API differences.
And what about 1st arg to createStyled
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are no such API differences except we use StyleSheet
constructor and a little refactored code taken from @emotion/primitives
. The goal is to keep the signature of functions similar across the env. whether it's web, native or sketch. I liked your suggestion and will make the changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your argument is valid here since having such API reduces the maintenance cost.
) { | ||
const css = createCss(StyleSheet) | ||
|
||
return function createEmotion(component: React.ElementType) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
on web this is called createEmotionStyled
, while returned function is called createStyled
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm... it's a little inconsistent with the nomenclature. I'll fix that later!
|
||
Styled.displayName = `emotion(${getDisplayName(component)})` | ||
|
||
return Styled |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would be cool to support component as selectors, not sure if possible though and can be added later if yes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't looked into it yet to check whether its possible or not. Let's save it up for later!
import { createStyled } from './styled' | ||
import { styled as createStyled } from './styled' | ||
|
||
const css = createCss(StyleSheet) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a good candidate for PURE
I've made some changes. I am still not sure about annotating call expressions with Thanks for the review! |
The pure comment tells uglify that a function call can be removed if the return value is not used so it doesn't really matter whether something has side effects or not but rather if they have side effects that are useful without the return value. For example, on the web, emotion's |
I think we can merge this now. The remaining changes don't affect the API design! |
This is the same peerDep that glamorous-native has.
Codecov Report
|
@mitchellhamilton have you published the package ? Haha someone jumped in my Twitter DM to ask about our work on emotion native 😅 |
@nitin42 Yup, it’s published! |
What: Styling Native components using emotion and a new
primitives-core
package for shared utils.Why:
How: This PR adds support for styling React Native components using emotion, adds a new package
primitives-core
for primitive shared utils and also refactors theprimitives
package.Checklist:
Related #755