@bloomreach/react-banana-ui 1.32.1 → 1.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +229 -50
- package/dist/bloomreach-react-banana-ui.es.js +12415 -11640
- package/dist/bloomreach-react-banana-ui.es.js.map +1 -1
- package/dist/bloomreach-react-banana-ui.umd.js +18 -43
- package/dist/bloomreach-react-banana-ui.umd.js.map +1 -1
- package/dist/components/data-display/actions-container/actions-container.types.d.ts +2 -2
- package/dist/components/data-display/badge/badge.types.d.ts +2 -2
- package/dist/components/data-display/description/description.types.d.ts +2 -2
- package/dist/components/data-display/header/header.types.d.ts +2 -2
- package/dist/components/data-display/index.d.ts +1 -11
- package/dist/components/data-display/internal.d.ts +1 -1
- package/dist/components/data-display/table/index.d.ts +8 -2
- package/dist/components/data-display/table/table/index.d.ts +2 -0
- package/dist/components/data-display/tags/index.d.ts +4 -0
- package/dist/components/data-display/{tag → tags/tag}/tag.types.d.ts +2 -2
- package/dist/components/data-display/{tag-group → tags/tag-group}/tag-group.types.d.ts +2 -2
- package/dist/components/date/date-range-quick-selections/date-range-quick-selections.d.ts +9 -0
- package/dist/components/date/date-range-quick-selections/date-range-quick-selections.types.d.ts +25 -0
- package/dist/components/date/date-range-quick-selections/index.d.ts +2 -0
- package/dist/components/date/date-time-picker/date-time-picker.stories.d.ts +6 -0
- package/dist/components/date/date-time-picker/date-time-picker.types.d.ts +23 -1
- package/dist/components/date/date-time-range-picker/date-time-range-picker.stories.d.ts +11 -0
- package/dist/components/date/date-time-range-picker/date-time-range-picker.types.d.ts +86 -1
- package/dist/components/date/date-time-range-picker/index.d.ts +1 -0
- package/dist/components/dropdowns/menu/menu.stories.d.ts +9 -1
- package/dist/components/inputs/autocomplete/autocomplete.types.d.ts +8 -1
- package/dist/components/inputs/autocomplete-field/autocomplete-field.d.ts +26 -0
- package/dist/components/inputs/autocomplete-field/autocomplete-field.qa.stories.d.ts +34 -0
- package/dist/components/inputs/autocomplete-field/autocomplete-field.stories.d.ts +43 -0
- package/dist/components/inputs/autocomplete-field/autocomplete-field.types.d.ts +34 -0
- package/dist/components/inputs/autocomplete-field/index.d.ts +2 -0
- package/dist/components/inputs/base-field/base-field.types.d.ts +4 -0
- package/dist/components/inputs/index.d.ts +1 -0
- package/dist/components/inputs/input-field/input-field.stories.d.ts +1 -0
- package/dist/components/inputs/internal.d.ts +1 -0
- package/dist/components/inputs/select-field/select-field.stories.d.ts +1 -0
- package/dist/components/inputs/text-field/text-field.stories.d.ts +1 -0
- package/dist/components/lists/listbox-item/listbox-item.types.d.ts +9 -1
- package/dist/components/lists/listbox-separator/index.d.ts +2 -0
- package/dist/components/lists/listbox-separator/listbox-separator.d.ts +24 -0
- package/dist/components/lists/listbox-separator/listbox-separator.types.d.ts +6 -0
- package/dist/components/popovers/tooltip/tooltip.qa.stories.d.ts +8 -2
- package/dist/components/popovers/tooltip/tooltip.stories.d.ts +43 -13
- package/dist/components/popovers/tooltip/tooltip.types.d.ts +6 -0
- package/dist/react-banana-ui.css +1 -1
- package/dist/utils/date/date-utils.d.ts +3 -1
- package/dist/utils/date-range-presets.d.ts +144 -0
- package/dist/utils/hooks/index.d.ts +1 -0
- package/dist/utils/hooks/use-sync-max-height.d.ts +8 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/use-id.d.ts +39 -0
- package/package.json +42 -42
- package/dist/components/dropdowns/menu/menu/menu.stories.d.ts +0 -6
- package/dist/components/dropdowns/menu/menu-button/menu-button.stories.d.ts +0 -6
- package/dist/components/dropdowns/menu/menu-content/menu-content.stories.d.ts +0 -10
- package/dist/components/dropdowns/menu/menu-group/menu-group.stories.d.ts +0 -6
- package/dist/components/dropdowns/menu/menu-group-label/menu-group-label.stories.d.ts +0 -6
- package/dist/components/dropdowns/menu/menu-item/menu-item.stories.d.ts +0 -6
- package/dist/components/dropdowns/menu/menu-separator/menu-separator.stories.d.ts +0 -6
- package/dist/components/inputs/base-field/generate-field-id.d.ts +0 -4
- /package/dist/components/data-display/table/{table-context.d.ts → table/table-context.d.ts} +0 -0
- /package/dist/components/data-display/table/{table-section-context.d.ts → table/table-section-context.d.ts} +0 -0
- /package/dist/components/data-display/table/{table.d.ts → table/table.d.ts} +0 -0
- /package/dist/components/data-display/table/{table.qa.stories.d.ts → table/table.qa.stories.d.ts} +0 -0
- /package/dist/components/data-display/table/{table.stories.d.ts → table/table.stories.d.ts} +0 -0
- /package/dist/components/data-display/table/{table.types.d.ts → table/table.types.d.ts} +0 -0
- /package/dist/components/data-display/{table-body → table/table-body}/index.d.ts +0 -0
- /package/dist/components/data-display/{table-body → table/table-body}/table-body.d.ts +0 -0
- /package/dist/components/data-display/{table-body → table/table-body}/table-body.types.d.ts +0 -0
- /package/dist/components/data-display/{table-cell → table/table-cell}/index.d.ts +0 -0
- /package/dist/components/data-display/{table-cell → table/table-cell}/table-cell.d.ts +0 -0
- /package/dist/components/data-display/{table-cell → table/table-cell}/table-cell.types.d.ts +0 -0
- /package/dist/components/data-display/{table-cell-action → table/table-cell-action}/index.d.ts +0 -0
- /package/dist/components/data-display/{table-cell-action → table/table-cell-action}/table-cell-action.d.ts +0 -0
- /package/dist/components/data-display/{table-cell-action → table/table-cell-action}/table-cell-action.types.d.ts +0 -0
- /package/dist/components/data-display/{table-foot → table/table-foot}/index.d.ts +0 -0
- /package/dist/components/data-display/{table-foot → table/table-foot}/table-foot.d.ts +0 -0
- /package/dist/components/data-display/{table-foot → table/table-foot}/table-foot.types.d.ts +0 -0
- /package/dist/components/data-display/{table-head → table/table-head}/index.d.ts +0 -0
- /package/dist/components/data-display/{table-head → table/table-head}/table-head.d.ts +0 -0
- /package/dist/components/data-display/{table-head → table/table-head}/table-head.types.d.ts +0 -0
- /package/dist/components/data-display/{table-row → table/table-row}/index.d.ts +0 -0
- /package/dist/components/data-display/{table-row → table/table-row}/table-row-context.d.ts +0 -0
- /package/dist/components/data-display/{table-row → table/table-row}/table-row.d.ts +0 -0
- /package/dist/components/data-display/{table-row → table/table-row}/table-row.types.d.ts +0 -0
- /package/dist/components/data-display/{table-sort-label → table/table-sort-label}/index.d.ts +0 -0
- /package/dist/components/data-display/{table-sort-label → table/table-sort-label}/table-sort-label.d.ts +0 -0
- /package/dist/components/data-display/{table-sort-label → table/table-sort-label}/table-sort-label.types.d.ts +0 -0
- /package/dist/components/data-display/{asset-tag → tags/asset-tag}/asset-tag.d.ts +0 -0
- /package/dist/components/data-display/{asset-tag → tags/asset-tag}/asset-tag.qa.stories.d.ts +0 -0
- /package/dist/components/data-display/{asset-tag → tags/asset-tag}/asset-tag.stories.d.ts +0 -0
- /package/dist/components/data-display/{asset-tag → tags/asset-tag}/asset-tag.types.d.ts +0 -0
- /package/dist/components/data-display/{asset-tag → tags/asset-tag}/index.d.ts +0 -0
- /package/dist/components/data-display/{filter-tag → tags/filter-tag}/filter-tag.d.ts +0 -0
- /package/dist/components/data-display/{filter-tag → tags/filter-tag}/filter-tag.qa.stories.d.ts +0 -0
- /package/dist/components/data-display/{filter-tag → tags/filter-tag}/filter-tag.stories.d.ts +0 -0
- /package/dist/components/data-display/{filter-tag → tags/filter-tag}/filter-tag.types.d.ts +0 -0
- /package/dist/components/data-display/{filter-tag → tags/filter-tag}/index.d.ts +0 -0
- /package/dist/components/data-display/{input-tag → tags/input-tag}/index.d.ts +0 -0
- /package/dist/components/data-display/{input-tag → tags/input-tag}/input-tag.d.ts +0 -0
- /package/dist/components/data-display/{input-tag → tags/input-tag}/input-tag.qa.stories.d.ts +0 -0
- /package/dist/components/data-display/{input-tag → tags/input-tag}/input-tag.stories.d.ts +0 -0
- /package/dist/components/data-display/{input-tag → tags/input-tag}/input-tag.types.d.ts +0 -0
- /package/dist/components/data-display/{tag → tags/tag}/index.d.ts +0 -0
- /package/dist/components/data-display/{tag → tags/tag}/tag.d.ts +0 -0
- /package/dist/components/data-display/{tag-group → tags/tag-group}/index.d.ts +0 -0
- /package/dist/components/data-display/{tag-group → tags/tag-group}/tag-group.d.ts +0 -0
- /package/dist/components/data-display/{tag-group → tags/tag-group}/tag-group.qa.stories.d.ts +0 -0
- /package/dist/components/data-display/{tag-group → tags/tag-group}/tag-group.stories.d.ts +0 -0
package/README.md
CHANGED
|
@@ -1,12 +1,56 @@
|
|
|
1
1
|
# React Banana UI
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
A TypeScript React component library of primitive and common UI components used across Bloomreach apps.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Viewing Available Components](#viewing-available-components)
|
|
8
|
+
- [Guide from Figma Design to the React Banana UI Components](#guide-from-figma-design-to-the-react-banana-ui-components)
|
|
9
|
+
- [Using library in a project](#using-library-in-a-project)
|
|
10
|
+
- [Components](#components)
|
|
11
|
+
- [Styles & Fonts](#styles--fonts)
|
|
12
|
+
- [IMPORTANT](#important)
|
|
13
|
+
- [Development](#development)
|
|
14
|
+
- [Prerequisites](#prerequisites)
|
|
15
|
+
- [Getting Started](#getting-started)
|
|
16
|
+
- [Build](#build)
|
|
17
|
+
- [Docker Services](#docker-services)
|
|
18
|
+
- [Branching types](#branching-types)
|
|
19
|
+
- [Commit Message Format](#commit-message-format)
|
|
20
|
+
- [The commit contains the following structural elements:](#the-commit-contains-the-following-structural-elements)
|
|
21
|
+
- [Commit Message Header](#commit-message-header)
|
|
22
|
+
- [Type](#type)
|
|
23
|
+
- [Scope](#scope)
|
|
24
|
+
- [Summary](#summary)
|
|
25
|
+
- [Commit Message Body](#commit-message-body)
|
|
26
|
+
- [Commit Message Footer](#commit-message-footer)
|
|
27
|
+
- [Revert commits](#revert-commits)
|
|
28
|
+
- [Creating a new component](#creating-a-new-component)
|
|
29
|
+
- [Storybook](#storybook)
|
|
30
|
+
- [Autogen](#autogen)
|
|
31
|
+
- [Icons](#icons)
|
|
32
|
+
- [Testing](#testing)
|
|
33
|
+
- [Unit tests](#unit-tests)
|
|
34
|
+
- [End-to-end tests](#end-to-end-tests)
|
|
35
|
+
- [Run e2e tests](#run-e2e-tests)
|
|
36
|
+
- [Update failed visual regression tests](#update-failed-visual-regression-tests)
|
|
37
|
+
- [The e2e tests configuration for CI and local development](#the-e2e-tests-configuration-for-ci-and-local-development)
|
|
38
|
+
- [Configuration Synchronization](#configuration-synchronization)
|
|
39
|
+
- [Releasing](#releasing)
|
|
40
|
+
- [GitLab Pipeline](#gitlab-pipeline)
|
|
41
|
+
- [Contributing Guidelines](#contributing-guidelines)
|
|
42
|
+
- [Code Quality Standards](#code-quality-standards)
|
|
43
|
+
- [Linting & Formatting](#linting--formatting)
|
|
44
|
+
- [Git Hooks (Husky)](#git-hooks-husky)
|
|
45
|
+
- [Security Best Practices](#security-best-practices)
|
|
46
|
+
- [Performance Guidelines](#performance-guidelines)
|
|
47
|
+
- [CSS Performance](#css-performance)
|
|
48
|
+
- [Performance Budgets](#performance-budgets)
|
|
49
|
+
- [Common Pitfalls to Avoid](#common-pitfalls-to-avoid)
|
|
6
50
|
|
|
7
51
|
## Viewing Available Components
|
|
8
52
|
|
|
9
|
-
Visit the library [
|
|
53
|
+
Visit the library [Storybook](https://design.corp.bloomreach.com/storybooks/react-banana-ui/master/) to view the latest available components.
|
|
10
54
|
|
|
11
55
|
## Guide from Figma Design to the React Banana UI Components
|
|
12
56
|
|
|
@@ -20,60 +64,111 @@ Install the library as a dependency in the project
|
|
|
20
64
|
npm i --save --save-exact @bloomreach/react-banana-ui
|
|
21
65
|
```
|
|
22
66
|
|
|
67
|
+
This package requires React 17/18 as peer dependencies:
|
|
68
|
+
|
|
69
|
+
- react (peer)
|
|
70
|
+
- react-dom (peer)
|
|
71
|
+
- @types/react (optional peer in TS projects)
|
|
72
|
+
|
|
23
73
|
### Components
|
|
24
74
|
|
|
25
|
-
|
|
75
|
+
To use components in your application, import them as named exports:
|
|
26
76
|
|
|
27
|
-
```
|
|
28
|
-
import {
|
|
77
|
+
```tsx
|
|
78
|
+
import { Button } from '@bloomreach/react-banana-ui';
|
|
79
|
+
|
|
80
|
+
function MyComponent() {
|
|
81
|
+
return <Button onClick={() => console.log('Button clicked!')}>Click Me</Button>;
|
|
82
|
+
}
|
|
29
83
|
```
|
|
30
84
|
|
|
85
|
+
Prefer named imports for effective tree shaking.
|
|
86
|
+
|
|
31
87
|
### Styles & Fonts
|
|
32
88
|
|
|
33
|
-
|
|
89
|
+
To make the library's styles and fonts available in your project, follow these steps:
|
|
34
90
|
|
|
35
|
-
|
|
91
|
+
1. **Import the main stylesheet**: Add the following line to your main application's style file (e.g., `main.scss` or `index.css`):
|
|
36
92
|
|
|
37
|
-
|
|
38
|
-
|
|
93
|
+
```css
|
|
94
|
+
/* main.scss */
|
|
39
95
|
|
|
40
|
-
|
|
96
|
+
@import '@bloomreach/react-banana-ui/style.css';
|
|
41
97
|
|
|
42
|
-
|
|
43
|
-
|
|
98
|
+
/* ... other styles ... */
|
|
99
|
+
```
|
|
44
100
|
|
|
45
|
-
|
|
101
|
+
2. **Font Family**: The `html` and `body` tags' font families are already defined within the library's styles, ensuring consistent typography across your application without additional configuration.
|
|
46
102
|
|
|
47
103
|
### IMPORTANT
|
|
48
104
|
|
|
49
|
-
|
|
50
|
-
as they are intended to be used inside the library only.
|
|
51
|
-
Stick to use library components to bring the styles into the application.
|
|
105
|
+
**Avoid directly using `--rbui-...` and/or `--banana-...` CSS custom properties in your application styles.** These variables are intended for internal library use only. Always use the library components to ensure proper styling and adherence to the design system.
|
|
52
106
|
|
|
53
107
|
## Development
|
|
54
108
|
|
|
109
|
+
This section outlines the necessary steps and commands for developing with the React Banana UI library.
|
|
110
|
+
|
|
55
111
|
### Prerequisites
|
|
56
112
|
|
|
57
|
-
|
|
58
|
-
|
|
113
|
+
Ensure you have the following installed:
|
|
114
|
+
|
|
115
|
+
- **Node.js**: >=18
|
|
116
|
+
- **NPM**: >=9
|
|
117
|
+
|
|
118
|
+
### Getting Started
|
|
119
|
+
|
|
120
|
+
1. **Install Dependencies**: Run the following command to install all project dependencies:
|
|
121
|
+
|
|
122
|
+
```sh
|
|
123
|
+
npm ci
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
This command performs a clean installation of dependencies, ensuring consistency across environments.
|
|
127
|
+
|
|
128
|
+
2. **Run Storybook**: Start the Storybook development server (alias of `npm run storybook`) to view and develop components in isolation:
|
|
129
|
+
|
|
130
|
+
```sh
|
|
131
|
+
npm run start
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Storybook will open at http://localhost:6006, and any changes saved in the source code will automatically reflect in the Storybook UI.
|
|
59
135
|
|
|
60
|
-
|
|
136
|
+
3. **Generate New Components**: To create a new component with the standard file structure, use the component generation script:
|
|
137
|
+
|
|
138
|
+
```sh
|
|
139
|
+
npm run generate
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Follow the prompts to set up your new component. More details can be found in the [Creating a new component](#creating-a-new-component) section.
|
|
143
|
+
|
|
144
|
+
### Build
|
|
145
|
+
|
|
146
|
+
To build the library for production, run the following command:
|
|
61
147
|
|
|
62
148
|
```sh
|
|
63
|
-
npm
|
|
149
|
+
npm run build
|
|
64
150
|
```
|
|
65
151
|
|
|
66
|
-
|
|
152
|
+
This command compiles the TypeScript code, bundles the components, and generates the necessary output files for distribution. The built files will be located in the `dist/` directory.
|
|
153
|
+
|
|
154
|
+
To build the Storybook for deployment, run the following command:
|
|
67
155
|
|
|
68
156
|
```sh
|
|
69
|
-
npm run
|
|
157
|
+
npm run storybook:build
|
|
70
158
|
```
|
|
71
159
|
|
|
72
|
-
|
|
160
|
+
This command compiles the Storybook stories and generates a static Storybook build, which can be deployed to a web server. The output will be in the `storybook-static/` directory.
|
|
161
|
+
|
|
162
|
+
### Docker Services
|
|
163
|
+
|
|
164
|
+
We use Docker Compose to manage various services required for local development and testing. The `docker-compose.yml` file defines these services.
|
|
165
|
+
|
|
166
|
+
- **Playwright E2E Testing**: The `e2e` service in `docker-compose.yml` sets up a Playwright test environment within a Docker container, ensuring consistent end-to-end test execution across different environments. You can run these tests using `npm run e2e`.
|
|
167
|
+
- **SonarQube Analysis**: The `sonar` service provides a local SonarQube instance for static code analysis. This helps in identifying code quality and security vulnerabilities early in the development cycle. You can start this service and perform analysis using `npm run sonar` (after configuring SonarQube locally). Ensure the `SONAR_TOKEN` environment variable is set.
|
|
73
168
|
|
|
74
169
|
## Branching types
|
|
75
170
|
|
|
76
|
-
To manage and automate complex release workflow based on multiple Git branches and distribution channels
|
|
171
|
+
To manage and automate complex release workflow based on multiple Git branches and distribution channels, we utilize the `semantic-release` library. Refer to the [documentation](https://semantic-release.gitbook.io/semantic-release/) for comprehensive details. Our current setup is streamlined but designed for future extensibility.
|
|
77
172
|
|
|
78
173
|
The current branch types are explained below.
|
|
79
174
|
|
|
@@ -84,8 +179,8 @@ The current branch types are explained below.
|
|
|
84
179
|
|
|
85
180
|
The following changes should be done to change or extend the current setup:
|
|
86
181
|
|
|
87
|
-
- Add a new release/maintenance/pre-release branch to the `semantic-release` configuration in
|
|
88
|
-
- Update the
|
|
182
|
+
- Add a new release/maintenance/pre-release branch to the `semantic-release` configuration in `./release.config.cjs`, check the [documentation](https://semantic-release.gitbook.io/semantic-release/usage/configuration#branches) for more details;
|
|
183
|
+
- Update the GitLab pipeline `release` job to allow running it with the new branch, check `./.gitlab-ci.yml`;
|
|
89
184
|
- Verify that the new branch is marked as `protected` in the repository settings.
|
|
90
185
|
|
|
91
186
|
Find more examples of possible release workflows in the official `semantic-release` [documentation](https://semantic-release.gitbook.io/semantic-release/recipes/release-workflow).
|
|
@@ -232,41 +327,67 @@ The old components stories are located in the `./stories` folder. They are going
|
|
|
232
327
|
|
|
233
328
|
### Icons
|
|
234
329
|
|
|
235
|
-
The icon files and exports are auto-generated using the script at `scripts/gen-icons`. If new icons are added in the banana-theme project, run `npm run generate:icons` to regenerate the icon exports
|
|
330
|
+
The icon files and exports are auto-generated using the script at `scripts/gen-icons`. If new icons are added in the banana-theme project, run `npm run generate:icons` to regenerate the icon exports.
|
|
331
|
+
|
|
332
|
+
Note: running the generator deletes and recreates `src/components/foundations/icon/icons/`.
|
|
236
333
|
|
|
237
334
|
## Testing
|
|
238
335
|
|
|
239
|
-
|
|
240
|
-
The library is developed with a two-level testing approach in mind like unit tests and E2E tests. Each component should have unit tests and E2E tests. The unit tests should cover the component logic and the E2E tests should cover the component behavior in the real browser environment together with visual regression testing.
|
|
336
|
+
Comprehensive testing is crucial for maintaining the quality and stability of the React Banana UI library. We employ a two-level testing strategy: unit tests for isolated logic and end-to-end (E2E) tests for overall component behavior in a real browser environment, including visual regression. Each new or modified component is expected to have thorough test coverage.
|
|
241
337
|
|
|
242
338
|
### Unit tests
|
|
243
339
|
|
|
244
|
-
|
|
340
|
+
We use the [Vitest](https://vitest.dev/) framework for unit testing. Unit test files should end with `*.spec.ts(x)` and be co-located with the component or module being tested. When writing unit tests:
|
|
341
|
+
|
|
342
|
+
- **Focus on isolated logic**: Test individual functions, components, or modules in isolation, mocking dependencies as needed.
|
|
343
|
+
- **Cover edge cases**: Ensure your tests cover boundary conditions, invalid inputs, and error states.
|
|
344
|
+
- **Assert component behavior**: Verify that components render correctly, respond to user interactions, and manage their state as expected.
|
|
345
|
+
|
|
346
|
+
Common unit test commands:
|
|
347
|
+
|
|
348
|
+
```sh
|
|
349
|
+
npm test
|
|
350
|
+
npm run test:watch
|
|
351
|
+
npm run test:ui
|
|
352
|
+
npm run test:coverage
|
|
353
|
+
```
|
|
245
354
|
|
|
246
355
|
### End-to-end tests
|
|
247
356
|
|
|
248
|
-
|
|
249
|
-
The stories for the e2e test should be located in the same place as tests and component stories and end with `*.qa.stories.ts(x)`. The title of test stories should contain `QA` at the end and look something like this: `<Component Group>/<Component Name>/QA`. The e2e stories should be used only for e2e tests and not for documentation purposes. The e2e stories should reuse the component stories metadata and base stories as much as possible but at the same time, they should give flexibility to test different scenarios.
|
|
357
|
+
We utilize the [Playwright](https://playwright.dev/) framework for end-to-end testing. These tests are co-located with their respective components (files ending with `*.test.ts(x)`) and run against dedicated Storybook stories (`*.qa.stories.ts(x)`). The primary goal of E2E tests is to eliminate manual QA efforts and ensure high-quality components for end-users. Key aspects of our E2E testing strategy include:
|
|
250
358
|
|
|
251
|
-
|
|
359
|
+
- **Comprehensive Scenarios**: Each component should be covered with E2E tests that simulate various user interactions, component states, and different scenarios.
|
|
360
|
+
- **Visual Regression Testing**: This is a critical part of our E2E suite, ensuring that visual changes are intentional and do not introduce unexpected regressions. When visual failures occur and are deemed correct, update the snapshots using `npm run e2e:update`.
|
|
361
|
+
- **Balancing Coverage and Performance**: While extensive coverage is vital, E2E tests can be slow. Strive for a balance between comprehensive test scenarios and efficient test execution. Prioritize the quality of components, and always consider performance optimizations for CI.
|
|
252
362
|
|
|
253
363
|
#### Run e2e tests
|
|
254
364
|
|
|
255
365
|
- Use the command `npm run e2e` to start end-to-end tests inside the Docker container (the `docker` and `docker compose` should be installed on your machine).
|
|
256
366
|
- When tests are done check the Playwright output in the console if some of the tests failed use the following command to open the Playwright report: `npm run e2e:report`
|
|
367
|
+
- For a local run without Docker, use `npm run e2e:internal` (builds Storybook then runs Playwright).
|
|
257
368
|
|
|
258
369
|
#### Update failed visual regression tests
|
|
259
370
|
|
|
260
|
-
- If the failure appeared in the visual regression tests and those changes are correct, please update the existing reference images with the following command: `npm run e2e:update`. The Playwright will generate new correct reference images which should be committed to the repository
|
|
371
|
+
- If the failure appeared in the visual regression tests and those changes are correct, please update the existing reference images with the following command: `npm run e2e:update`. The Playwright will generate new correct reference images which should be committed to the repository.
|
|
372
|
+
- **Important**: Playwright snapshots should always be generated within the Docker environment (`npm run e2e:update` will use Docker by default). This ensures consistency with the Linux environment used in the GitLab pipeline, preventing discrepancies caused by operating system-specific rendering differences.
|
|
261
373
|
|
|
262
374
|
### The e2e tests configuration for CI and local development
|
|
263
375
|
|
|
264
|
-
|
|
265
|
-
|
|
376
|
+
E2E tests are executed in a Docker container, both locally and in CI, leveraging the official Playwright Docker image. This approach ensures a consistent and predictable testing environment across all development and integration stages. The CI setup mirrors the local `docker-compose.yml` configuration.
|
|
377
|
+
|
|
378
|
+
#### Configuration Synchronization
|
|
379
|
+
|
|
380
|
+
It is crucial to **keep the CI setup for the `e2e tests` job (defined in `.gitlab-ci.yml`) synchronized with the local Docker Compose configuration (`docker-compose.yml`)**. Any changes made to one should be carefully applied to the other to maintain environment consistency and avoid unexpected test failures.
|
|
381
|
+
|
|
382
|
+
## Contributing Guidelines
|
|
266
383
|
|
|
267
|
-
|
|
384
|
+
We welcome contributions to the React Banana UI library! To ensure a smooth and collaborative development process, please adhere to the following guidelines:
|
|
268
385
|
|
|
269
|
-
|
|
386
|
+
- **Commit Message Format**: All commit messages must follow the [Conventional Commits specification](#commit-message-format). This helps automate releases and generate accurate changelogs. Please review the [Commit Message Format](#commit-message-format) section for detailed instructions.
|
|
387
|
+
- **Testing**: Before submitting any changes, ensure your code is thoroughly tested. This includes both [Unit Tests](#unit-tests) for isolated logic and [End-to-end Tests](#end-to-end-tests) for comprehensive component behavior and visual regression. Refer to the [Testing](#testing) section for detailed guidance on writing and running tests.
|
|
388
|
+
- **Code Quality**: Maintain high code quality by adhering to the project's linting, formatting, and security best practices. (Refer to the `always_applied_workspace_rules` in the documentation for more details.)
|
|
389
|
+
- **Development Workflow**: Follow the established [Development](#development) workflow for installing dependencies, running Storybook, and generating new components.
|
|
390
|
+
- **Branching**: Understand and follow our [Branching types](#branching-types) for feature development, bug fixes, and releases.
|
|
270
391
|
|
|
271
392
|
## Releasing
|
|
272
393
|
|
|
@@ -278,16 +399,74 @@ To preview the possible release version and release notes based on already exist
|
|
|
278
399
|
npm run release:dry-run
|
|
279
400
|
```
|
|
280
401
|
|
|
281
|
-
|
|
402
|
+
See `MIGRATION.md` for migration guidance and `RELEASE_NOTES.md` for detailed changes between versions.
|
|
403
|
+
|
|
404
|
+
### GitLab Pipeline
|
|
405
|
+
|
|
406
|
+
The GitLab pipeline automates the build, test, and deployment processes for the React Banana UI library. It consists of several stages, each designed to ensure code quality, functionality, and proper release management.
|
|
407
|
+
|
|
408
|
+
- **Build Stage**: This stage is responsible for compiling the TypeScript code, bundling the components, and generating the necessary output files for distribution. It also builds the Storybook for deployment.
|
|
409
|
+
- **Test Stage**: In this stage, unit tests and end-to-end (E2E) tests are executed to ensure the functionality and visual integrity of the components.
|
|
410
|
+
- **Lint Stage**: This stage performs linting and formatting checks on the codebase to enforce code quality standards.
|
|
411
|
+
- **Type Check Stage**: TypeScript type checking is performed in this stage to catch any type-related issues.
|
|
412
|
+
- **Deploy Stage**: This final stage is responsible for publishing the new version of the library to npm and updating the release notes, provided all previous stages pass successfully.
|
|
413
|
+
|
|
414
|
+
The GitLab pipeline runs all the checks and if the library is in good order, the following automated steps occur:
|
|
415
|
+
|
|
416
|
+
1. The [release notes](./RELEASE_NOTES.md) will be updated according to commit messages history;
|
|
417
|
+
2. The library version will be bumped;
|
|
418
|
+
3. A new commit will be created with the updated version and release notes;
|
|
419
|
+
4. A new Git tag will be created in the repository;
|
|
420
|
+
5. The new version of the library will be published to npm;
|
|
421
|
+
|
|
422
|
+
After these automated steps, a few manual actions are required:
|
|
423
|
+
|
|
424
|
+
1. Announce the new release in the slack channel [#react-banana-ui-component-library](https://bloomreach.slack.com/archives/C05E4672ZLZ) :tada:;
|
|
425
|
+
2. Mark the new version as `released` in the [releases section in Jira](https://bloomreach.atlassian.net/projects/BU?selectedItem=com.atlassian.jira.jira-projects-plugin%3Arelease-page) once the ticket is merged and closed;
|
|
426
|
+
3. Take a break and then pick up the next challenge :muscle:!
|
|
427
|
+
|
|
428
|
+
## Code Quality Standards
|
|
429
|
+
|
|
430
|
+
This section outlines the code quality standards enforced in the React Banana UI library, covering linting, formatting, security, and performance. Adhering to these standards ensures maintainable, secure, and performant code.
|
|
431
|
+
|
|
432
|
+
### Linting & Formatting
|
|
433
|
+
|
|
434
|
+
- **ESLint Configuration**: We use a comprehensive ESLint configuration to enforce code quality and consistency. Refer to the `eslint.config.js` file for detailed rules.
|
|
435
|
+
- **Import Organization**: Maintain a structured import order for readability and consistency. Generally, external libraries come first, followed by internal utilities, components, types, and finally, styles.
|
|
436
|
+
- **Prettier Settings**: Our codebase adheres to a strict Prettier formatting configuration. Ensure your code is formatted using the provided scripts (`npm run format` / `npm run format:check`).
|
|
437
|
+
- **Quality Scripts**: Utilize `npm run lint` (`npm run lint:fix` for auto-fixing), `npm run format` (`npm run format:check` for checking), and `npm run check:types` for type validation.
|
|
438
|
+
|
|
439
|
+
### Git Hooks (Husky)
|
|
440
|
+
|
|
441
|
+
We utilize [Husky](https://typicode.github.io/husky/#/) to manage Git hooks, ensuring that certain scripts are run automatically before commits or pushes. This helps maintain code quality and consistency across the repository.
|
|
442
|
+
|
|
443
|
+
- **Pre-commit hook**: Runs `npm run lint` and `npm run format` to check for linting errors and enforce code formatting before a commit is created. This ensures that only properly formatted and linted code is committed to the repository.
|
|
444
|
+
- **Pre-push hook**: Runs `npm run check:types` to perform TypeScript type checking before code is pushed to the remote repository. This helps catch type-related issues early in the development cycle.
|
|
445
|
+
|
|
446
|
+
### Security Best Practices
|
|
447
|
+
|
|
448
|
+
- **Input Validation**: Use specific types (avoid `any`), union types for variants (e.g., `primary | secondary`), and avoid `dangerouslySetInnerHTML`. Sanitize `className` inputs to allow only trusted class combinations.
|
|
449
|
+
- **Event Handler Security**: Prevent default actions when components are loading or disabled. Safely call optional callbacks using optional chaining (e.g., `onClick?.(event)`).
|
|
450
|
+
- **XSS Prevention**: Avoid `dangerouslySetInnerHTML`, leverage React's built-in escaping, validate SVG props, and use trusted sources for assets.
|
|
451
|
+
- **Dependency Security**: Regularly run `npm run security-audit`, adhere to specified Node.js and npm version requirements, control React peer dependencies, and commit `package-lock.json`.
|
|
452
|
+
|
|
453
|
+
### Performance Guidelines
|
|
454
|
+
|
|
455
|
+
- **Component Optimization**: Memoize expensive components (`memo`) and calculations (`useMemo`), and useCallback for event handlers to prevent unnecessary re-renders.
|
|
456
|
+
- **Bundle Optimization**: Prefer named imports (e.g., `import { Button } from ...`) for effective tree shaking and modular utility imports.
|
|
457
|
+
- **Efficient Patterns**: Memoize class computations with `useMemo`, avoid inline object creation for styles, and use controlled value hooks.
|
|
458
|
+
- **Memory Management**: Implement cleanup functions in `useEffect` for subscriptions and event listeners to prevent memory leaks.
|
|
459
|
+
|
|
460
|
+
### CSS Performance
|
|
461
|
+
|
|
462
|
+
- **Efficient Selectors**: Favor single-class selectors (e.g., `.rbui-button--primary`) over complex, nested selectors. Use design tokens (e.g., `var(--banana-text-primary)`) and avoid deep nesting (max 3 levels).
|
|
463
|
+
|
|
464
|
+
### Performance Budgets
|
|
282
465
|
|
|
283
|
-
-
|
|
284
|
-
-
|
|
285
|
-
-
|
|
286
|
-
- The new git tag will be created in the repository;
|
|
287
|
-
- The new version of the library will be published to npm;
|
|
466
|
+
- **Bundle size**: Aim for minimal bundle sizes, typically <50KB per component and <100KB for core components.
|
|
467
|
+
- **Build Optimization**: Externalize peer dependencies to reduce bundle size.
|
|
468
|
+
- **Asset Optimization**: Optimize SVG assets for efficient loading.
|
|
288
469
|
|
|
289
|
-
|
|
470
|
+
### Common Pitfalls to Avoid
|
|
290
471
|
|
|
291
|
-
|
|
292
|
-
- Mark the new version as `released` in the [releases section in Jira](https://bloomreach.atlassian.net/projects/BU?selectedItem=com.atlassian.jira.jira-projects-plugin%3Arelease-page) once the ticket is merged and closed;
|
|
293
|
-
- Take a break and then pick up the next challenge :muscle:!
|
|
472
|
+
Avoid inline arrow functions for `onClick`, inline style objects, and unmemoized expensive calculations.
|