mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
chore(ui-components): simplify color tokens (#45848)
* chore: rename color tokens * chore: clean up hover tokens * docs: add a note on colors usage
This commit is contained in:
@@ -50,6 +50,18 @@ Each component is different, but in general a component should:
|
||||
- Be styled internally based on their props (the consumers should not need to restyle the component with the `className` prop)
|
||||
- Utilize the built-in styling system from Tailwind instead of having custom styles
|
||||
|
||||
### Using colors
|
||||
|
||||
There are two color "layers" in the component library:
|
||||
|
||||
- The base layer, where the color names describe what the colors are, e.g. `gray00`, `blue50`
|
||||
- The semantic layer, where the color names describe what the colors are for, e.g. `foreground-primary`, `background-danger`
|
||||
|
||||
Generally when using colors in a component, you should choose semantic variables over the base ones. There are exceptions, however, specifically when you are styling the component's states such as hover, active, disabled, etc. In these cases, we recommend using the base variables directly instead of creating new semantic variables, since each component can have different styles for their states.
|
||||
|
||||
> [!NOTE]
|
||||
> Color definition can be found in the [`colors.css` file](https://github.com/freeCodeCamp/freeCodeCamp/blob/main/tools/ui-components/src/colors.css). A color is only available for use if it is added to the [`tailwind.config.js` file](https://github.com/freeCodeCamp/freeCodeCamp/blob/main/tools/ui-components/tailwind.config.js) under the `colors` property.
|
||||
|
||||
### Useful links
|
||||
|
||||
- [Tailwind CSS Configuration](https://tailwindcss.com/docs/configuration)
|
||||
|
||||
@@ -42,41 +42,47 @@ const computeClassNames = ({
|
||||
switch (variant) {
|
||||
case 'danger':
|
||||
classNames.push(
|
||||
'border-default-foreground-danger',
|
||||
'bg-default-background-danger',
|
||||
'text-default-foreground-danger',
|
||||
'border-foreground-danger',
|
||||
'bg-background-danger',
|
||||
'text-foreground-danger',
|
||||
...(disabled
|
||||
? ['active:before:hidden']
|
||||
: [
|
||||
'hover:bg-default-background-danger-hover',
|
||||
'hover:text-default-foreground-danger-hover'
|
||||
'hover:bg-red-150',
|
||||
'hover:text-red-900',
|
||||
'dark:hover:bg-red-900',
|
||||
'dark:hover:text-red-150'
|
||||
])
|
||||
);
|
||||
break;
|
||||
case 'info':
|
||||
classNames.push(
|
||||
'border-default-foreground-info',
|
||||
'bg-default-background-info',
|
||||
'text-default-foreground-info',
|
||||
'border-foreground-info',
|
||||
'bg-background-info',
|
||||
'text-foreground-info',
|
||||
...(disabled
|
||||
? ['active:before:hidden']
|
||||
: [
|
||||
'hover:bg-default-background-info-hover',
|
||||
'hover:text-default-foreground-info-hover'
|
||||
'hover:bg-blue-300',
|
||||
'hover:text-blue-900',
|
||||
'dark:hover:bg-blue-900',
|
||||
'dark:hover:text-blue-300'
|
||||
])
|
||||
);
|
||||
break;
|
||||
// default variant is 'primary'
|
||||
default:
|
||||
classNames.push(
|
||||
'border-default-foreground-secondary',
|
||||
'bg-default-background-quaternary',
|
||||
'text-default-foreground-secondary',
|
||||
'border-foreground-secondary',
|
||||
'bg-background-quaternary',
|
||||
'text-foreground-secondary',
|
||||
...(disabled
|
||||
? ['active:before:hidden']
|
||||
: [
|
||||
'hover:bg-default-background-primary-hover',
|
||||
'hover:text-default-foreground-primary-hover'
|
||||
'hover:bg-gray-900',
|
||||
'hover:text-gray-0',
|
||||
'dark:hover:bg-gray-0',
|
||||
'dark:hover:text-gray-900'
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
@@ -91,54 +91,38 @@
|
||||
|
||||
html,
|
||||
div.light {
|
||||
--default-foreground-primary: var(--gray90);
|
||||
--default-foreground-secondary: var(--gray85);
|
||||
--default-foreground-tertiary: var(--gray80);
|
||||
--default-foreground-quaternary: var(--gray75);
|
||||
--default-foreground-danger: var(--red15);
|
||||
--default-foreground-info: var(--blue30);
|
||||
--foreground-primary: var(--gray90);
|
||||
--foreground-secondary: var(--gray85);
|
||||
--foreground-tertiary: var(--gray80);
|
||||
--foreground-quaternary: var(--gray75);
|
||||
--foreground-danger: var(--red15);
|
||||
--foreground-info: var(--blue30);
|
||||
|
||||
--default-background-primary: var(--gray00);
|
||||
--default-background-secondary: var(--gray05);
|
||||
--default-background-tertiary: var(--gray10);
|
||||
--default-background-quaternary: var(--gray15);
|
||||
--default-background-danger: var(--red90);
|
||||
--default-background-info: var(--blue90);
|
||||
|
||||
--default-foreground-primary-hover: var(--gray00);
|
||||
--default-foreground-danger-hover: var(--red90);
|
||||
--default-foreground-info-hover: var(--blue90);
|
||||
|
||||
--default-background-primary-hover: var(--gray90);
|
||||
--default-background-danger-hover: var(--red15);
|
||||
--default-background-info-hover: var(--blue30);
|
||||
--background-primary: var(--gray00);
|
||||
--background-secondary: var(--gray05);
|
||||
--background-tertiary: var(--gray10);
|
||||
--background-quaternary: var(--gray15);
|
||||
--background-danger: var(--red90);
|
||||
--background-info: var(--blue90);
|
||||
|
||||
--focus-outline-color: var(--blue50);
|
||||
}
|
||||
|
||||
html.dark,
|
||||
div.dark {
|
||||
--default-foreground-primary: var(--gray00);
|
||||
--default-foreground-secondary: var(--gray05);
|
||||
--default-foreground-tertiary: var(--gray10);
|
||||
--default-foreground-quaternary: var(--gray15);
|
||||
--default-foreground-danger: var(--red90);
|
||||
--default-foreground-info: var(--blue90);
|
||||
--foreground-primary: var(--gray00);
|
||||
--foreground-secondary: var(--gray05);
|
||||
--foreground-tertiary: var(--gray10);
|
||||
--foreground-quaternary: var(--gray15);
|
||||
--foreground-danger: var(--red90);
|
||||
--foreground-info: var(--blue90);
|
||||
|
||||
--default-background-primary: var(--gray90);
|
||||
--default-background-secondary: var(--gray85);
|
||||
--default-background-tertiary: var(--gray80);
|
||||
--default-background-quaternary: var(--gray75);
|
||||
--default-background-danger: var(--red15);
|
||||
--default-background-info: var(--blue30);
|
||||
|
||||
--default-foreground-primary-hover: var(--gray90);
|
||||
--default-foreground-danger-hover: var(--red15);
|
||||
--default-foreground-info-hover: var(--blue30);
|
||||
|
||||
--default-background-primary-hover: var(--gray00);
|
||||
--default-background-danger-hover: var(--red90);
|
||||
--default-background-info-hover: var(--blue90);
|
||||
--background-primary: var(--gray90);
|
||||
--background-secondary: var(--gray85);
|
||||
--background-tertiary: var(--gray80);
|
||||
--background-quaternary: var(--gray75);
|
||||
--background-danger: var(--red15);
|
||||
--background-info: var(--blue30);
|
||||
|
||||
--focus-outline-color: var(--blue50);
|
||||
}
|
||||
|
||||
@@ -7,8 +7,7 @@ export const FormControlStatic = ({
|
||||
children,
|
||||
testId
|
||||
}: FormControlVariationProps) => {
|
||||
const defaultClasses =
|
||||
'py-1.5 mb-0 min-h-43-px text-default-foreground-secondary';
|
||||
const defaultClasses = 'py-1.5 mb-0 min-h-43-px text-foreground-secondary';
|
||||
|
||||
const classes = [defaultClasses, className].join(' ');
|
||||
return (
|
||||
|
||||
@@ -25,10 +25,10 @@ const FormControl = React.forwardRef<FormControlElement, FormControlProps>(
|
||||
ref
|
||||
): JSX.Element => {
|
||||
let defaultClasses =
|
||||
'outline-0 block w-full py-1.5 px-2.5 text-md text-default-foreground-primary ' +
|
||||
'bg-default-background-primary bg-none rounded-none border-1 border-solid ' +
|
||||
'border-default-background-quaternary shadow-none ' +
|
||||
'transition ease-in-out duration-150 focus:border-default-foreground-tertiary';
|
||||
'outline-0 block w-full py-1.5 px-2.5 text-md text-foreground-primary ' +
|
||||
'bg-background-primary bg-none rounded-none border-1 border-solid ' +
|
||||
'border-background-quaternary shadow-none ' +
|
||||
'transition ease-in-out duration-150 focus:border-foreground-tertiary';
|
||||
|
||||
let variantClass;
|
||||
if (Component === 'textarea') variantClass = 'h-auto';
|
||||
|
||||
@@ -7,7 +7,7 @@ describe('Render the helpblock component', () => {
|
||||
render(<HelpBlock />);
|
||||
expect(screen.getByTestId('help-block')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('help-block')).toHaveClass(
|
||||
'block mt-1 mb-2 text-default-foreground-quaternary',
|
||||
'block mt-1 mb-2 text-foreground-quaternary',
|
||||
{ exact: true }
|
||||
);
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@ import { HelpBlockProps } from './types';
|
||||
|
||||
export const HelpBlock = React.forwardRef<HTMLSpanElement, HelpBlockProps>(
|
||||
({ className, children }, ref): JSX.Element => {
|
||||
const defaultClasses = 'block mt-1 mb-2 text-default-foreground-quaternary';
|
||||
const defaultClasses = 'block mt-1 mb-2 text-foreground-quaternary';
|
||||
const classes = [defaultClasses, className].join(' ');
|
||||
return (
|
||||
<span ref={ref} data-testid='help-block' className={classes}>
|
||||
|
||||
@@ -14,31 +14,19 @@ module.exports = {
|
||||
'dark-theme-background': 'var(--gray90)',
|
||||
'light-theme-background': 'var(--gray00)',
|
||||
// Foreground
|
||||
'default-foreground-primary': 'var(--default-foreground-primary)',
|
||||
'default-foreground-secondary': 'var(--default-foreground-secondary)',
|
||||
'default-foreground-tertiary': 'var(--default-foreground-tertiary)',
|
||||
'default-foreground-quaternary': 'var(--default-foreground-quaternary)',
|
||||
'default-foreground-danger': 'var(--default-foreground-danger)',
|
||||
'default-foreground-info': 'var(--default-foreground-info)',
|
||||
'foreground-primary': 'var(--foreground-primary)',
|
||||
'foreground-secondary': 'var(--foreground-secondary)',
|
||||
'foreground-tertiary': 'var(--foreground-tertiary)',
|
||||
'foreground-quaternary': 'var(--foreground-quaternary)',
|
||||
'foreground-danger': 'var(--foreground-danger)',
|
||||
'foreground-info': 'var(--foreground-info)',
|
||||
// Background
|
||||
'default-background-primary': 'var(--default-background-primary)',
|
||||
'default-background-secondary': 'var(--default-background-secondary)',
|
||||
'default-background-tertiary': 'var(--default-background-tertiary)',
|
||||
'default-background-quaternary': 'var(--default-background-quaternary)',
|
||||
'default-background-danger': 'var(--default-background-danger)',
|
||||
'default-background-info': 'var(--default-background-info)',
|
||||
// Foreground hover
|
||||
'default-foreground-primary-hover':
|
||||
'var(--default-foreground-primary-hover)',
|
||||
'default-foreground-danger-hover':
|
||||
'var(--default-foreground-danger-hover)',
|
||||
'default-foreground-info-hover': 'var(--default-foreground-info-hover)',
|
||||
// Background hover
|
||||
'default-background-primary-hover':
|
||||
'var(--default-background-primary-hover)',
|
||||
'default-background-danger-hover':
|
||||
'var(--default-background-danger-hover)',
|
||||
'default-background-info-hover': 'var(--default-background-info-hover)',
|
||||
'background-primary': 'var(--background-primary)',
|
||||
'background-secondary': 'var(--background-secondary)',
|
||||
'background-tertiary': 'var(--background-tertiary)',
|
||||
'background-quaternary': 'var(--background-quaternary)',
|
||||
'background-danger': 'var(--background-danger)',
|
||||
'background-info': 'var(--background-info)',
|
||||
// Focus outline
|
||||
'focus-outline-color': 'var(--focus-outline-color)',
|
||||
gray: {
|
||||
|
||||
Reference in New Issue
Block a user