This is a simplified version of the Code Styleguide used at Seven West Media where we use Glamorous for styles on https://thewest.com.au and http://www.perthnow.com.au
All styled items should have a separate file in the componets folder named according to the component name e.g. heading.styled.tsx
Sub-components should exist in a separate folder with the components folder called component
If there is more than one component, components should be put into their own files
- ./Foo
- /components
- /Bar
- Bar.glamorous.tsx
- Bar.tsx
- Foo.glamorous.tsx
- Foo.tsx
// ./Foo/components/Bar/Bar.glamorous.tsx
import * as React from 'react'
import glamorous from 'glamorous'
export const StyledBar = glamorous.div({
/* styles */
})
// ./Foo/components/Bar/Bar.tsx
import * as React from 'react'
import { StyledBar } from './Bar.glamorous.tsx'
export const Bar: React.SFC<object> = (props) => {
...
return (
<StyledBar>
...
</StyledBar>
)
}
// ./Foo/Foo.glamorous.tsx
import * as React from 'react'
import glamorous from 'glamorous'
export const StyledFoo = glamorous.div({
/* styles */
})
export const StyledBaz = glamorous.span({
/* styles */
})
// ./Foo/Foo.tsx
import * as React from 'react'
import { StyledFoo } from './Foo.glamorous.tsx'
export const Foo: React.SFC<object> = (props) => {
...
return (
<StyledFoo>
...
<StyledBaz>
...
</StyledBaz>
</StyledFoo>
)
}
import { withTheme as oldWithTheme } from 'glamorous'
import { Theme } from '.. /__styling/themes'
export interface WithTheme {
<Props>(component: React.ComponentClass<Props & { theme: Theme }>): React.ComponentClass<Props>
}
export interface WithTheme {
<Props>(
component: React.StatelessComponent<Props & { theme: Theme }>
): React.StatelessComponent<Props>
}
const withTheme: WithTheme = oldWithTheme
export { withTheme }
import { Theme } from '.. /__styling/themes'
import { withTheme } from '.. /__styling/glamorous-v4'
export interface Props {
theme: Theme
}
const InternalComponentName: React.SFC<Props> = () => (
...
)
export const ComponentName = withTheme<Props>(InternalComponentName)
// ./Foo/Foo.tsx
import { StyledFoo } from './Foo.glamorous.tsx'
export const Foo: React.SFC<object> = (props) => {
...
return (
<StyledFoo isBar={isBar}>
...
</StyledFoo>
)
}
// ./Foo.glamorous.tsx
export interface StyledFooProps {
isBar: boolean
}
export const StyledFoo = glamorous.span<StyledFooProps>(
{
width: '100%',
},
(props: StyledFooProps) => ({
display: props.isBar ? none : block
})
)
- Settings, mixins, global variables should be imported after components
- Use one level of indentation for each declaration
- Add a line break between declarations
- Grouping
- States (e.g. hover) should be grouped and come after base theme styles
- Breakpoints should be included after states and grouped under the breakpoint name (these should increase based on size, e.g. sm, md, lg)
- Themes are optional
- If you define a theme you must specify the same keys in all themes, even if they are undefined
The following outlines the order for writing your glamorous files in a way that will be easier for you to manage.
-
Global Styles (e.g. Mixins ) Knowing that you are inheriting a bunch of styles from somewhere else is important, and listing first means you can override the inherited set if you need to.
-
Component Styles Adding regular styles after allows us to properly override those properties if needed (Overriding styles should be limited as much as possible)
-
Dynamic Theming ( Product themes / Component themes) Dynamic theming refers to theme based styling - there are two types of styling - Product themes such as fonts or global margins which are applied across the entire project and local themes which are relevant just to the specific component you are working on. Global themes should come before local themes.
-
Media Queries Media queries typically affect regular styles or includes so we nest them before any pseudo elements of selectors
-
Pseudo-classes and pseudo-elements Pseudo elements and pseudo classes are directly related to the element itself so, for that reason, we nest them first before other selectors.
-
Nested components Nested selectors should be avoided where possible, if needed they should come after pseudo-classes and pseudo-elements
Please do not be afraid to use the CSS prop on glamorous components, this does not create inline styles on the component, it pulls the styles out with the rest of the component styles.
- Should reference a pre-defined colour variable
- If it doesn't exist in
__styling > settings > colors
it speak with design to discuss adding a new colour to the styleguide - Once it exists add it to the
__styling > settings > colors
file under the relevant theme- Note: black and white are defined separately
- It should be given a unique name and prefixed with the base colour e.g.
greyKoala
orblueSapphire
All z-indexes must be defined in the global z-index file under __styling > settings > z-index.ts
Absolutely no hardcoded z-indexes allowed in the codebase
Functions can be used in replacement of some scss mixins & functions e.g. calcRem & calcEm
If needed for third parties, javascript hooks can be added as classes, they should be prefixed e.g. gtm-track, gemini-card etc
This is to ensure we don't remove classes that are used by other scripts
All glamorous components should be prefixed with "Styled" and the name should be based on item you are extending e.g. if extending the styles on a Link component it should be StyledLink not StyledTotallyAwesomeThing
export const StyledOrderedList = glamorous.ol(
{
padding: `0 ${calcRem(16)}`
},
componentTheme(theme => ({
margin: theme.list.margin
}))
)
export const StyledUnorderedList = glamorous.ul(
{
padding: `0 ${calcRem(16)}`
},
componentTheme(theme => ({
margin: theme.list.margin
}))
)
As we are using a JS based solution for our css you need write css entities slightly different
content: '\\002f'
, // instead of content: '/002f',
To help, here is a handy conversion table: https://brajeshwar.github.io/entities/
DO NOT rely on Glamrorous display names in your css - as they are not added in production only in dev.
[[TODO: SUPPORT WITH LINTING]] While this would be great we do not expect you to do this without linting so don't get hung up on it, no one's going to pull you up on it!
Grouping your properties will help to create consistent stylesheets.
Grouping order:
- Positioning - Positioning comes first because it can remove an element from the normal flow of the document and override box model related styles.
- Layout - Dictates a components dimensions and placement.
- Text
- Visual
Typography and visual comes last because it takes place inside the component or without having an impact on positioning and box model.
// positioning
position: 'absolute'
top: 0
right: 0
bottom: 0
left: 0
zIndex: 1
// Layout
display: 'block'
float: 'right
width: 100
height: 100
padding: 1em
margin: 1em
// Text
fontFamily: fonts.sansSerif
fontSize: calcRem(16)
lineHeight: 1.5
color: colors.black
textAlign: 'center'
// Visual
backgroundColor: colors.white
border: 1px solid colors.black
borderRadius: 3px
// Misc
opacity: 1
Created by the awesome frontend team at Seven West Media