Skip to content
This repository has been archived by the owner on Dec 11, 2019. It is now read-only.

[Proposal] CSS in JS documentation #5205

Merged
merged 1 commit into from
Nov 9, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 141 additions & 0 deletions docs/style.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# Overview

All applicable styles should be colocated with their corresponding JavaScript component using [Aphrodite](https://github.com/Khan/aphrodite).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about for example our Dialogs.
https://github.com/brave/browser-laptop/blob/master/less/forms.less#L100
https://github.com/brave/browser-laptop/blob/master/less/forms.less#L144
https://github.com/brave/browser-laptop/blob/master/less/forms.less#L194
...

It's a lot of repeated styles and could benefit from shared re-use. I'm thinking in those cases we jus require in a shared common style from app/renderer/styles/*.js?


## Legacy

All legacy styles are processed with [Less](http://lesscss.org/) and can be found in the /less directory. These should still be maintained but all future CSS should be written in JavaScript and kept inside the appropriate component file.

## Example

Here is an example of a React component styled with Aphrodite.

Aphrodite will automatically create a single `<style>` tag in the document `<head>` to put its generated styles in.

```jsx
const React = require('react')
const ImmutableComponent = require('./immutableComponent')
const {StyleSheet, css} = require('aphrodite')

class Button extends ImmutableComponent {
render () {
return <span className={css(styles.browserButton)}
disabled={this.props.disabled}
data-l10n-id={this.props.l10nId}
data-button-value={this.props.dataButtonValue}
onClick={this.props.onClick} />
}
}

const styles = StyleSheet.create({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Side note is we could probably hook this easily in the future if KA didn't already do this and inspect the style properties and strings and do certain checks and console.warn for problems.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bbondy that is a great point- we should be able to do testing for important styles 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah totally. My only point with "linting" was that Aphrodite doesn't have a robust ecosystem of tools available like PostCSS does.

browserButton: {
cursor: 'default',
display: 'inline-block',
lineHeight: '25px',
width: '25px',
height: '25px',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you make a recommendation on units as well as part of this documentation? Should we avoid px for example on new stuff or is it ok? We seem to have some support issues along the lines of things look tiny, maybe due to dpi? Not sure but just wondering if this type of thing could be handled at the same time as we do a new style system. Now would be a great time to figure that type o thing out and make sure new things use the new system.


':hover': {
color: 'black'
},

'@media (min-width: 500px)': {
width: '100px'
}
}
})

module.exports = Button
```

A few things to note:

1. All multi-word properties become camel cased (lineHeight instead of line-height).
2. Pseudo selectors and media queries can be given their own class or be nested within a selector.

## Sharing Styles

Shared styles go in the `app/styles` directory. For example, we could create a Buttons.js file in `app/styles` with something like:

```jsx
import { StyleSheet } from 'aphrodite'

export default StyleSheet.create({
Button: {
background: 'red'
}
})
```

And then in a component file we could:

```jsx
import ButtonStyles from './styles/Buttons'

...

<button className={css(ButtonStyles.Button)}>Click Me</button>
```


### Passing Styles to Child Components

Alternatively, styles can be treated as props and passed down from parent to child. Here is an example:

```jsx
// addEditBookmarkHanger.js

const React = require('react')
const ImmutableComponent = require('../../../js/components/immutableComponent')
const Button = require('../../../js/components/button')
const {StyleSheet, css} = require('aphrodite')

class AddEditBookmarkHanger extends ImmutableComponent {
render () {
<Button styles={[styles.hangerButton, styles.hangerText]} />
}
}

const styles = StyleSheet.create({
hangerButton: {
width: '50px',
height: '25px',

':hover': {
color: orange
}
},

hangerText: {
fontSize: '20px'
}
})

// button.js

const React = require('react')
const ImmutableComponent = require('./immutableComponent')
const {StyleSheet, css} = require('aphrodite')

class Button extends ImmutableComponent {
render () {
return <span className={css(this.props.styles)} />
}
}
```

## Testing

As styles are converted from LESS to Aphrodite, we will lose the ability to control the generated class names. This means for our webdriver tests will no longer be able to use class names as selectors. Instead we will be adding the attribute `data-test-id` to elements. This approach gives us the added benefit of differentiating between code meant for presentation and code meant for testing.

An example would be moving:

```jsx
<Button className='paymentHistoryButton' l10nId={buttonText} onClick={onButtonClick.bind(this)} />
```

to:

```jsx
<Button className={css(paymentButton)} data-test-id='paymentHistoryButton' l10nId={buttonText} onClick={onButtonClick.bind(this)} />
```
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
"dependencies": {
"abp-filter-parser-cpp": "1.2.x",
"acorn": "3.2.0",
"aphrodite": "^1.0.0",
"async": "^2.0.1",
"electron-localshortcut": "^0.6.0",
"electron-prebuilt": "brave/electron-prebuilt",
Expand Down