Skip to content

[discovery] Apply styles to React component via CSS modules + write ADR #505

@adamstankiewicz

Description

@adamstankiewicz

The primary mechanism for CSS styles authoring across Open edX micro-frontends (MFEs) is through the use of SCSS. Generally, MFEs will create custom stylesheets and import them from a global stylesheet acting as the styles entry point (example). By doing so, all component-specific stylesheets have access to global tokens (e.g., SCSS variables from Paragon like $primary-500).

The other alternative used through Open edX MFEs is to import the SCSS/CSS file directly within the React component itself. This approach has the downside that Paragon's SCSS variables are not available to these stylesheets when imported in this manner.

However, both of these approaches generally result in all styles getting combined and applied globally across the entire MFE application. The risk of this approach, which has caused style regressions numerous times throughout the years, is that engineers may not know their custom styles are impacting UI unrelated to their specific component(s).

For example, if I create the following component-specific stylesheet and import it using either of the aforementioned approaches, it's override of the .card class name will apply to every single Card in the application, not just my one intended feature.

// MyComponent.scss
.card {
  min-height: 10rem;
}

The current workaround to this downside is to make the class name definition have more specificity, whereby the .card styles are scoped to a specific feature/component, e.g.:

// MyComponent.scss
.my-component {
  .card {
    min-height: 10rem;
  }
}

However, needing to rely on specificity to prevent unintended style conflicts/regressions is arguably fairly brittle. Ideally, we could rely on more modern approaches to applying styles to React components. One proposed idea in the past (see discussion) was CSS modules (spec). By using CSS modules, engineers can guarantee their custom styles only apply to their specific UI elements/components, without risking style regressions throughout the entire application.

Example:

// MyComponent.scss
.card {
  min-height: 10rem;
}
import styles from './path/to/MyComponent.module.scss';

function MyComponent() {
  return (
    <Card className={styles.card}>
      ...
    </Card>
  );
}

The difference here is that .card is now locally scoped to MyComponent and can never apply outside of this one component.

### Tasks
- [ ] Perform technical discovery around whether Open edX MFEs support CSS modules today. If not, figure out what it would take to support CSS modules. For example, perhaps the Webpack configuration needs to change around the `css-loader` ([docs](https://github.com/css-modules/css-modules/blob/master/docs/get-started.md#webpack)).
- [ ] Write an ADR documenting the support for CSS modules and the recommendation for consumers to start adopting them in MFEs (could be done incrementally).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions