Guide to contribute to the Sourcegraph webapp. Please also see our general TypeScript documentation.
If the file only contains one main export (e.g. a component class + some interfaces), name the file like the main export.
This name is PascalCase if the main export is a class.
This makes it easy to find it with file search.
If the file has no main export (e.g. a file with utility functions), give the file a name that groups the exports semantically.
This name is usually short and lowercase or kebab-case, e.g. util/errors.ts
contains error utilities.
Avoid adding utilities into a util.ts
file, it is doomed to become a mess over time.
.ts
vs .tsx
You must use the tsx
file extension if the file contains TSX (React) syntax.
You should use the normal ts
extension if it does not.
The tsx
extension makes certain generic syntax impossible and also enables emmet suggestions in editors, which are annoying in normal TypeScript code.
index.*
filesIndex files should not never contain declarations on their own. Their purpose is to reexport symbols from a number of other files to make imports easier and define the the public API.
&
operatorrem
units (when converting designs, 1rem
= 16px
). This allows us to scale the whole UI by modifying the root font size.Code splitting refers to the practice of bundling the frontend code into multiple JavaScript files, each with a subset of the frontend code, so that the client only needs to download and parse/run the code necessary for the page they are viewing. We use the react-router code splitting technique to accomplish this.
When adding a new route (and new components), you can opt into code splitting for it by referring to a lazy-loading reference to the component (instead of a static import binding of the component). To create the lazy-loading reference to the component, use React.lazy
, as in:
const MyComponent = React.lazy(async () => ({ default: (await import('./path/to/MyComponent)).MyComponent, }))
If you don't do this (and just use a normal import
), it will still work, but it will increase the initial bundle size for all users.
(It is necessary to return the component as the default
property of an object because React.lazy
is hard-coded to look there for it. We could avoid this extra work by using default exports, but we chose not to use default exports (reasons).)
Theming is done through toggling top-level CSS classes theme-light
and theme-dark
.
Any style can be made different on either theme by scoping it to one of those two classes.
Where possible, we use CSS variables, but unfortunately they don't work with compile-time color manipulation (darken()
etc)
and runtime color manipulation is not yet implemented in CSS (coming in CSS Color Level 4).
We use Prettier so you never have to worry about how to format your code.
yarn run prettier
will check & autoformat all code.
We write unit tests and e2e tests.
Unit tests are for things that can be tested in isolation; you provide inputs and make assertion on the outputs and/or side effects.
React component snapshot tests are a special kind of unit test that we use to test React components. See "React component snapshot tests" for more information.
You can run unit tests via yarn test
(to run all) or yarn test --watch
(to run only tests changed since the last commit). See "Testing" for more information.
See testing.md.