The pattern should be exported as a named export from a index file in the Pattern folder.
Any pattern specific styled components used in the jsx for the patterns react component should come from an adjacent styled.ts
file.
Sub components (react components which are not part of the libraries public api, but used as part of the main react component) should be setup under a components folder.
- ./Tabs
- /components
- /Tab
- index.tsx
- Tabs.vr-test.tsx
- Tabs.test.tsx
- CHANGELOG.md
- styled.ts
- index.tsx
// ./Tabs/components/Tab/index.tsx
import * as React from 'react';
import styled from 'styled-components';
export const StyledTabContainer = styled.div`
/* styles */
`;
export const Tab: React.SFC = props => {
return <StyledTabContainer>{props.children}</StyledTabContainer>;
};
// ./Tabs/styled.ts
import * as React from 'react';
import styled from 'styled-components';
export const StyledTabsContainer = styled.div`
/* styles */
`;
// ./Tabs/index.tsx
import * as React from 'react';
import { Tab } from './components/Tab.tsx';
import { StyledTabsContainer } from './styled.tsx';
interface Props {
tabTitles: string[];
}
export const Tabs: React.SFC<Props> = props => {
return (
<StyledTabsContainer>
{props.tabTitles.map(tabTitle => (
<Tab key={tabTitle}>{tabTitle}</Tab>
))}
</StyledTabsContainer>
);
};
The props interface should;
- be directly above the react component it is for,
- should not extend other types
- if it contains nested types used by internal child components (ie declared in a file under
/components
)- these should be declared in the main component file, above the Props interface
- and a consumer should be able to reason about it without having to open other files.
// ./Tabs/index.tsx
interface TabProps {
/** title displayed on tab button */
title: string;
}
interface Props {
tabs: Tab[];
}
export const Tabs: React.SFC<Props> = props => {
return (
<StyledTabsContainer>
{props.tabs.map(tab => (
<Tab key={tab.title} title={tab.title} />
))}
</StyledTabsContainer>
);
};
// ./Tabs/components/Tab/index.tsx
import { TabProps } from '../Tabs';
export const Tab: React.SFC<TabProps> = props => {
return <StyledTabContainer>{props.title}</StyledTabContainer>;
};
All styled-components should be prefixed with "Styled".
export const StyledTabsContainer = styled.div``;
export const StyledTabTitle = styled.span``;
- Add a line break between declarations
- Grouping
- Interactive 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)
The following outlines the order for writing your styled components styles in a way that will be easier for you to manage.
- External Styles
- 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 (includes interactive states and breakpoints)
- Adding component styles after allows us to properly override those properties if needed (Overriding styles should be limited as much as possible)
- 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.
- Variant Styles
- Variant styles which are how are variants unique visual execution are achieved
- State Styles
- States styles should be common across variants and should work for all variants
- Nested components
- Nested selectors should be avoided where possible, if needed they should come after pseudo-classes and pseudo-elements
- Should reference a pre-defined colour from
./src/styles/tokens.ts
- If it doesn't exist in
./src/styles/tokens.ts
speak with design about either- adjusting to use one of these colours
- or adding a new colour
All z-indexes must be defined in the global z-index file under ./src/styles/z-index.ts
Absolutely no hardcoded z-indexes allowed in the codebase.
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
DO NOT rely on styled components class names in your css or js - as they are based on a hash of the styles and will change with style changes.
When declaring css entities in a style object 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/
[[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.
- Typography
- Visual
Typography and visual come last because they take 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;
z-index: 1;
/** layout */
display: block;
float: right;
width: 10rem;
height: 10rem;
padding: 1rem;
margin: 1rem;
/** text */
font-size: 1rem;
line-height: 1.5;
color: #fff;
text-align: center;
/** visual */
background-color: #fff;
border: 1px solid #000000;
border-radius: 3px;
/** misc */
opacity: 1;