From c0af77faf705d9e63d89eff8b7831a357f5d5219 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Thu, 22 May 2025 10:06:03 +0200 Subject: [PATCH] :books: Add css rules to the UI guide (#6521) * :books: Add css rules to UI guide * :bug: Solve comments on PR * :bug: Add missing class * :bug: Improve css modules improvement * :bug: Fix width * :bug: Fix note --- docs/technical-guide/developer/ui.md | 197 ++++++++++++++++++++++----- 1 file changed, 163 insertions(+), 34 deletions(-) diff --git a/docs/technical-guide/developer/ui.md b/docs/technical-guide/developer/ui.md index 5105e2bc5..c5c5cdd02 100644 --- a/docs/technical-guide/developer/ui.md +++ b/docs/technical-guide/developer/ui.md @@ -160,7 +160,7 @@ Nested styles for DOM elements that are not instantiated by our component should [{:keys [icon children class] :rest props}] (let [props (mf/spread-props props {:class (stl/css :button)})] [:> "button" props - (when icon [:> icon* {:icon-id icon :size "m"}]) + (when icon [:> icon* {:icon-id icon :size "m" :class (stl/css :icon)}]) [:span {:class (stl/css :label-wrapper)} children]])) ;; later in code @@ -205,6 +205,167 @@ Remember that nesting selector increases specificity, and it's usually not neede fill: var(--icon-color); } ``` +Note: Thanks to CSS Modules, identical class names defined in different files are scoped locally and do not cause naming collisions. + +### Use CSS logical properties + +The [logical properties](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_logical_properties_and_values) define styles relative to the content’s writing mode (e.g., inline, block) instead of physical directions (left, right, etc). This improves support for right-to-left (RTL) languages and enhances layout flexibility. + +❌ **AVOID: Physical properties** + +```scss +.btn { + padding-left: var(--sp-xs); +} +``` + +✅ **DO: Use direction‐relative equivalents** + +```scss +.btn { + padding-inline-start: var(--sp-xs); +} +``` + +Note: Although `width` and `height` are physical properties, their use is allowed in CSS files. They remain more readable and intuitive than their logical counterparts (`inline-size`, `block-size`) in many contexts. Since our layouts are not vertically-sensitive, we don't gain practical benefits from using logical properties here. + +### Use named DS variables + +Avoid hardcoded values like `px`, `rem`, or raw SASS variables `($s-*)`. Use semantic, named variables provided by the Design System to ensure consistency and scalability. + +#### Spacing (margins, paddings, gaps...) +Use variables from `frontend/src/app/main/ui/ds/spacing.scss`. These are predefined and approved by the design team — **do not add or modify values without design approval**. + +#### Fixed dimensions +For fixed dimensions (e.g., modals' widths) defined by design and not layout-driven, use or define variables in `frontend/src/app/main/ui/ds/_sizes.scss`. To use them: + +```scss +@use "../_sizes.scss" as *; +``` +Note: Since these values haven't been semantically defined yet, we’re temporarily using SASS variables instead of named CSS custom properties. + +#### Border Widths +Use border thickness variables from `frontend/src/app/main/ui/ds/_borders.scss`. To import: + +```scss +@use "../_borders.scss" as *; +``` + +Avoid using sass variables defined on `frontend/resources/styles/common/refactor/spacing.scss` that are deprecated. + +❌ **AVOID: Using sass unnamed variables or hardcoded values** + +```scss +.btn { + padding: $s-24; +} + +.icon { + width: 16px; +} +``` + +✅ **DO: Use DS variables** + +```scss +.btn { + padding: var(--sp-xl); +} + +.icon { + width: var(--sp-l); +} +``` + +### Use Proper Typography Components + +Replace plain text tags with `text*` or `heading*` components from the Design System to ensure visual consistency and accessibility. + +❌ **AVOID: Using text wrappers** + +```clojure + [:h2 {:class (stl/css :modal-title)} title] + [:div {:class (stl/css :modal-content)} + "Content"] +``` + +✅ **DO: Use spacing named variables** + +```clojure +... + [app.main.ui.ds.foundations.typography :as t] + [app.main.ui.ds.foundations.typography.heading :refer [heading*]] + [app.main.ui.ds.foundations.typography.text :refer [text*]] +... + + [:> heading* {:level 2 + :typography t/headline-medium + :class (stl/css :modal-title)} + title] + [:> text* {:as "div" + :typography t/body-medium + :class (stl/css :modal-content)} + "Content"] +``` + +When applying typography in SCSS, use the proper mixin from the Design System. + +❌ **AVOID: Deprecated mixins** + +```scss +.class { + @include headlineLargeTypography; +} +``` + +✅ **DO: Use the DS mixin** +```scss +@use "../ds/typography.scss" as t; + +.class { + @include t.use-typography("body-small"); +} +``` +You can find the full list of available typography tokens in [Storybook](https://design.penpot.app/storybook/?path=/docs/foundations-typography--docs). +If the design you are implementing doesn't match any of them, ask a designer. + + +### Use custom properties within components + +Reduce the need for one-off SASS variables by leveraging [CSS custom properties](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_cascading_variables/Using_CSS_custom_properties) in your component styles. This keeps component theming flexible and composable. + +For instance, this is how we handle the styles of \, which have a different style depending on the level of the message (default, info, error, etc.) + +```scss +.toast { + // common styles for all toasts + // ... + + --toast-bg-color: var(--color-background-primary); + --toast-icon-color: var(--color-foreground-secondary); + // ... more variables here + + background-color: var(--toast-bg-color); +} + +.toast-icon { + color: var(--toast-bg-color); +} + +.toast-info { + --toast-bg-color: var(--color-background-info); + --toast-icon-color: var(--color-accent-info); + // ... override more variables here +} + +.toast-error { + --toast-bg-color: var(--color-background-error); + --toast-icon-color: var(--color-accent-error); + // ... override more variables here +} + +// ... more variants here +``` ## Semantics and accessibility @@ -516,40 +677,8 @@ We use three **levels of tokens**: ### Implementing variants -We can leverage component tokens to easily implement variants, by overriding their values in each component variant. +We can leverage component tokens to easily implement variants as explained [here](/technical-guide/developer/ui/#use-custom-properties-within-components). -For instance, this is how we handle the styles of \, which have a different style depending on the level of the message (default, info, error, etc.) - -```scss -.toast { - // common styles for all toasts - // ... - - --toast-bg-color: var(--color-background-primary); - --toast-icon-color: var(--color-foreground-secondary); - // ... more variables here - - background-color: var(--toast-bg-color); -} - -.toast-icon { - color: var(--toast-bg-color); -} - -.toast-info { - --toast-bg-color: var(--color-background-info); - --toast-icon-color: var(--color-accent-info); - // ... override more variables here -} - -.toast-error { - --toast-bg-color: var(--color-background-error); - --toast-icon-color: var(--color-accent-error); - // ... override more variables here -} - -// ... more variants here -``` ### Using icons and SVG assets