saleor / macaw-ui Goto Github PK
View Code? Open in Web Editor NEWMacawUI: an official UI design kit for Saleor
Home Page: https://macaw-ui.vercel.app
MacawUI: an official UI design kit for Saleor
Home Page: https://macaw-ui.vercel.app
When using CSS grid values like flex-start
for alignItems
property are incorrect and vice versa, when using flexbox start
or end
are incorrect.
alignItems
should be split into gridAlignItems
and flexAlignItems
.
We should have color naming that helps us apply colors to different elements in different themes so that I as a developer do not need to use conditional statements for my colors e.g dark ? color.bg-1 : color.bg-2
. Those overrides should be applied on color tokens level e.g color.background
which then for the light theme will have a value of bg-2
and for the dark theme it will have a value of bg-1
.
We should use color names based on broader elements e.g surface
or icons
- similar to what Shopify Polaris is doing.
surface-gray
only to background-color
, not to color
or border-color
The Sidebar and SidebarDrawer logo is not optional, They are hard coded in code.
Why this ui library so strict to change logo?
themeType === "dark" ? <LogoDark /> : <Logo />
We currently load Inter font for old MacawUI from CDN - we should use one bundled with the new version.
Remove code that uses CDN to load Inter font and add missing (if there are) font weights to the current variable font.
We want to introduce a new version of MacawUI which will be a design system. The current version has a few problems:
Introduce a design system consisting of 3 parts:
Design primitives (tokens) should be the foundation of the Design System. We will have primitives for:
Warning
Code examples are created with CSS calc to demonstrate scales but in implementation, we are going to calculate variables inside JS and expose ready values as CSS variables.
Specific values of tokens can be adjusted by the theme creator - in this RFC we want to show the approach to managing and defining them.
CSS variables example:
:root {
--font-size-scale: 1.2;
--font-size-1: 0.75rem;
--font-size-2: calc(var(--font-size-1) * var(--font-size-scale));
--font-size-3: calc(var(--font-size-2) * var(--font-size-scale));
--font-size-4: calc(var(--font-size-3) * var(--font-size-scale));
--font-size-5: calc(var(--font-size-4) * var(--font-size-scale));
--font-size-6: calc(var(--font-size-5) * var(--font-size-scale));
--font-size-7: calc(var(--font-size-6) * var(--font-size-scale));
--font-size-8: calc(var(--font-size-7) * var(--font-size-scale));
--font-size-9: calc(var(--font-size-8) * var(--font-size-scale));
--font-size-10: calc(var(--font-size-9) * var(--font-size-scale));
--line-height-heading: 1.5;
--line-height-text: 1.2;
}
Handpicked by us. CSS variables example:
:root {
--space-1: 0.0625rem;
--space-2: 0.125rem;
--space-3: 0.25rem;
--space-4: 0.5rem;
--space-5: 0.75rem;
--space-6: 1rem;
--space-7: 1.25rem;
--space-8: 1.5rem;
--space-9: 2rem;
--space-10: 2.5rem;
--space-11: 3rem;
--space-12: 4rem;
--space-13: 5rem;
}
Hand-picked by us based on color scale generator. MacawUI will then map values from palettes into specific colors for component variants and states. You can see an example mapping on the diagram below.
Image 1: Mapping between design primitives for colors.
Image 2: Example of default palette.
Image 2: Example of brand palette.
CSS variables:
:root {
/* values from the palettes */
--text-primary-foreground: hsla(210, 60%, 60%, 1);
--button-primary-foreground: hsla(215, 96%, 43%, 1);
--button-primary-background: hsla(215, 84%, 73%, 1);
--button-primary-background-active: hsla(215, 94%, 58%, 1);
--button-primary-background-hover: hsla(215, 100%, 51%, 0.08);
--button-primary-background-focus: hsla(215, 100%, 51%, 0.12);
--button-secondary-foreground: hsla(215, 97%, 35%, 1);
}
Picked by us. CSS variables:
:root {
--shadow-1: 0 26px 80px hsla(0, 0, 0, 0);
--shadow-2: 0 26px 100px hsla(0, 0, 0, 0);
--shadow-3: 0 26px 80px hsla(0, 0, 0, 0);
}
Picked by us. CSS variables:
:root {
--border-radius-1: 2px;
--border-radius-2: 4px;
--border-radius-3: 6px;
}
:root {
--font-size-1: 0.75rem;
--font-size-2: calc(var(--font-size-1) * var(--font-size-scale));
--font-size-3: calc(var(--font-size-2) * var(--font-size-scale));
--font-size-4: calc(var(--font-size-3) * var(--font-size-scale));
--font-size-5: calc(var(--font-size-4) * var(--font-size-scale));
--font-size-6: calc(var(--font-size-5) * var(--font-size-scale));
--font-size-7: calc(var(--font-size-6) * var(--font-size-scale));
--font-size-8: calc(var(--font-size-7) * var(--font-size-scale));
--font-size-9: calc(var(--font-size-8) * var(--font-size-scale));
--font-size-10: calc(var(--font-size-9) * var(--font-size-scale));
--line-height-heading: 1.5;
--line-height-text: 1.2;
--space-1: 0.0625rem;
--space-2: 0.125rem;
--space-3: 0.25rem;
--space-4: 0.5rem;
--space-5: 0.75rem;
--space-6: 1rem;
--space-7: 1.25rem;
--space-8: 1.5rem;
--space-9: 2rem;
--space-10: 2.5rem;
--space-11: 3rem;
--space-12: 4rem;
--space-13: 5rem;
--text-primary-foreground: hsla(210, 60%, 60%, 1);
--button-primary-foreground: hsla(215, 96%, 43%, 1);
--button-primary-background: hsla(215, 84%, 73%, 1);
--button-primary-background-active: hsla(215, 94%, 58%, 1);
--button-primary-background-hover: hsla(215, 100%, 51%, 0.08);
--button-primary-background-focus: hsla(215, 100%, 51%, 0.12);
--button-secondary-foreground: hsla(215, 97%, 35%, 1);
--shadow-1: 0 26px 80px hsla(0, 0, 0, 0);
--shadow-2: 0 26px 100px hsla(0, 0, 0, 0);
--shadow-3: 0 26px 80px hsla(0, 0, 0, 0);
--border-radius-1: 2px;
--border-radius-2: 4px;
--border-radius-3: 6px;
}
The code snippet above presents CSS variables that act as a theme contract. If a developer wants to create a new theme they need to use those variables and fulfill the contract. Contract variables should not change.
Changing from one to another theme (e.g light to dark) will use JS API to set CSS variables on root
HTML element:
const defaultLightTheme = {
"--font-size-1": "0.75rem",
"--font-size-2": "0.9rem",
"--font-size-3": "1.08rem",
"--font-size-4": "1.296rem",
"--font-size-5": "1.5552rem",
"--font-size-6": "1.86624rem",
"--font-size-7": "2.23949rem",
"--font-size-8": "2.68739rem",
"--font-size-9": "3.22486rem",
"--font-size-10": "3.86984rem",
"--line-height-heading": "1.5",
"--line-height-text": "1.2",
"--space-1": "0.0625rem",
"--space-2": "0.125rem",
"--space-3": "0.25rem",
"--space-4": "0.5rem",
"--space-5": "0.75rem",
"--space-6": "1rem",
"--space-7": "1.25rem",
"--space-8": "1.5rem",
"--space-9": "2rem",
"--space-10": "2.5rem",
"--space-11": "3rem",
"--space-12": "4rem",
"--space-13": "5rem",
"--text-primary-foreground": "hsla(210, 60%, 60%, 1)",
"--button-primary-foreground": "hsla(215, 96%, 43%, 1)",
"--button-primary-background": "hsla(215, 84%, 73%, 1)",
"--button-primary-background-active": "hsla(215, 94%, 58%, 1)",
"--button-primary-background-hover": "hsla(215, 100%, 51%, 0.08)",
"--button-primary-background-focus": "hsla(215, 100%, 51%, 0.12)",
"--button-secondary-foreground": "hsla(215, 97%, 35%, 1)",
"--shadow-1": "0 26px 80px hsla(0,0,0,0)",
"--shadow-2": "0 26px 100px hsla(0,0,0,0)",
"--shadow-3": "0 26px 80px hsla(0,0,0,0)",
"--border-radius-1": "2px",
"--border-radius-2": "4px",
"--border-radius-3": "6px",
};
const root = document.documentElement;
Object.entries(defaultLightTheme).map(([key, value]) =>
root.style.setProperty(key, value)
);
Components will use second-level CSS variables for colors and first-level variables for the rest of the properties. This allows us to have more control in applying different themes. CSS variables will be defined in the global CSS variables space (:root
). For example Text
and Button
components will have the following variables:
:root {
/* 1st level of variables */
--font-size-1: 1rem;
--line-height-heading: 1.5;
/* 2nd level of variables */
--text-primary-foreground: hsla(210, 60%, 60%, 1);
--button-primary-foreground: hsla(215, 96%, 43%, 1);
--button-primary-background: hsla(215, 84%, 73%, 1);
--button-primary-background-hover: hsla(215, 100%, 51%, 0.08);
--button-secondary-foreground: hsla(215, 97%, 35%, 1);
}
.text {
font-size: var(--font-size-1);
line-height: var(--line-height-heading);
color: var(--text-primary-foreground);
}
.buttonPrimary {
color: var(--button-primary-foreground);
background-color: var(--button-primary-background);
}
.buttonPrimary:hover {
background-color: var(--button-primary-background-hover);
}
.buttonSecondary {
color: var(--button-secondary-foreground);
}
Image 3: Mappings between UI components and design tokens.
API interface for using components will be created using TypeScript interfaces. The component library will be created as React components. If a component is simple like a button or text we should expose all props. Following the text example we will have:
interface TextProps extends React.ComponentPropsWithoutRef<"p"> {
variant: "base" | "heading" | "subheading";
weight: "normal" | "bold";
as: "h1" | "p";
children: React.Node;
}
// Later in the code
<Text variant="base" weight="normal" as="h1">
Short sleeve T-Shirt
</Text>;
Note
UI components API shouldn’t expose the internals of the design system e.g what library we use to build component primitives or what tool we are using as CSS foundation.
Will be responsible for visual testing. It will work as documentation in the first stages of the library.
We can use a single-repo setup with the following directories:
src/
- holds the newly created components (new macaw)legacy/
- holds the whole legacy macaw.storybook/
- configuration of storybookdist/
- build outputYou can see an example repository structure for CSS Modules
$ tree macaw-ui
macaw-ui
├── dist
├── legacy
├── .storybook
└── src
├── index.ts
├── styles
│ ├── globals.css
│ ├── index.css
│ └── reset.css
├── text
│ ├── index.ts
│ ├── text.module.css
│ ├── text.spec.ts
│ ├── text.stories.tsx
│ └── text.tsx
└── theme
├── index.ts
└── provider.tsx
Given that we have two outputs: old macaw (legacy directory) and new macaw (src directory), we can present them as separate sections within the storybook:
Image 4: Storybook with two sections: legacy and new macaw.
Note
Why not use monorepo? We need to keep it as simple as possible. More complexity, harder to maintain as well as can put a hurdle for contributors. Additionally, monorepos are designed for having multiple packages, that are shared with each other, while in macaw we share just one library and some addons, such as docs or storybook.
Example: macaw-ui/single-repo-concept (with pnpm)
This is where the problems pop up. Since our library now exposes old and new components, undoubtedly we will face naming conflicts (eg. both versions expose a component named Button). To address it, we essentially have the following options:
We can define the following entry points definition within package.json
"exports": {
"./next": {
"import": "dist/src/index.mjs",
"require": "dist/src/index.js"
},
".": {
"import": "dist/legacy/index.mjs",
"require": "dist/legacy/index.js"
}
},
After installing macaw-ui everything will work as previously, but whenever we want to use new components we will use @saleor/macaw-ui/next
instead of @saleor/macaw-ui
import { Button as ButtonOld }, mc from "@saleor/macaw-ui"
import { Button as ButtonNew }, mc from "@saleor/macaw-ui/Next"
<ButtonOld>Legacy button</ButtonOld>
<ButtonNew>New button</ButtonNew>
Pros:
Cons:
@saleor/macaw-ui/next
to @saleor/macaw-ui
everywhere in the project!).We can expose everything that is legacy as it is right now, but newly created components under the namespace eg. mc
import { Button }, mc from "@saleor/macaw-ui"
<Button>Legacy button</Button>
<mc.Button>New button</mc.Button>
Pros:
Cons:
We can use prefixes for the newly created components:
import { Button, mcButton } from "@saleor/macaw-ui"
<Button>Legacy button</Button>
<mcButton>New button</mcButton>
Where the mc
is the prefix
Pros:
Cons:
We can simply create a new repository with a different package name it addresses all of the problems mentioned above, but that means sort of rebranding.
We have 3 different approaches to technology that will be used:
background-color
, text-color
, border-color
which can be problematic as we have colors for backgrounds only, etc - we lost semanticssize={1}
to gap-1
I want to have a text input with the new MacawUI design based on Figma.
We should implement BaseInput
that will hold base styles for all inputs in MacawUI and then
build TextInput
on top of that.
We should also check the current Dashboard for MUI TextField usage and add the missing API
Note: remember about labels and icons inside the input
I want to have the loading Autocomplete component in the new MacawUI
Implement Switch component.
Desings WIP
We currently apply pointer-events:none
to disabled components.
This is causing a problem with for example list items that have a button inside - after you apply pointer-events
user can't click the button in the disabled list item. Currently, developers need to add pointer-events:all
to the button in this case but I think this is suboptimal and should be fixed.
We should remove pointer-events:none
for disabled components and change cursor to not-allowed
instead.
pointer-events:none
should be migrated
Button
List.Item
Notifications should have a dedicated subtitle for messages such as "From app: XYZ". The subtitle should be in the bottom left corner and have a lighter and smaller font.
We need to set up a new repository structure that allows us to develop & maintain both the old (named: legacy
) and the latest version (named: next
) of MacawUI. After this change, this repository will have the following structure:
legacy
folder that has current MacawUI filessrc
with new components and tokens.storybook
folderlegacy
folderexports
defined that points to the legacy
folder and exports
that points to current src under /next
pathlegacy
macaw-ui and new macaw-ui. Then it should create a new tag (next
) in GitHub and NPM.Material-UI v5 (MUI 5) Released.
what about mui 5 support?
/next/theme
or /next/components
paths.As a developer, I want to be able to extend props via declaration merging if some definitions are missing.
We should migrate to interfaces for typing our code.
App avatars require style
prop which allows setting custom background colors.
Sentry Issue: SALEOR-APP-CHECKOUT-2G
SecurityError: Failed to read the 'localStorage' property from 'Window': Access is denied for this document.
at a (webpack://_N_E/../../node_modules/.pnpm/registry.npmjs.org+@[email protected]_vdvb7n236vx4s4shxyxtl27fte/node_modules/@saleor/macaw-ui/dist/esm/index.js:2:603)
at qi (webpack://_N_E/../../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js:176:25)
at exports.useState (webpack://_N_E/../../node_modules/.pnpm/[email protected]/node_modules/react/cjs/react.production.min.js:26:83)
at <anonymous> (webpack://_N_E/../../node_modules/.pnpm/registry.npmjs.org+@[email protected]_vdvb7n236vx4s4shxyxtl27fte/node_modules/@saleor/macaw-ui/dist/esm/index.js:2:603)
at c (webpack://_N_E/../../node_modules/.pnpm/registry.npmjs.org+@[email protected]_vdvb7n236vx4s4shxyxtl27fte/node_modules/@saleor/macaw-ui/dist/esm/index.js:2:603)
...
(12 additional frame(s) were not displayed)
We currently have a naive way of rendering MacawUI - we apply CSS variables on the client. As a proper solution, we should apply them in SSR as well.
macaw-ui/src/theme/context.tsx
Line 25 in 8d3da0c
Currently all class names begin with prefix makestyles-hook
which makes style debugging hard. We should be using proper hook naming.
Line 2 in 695fb99
We need to create a ThemeProvider
that will create CSS variables that are derived from design tokens. To make it more type-safe we are going to use https://vanilla-extract.style/.
As a developer, I want to add my self-hosted font to MacawUI.
We should be able to accept custom CSS with font files into the new MacawUI.
Add button component matching Figma designs
On some views, we have status indicators, usually presented as a rounded badge (see screenshot below). Would be nice to re-use these indicators across the views.
An example can be product flow, the product table list has channel availability status badges, while when we go to the product page, under the availability section it is not yet present (a bit incossistent)
Let's investigate how we can approach this.
I want to be able to change the theme while working on components inside Storybook.
Add theme toggle to Storybook stories.
I want to have a Radio input with the new MacawUI design based on Figma.
We should implement Radio Input
based on Figma designs.
We should also check the current Dashboard for MUI Radio usage and add the missing API.
Create a Text component that applies design from Figma.
as
prop that allows it to be rendered as "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "span"
with default as span
After several discussion we have some reasons to remove MUI from Macaw.
I keep this issue open to evaluate:
ThemeProvider
is used it also applies CSS resetMacaw UI setup (example/concept for the RFC)
Considering areas to cover:
Result: concept of how we address that setup, include everything in the RFC
I want to have the Combobox component in the new MacawUI
Combine the existing Input
component and Downshift
library to create the Select
component
I want a dropdown input with the new MacawUI design based on Figma.
We should implement Dropdown
on top of BaseInput
from #232. This story is only about simple Dropdowns without autocomplete.
We should also check the current Dashboard for MUI Dropdown
usage and add the missing API
As #342 will be merged we can add a new prop to combobox that will allow users only to select a value from combobox without autocomplete.
Create an Icon component that applies design from Figma.
Sentry Issue: SALEOR-APP-CHECKOUT-9
SecurityError: Failed to read the 'localStorage' property from 'Window': Access is denied for this document.
at a (webpack://_N_E/../../node_modules/.pnpm/@[email protected]_2y22cl4s2qbk2dsjoypyjtjdfu/node_modules/@saleor/macaw-ui/dist/esm/index.js:1:2119)
at useState (webpack://_N_E/../../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js:175:53)
at n.useState (webpack://_N_E/../../node_modules/.pnpm/[email protected]/node_modules/react/cjs/react.production.min.js:25:394)
at n1 (webpack://_N_E/../../node_modules/.pnpm/@[email protected]_2y22cl4s2qbk2dsjoypyjtjdfu/node_modules/@saleor/macaw-ui/dist/esm/index.js:1:2101)
at c (webpack://_N_E/../../node_modules/.pnpm/@[email protected]_2y22cl4s2qbk2dsjoypyjtjdfu/node_modules/@saleor/macaw-ui/dist/esm/index.js:4:10531)
...
(9 additional frame(s) were not displayed)
I want to have a Checkbox with the new MacawUI design based on Figma.
We should implement the Checkbox
component based on Figma designs. It should be accessible so we could use Radix Checkbox for that.
We should also check the current Dashboard for MUI Checkbox usage and add the missing API
Note: remember about labels
Implement Popover component which will replace popper from MUI.
Use popover from radix ui.
<Button color={"textNeutralSubdued"} variant={"tertiary"}>
Log in
</Button>
Color will be overwritten with textNeutralSubdued
Prop is not working at all
Add inside
I want to have the proper font used in MacawUI.
Apply Inter (variable) font.
<Text />
component should use the Inter
fontInter
font inside MacawUI (??)A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.