Please take a moment to review this document in order to make the contribution process easy and effective for everyone involved.
Following these guidelines helps to get issues organised and PRs merged faster!
- Components should work across all platforms (web, iOS, Android) to the same level of minimum functionality (as determined by UX). This is to ensure that master is always in a releasable state and app projects can use our components with confidence. To enable this we're using react-native-web
- Components should provide a suite of sensible events for their interactions. This will allow metric components to report back for a given context
- Screenshots are required for visual changes on web, iOS and Android. Pictures are worth a thousand words
- Only add components that are wanted. They should form part of a larger feature and not be added in isolation because they might be useful in the future
- Use React perf and Chrome dev tools to identify issues AFTER the code is functionally complete
- In general we use yarn, add a yarn.lock file and keep it up to date for faster builds
- We use flow and Prettier to ensure code consistency and reliability, this pattern should also be followed to avoid typical dev bike-shedding
- For testing we’re using Jest for unit and integration tests. React Native integration tests will use Detox
We're using lerna for the monorepo with each component in it's own package that should stand alone with it's own tests and react story etc. A component is simply the exported JSX with no compilation
For ease of use there is a CLI for creating a component. Run
./times-components for instructions, this is the quickest way to create a
package with the required scaffolding which is; a component, package.json,
stubbed test and story. Note that the stubbed test will fail until a snapshot is
created with jest --updateSnapshot or a test run is made without the --CI
flag
When developing a component it's easiest to use the storybooks with hot reloading. Make sure you follow the React Native instructions to get up and running first. See README.md for commands to run the storybook.
There are some problems regarding the usage of native storybooks with the Android simulator, mainly with hot module reloading (HMR). To take full advantage of HMR while developing components while testing with storybooks use the iOS simulator instead.
npm run storybook:build will output the built web storybook into the default
storybook-static folder that is synced to the gh_pages branch to demo the
components in the web
When the CI passes packages:publish will be run that uses
conventional commits to bump to the correct
semver version, create a CHANGELOG and push to the @times-components org on
npm
update-deps is run postinstall to add node_modules to each of the packages
Good pull requests, such as patches, improvements, and new features, are a fantastic help. They should remain focused in scope and avoid containing unrelated commits. There should be a single PR for each component/package
Please ask first if somebody else is already working on this or the core developers think your feature is in-scope. Generally always have a related issue with discussions for whatever you are including.
Every component should have a XXXX.test.js file with the component's Jest
tests.
If the component contains functionality that requires functional testing on a
device or browser, you can use Fructose.
This should follow the naming convention, XXXX.fructose.js.
Fructose uses detox to instrument the tests. In order to run the tests you will need to install some additional dependencies. Follow steps 1-4 in these detox docs.
Fructose also relies on an application existing within the project, in this case
we are using the storybook app. If you have not installed it, you can do so by
running yarn ios. You will need to terminate the server that is run with
this as fructose will run its own at the time of testing. As long as you do not
delete the app, you will only have to build the app once.
If you run npm run functional-test:ios in the root directory it will run
fructose tests for all of the components. This will similarly work for android
and web.
Dextrose is a visual snapshotting tool designed to make the visual inspection of components easier.
In order to run dextrose simply use yarn visual-snapshot-web,
yarn visual-snapshot-ios or yarn visual-snapshot-android. Each component
that has differences from master will be visually snapshotted and saved under the
/dextrose/snappy folder. This can be very useful for visually validating components.
Follow these steps to deploy storybook native to a real android device.
- Plug the device into the computer
- Make sure your android device has trusted the connected computer and that
usb debugging / developer modehas been turned on. - For Android <4.2 go to Developer Options => Enable USB Debugging, and for Android >=4.2 go to About Phone/Tablet => Tap Build Number 7 Times => Developer Options => Enable USB Debugging
- Install android tooling through
brew cask install android-platform-tools - Optionally start a local instance of The Times Public Api (dependent on the stories you intend to view)
- Run
yarn - Run
yarn storybook-native - Run
yarn android:device(to enable Times API) - Open storybook native on your computer and load a story
- If your device is complaining about about
story-loader.jsnot existing - runyarn storybook-nativebeforeyarn android. This should generate the missing file. - If your device is complaining about being unable to reach
localhostor404use theadbcommands. Shake the device to bring up the developer menu and reload the app - If still struggling; shake the device and
debug js remotely. Open a console on your computer for more info on the error - If you're still struggling verify that you are able to run
yarn storybookand that it works in web view. - If you receive a
":CFBundleIdentifier", Does Not Existerror when trying to runyarn ios, try clearing your React Native cache withrm -r ~/.rncacheand clearing third part librariesrm -r <your-project>/node_modules/react-native/third_party. This happens when React Native caches third party tools for previous versions of React Native.
Android and iOS interpret fonts differently. The style property for fontFamily
on iOS refers to the internal post script name of the font. The style property
for fontFamily on Android refers to the filename of the font. React Native
Android only supports
4 font weights,
therefore we have made the following conventions
Also the fonts should have the correct weight and style meta attributes
- TimesDigitalW04.ttf
- TimesDigitalW04_italic.ttf
- TimesDigitalW04_bold.ttf
EXCEPT FOR REGULAR eg
TimesDigitalW04.ttf for a TimesDigitalW04-Regular.ttf font
- TimesDigitalW04-Regular
- TimesDigitalW04-Italic
- TimesDigitalW04-Bold
- TimesDigitalW04
The filename, font name and family name should refer to the complete font file name
- Filename format:
<fontname>-<weight> - Font Name / Full name format :
<fontname>-<weight> - Family Name format:
<fontname>-<weight>
eg
- Filename = GillSansMTStd-Medium
- FontName / Full name = GillSansMTStd-Medium
- FamilyName = GillSansMTStd-Medium
An example component/package looks like this:
.
└── card
├── CHANGELOG.md
├── __snapshots__
│ └── card.test.js.snap
├── card.js
├── card.stories.js
├── card.test.js
├── package.json
└── yarn.lock
- .storybook houses the web storybook config that dynamically loads the component stories and aliases the native imports to web
- .storybook.native is home to the generated
story-loader.jsfrom theprestorybook-nativenpm script, and the storybook bootstrapping - android, ios, .babelrc, .buckconfig, .flowconfig, .gitattributes, .watchmanconfig, app.json are all from a stock react-native project in order to run the native storybook
- lerna.json specifies that the packages are independent so different platforms can control which versions they consume and allows them to develop organically
-
Clone the repo with
https://github.com/newsuk/times-components.git -
Run
yarnin the root folder.
Once it is done, you can run npm run storybook and/or npm run storybook-native
The Provider package is home to any GraphQL queries that should be shared
across the various platforms. The
Times Public API schema is checked
in as schema.json which should be updated when any fields are changed. The
packages linting will then check that each of the gql queries within the
package are properly formed
Each component should be bumped and published correctly when it is merged to master and has passed the CI process
This was heavily sourced from CRA