From e1b85c8fe608f786ad8ec60412af657c6851c588 Mon Sep 17 00:00:00 2001 From: Xaviju Date: Tue, 14 Jan 2025 14:57:12 +0100 Subject: [PATCH] :books: Add semantics and accessibility requirements --- docs/technical-guide/developer/ui.md | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/docs/technical-guide/developer/ui.md b/docs/technical-guide/developer/ui.md index db958e2cd..24628ce97 100644 --- a/docs/technical-guide/developer/ui.md +++ b/docs/technical-guide/developer/ui.md @@ -15,13 +15,20 @@ The UI in Penpot uses React v18 , with the help of [rumext](https://github.com/f We want to hold our UI code to the same quality standards of the rest of the codebase. In practice, this means: - UI components should be easy to maintain over time, especially because our design system is ever-changing. -- UI components should be accessible, and use the relevant HTML elements and/or Aria roles when applicable. - We need to apply the rules for good software design: - The code should adhere to common patterns. - UI components should offer an ergonomic "API" (i.e. props). - UI components should favor composability. - Try to have loose coupling. +### Semantics and accessibility + +**Semantic HTML** When developing UI components in Penpot, we believe it is crucial to ensure that our frontend code is semantic and follows HTML conventions. Semantic HTML helps improve the readability and accessibility of Penpot. Use appropriate HTML tags to define the structure and purpose of your content. This not only enhances the user experience but also ensures better accessibility. + +**Accessibility** All UI code must be accessible. Ensure that your components are designed to be usable by people with a wide range of abilities and disabilities. + +> ✅ When a component follows a pattern set in the WCAG patterns page, we adhere to the rules and guidelines specified there. This ensures consistency and compliance with accessibility standards. See more at [Patterns | APG | WAI | W3C](https://www.w3.org/WAI/ARIA/apg/patterns/) + ### Composability **Composability is a common pattern** in the Web. We can see it in the standard HTML elements, which are made to be nested one inside another to craft more complex content. Standard Web components also offer slots to make composability more flexible. @@ -356,7 +363,7 @@ When we do this inside of a component, a brand new function is created in every #### Avoid defining functions with partial inside of components -partial returns a brand new anonymous function, so we should avoid using it in each render. For callback handlers that need parameters, a work around is to store these as data-* attributes and retrieve them inside the function. +partial returns a brand new anonymous function, so we should avoid using it in each render. For callback handlers that need parameters, a work around is to store these as data-\* attributes and retrieve them inside the function. ❌ **AVOID: Using `partial` inside of a component** @@ -371,7 +378,7 @@ When we do this inside of a component, a brand new function is created in every [:> numeric-input* {:on-change (partial set-margin :right)}] ]) ``` -✅ **DO: Use data-* attributes to modify a function (many uses)** +✅ **DO: Use data-\* attributes to modify a function (many uses)** ```clojure (defn- set-margin [value event] @@ -573,7 +580,7 @@ Things to take into account when considering which stories to add and how to wri - Leverage setting base prop values in args and common rendering code in render to reuse those in the stories and avoid code duplication. -For instance, the stories file for the button* component looks like this: +For instance, the stories file for the button\* component looks like this: ```jsx // ... @@ -620,7 +627,7 @@ export const Secondary = { In addition to the above, please **use the [Controls addon](https://storybook.js.org/docs/essentials/controls)** to let users change props and see their effect on the fly. -Controls are customized with argTypes, and you can control which ones to show / hide with parameters.controls.exclude. For instance, for the button* stories file, its relevant control-related code looks like this: +Controls are customized with argTypes, and you can control which ones to show / hide with parameters.controls.exclude. For instance, for the button\* stories file, its relevant control-related code looks like this: ```jsx // ... @@ -668,17 +675,20 @@ You can find an example MDX file in the [Buttons docs](https://hourly.penpot.dev We need to generate the screenshots for the visual regression tests _before_ making any changes, so we can compare the "before substitution" and "after substitution" states. - Execute the tests in the playwright's ds project. In order to do so, stop the Shadow CLJS compiler in tmux tab #1 and run; + ```bash clojure -M:dev:shadow-cljs release main ``` + This will package the frontend in release mode so the tests run faster. In your terminal, in the frontend folder, run: + ```bash npx playwright test --ui --project=ds ``` + This will open the test runner UI in the selected project. ![Playwright UI](/img/tech-guide/playwright-projects.webp) @@ -696,7 +706,7 @@ In the selected file add the new namespace from the [:> tab-switcher* {}] ``` -> **⚠️ NOTE**: Components with a * suffix are meant to be used with the [:> handler. +> **⚠️ NOTE**: Components with a \* suffix are meant to be used with the [:> handler. Please refer to [Rumext User Guide](https://funcool.github.io/rumext/latest/user-guide.html) for more information. @@ -718,6 +728,7 @@ Check the props schema in the component’s source file {::mf/props :obj ::mf/schema schema:tab-switcher}...) ``` + This schema shows which props are required and which are optional, so you can include the necessary values with the correct types.