Skip to content

feat: Brand UI updates (M2-9137) - #2091

Merged
andrevitalb merged 50 commits into
developfrom
feat/M2-9137-brand-ui-updates
Jun 20, 2025
Merged

feat: Brand UI updates (M2-9137)#2091
andrevitalb merged 50 commits into
developfrom
feat/M2-9137-brand-ui-updates

Conversation

@andrevitalb

@andrevitalb andrevitalb commented Jun 11, 2025

Copy link
Copy Markdown
Contributor
  • Tests for the changes have been updated
  • Delivered the fix or feature branches into develop or release branches via Squash and Merge (to keep clean history)

📝 Description

🔗 Jira Ticket M2-9137
🔗 Jira Ticket M2-9396
🔗 Jira Ticket M2-9421
🔗 Jira Ticket M2-9422
🔗 Jira Ticket M2-9425

This PR introduces the main new brand UI changes to align with Curious's branding. The two main changes covered in this PR are:

🎨 Palette updates

A whole revamp of the current palette system was introduced, with new helper functions like flattenPaletteObject and hexToRgba. This revamp will allow for easier maintainability in the future and reduced modifications needed for a single change.

The palette object is now constructed from three main pieces:

  1. The basePalette object. This object contains all base "primitive" colors, taken straight out of the design system. No semantics here, just main name and numeric or string items inside to target a specific color. For example: primary[90], blue.light, neutral_variant[95], etc. These will serve as a reference base for the next object. To understand the next two objects, a simple palette object with tonal variations will be used:

    const baseExamplePalette = {
      primary: {
        default: '#0B0907',
        0: '#000',
        10: '#1D1B19',
        20: '#32302D',
        30: '#484744',
        40: '#5F5E5B',
        50: '#787773',
        60: '#91918E',
        70: '#ACABA9',
        80: '#C6C6C5',
        90: '#E3E2E1',
        95: '#F1F0EF',
        99: '#FDFCFC',
        100: '#FFF',
      },
      secondary: {
        0: '#000',
        10: '#041847',
        20: '#182D65',
        30: '#173F9F',
        40: '#004CED',
        50: '#216DFF',
        60: '#3C90FF',
        70: '#55B1FF',
        80: '#8BCEFF',
        90: '#CAE6FF',
        95: '#E5F3FF',
        99: '#FBFCFF',
        100: '#FFF',
      },
    }
  2. The semanticPalette object. This object consists of two main components:

    1. The flattened palette objects from basePalette, transforming object references like that of primary (containing different tonal variations within it) and flattening them into values like primary30, primary40, primary50, and so on. One special note to make for these flattened objects is that for each palette object, either the value for default (if any exists) or the value from the tonal 40 (primary[40], in the example that's being used) will be used as the main color reference so that the color can be used as usually expected palette.primary. In the case that a "default" value exists, the value will ONLY be returned as the main color entry (palette.primary), otherwise the tonal value 40 will be returned as both the main color entry and its corresponding tonal value (palette.secondary and palette.secondary40). This all happens within the flattenPaletteObject helper function.
    2. The semantic names for palette entries like surface, on_surface, on_primary, primary_container, on_primary_container, etc.
  3. The alphaVariantsPalette object. This object contains any variants that make use of the semantic values from the semanticPalette object, and then applies a custom alpha value to them, giving values to the required color variables like on_secondary_container_alpha12. The helper function hexToRgba is crucial for this to happen.

The final palette object is built with the values from both the semanticPalette and alphaVariantsPalette objects.

⌨️ Typography updates

An initial base revamp on how are font stylings alined to the design system was also introduced, with one main change in mind:

Improving font-size, line-height and letter-spacing consistency to match the new typography styles, comprised of 5 main categories (display, headline, title, label and body) and each of those subdivided into sizes.

This was achieved by providing updates to two main areas:

  • Custom styled components that make use of the corresponding typography styles values (see Typography.ts).
  • Custom typography variants introduced to the main MUI theme, so that they can be used in any MUI component (see theme.tsx)

Along these two main areas of changes, specific changes were introduced:

  • Hyperlinks are now to use "secondary" as color.
  • All buttons of the "outline" variant are now to have outline_variant as their border color.
  • A component specific change: Notification badge on the avatar in the top right of the admin panel to now use "tertiary" as background color.
  • Updates to Breadcrumbs, Button and MUI Menu.
  • Favicon updated

Finally, propagation to custom overwrites to match new design system were included.

📸 Screenshots

A couple of screenshots across the platform:

90220
58208
67489
49377
95049

🪤 Peer Testing

These changes are now reflected throughout the entire platform and are aligned with the new design system.

📝 Notes

An interesting find during the test updates for these changes was an issue with cyclic barrel imports:

When running tests, a single error was being raised in multiple places, all in reference to styled components:

TypeError: Cannot read properties of undefined (reading '__emotion_styles')

      31 | ;
      32 |
    > 33 | export const StyledPlaceholder = styled(StyledBodyLarge)
         |                                        ^
      34 |   position: absolute;
      35 |   left: 1.65rem;
      36 |   top: 1.6rem;

After some digging, these are the findings:

Root cause

  1. SelectController.styles.ts (and a few other files) do this:

    import { StyledBodyLarge, variables, theme } from 'shared/styles';
  2. shared/styles/index.ts re-exports everything from shared/styles/styledComponents.

  3. One of those re-exported files (shared/styles/styledComponents/ConditionalSummary.ts) imports SelectController again, which of course pulls in SelectController.styles.ts.

This gives the circular loading chain below (→ means “requires”):

shared/components/FormComponents/SelectController.styles
    → shared/styles            (barrel)
      → shared/styles/styledComponents/index
        → …ConditionalSummary
          → SelectController
            → SelectController.styles   (already running!)

When Node (used by Jest) hits the arrow that goes back to a module that is still being evaluated, the current, half-initialised exports object is returned. At that moment StyledBodyLarge has not been defined yet, so inside SelectController.styles.ts it is undefined.

styled(StyledBodyLarge) therefore tries to read __emotion_styles on undefined and we get the runtime error only during tests.

Why the app still works in the browser Webpack bundles the code as ES-modules with live bindings; the second access to StyledBodyLarge happens after the module finishes evaluating, so the value is there. Jest runs the CommonJS build produced by babel-jest, where the value is captured at import-time, so the cycle bites.

This issue was solved with a simple fix: Breaking the cycle.

Updates were added to SelectController.styles.ts, ActivityThumbnail.ts and Badge.ts.

The imports were updated moving from something like this:

import { StyledBodyLarge, variables, theme } from 'shared/styles';

To something like this:

import { variables } from 'shared/styles/variables';
import theme from 'shared/styles/theme';
import { StyledBodyLarge } from 'shared/styles/styledComponents/Typography';

This was the exact update done to SelectController.styles.ts, the first (and worst) offender.

Now, we can live worry free of this being an issue again (at least while we keep that it was an issue in mind).

My research took me a tad (way) further down the road on this, but I believe enough context was given to note the importance of avoiding this issue. Always up for sharing more notes for those who want to see just how deep the rabbit hole goes.

@aws-amplify-us-east-1

Copy link
Copy Markdown

This pull request is automatically being deployed by Amplify Hosting (learn more).

Access this pull request here: https://pr-2091.d19gtpld8yi51u.amplifyapp.com

@farmerpaul farmerpaul left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have 5 pending comments but I can't seem to locate them on this rather slow Files changed tab… so gonna post what I have so far!

Comment thread src/assets/fonts/Affix/Affix-Light.otf
Comment thread src/modules/Auth/features/Login/Login.styles.ts
Comment thread src/shared/styles/variables/palette.ts
Comment thread src/shared/styles/variables/palette.ts

@farmerpaul farmerpaul left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm gonna approve this, pending my earlier comments. I haven't looked at every single code change but I trust the quality of it, and it appears to be mainly search & replace. I've mentioned the couple things that stood out to me, and I think the remaining peer testing can be done by QA.

Amazing work in such a short period of time! 💪🏻

Comment thread src/shared/styles/variables/palette.ts
@andrevitalb
andrevitalb merged commit 8eb75bf into develop Jun 20, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants