---
# System prepended metadata

title: how is the frontend team using the design system

---

# The Base unit system
- Units are based on 4px
- For examples:
    - Padding: 4 translates to 16px.
    - While half units are possible, **we discourage their use (e.g., padding: 0.5 equals 2px)**.
    - The choice of 4px as the base unit is rooted in accommodating higher screen densities in modern devices, such as the iPhone 3G's Retina display where 4px is equivalent to 1px.


# Design tokens

- variable names in theme object **cannot** be changed
- changing existing variable values impacts MUI components
- https://bareynol.github.io/mui-theme-creator/
- adding custom variables is possible
- typography is exendable e.g adding typography.title1 token
- palletes are extendable, e.g adding a brand: {} token to palletes

- **breakpoints**
    - Safe to customize
- **elevation** (see https://mui.com/material-ui/react-paper/)
    - **Caution: Adjusting elevation impacts all Material-UI components.**
    - Used by MUI Paper Element and Modules that uses it e.g Cards
    - ![image](https://hackmd.io/_uploads/r13MHCEBT.png)
- **pallete** **
    - **Leverage recommended tools below because it ensures that existing MUI modules retains its color accessibility feature.**
    - mui color doc https://mui.com/material-ui/customization/color/
    - color system doc https://m2.material.io/design/color/the-color-system.html#color-theme-creation
    - use this tool to configure https://m2.material.io/inline-tools/color/ 
    - use only colors from here https://mui.com/material-ui/customization/color/ ![image](https://hackmd.io/_uploads/SyQQUC4S6.png)
- **pallete.action** **
    - Governs the state colors of interactive elements such as Buttons, Dropdowns, Inputs, IconButtons, Popover(Tooltip and Modal), Links 
        - "active": "rgba(0, 0, 0, 0.54)",
        - "hover": "rgba(0, 0, 0, 0.04)",
        - "hoverOpacity": 0.04,
        - "selected": "rgba(0, 0, 0, 0.08)",
        - "selectedOpacity": 0.08,
        - "disabled": "rgba(0, 0, 0, 0.26)",
        - "disabledBackground": "rgba(0, 0, 0, 0.12)",
        - "disabledOpacity": 0.38,
        - "focus": "rgba(0, 0, 0, 0.12)",
        - "focusOpacity": 0.12,
        - "activatedOpacity": 0.12

- **pallete.divider**
    - used by https://mui.com/system/react-stack/#dividers module
    - ![image](https://hackmd.io/_uploads/SkOvPkHH6.png)

- **shadows** ** 
    - **Approach with caution**; altering shadows resonates across the entire Material-UI ecosystem.
    - see all available shadows here https://codepen.io/Kenan-Xin/pen/vYbzjpw
    - Addition of new shadow variants is possible
- **shape.borderRadius** **
    - The base unit for border radius calculation, it is applied to all MUI's components from buttons to cards to everywhere where there is a rounded corner
    - The default base unit is **4**
    - UI components defines its border radius based on this base unit, **internally**, for example ,a Button **MIGHT** have shape.borderRadius * 1 = 4px, Card **Might** have shape.borderRadius * 2 = 8px
    - Changing the **base unit** results in a **change globally** for all **MUI modules**
- **typography** ***
    - default base unit is 14px, all rem values are based of 14px
    - this default **can be changed/overridden**
    - **always use rem units**
    - each typography variant to have a responsive variant that **changes/scales automatically based on screen size**
    - for example
        - h1: 
            - xs: 1.8rem
            - md: 2.2rem
        - ![image](https://hackmd.io/_uploads/rJhoheHHa.png)
    - **using a different typography variant on the same Module is not possible**
        - ![image](https://hackmd.io/_uploads/r1zpClSH6.png)



# Fontend component design methodology
## Elements
- The **base composable units** for **modules** and **layouts**:
    - Paper
    - Box
    - Button
    - TextBox
    - Select
    - List
    - Card
    - Tabs
    - Grid
    - Link
    - Menu
    - ......
- Elements **cannot contain modules**, elements sits within the scope of other modules and layouts
- Elements **can contain layouts**
- Elements should not have margins and should be isolated inside its own imaginanary box(border)
- Elements can be either **Inline** (width depends on its content), or **Block** (occupies full width of its **parent container** )
- Elements are Flexible (**one off customization/override is possible but not recommended**)
- Elements have variants 
    - <Button variant="outlined" size="small|medium|large" />
- Elements can have states
    - Checkbox [state = checked]
    - ListItem [state = selected]
- Elements are **ALWAYS** generic and **should not have any application-specific behaviour/logic/knowledge**


## Modules
- A Module is made of a group of elements and layouts. 
- A Module is a discrete component of the page. It is **Navigation bars** and  **Modals** and **Projection graph** and **Goal Card** and **Goal List**
- Modules **sit inside the scope of Layout components**.
- Modules **can sometimes sit within other Modules**, too. 
- Each Module should be designed to exist as a **standalone component**. In doing so, the page will be more flexible.
- Modules can easily be moved to different parts of the layout without breaking
- Modules **MUST have its own responsive behaviours** based on mobile responsive breakpoints
- Modules **should not have margin** that sticks out of its container and should not have design elements that affact other modules. 
- Modules **can have Responsive Paddings** based on **breakpoints*

### Master Modules
- Generic components regardless of project
- Can be 'plugged in' to any project/application
    - ErrorLoading
    - Modal
    - PieChart
    - ProjectionGraph
    - TextEditor
    - TextFieldWithValidationError
    - Accordion
    - Error404
    - FileUpload
    - Header
    - .....

### Project specific modules
- Contains business specific/application specific logics
    - BambuGo's Configure Transact Form
    - BambuGo's Create Account Form
    - BambuGo's KycForm

    
## Layouts
- Layouts dictates the positional relationship among modules and elements
- This includes padding, margin and spacing (between components)
- Examles of layouts in the wild: 
    - The **two column layout**
        - Specification:
            - Left and right side are of equal width
            - The contents of the layout can be aligned to 
                - left side of the imaginary borders
                - right side of the imaginary borders
                - Outter sides of the imaginary borders
                - Inner sides of the imginry borders

        - ![image](https://hackmd.io/_uploads/ByOBelBSp.png)
        - ![image](https://hackmd.io/_uploads/BypqeeHB6.png)
    - The **Bottom Action layout**
        - Specification:
            - On breakpoint xs, always stick to the bottom of the screen without blocking the contents above it
            - On breakpoint sm and up, is placed after the last element
        - ![image](https://hackmd.io/_uploads/Syk0-xrHp.png)
 
## component design thought process
https://excalidraw.com/#json=zZOXwQEifd4y_x9ZRz530,2Fdwt7g9jX7Ug4TfuxW5Rw


### Responsive design
- Mobile first, desktop design based off mobile by
    - Hiding elements
    - Switching direction: row/column
    - Changing module order:
        - e.g xs: [1][2][3] md:[3][1][2]
    - Placing modules inside responsive Layout components
    - Use responsive spacing units inside Modules
        - e.g xs: 1, sm:2, md:3 lg:4
    - Use Percentage units 
        - e.g margin: 10% of resizable **Browser window**, padding: 15% of **Module Container**
- Do not use a different module different breakpoints 



## References
### Available tokens overview with explanation


### Current Master theme object
```jsonld
{
    "breakpoints": {
        "keys": [
            "xs",
            "sm",
            "md",
            "lg",
            "xl"
        ],
        "values": {
            "xs": 0,
            "sm": 600,
            "md": 905,
            "lg": 1240,
            "xl": 1440
        },
        "unit": "px"
    },
    "direction": "ltr",
    "components": {
        "MuiAccordionSummary": {
            "styleOverrides": {}
        },
        "MuiAccordionDetails": {
            "styleOverrides": {}
        },
        "MuiAppBar": {
            "defaultProps": {
                "color": "default",
                "position": "static",
                "elevation": 1
            },
            "styleOverrides": {
                "colorDefault": {
                    "backgroundColor": "#fff"
                }
            }
        },
        "MuiAvatar": {
            "styleOverrides": {
                "root": {
                    "fontSize": "1rem"
                }
            }
        },
        "MuiButton": {
            "styleOverrides": {
                "root": {
                    "borderRadius": 2,
                    "textTransform": "none",
                    "minWidth": 99
                },
                "contained": {
                    "boxShadow": "none"
                },
                "containedPrimary": {
                    "color": "white"
                },
                "text": {
                    "minWidth": 64
                }
            },
            "defaultProps": {
                "variant": "contained"
            }
        },
        "MuiCard": {
            "styleOverrides": {
                "root": {
                    "borderRadius": 2
                }
            }
        },
        "MuiCheckbox": {
            "styleOverrides": {
                "root": {
                    "height": 18,
                    "width": 18
                }
            }
        },
        "MuiDialogActions": {
            "styleOverrides": {}
        },
        "MuiLink": {
            "defaultProps": {
                "underline": "none"
            }
        },
        "MuiMenu": {
            "styleOverrides": {
                "paper": {
                    "borderRadius": 2
                }
            },
            "defaultProps": {
                "elevation": 2
            }
        },
        "MuiOutlinedInput": {
            "styleOverrides": {
                "root": {
                    "backgroundColor": "#fff"
                }
            }
        },
        "MuiPaper": {
            "styleOverrides": {
                "elevation1": {
                    "boxShadow": "0px 1px 2px rgba(0, 0, 0, 0.05), 0px 1px 6px rgba(0, 0, 0, 0.1)"
                },
                "elevation2": {
                    "boxShadow": "0px 1px 3px rgba(0, 0, 0, 0.1), 0px 1px 7px rgba(0, 0, 0, 0.15)"
                },
                "elevation3": {
                    "boxShadow": "0px 1px 4px rgba(0, 0, 0, 0.15), 0px 1px 8px rgba(0, 0, 0, 0.2)"
                },
                "elevation4": {
                    "boxShadow": "0px 1px 5px rgba(0, 0, 0, 0.2), 0px 1px 9px rgba(0, 0, 0, 0.25)"
                },
                "elevation5": {
                    "boxShadow": "0px 2px 6px rgba(0, 0, 0, 0.2), 0px 2px 10px rgba(0, 0, 0, 0.3)"
                }
            }
        },
        "MuiTab": {
            "styleOverrides": {
                "root": {
                    "textTransform": "none"
                }
            }
        },
        "MuiSlider": {
            "defaultProps": {
                "valueLabelDisplay": "auto"
            },
            "variants": [
                {
                    "props": {
                        "size": "big"
                    },
                    "style": {
                        ".MuiSlider-thumb": {
                            "width": 44,
                            "height": 44
                        },
                        ".MuiSlider-markLabel": {
                            "top": 44
                        }
                    }
                }
            ]
        }
    },
    "palette": {
        "primary": {
            "main": "#00876A",
            "light": "rgb(51, 159, 135)",
            "dark": "rgb(0, 94, 74)",
            "contrastText": "#fff"
        },
        "secondary": {
            "main": "#406376",
            "light": "rgb(102, 130, 145)",
            "dark": "rgb(44, 69, 82)",
            "contrastText": "#fff"
        },
        "text": {
            "primary": "#191C1B",
            "secondary": "rgba(0, 0, 0, 0.6)",
            "disabled": "rgba(0, 0, 0, 0.38)"
        },
        "error": {
            "main": "#BA1A1A",
            "light": "rgb(199, 71, 71)",
            "dark": "rgb(130, 18, 18)",
            "contrastText": "#fff"
        },
        "background": {
            "default": "#FAFAFA",
            "paper": "#fff"
        },
        "warning": {
            "main": "#FFC025",
            "light": "rgb(255, 204, 80)",
            "dark": "rgb(178, 134, 25)",
            "contrastText": "rgba(0, 0, 0, 0.87)"
        },
        "common": {
            "black": "#000",
            "white": "#fff"
        },
        "info": {
            "main": "#0288d1",
            "light": "#03a9f4",
            "dark": "#01579b",
            "contrastText": "#fff"
        },
        "success": {
            "main": "#2e7d32",
            "light": "#4caf50",
            "dark": "#1b5e20",
            "contrastText": "#fff"
        },
        "grey": {
            "50": "#fafafa",
            "100": "#f5f5f5",
            "200": "#eeeeee",
            "300": "#e0e0e0",
            "400": "#bdbdbd",
            "500": "#9e9e9e",
            "600": "#757575",
            "700": "#616161",
            "800": "#424242",
            "900": "#212121",
            "A100": "#f5f5f5",
            "A200": "#eeeeee",
            "A400": "#bdbdbd",
            "A700": "#616161"
        },
        "contrastThreshold": 3,
        "tonalOffset": 0.2,
        "divider": "rgba(0, 0, 0, 0.12)",
        "action": {
            "active": "rgba(0, 0, 0, 0.54)",
            "hover": "rgba(0, 0, 0, 0.04)",
            "hoverOpacity": 0.04,
            "selected": "rgba(0, 0, 0, 0.08)",
            "selectedOpacity": 0.08,
            "disabled": "rgba(0, 0, 0, 0.26)",
            "disabledBackground": "rgba(0, 0, 0, 0.12)",
            "disabledOpacity": 0.38,
            "focus": "rgba(0, 0, 0, 0.12)",
            "focusOpacity": 0.12,
            "activatedOpacity": 0.12
        }
    },
    "shape": {
        "borderRadius": 4
    },
    "typography": {
        "fontFamily": "Lato,Roboto,sans-serif",
        "htmlFontSize": 16,
        "fontSize": 14,
        "fontWeightLight": 300,
        "fontWeightRegular": 400,
        "fontWeightMedium": 500,
        "fontWeightBold": 700,
        "h1": {
            "fontFamily": "Lato,Roboto,sans-serif",
            "fontWeight": 300,
            "fontSize": "6rem",
            "lineHeight": 1.167
        },
        "h2": {
            "fontFamily": "Lato,Roboto,sans-serif",
            "fontWeight": 300,
            "fontSize": "3.75rem",
            "lineHeight": 1.2
        },
        "h3": {
            "fontFamily": "Lato,Roboto,sans-serif",
            "fontWeight": 400,
            "fontSize": "3rem",
            "lineHeight": 1.167
        },
        "h4": {
            "fontFamily": "Lato,Roboto,sans-serif",
            "fontWeight": 400,
            "fontSize": "2.125rem",
            "lineHeight": 1.235
        },
        "h5": {
            "fontFamily": "Lato,Roboto,sans-serif",
            "fontWeight": 400,
            "fontSize": "1.5rem",
            "lineHeight": 1.334
        },
        "h6": {
            "fontFamily": "Lato,Roboto,sans-serif",
            "fontWeight": 500,
            "fontSize": "1.25rem",
            "lineHeight": 1.6
        },
        "subtitle1": {
            "fontFamily": "Lato,Roboto,sans-serif",
            "fontWeight": 400,
            "fontSize": "1rem",
            "lineHeight": 1.75
        },
        "subtitle2": {
            "fontFamily": "Lato,Roboto,sans-serif",
            "fontWeight": 500,
            "fontSize": "0.875rem",
            "lineHeight": 1.57
        },
        "body1": {
            "fontFamily": "Lato,Roboto,sans-serif",
            "fontWeight": 400,
            "fontSize": "1rem",
            "lineHeight": 1.5
        },
        "body2": {
            "fontFamily": "Lato,Roboto,sans-serif",
            "fontWeight": 400,
            "fontSize": "0.875rem",
            "lineHeight": 1.43
        },
        "button": {
            "fontFamily": "Lato,Roboto,sans-serif",
            "fontWeight": 500,
            "fontSize": "0.875rem",
            "lineHeight": 1.75,
            "textTransform": "uppercase"
        },
        "caption": {
            "fontFamily": "Lato,Roboto,sans-serif",
            "fontWeight": 400,
            "fontSize": "0.75rem",
            "lineHeight": 1.66
        },
        "overline": {
            "fontFamily": "Lato,Roboto,sans-serif",
            "fontWeight": 400,
            "fontSize": "0.75rem",
            "lineHeight": 2.66,
            "textTransform": "uppercase"
        },
        "inherit": {
            "fontFamily": "inherit",
            "fontWeight": "inherit",
            "fontSize": "inherit",
            "lineHeight": "inherit",
            "letterSpacing": "inherit"
        }
    },
    "mixins": {
        "toolbar": {
            "minHeight": 56,
            "@media (min-width:0px)": {
                "@media (orientation: landscape)": {
                    "minHeight": 48
                }
            },
            "@media (min-width:600px)": {
                "minHeight": 64
            }
        }
    },
    "shadows": [
        "none",
        "0px 2px 1px -1px rgba(0,0,0,0.2),0px 1px 1px 0px rgba(0,0,0,0.14),0px 1px 3px 0px rgba(0,0,0,0.12)",
        "0px 3px 1px -2px rgba(0,0,0,0.2),0px 2px 2px 0px rgba(0,0,0,0.14),0px 1px 5px 0px rgba(0,0,0,0.12)",
        "0px 3px 3px -2px rgba(0,0,0,0.2),0px 3px 4px 0px rgba(0,0,0,0.14),0px 1px 8px 0px rgba(0,0,0,0.12)",
        "0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12)",
        "0px 3px 5px -1px rgba(0,0,0,0.2),0px 5px 8px 0px rgba(0,0,0,0.14),0px 1px 14px 0px rgba(0,0,0,0.12)",
        "0px 3px 5px -1px rgba(0,0,0,0.2),0px 6px 10px 0px rgba(0,0,0,0.14),0px 1px 18px 0px rgba(0,0,0,0.12)",
        "0px 4px 5px -2px rgba(0,0,0,0.2),0px 7px 10px 1px rgba(0,0,0,0.14),0px 2px 16px 1px rgba(0,0,0,0.12)",
        "0px 5px 5px -3px rgba(0,0,0,0.2),0px 8px 10px 1px rgba(0,0,0,0.14),0px 3px 14px 2px rgba(0,0,0,0.12)",
        "0px 5px 6px -3px rgba(0,0,0,0.2),0px 9px 12px 1px rgba(0,0,0,0.14),0px 3px 16px 2px rgba(0,0,0,0.12)",
        "0px 6px 6px -3px rgba(0,0,0,0.2),0px 10px 14px 1px rgba(0,0,0,0.14),0px 4px 18px 3px rgba(0,0,0,0.12)",
        "0px 6px 7px -4px rgba(0,0,0,0.2),0px 11px 15px 1px rgba(0,0,0,0.14),0px 4px 20px 3px rgba(0,0,0,0.12)",
        "0px 7px 8px -4px rgba(0,0,0,0.2),0px 12px 17px 2px rgba(0,0,0,0.14),0px 5px 22px 4px rgba(0,0,0,0.12)",
        "0px 7px 8px -4px rgba(0,0,0,0.2),0px 13px 19px 2px rgba(0,0,0,0.14),0px 5px 24px 4px rgba(0,0,0,0.12)",
        "0px 7px 9px -4px rgba(0,0,0,0.2),0px 14px 21px 2px rgba(0,0,0,0.14),0px 5px 26px 4px rgba(0,0,0,0.12)",
        "0px 8px 9px -5px rgba(0,0,0,0.2),0px 15px 22px 2px rgba(0,0,0,0.14),0px 6px 28px 5px rgba(0,0,0,0.12)",
        "0px 8px 10px -5px rgba(0,0,0,0.2),0px 16px 24px 2px rgba(0,0,0,0.14),0px 6px 30px 5px rgba(0,0,0,0.12)",
        "0px 8px 11px -5px rgba(0,0,0,0.2),0px 17px 26px 2px rgba(0,0,0,0.14),0px 6px 32px 5px rgba(0,0,0,0.12)",
        "0px 9px 11px -5px rgba(0,0,0,0.2),0px 18px 28px 2px rgba(0,0,0,0.14),0px 7px 34px 6px rgba(0,0,0,0.12)",
        "0px 9px 12px -6px rgba(0,0,0,0.2),0px 19px 29px 2px rgba(0,0,0,0.14),0px 7px 36px 6px rgba(0,0,0,0.12)",
        "0px 10px 13px -6px rgba(0,0,0,0.2),0px 20px 31px 3px rgba(0,0,0,0.14),0px 8px 38px 7px rgba(0,0,0,0.12)",
        "0px 10px 13px -6px rgba(0,0,0,0.2),0px 21px 33px 3px rgba(0,0,0,0.14),0px 8px 40px 7px rgba(0,0,0,0.12)",
        "0px 10px 14px -6px rgba(0,0,0,0.2),0px 22px 35px 3px rgba(0,0,0,0.14),0px 8px 42px 7px rgba(0,0,0,0.12)",
        "0px 11px 14px -7px rgba(0,0,0,0.2),0px 23px 36px 3px rgba(0,0,0,0.14),0px 9px 44px 8px rgba(0,0,0,0.12)",
        "0px 11px 15px -7px rgba(0,0,0,0.2),0px 24px 38px 3px rgba(0,0,0,0.14),0px 9px 46px 8px rgba(0,0,0,0.12)"
    ],
    "transitions": {
        "easing": {
            "easeInOut": "cubic-bezier(0.4, 0, 0.2, 1)",
            "easeOut": "cubic-bezier(0.0, 0, 0.2, 1)",
            "easeIn": "cubic-bezier(0.4, 0, 1, 1)",
            "sharp": "cubic-bezier(0.4, 0, 0.6, 1)"
        },
        "duration": {
            "shortest": 150,
            "shorter": 200,
            "short": 250,
            "standard": 300,
            "complex": 375,
            "enteringScreen": 225,
            "leavingScreen": 195
        }
    },
}

```

### Sample workflow
#### Design token 
1. design team to figure out and finalise design tokens progressively , piece by piece, for example start with spacings
2. frontend team to integrate that design token into FE theme object
3. FE test/UI test/Automated visual test (chromatic)/QA test
4. repeat 1-4
5. frontend team to perform ongoing restructuring/clean up for existing components and ensure that design token is used for new code addition

#### Layouts and Modules
1. Design team to study existing design files and extract 1 layout/module that can be extracted/abstracted
	1. Ensure that layouts have responsive paddings e.g xs: 1 , sm:2,  md:3
	2. Ensure that modules have its responsive variants and TRY only change
		1. Direction: row or column
		2. spacing (padding only)
		3. alignment : left, right, center, space-between, space-around
		4. Orderings of elements inside
	3. Ensure that layouts/modules  have no margin
	4. Define  variants (fixed sets), be restrictive and keep the number of variants small. The more variants , the more complex the code becomes and the easier it is for undiscovered bugs to sneak in , and spread, and crawl onto your bed ...
	5. It is (Recommended) to create separate component as opposed to using variants e.g
		1. BigButton, SmallButton  vs Button[size="small']  Button[size="big"]
2. Extract it 
3. Apply that layout throughout project files and make modifications to designs such that that layout can be used in as many places as possible
4. Create a ticket and assign to FE
5. FE to integrate the module/component into code base
6. FE test/UI test/Automated visual test (chromatic)/QA test
7. repeat 1-6
8. frontend team to perform ongoing restructuring/clean up for existing components and ensure that design token is used for new code addition