woocommerce/plugins/woocommerce-blocks/docs/contributors/coding-guidelines.md

186 lines
8.8 KiB
Markdown
Raw Normal View History

# Coding Guidelines <!-- omit in toc -->
## Table of contents <!-- omit in toc -->
- [CSS Class Names](#css-class-names)
- [Prefixing](#prefixing)
- [Naming](#naming)
- [RTL Styles](#rtl-styles)
- [SCSS File Naming Conventions for Blocks](#scss-file-naming-conventions-for-blocks)
- [Accessible font sizes](#accessible-font-sizes)
- [CSS specificity wars with 3rd party themes](#css-specificity-wars-with-3rd-party-themes)
This living document serves to prescribe coding guidelines specific to the WooCommerce Blocks project. Base coding guidelines follow the [WordPress Coding Standards](https://make.wordpress.org/core/handbook/best-practices/coding-standards/) and [Gutenberg coding standards](https://developer.wordpress.org/block-editor/contributors/develop/coding-guidelines/). The following sections outline additional patterns and conventions used in the Blocks project.
## CSS Class Names
To avoid class name collisions, class names must adhere to the following guidelines, based on the [BEM methodology](https://en.bem.info/methodology/) and [Gutenberg coding standards](https://developer.wordpress.org/block-editor/contributors/develop/coding-guidelines/).
### Prefixing
As a WordPress plugin, Blocks has to play nicely with other plugins and themes, and WordPress itself. To minimize potential conflicts, all classes should be prefixed with `.wc-block-`.
### Naming
All class names assigned to an element must be prefixed. We use different prefixes to differentiate frontend and editor elements as well as identifying if they are components or not:
- `wc-block` for classes applied to a single block.
- `wc-block-components` for classes applied to a component, which might be used by several blocks.
- `wc-block-editor` for classes applied to a single block but only used in the editor UI.
- `wc-block-editor-components` for classes applied to an editor component.
As a rule of thumb, this is the relation between location in the source tree and class name used:
| Location in the tree | Class names used | Can be styled by themes? |
| --------------------------- | ------------------------------ | :----------------------: |
| assets/js/atomic/blocks | `.wc-block-components-` | ✓ |
| assets/js/base/components | `.wc-block-components-` | ✓ |
| assets/js/blocks | Frontend: `.wc-block-` | ✓ |
| assets/js/blocks | Editor: `.wc-block-editor-` | ✘ |
| assets/js/editor-components | `.wc-block-editor-components-` | ✘ |
After the prefix, class names are built using BEM:
A **root element** (or **Block** in BEM notation) is a standalone entity that is meaningful on its own. Whilst they can be nested and interact with each other, semantically they remain equal; there is no precedence or hierarchy.
Example: `wc-block-directory-name`
Any descendant of the component's root element must append a dash-delimited descriptor, separated from the base by two consecutive underscores `__`.
A **child element** (or **Element** in BEM notation) has no standalone meaning and is semantically tied to its block.
Example: `wc-block-directory-name__descriptor-foo-bar`
Finally, A **modifier** is a flag on an element which can be used to change appearance, behavior or state.
Example: `wc-block-directory-name__descriptor-foo-bar--state`
The **root element** is considered to be the highest ancestor element returned by the default export in the index.js. Notably, if your folder contains multiple files, each with their own default exported component, only the element rendered by that of index.js can be considered the root. All others should be treated as **descendants**.
Naming is not strictly tied to the DOM so it **doesnt matter how many nested levels deep a descendant element is**. The naming convention is there to help you identify relationships with the root element.
**Nesting Example:**
- `wc-block-components-dropdown-selector` (Root Element/BEM Block)
- ├── `wc-block-components-dropdown-selector__input` (Child Element/BEM Element)
- ├── `wc-block-components-dropdown-selector__input--hidden` (Modifier)
- └── `wc-block-components-dropdown-selector__placeholder` (Child Element/BEM Element)
## RTL Styles
Upgrade webpack to version 5 (https://github.com/woocommerce/woocommerce-blocks/pull/8013) * Upgrade terser-webpack-plugin to version 4.2.3 * Upgrade webpack-bundle-analyzer to 4.7.0 * Upgrade to Webpack version 5 * Upgrade @wordpress/dependency-extraction-webpack-plugin to 4.6.0 * Upgrade dependency copy-webpack-plugin to version 11.0.0 * Upgrade dependency terser-webpack-plugin to version 5.3.6 * Replace webpack-rtl-plugin with the new @automattic/webpack-rtl-plugin * Replace module.issuer with the new ModuleGraph API There is a warning appearing in the console when running the application. This is due to the fact that the module.issuer has been deprecated on Webpack 5 and replaced with the new ModuleGraph API. This commit replaces the deprecated API with the new one. * Upgrade babel and babel plugins to latest version * Replace jsonpFunction with the new uniqueName property Add a unique name of the webpack build to avoid multiple webpack runtimes to conflict when using globals. It defaults to output.library name or the package name from package.json in the context, if both aren't found, it is set to an ''. * Replace cacheDirectory inline configuration with options.cacheDirectory * Upgrade @wordpress/e2e-tests dependency to version 5.6.0 * Remove babel-plugin-transform-react-jsx dependency Remove babel-plugin-transform-react-jsx dependency because it is already included in @wordpress/babel-preset-default * Remove unnecessary Babel dependencies Remove some unnecessary babel dependencies that are already included in the @babel/preset-env package. * Upgrade puppeteer dependency to version 16.2.0 * Remove caret from package.json dependencies * Fix Storybook build error This commit fixes the Storybook build error that was being caused because of Storybook by default uses Webpack 4, but since we are currently upgrading our webpack to version 5, we need to install some required dependencies and also explicitly tell Storybook to use Webpack 5. * Fix package-lock.json after merging with trunk * Add own webpack-rtl-plugin implementation to the project Before upgrading Webpack to version 5, we were using the original `webpack-rtl-plugin` released by Romain Berger; unfortunately, this plugin is not compatible with Webpack 5, so we replaced it with `@automattic/webpack-rtl-plugin`. The problem is that `@automattic/webpack-rtl-plugin` by default generates files with the '.rtl.css' suffix and does not provide a way to change that. This commit adds our own implementation of the `webpack-rtl-plugin` (adapted from `@automattic/webpack-rtl-plugin`) that is compatible with Webpack 5 and allows us to change the suffix of the generated files to follow the recommended way defined by Wordpress (https://codex.wordpress.org/Right-to-Left_Language_Support) * Change conditional clause to be multiline * Fix package-lock.json after merge with trunk * Fix package-lock.json after merge with trunk * Rename files to fix ESLint errors This commit renames files that have the .js extension but contain JSX code. This is causing ESLint to throw errors because by default our Eslint configuration expects only files with the .jsx extension to contain JSX code. * Fix package-lock.json file * Add is-plain-obj module to the transformIgnorePatterns of jest config * Update package-lock.json * Fix package-lock.json * Upgrade @wordpress/i18n dependency to version 4.31.0 * Update package-lock.json * Update composer lock file * Fix Webpack config for Webpack 5 * Add the package-lock.json * Remove unsupported config from webpack * Fix error with Webpack build * Add wait for network idle to the tests * Attempt to fix e2e test * Restore promise.all * Upgrade puppeteer to v17.1.3 * Upgrade expect-puppeteer * Update expect-puppeteer * Downgrade expect-puppeteer * Revert "Upgrade puppeteer to v17.1.3" This reverts commit 61ed52a56f131961f3970b6fb22cdd8b540bada3. * Upgrade Puppeteer to version 17.1.3 * Fix executionContext.frame is not a function error * Fix e2e tests * Remove isExperimentalBuild from Product Gallery inner blocks * Upgrade Webpack and Webpack-cli to latest version * Upgrade postcss and mini-css plugins * Fix error with mini-cart block * Fix styling error with filter blocks * Fix issue when running unit tests * Fix storybook script not loading * Fix a11y issue in Storybook * Fix error when multiple isExperimentalBuild was being used * Prevent error when layout is not present in the attributes object * Update `chunkIds` to `named` in Webpack * Add cache groups to the Webpack configs
2023-09-20 20:31:52 +00:00
Blocks uses the `@automattic/webpack-rtl-plugin` package to generate styles for Right-to-Left languages. These are generated automatically.
To make adjustments to the generated RTL styles, for example, excluding certain rules from the RTL stylesheets, you should use the [control directives here](https://rtlcss.com/learn/usage-guide/control-directives/index.html).
For example, you can exclude individual lines:
```css
.code {
/*rtl:ignore*/
direction: ltr;
/*rtl:ignore*/
text-align: left;
}
```
Or exclude blocks of CSS:
```css
.code {
/*rtl:begin:ignore*/
direction: ltr;
text-align: left;
/*rtl:end:ignore*/
}
```
## SCSS File Naming Conventions for Blocks
The build process will split SCSS from within the blocks library directory into two separate CSS files when Webpack runs.
Styles placed in a `style.scss` file will be built into `build/style.css`, to load on the front end theme as well as in the editor. If you need additional styles specific to the block's display in the editor, add them to an `editor.scss`.
## Accessible font sizes
Font sizes must be defined using the `font-size()` mixin, it takes a named size (`smaller`, `small`, `regular`, `large`. `larger`) and returns a font-size declaration in `em` units. This provides a consistent set of font sizes to be used across blocks, and by using `em` it increases the likelihood that blocks are accessible and fit better within different themes.
In parallel to that, consider whether other size/distance units in your CSS need to be em instead of px. In general, em should be preferred if it doesn't break the layout with big font sizes. There is another mixin named `em()` that helps converting px units to em (given a px size and optionally a base size).
## CSS specificity wars with 3rd party themes
We want our blocks to look good with as many themes as possible out of the box. Sometimes our styles will conflict with theme styles that have higher specificity. In these cases it may be tempting to increase the specificity of selectors, but increasing them too much makes it harder for other themes to style our blocks.
The following guidelines should help you decide _when_ to increase specificity, if at all. They are not hard rules so feel free to apply your best judgement on a case-by-case basis.
Imagine we are styling the radio control input but our styles are conflicting with some themes. For example, two themes that have the following styles:
Theme A:
```css
input[type='radio'] {
// specificity 0, 1, 1
background: red;
}
```
Theme B:
```css
input[type='radio']:checked {
// specificity 0, 2, 1
background: blue;
}
```
And these are the styles of the block:
```css
.wc-block-components-radio-control__input {
// specificity 0, 1, 0
background: #fff;
}
```
As you can see, the styles coming from the themes have higher specificity, so our styles would be overriden. In order to solve this:
1. Never use `!important` rules in CSS to engage in a specificity war with a theme.
2. Never use ID selectors.
3. Try wrapping the entire component/block CSS with the root class name of that component, for example:
```css
.wc-block-components-radio-control {
.wc-block-components-radio-control__input {
// specificity 0, 2, 0, we win theme A!
background: #fff;
}
}
```
4. Try adding an extra css class (or tag selector) to increase specificity. When doing so, add a comment explaining it.
```css
.wc-block-components-radio-control {
// Extra class for specificity.
.wc-block-components-radio-control__option
.wc-block-components-radio-control__input {
// specificity 0, 3, 0, we win theme B!
background: #fff;
}
}
```
5. If these steps weren't enough, consider not increasing specificity at all. If it's just a minor visual issue, consider ignoring it and assume the theme will update its conflicting styles at some point. If it's completely breaking the block or component in that theme, consider sending feedback to theme authors so they can fix it on their side.
Notice in the worst case scenario we would have increased selector specificity by 2 classes (0, 2, 0). That shouldn't make it too difficult for other themes to write styles on top of ours.
<!-- FEEDBACK -->
---
[Docs] Update links from WooCommerce.com to Woo.com for the Woo Blocks documentation (#43055) * Update woocommerce.com URLs in documentation and code files * Add changelog * Fix github repository link in extend-rest-api-add-custom-fields.md Co-authored-by: Albert Juhé Lluveras <contact@albertjuhe.com> * Add github reporter (#42974) * Add github reporter * Add changelog --------- Co-authored-by: Jon Lane <jon.lane@automattic.com> * Fix product task redirect to support grouped and external products (#43051) * Rearrange product redirection logic to better accept grouped and external produc types * Add changelog * Modify feedback modal actions (#43005) * Adapt feedback modal actions * Add changelogs * Modify comments * Fix tests * Fix test * Update class-wc-gateway-bacs.php (#43054) * Update class-wc-gateway-bacs.php Fix typo in textdomain * Add changefile(s) from automation for the following project(s): woocommerce --------- Co-authored-by: github-actions <github-actions@github.com> * [Product Block Editor]: Add `Linked product` tab (#43009) * add linked-products to group IDs * add Linked Products tab * tweak hideConditions condition * changelog * fix typo in doc comment * Introduce a product type selection within the new experience (#41823) * Create a relation between the product type and the product block template * Add 'patterns' to name the kind of products that can be created for a specific template * Resolve template using its id as a template query param * Rename ProductEditPattern to ProductTemplate * Rename get_patterns hook to woocommerce_product_editor_get_product_templates * Return the list of templates to the client * Set layout template events as array * Register the layout template based on the product template or the post type in case of product variations * Registering non supported product types * Create and register the woocommerce/product-details-section-description block * Add the product type to the section description * Create product type selector * Fix menu item style * Highlight selected menu item * Set the selected product template * Set product template title to lowercase in the content description * Rename blocks by blockTemplates under the AbstractBlockTemplate class * Rename to woocommerce_product_editor_product_templates filter * Remove product_template_ prefix from the supported_product_types map * Rename get_formatted to to_JSON and convert the props to client side like * Refactor get_product_templates * Fix icon resolution * Add a confirmation modal for unsupported product templates * Add changelog files * Remove product types using for testing * Fix redirection when changing to a non supported product template * Set the change button state to busy when it is saving the product * Fix php linter errors * Fix rebase conflict * Move ProductTemplate to Automattic\WooCommerce\Admin\Features\ProductBlockEditor namespace * Add the to_json definition to the BlockTemplateInterface * Create default product template by custom product type if it does not have a template associated yet * Fix some comments and product template creation validation * Add support to load the product template icon from an external resource * Fix php linter * Fix the changelog description * [Experimental] Interactivity Dropdown multi-select mode, ratings filter and introduce each directive (#42981) --------- Co-authored-by: David Arenas <david.arenas@automattic.com> * Introduce the transient files engine (#42877) Co-authored-by: Corey McKrill <916023+coreymckrill@users.noreply.github.com> * Change marketplace install API request to POST instead of GET (#43033) * Change marketplace install API to using POST instead of GET * Fix linting error * Add changefile(s) from automation for the following project(s): woocommerce --------- Co-authored-by: github-actions <github-actions@github.com> * Prep trunk for 8.6 cycle (#43021) Prep trunk for 8.6 cycle with version bump to 8.6.0-dev Co-authored-by: WooCommerce Bot <no-reply@woo.com> * Add Playwright tests for All Reviews, Reviews by Product and Reviews by Category blocks (#42903) * Remove Reviews blocks Puppeteer tests * Minor code cleanup * Typos * Create publishAndVisitPost() editor util * Fix subcategories when importing products in Playwright and add reviews * Add Reviews blocks tests in Playwright * More typos * Add changefile(s) from automation for the following project(s): woocommerce-blocks * Create a 'reviews' object in data.ts so we can store reviews data in one single place * Update test so instead of creating a new post in each test, we go to the already-created post * Add source comments to reviews data to match it with the script --------- Co-authored-by: github-actions <github-actions@github.com> * Release: Remove 8.5 change files (#43022) Delete changelog files from 8.5 release Co-authored-by: WooCommerce Bot <no-reply@woo.com> Co-authored-by: Alex López <alex.lopez@automattic.com> * Delete changelog files based on PR 43033 (#43079) Delete changelog files for 43033 Co-authored-by: WooCommerce Bot <no-reply@woo.com> * Delete changelog files based on PR 43051 (#43081) Delete changelog files for 43051 Co-authored-by: WooCommerce Bot <no-reply@woo.com> * Interactive Price Filter: use `context` instead of `state` (#42980) * feat: use context instead of state * fix: temporary move the context to inner element for diffing to work * fix: update context before navigation for optimistic UI * Load google analytics gtag script asynchronously in WooCommerce Blocks (#43040) Co-authored-by: github-actions <github-actions@github.com> * set WOOCOMMERCE_BLOCKS_PHASE to 1 for the production build (#43074) * set WOOCOMMERCE_BLOCKS_PHASE to 1 for the production build * Add changefile(s) from automation for the following project(s): woocommerce --------- Co-authored-by: github-actions <github-actions@github.com> * Revert "Fix schedule sales error" (#43094) Revert "Fix schedule sales error (#42700)" This reverts commit 9b800aa179b25bafebfed0da8c00eec892272cb4. * [Product Block Editor]: add Linked product sections. First approach. (#43013) * add Linked products, Upsell section * changelog * add Cross-lens section * add links to the Upsell sections * changelog * fix lint issues * fix lint issus * fix linting issue :-| * check whether the linked product group is defined * [Product Block Editor]: introduce ShoppingBags component (#43042) * add ShoppingBags component * Add ShoppingBag story * changelog * Fix: Collection data being leaked between Collection Filters blocks (#43044) * fix: CYS - change heading color (#43076) * fix: CYS - change heading color * Add changefile(s) from automation for the following project(s): woocommerce --------- Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: Patricia Hillebrandt <patriciahillebrandt@gmail.com> * Delete changelog files based on PR 43074 (#43118) Delete changelog files for 43074 Co-authored-by: WooCommerce Bot <no-reply@woo.com> * [Product Block Editor]: fix feature flag to hide the Linked products (#43119) * fix flag to hide/show product editor * changelog * Add changelog --------- Co-authored-by: Albert Juhé Lluveras <contact@albertjuhe.com> Co-authored-by: Jonathan Lane <lanej0@users.noreply.github.com> Co-authored-by: Jon Lane <jon.lane@automattic.com> Co-authored-by: louwie17 <lourensschep@gmail.com> Co-authored-by: Fernando Marichal <fernando.marichal@automattic.com> Co-authored-by: Marc Guay <marc.guay@gmail.com> Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: Damián Suárez <rdsuarez@gmail.com> Co-authored-by: Maikel David Pérez Gómez <maikel.perez@automattic.com> Co-authored-by: Sam Seay <samueljseay@gmail.com> Co-authored-by: Néstor Soriano <konamiman@konamiman.com> Co-authored-by: Corey McKrill <916023+coreymckrill@users.noreply.github.com> Co-authored-by: Kyle Nel <22053773+kdevnel@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: WooCommerce Bot <no-reply@woo.com> Co-authored-by: Alex López <alex.lopez@automattic.com> Co-authored-by: Tung Du <dinhtungdu@gmail.com> Co-authored-by: Thomas Roberts <5656702+opr@users.noreply.github.com> Co-authored-by: Luigi Teschio <gigitux@gmail.com> Co-authored-by: Patricia Hillebrandt <patriciahillebrandt@gmail.com>
2023-12-29 15:28:11 +00:00
[We're hiring!](https://woo.com/careers/) Come work with us!
🐞 Found a mistake, or have a suggestion? [Leave feedback about this document here.](https://github.com/woocommerce/woocommerce-blocks/issues/new?assignees=&labels=type%3A+documentation&template=--doc-feedback.md&title=Feedback%20on%20./docs/contributors/coding-guidelines.md)
<!-- /FEEDBACK -->