Skip to content

Latest commit

 

History

History
175 lines (120 loc) · 10.1 KB

CONVENTIONS.md

File metadata and controls

175 lines (120 loc) · 10.1 KB

CONVENTIONS

This file describes the various styling conventions used with Mastodon GO! code. In general, we follow the styling conventions set forth by Mastodon proper, so this file will only describe those things which potentially might differ.

File Structure

Mastodon GO! has five main folders:

  • util : Helper functions and miscellaneous scripts.
  • DOM : Events and DOM access.
  • redux : Redux action creators and reducers.
  • localization : Localization info (planned).
  • components : React components.

These folders follow a specific heirarchy regarding which files they can or cannot import. util files, at the top of this heirarchy, cannot import any other files, except for those in their specific subdirectory. DOM and redux files can import from the util directory, or within their specific folders. components files can import from util, DOM and redux. localization files shouldn't need to import anything.

Redux Actions and Reducers

Naming:

Unlike upstream Mastodon, Mastodon GO! actions and reducers are named in the singular—so it's status not statuses.

Action types take the form KEY_ACTION_VERB. These are grouped together into a single actionKey() function, which is exported and made available from the root redux directory.

Example:

Statuses are fetched using fetchStatus(), which calls the following (unexported) action creators:

  • request()
  • success()
  • failure()

…which in turn create the following action types:

  • STATUS_FETCH_REQUEST
  • STATUS_FETCH_SUCCESS
  • STATUS_FETCH_FAILURE

The values of action types are just the string representations of their names.

You should endeavour to make related action types be of equal string length for code cleanliness; request/success/failure, singular/multiple, and connecting/disconnect are some words which help to achieve this. (If this isn't manageäble, that's okay 😛.)

Design:

The redux store should only be used for data storage related to Mastodon proper, and not the means by which that is rendered on the screen (ie, via React components). React components should maintain aspects of their state which relate to their form and function internally, and only rely on Redux for their contents.

The action types and reducers used with Redux should each represent a fundamental data type relating to the current state of information on the Mastodon server.

React Components

The components folder is broken up into five subfolders, each of which contains components of a different type:

  • common : These are common components which are not connected to the Redux store. They should not import any non-common components and should function in a more-or-less standalone manner.

  • connected : These are generalized components which have been connected to the Redux store. They may import other connected components (making them impure) or any common ones (which do not impact purity).

  • raw : These are components which designed to be connected to the Redux store in a customized manner. The only component which fits this description right now is the <RawPaneller>.

  • panelled : These are custom connections made between the Redux store, the <RawPaneller>, and various other (non-routed) components. These components are not created until every other module has run in order to ensure that <RawPaneller> is not undefined.

  • routed : These are connected components which are intended to be used inside of a React-Router <Route> element. They may import any other component type. Right now the only component which fits this description is <RoutedUI>.

Conforming to this structure allows us to import all of our components directly from themes/mastodon-go/components without having to worry about circular dependencies breaking our code. Only components whose parent folder rests directly in one of these folders are allowed to be imported from elsewhere in the frontend. Subsubfolders, etc. define further components which are required by Mastodon GO!'s various features, but which are not common. These components must be “simple,” which means that they do not have direct access to the store and must be passed information from their parents.

Components should always be packaged in a folder with a style.scss. The stylesheet for the component can be blank if it does not need additional styling.

Component guidelines:

Every component should have a className prop which can be used to add additional class names to its root element. For common components only, all unused props should be passed through to their root element.

Component names should reflect their path inside the components directory; for example, the component located at components/connected/status/content/gallery is named <ConnectedStatusContentGallery>.

Class structure

Unlike upstream Mastodon, Mastodon GO! doesn't specify properties, like state and propTypes, directly inside the class body. Furthermore, arrow functions are not used for class methods; rather, methods are explicitly bound to the object in the class constructor().

Concerning children:

If a component takes in children, those children must appear as direct children of that component's root element, so that the CSS > combinator works as expected. For example, if a <CommonIcon> is passed as a child to a <CommonButton>, the former can be selected in CSS using .MASTODON_GO--COMMON--BUTTON > .MASTODON_GO--COMMON--ICON. If passed components cannot reliably be placed in this fashion, they should be provided not as children but via a prop.

Importing and Exporting

Paths:

For Mastodon GO! imports, relative paths should only be used for files which are contained by the current directory (ie, paths which start with ./ not ../). The exception to this is within util folders, where all paths should be relative. Other paths should be absolute, of the form themes/mastodon-go/[parent-folder].

classNames:

Mastodon GO! always imports the function provided by the classnames package as classNames, not classnames, to match the package documentation. The result of this function is usually stored in a variable named computedClass.

Comments

JavaScript block comments (/* */) aren't used; instead use line comments (//). These come in two forms:

  • Standalone line comments should be used for longer explanations and documentation. These should be written on their own lines and indented to match the surrounding code. A newline should appear before (but usually not after) them, and they should always end with a period (.). Furthermore, they should be wrapped such that the length of the line (including indentation) is no longer than 71 characters + LF.

  • Inline comments should be used for short notes which are no longer than one sentence. They are appended to the end of a line of code and should not end in a period.

In both cases, two spaces should come between the // slash characters and the comment text, and (in the case of inline comments) between the // slash characters and any preceding code.

Classes

The primary class names for components match their path inside the components directory, in all-caps, with -- separating directories and _ separating words. This string is always prepended with the prefix MASTODON_GO-- so that Mastodon GO! components are clearly identified. For example, the component located at components/connected/status/action_bar is given the class name MASTODON_GO--CONNECTED--STATUS--ACTION_BAR.

Additional class names may be given to components to indicate certain features; these should be written in lowercase, as in active or disabled. When used as selectors in CSS, these lowercase class names are preceded by an asterisk when they stand alone, as with *.active.

Styles

Styles should strive to be as specific as possible to prevent unintended side-effects. Most importantly, they should only ever select elements within their associated component.

Stylesheets should not have knowledge of the internal structure of child components, or attempt to style them at any level beyond their root element. They may, however, have knowledge of what sorts of class names a child component might be expected to have (for example, a component's stylesheet might know that .MASTODON_GO--COMMON--BUTTONs are sometimes .disabled.) Naturally, they may also have knowledge of any children that they explicitly pass to these components through the usual React method. If it is important that the non-passed children of a certain component be styled in a particular way, this should be specified through React and that component's own stylesheet.

Functions

Arrow functions are generally only used for functions which immediately return a value. For IEFEs and more complicated function types, a function () expression is usually better. Inside of objects, the [method] () {} syntax is preferred.

Mastodon GO! always places a space before and after the parenthesized argument list of a function expression. Object destructuring should be used inside argument lists where applicable.

Objects and Arrays

Objects should be written with each key: value pair on a single line, ending with a comma. import statements, export statements, and object destructuring should also follow the one-per-line rule. When the object contains only one such pair, this should instead be written as { key: value }—but only if the value takes up only one line.

Arrays with three or fewer items should be written on a single line; those with more should follow the one-per-line syntax of objects.

Control Flow

if statements should always be followed by a block, even when the statement can be fit onto a single line. switch statements are preferred over if…else chains; switch (true) {} may be used with long chains of boolean comparisons.