Improve Button styles

Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
Charles de Dreuille
2025-02-10 14:23:21 +00:00
parent 71ba1e0566
commit 05a2cc685e
16 changed files with 171 additions and 208 deletions
@@ -186,7 +186,7 @@ are prefixed with `fg` to make it easier to identify.
<Table.Body>
<Table.Row>
<Table.Cell>
<Chip head>--canon-fg-text-primary</Chip>
<Chip head>--canon-fg-primary</Chip>
</Table.Cell>
<Table.Cell>
It should be used on top of `--canon-bg-app` or `--canon-bg-elevated`.
@@ -10,7 +10,7 @@
}
.icon path {
fill: var(--canon-fg-text-primary);
fill: var(--canon-fg-primary);
}
.content {
+1 -6
View File
@@ -1,15 +1,12 @@
import React from 'react';
import type { Preview, ReactRenderer } from '@storybook/react';
import { withThemeByDataAttribute } from '@storybook/addon-themes';
import { CanonProvider } from '../src/contexts/canon';
// Canon specific styles
import '../src/css/core.css';
import '../src/css/components.css';
// Custom themes
import './themes/backstage.css';
import { CanonProvider } from '../src/contexts/canon';
const preview: Preview = {
parameters: {
controls: {
@@ -79,8 +76,6 @@ const preview: Preview = {
themes: {
Light: 'light',
Dark: 'dark',
'Backstage Light': 'backstage-light',
'Backstage Dark': 'backstage-dark',
},
defaultTheme: 'Light',
}),
@@ -1,88 +0,0 @@
[data-theme-name='legacy'][data-theme='light'],
[data-theme-name='legacy'][data-theme='dark'] {
--canon-font-regular: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;
.canon-Button {
border-radius: 60px;
font-weight: 400;
text-transform: uppercase;
font-size: 0.875rem;
transition: background-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,
box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,
border 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
line-height: 1.75;
border-radius: 4px;
background-color: #1f5493;
padding: 6px 16px;
box-shadow: none;
&:hover {
box-shadow: none;
}
&.canon-Button--variant-primary {
color: #fff;
background-color: rgb(21, 58, 102);
box-shadow: 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);
&:hover {
box-shadow: 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);
}
}
&.canon-Button--variant-secondary {
background-color: transparent;
border: 1px solid rgba(31, 84, 147, 0.5);
color: #1f5493;
&:hover {
border: 1px solid #1f5493;
background-color: rgba(31, 84, 147, 0.04);
}
}
&.canon-Button--variant-tertiary {
background-color: transparent;
border: none;
color: #1f5493;
}
}
}
[data-theme-name='legacy'][data-theme='light'] {
/* Colors */
--canon-bg-accent: #2e77d0;
--canon-bg: #f8f8f8;
--canon-bg-elevated: #fff;
--canon-bg: #f4f4f4;
/* Text colors */
--canon-fg-text-primary: #000;
--canon-fg-accent: #fff;
--canon-fg-text-secondary: #646464;
}
[data-theme-name='legacy'][data-theme='dark'] {
/* Colors */
--canon-bg-accent: #fff;
--canon-bg: #000;
--canon-bg-elevated: #121212;
--canon-bg: #1a1a1a;
/* Borders */
--canon-border: rgba(255, 255, 255, 0.2);
--canon-border-warning: #f50000;
--canon-border-danger: #f87503;
--canon-border-focus: #25d262;
/* States - Add more states */
--canon-fg-danger: #f50000;
/* Text colors */
--canon-fg-text-primary: #fff;
--canon-fg-accent: #000;
--canon-fg-text-secondary: #b3b3b3;
}
+1 -1
View File
@@ -1,4 +1,4 @@
.canon-Box {
font-family: var(--canon-font-regular);
color: var(--canon-fg-text-primary);
color: var(--canon-fg-primary);
}
@@ -137,6 +137,12 @@ export const Playground: Story = {
<Text>{variant}</Text>
{['small', 'medium'].map(size => (
<Flex align="center" key={size}>
<Button
variant={variant as ButtonProps['variant']}
size={size as ButtonProps['size']}
>
Button
</Button>
<Button
iconStart="cloud"
variant={variant as ButtonProps['variant']}
@@ -160,6 +166,29 @@ export const Playground: Story = {
>
Button
</Button>
<Button
variant={variant as ButtonProps['variant']}
size={size as ButtonProps['size']}
disabled
>
Button
</Button>
<Button
iconStart="cloud"
variant={variant as ButtonProps['variant']}
size={size as ButtonProps['size']}
disabled
>
Button
</Button>
<Button
iconEnd="chevronRight"
variant={variant as ButtonProps['variant']}
size={size as ButtonProps['size']}
disabled
>
Button
</Button>
</Flex>
))}
</Flex>
@@ -42,7 +42,6 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
return (
<button
{...rest}
ref={ref}
disabled={disabled}
className={clsx(
@@ -52,19 +51,11 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
className,
)}
style={style}
{...rest}
>
<span
className={[
'canon-Button--content',
iconStart && iconEnd ? 'canon-Button--icon-start-end' : '',
]
.filter(Boolean)
.join(' ')}
>
{iconStart && <Icon name={iconStart} />}
{children}
</span>
{iconEnd && <Icon name={iconEnd} />}
{iconStart && <Icon name={iconStart} className="canon-Button--icon" />}
{children}
{iconEnd && <Icon name={iconEnd} className="canon-Button--icon" />}
</button>
);
},
+45 -25
View File
@@ -22,62 +22,82 @@
user-select: none;
font-family: var(--canon-font-regular);
font-weight: var(--canon-font-weight-bold);
font-size: var(--canon-font-size-3);
padding: 0;
transition: all 150ms ease;
cursor: pointer;
border-radius: var(--canon-radius-2);
gap: var(--canon-space-1_5);
&:disabled {
cursor: not-allowed;
}
}
.canon-Button--variant-primary {
background-color: var(--canon-bg-accent);
color: var(--canon-fg-accent);
background-color: var(--canon-bg-solid);
color: var(--canon-fg-solid);
transition: background-color 150ms ease;
&:hover {
background-color: transparent;
box-shadow: inset 0 0 0 1px var(--canon-border-focus);
color: var(--canon-fg-text-primary);
background-color: var(--canon-bg-solid-hover);
}
&:active {
background-color: var(--canon-bg-solid-pressed);
}
&:disabled {
background-color: var(--canon-bg-solid-disabled);
color: var(--canon-fg-solid-disabled);
}
}
.canon-Button--variant-secondary {
background-color: transparent;
background-color: var(--canon-bg-elevated);
box-shadow: inset 0 0 0 1px var(--canon-border);
color: var(--canon-fg-text-primary);
color: var(--canon-fg-primary);
transition: box-shadow 150ms ease;
&:hover {
box-shadow: inset 0 0 0 1px var(--canon-border-hover);
}
&:active {
box-shadow: inset 0 0 0 1px var(--canon-border-focus);
}
&:disabled {
box-shadow: inset 0 0 0 1px var(--canon-border-disabled);
color: var(--canon-fg-disabled);
}
}
.canon-Button--variant-tertiary {
background-color: transparent;
color: var(--canon-fg-text-primary);
color: var(--canon-fg-primary);
&:hover {
color: var(--canon-fg-text-secondary);
}
}
.canon-Button--size-small {
padding-left: 6px;
padding-right: 6px;
height: 32px;
}
.canon-Button--size-medium {
padding-left: 8px;
padding-right: 8px;
font-size: var(--canon-font-size-4);
padding: 0 var(--canon-space-3);
height: 40px;
}
.canon-Button--content {
display: flex;
align-items: center;
gap: var(--canon-space-3);
font-weight: var(--canon-font-weight-bold);
.canon-Button--size-small {
font-size: var(--canon-font-size-3);
padding: 0 var(--canon-space-2);
height: 32px;
}
.canon-Button--icon-start-end {
flex: 1;
.canon-Button--size-small .canon-Button--icon {
width: 1rem;
height: 1rem;
}
.canon-Button--size-medium .canon-Button--icon {
width: 1.5rem;
height: 1.5rem;
}
@@ -11,7 +11,7 @@
transition: all 0.2s ease-in-out;
&[data-checked] {
background-color: var(--canon-bg-accent);
background-color: var(--canon-bg-solid);
}
}
@@ -23,7 +23,7 @@
gap: var(--canon-space-2);
font-size: var(--canon-font-size-xs);
font-family: var(--canon-font-regular);
color: var(--canon-fg-text-primary);
color: var(--canon-fg-primary);
user-select: none;
&:hover {
@@ -24,7 +24,7 @@
.canon-FieldLabel {
font-size: var(--canon-font-size-2);
font-weight: var(--canon-font-weight-regular);
color: var(--canon-fg-text-primary);
color: var(--canon-fg-primary);
margin-bottom: var(--canon-space-1_5);
}
@@ -16,7 +16,7 @@
.canon-Heading {
font-family: var(--canon-font-regular);
color: var(--canon-fg-text-primary);
color: var(--canon-fg-primary);
line-height: 100%;
padding: 0;
margin: 0;
+5 -2
View File
@@ -21,7 +21,7 @@ import clsx from 'clsx';
/** @public */
export const Icon = (props: IconProps) => {
const { name, size = 16, className, style, ...restProps } = props;
const { name, size, className, style, ...restProps } = props;
const { icons } = useCanon();
const CanonIcon = icons[name] as React.ComponentType<Omit<IconProps, 'name'>>;
@@ -34,7 +34,10 @@ export const Icon = (props: IconProps) => {
return (
<CanonIcon
className={clsx('canon-Icon', className)}
style={{ width: size, height: size, ...style }}
style={{
...(size ? { width: size, height: size } : {}),
...style,
}}
{...restProps}
/>
);
@@ -21,7 +21,7 @@
background-color: var(--canon-bg-elevated);
font-size: var(--canon-font-size-3);
font-weight: var(--canon-font-weight-regular);
color: var(--canon-fg-text-primary);
color: var(--canon-fg-primary);
transition: border-color 0.2s ease-in-out, outline-color 0.2s ease-in-out;
width: 100%;
}
@@ -16,7 +16,7 @@
.canon-Text {
font-family: var(--canon-font-regular);
color: var(--canon-fg-text-primary);
color: var(--canon-fg-primary);
padding: 0;
margin: 0;
}
+74 -65
View File
@@ -62,81 +62,90 @@
--canon-space-14: calc(var(--canon-space) * 14); /* 56px */
/* Radius */
--canon-radius-factor: 1.5;
--canon-radius-1: calc(3px * var(--canon-radius-factor));
--canon-radius-2: calc(4px * var(--canon-radius-factor));
--canon-radius-3: calc(6px * var(--canon-radius-factor));
--canon-radius-4: calc(8px * var(--canon-radius-factor));
--canon-radius-5: calc(12px * var(--canon-radius-factor));
--canon-radius-6: calc(16px * var(--canon-radius-factor));
--canon-radius-1: calc(0.125rem);
--canon-radius-2: calc(0.25rem);
--canon-radius-3: calc(0.5rem);
--canon-radius-4: calc(0.75rem);
--canon-radius-5: calc(1rem);
--canon-radius-6: calc(1.25rem);
--canon-radius-full: 9999px;
/* Colors */
/* Background Colors */
--canon-bg: #f8f8f8;
--canon-bg-elevated: #fff;
--canon-bg-accent: #000;
--canon-bg-accent-focus: #000;
--canon-bg-accent-disabled: #000;
--canon-bg-accent-hover: #000;
--canon-bg-tint: #edf2fe;
--canon-bg-tint-active: #c7d7ff;
--canon-bg-tint-disabled: #f8f8f8;
--canon-bg-tint-hover: #dbe4ff;
--canon-bg-danger: #f8f8f8;
--canon-bg-elevated: #fff;
--canon-bg-success: #f8f8f8;
--canon-bg-warning: #f8f8f8;
--canon-border: rgba(0, 0, 0, 0.1);
--canon-border-accent: #000;
--canon-border-accent-focus: #000;
--canon-border-accent-hover: #000;
--canon-border-danger: #e22b2b;
--canon-border-focus: rgba(0, 0, 0, 0.4);
--canon-border-hover: rgba(0, 0, 0, 0.2);
--canon-border-success: #008000;
--canon-border-warning: #e36d05;
--canon-fg-text-primary: #000;
--canon-fg-text-secondary: #646464;
--canon-fg-link: #fff;
--canon-fg-link-hover: #fff;
--canon-fg-accent: #fff;
--canon-fg-tint: #000;
--canon-bg-solid: #1f5493;
--canon-bg-solid-hover: #163a66;
--canon-bg-solid-pressed: #0f2b4e;
--canon-bg-solid-disabled: #ebebeb;
--canon-bg-tint: transparent;
--canon-bg-tint-hover: rgba(31, 84, 147, 0.4);
--canon-bg-tint-pressed: rgba(31, 84, 147, 0.6);
--canon-bg-tint-disabled: #ebebeb;
--canon-bg-danger: #feebe7;
--canon-bg-warning: #fff2b2;
--canon-bg-success: #e6f6eb;
/* Foreground Colors */
--canon-fg-primary: #000000;
--canon-fg-secondary: #757575;
--canon-fg-link: #1f5493;
--canon-fg-link-hover: #1f2d5c;
--canon-fg-disabled: #9e9e9e;
--canon-fg-solid: #ffffff;
--canon-fg-solid-disabled: #9c9c9c;
--canon-fg-tint: #1f5493;
--canon-fg-tint-disabled: #9e9e9e;
--canon-fg-danger: #e22b2b;
--canon-fg-warning: #e36d05;
--canon-fg-success: #008000;
--canon-fg-success: #1db954;
/* Border Colors */
--canon-border: rgba(0, 0, 0, 0.1);
--canon-border-hover: rgba(0, 0, 0, 0.2);
--canon-border-focus: rgba(0, 0, 0, 0.4);
--canon-border-disabled: rgba(0, 0, 0, 0.1);
--canon-border-danger: #f87a7a;
--canon-border-warning: #e36d05;
--canon-border-success: #53db83;
}
/* Dark theme tokens */
[data-theme='dark'] {
--canon-bg: #f8f8f8;
--canon-bg-elevated: #fff;
--canon-bg-accent: #000;
--canon-bg-accent-focus: #000;
--canon-bg-accent-disabled: #000;
--canon-bg-accent-hover: #000;
--canon-bg-tint: #edf2fe;
--canon-bg-tint-active: #c7d7ff;
--canon-bg-tint-disabled: #f8f8f8;
--canon-bg-tint-hover: #dbe4ff;
--canon-bg-danger: #f8f8f8;
--canon-bg-elevated: #fff;
--canon-bg-success: #f8f8f8;
--canon-bg-warning: #f8f8f8;
--canon-border: rgba(0, 0, 0, 0.1);
--canon-border-accent: #000;
--canon-border-accent-focus: #000;
--canon-border-accent-hover: #000;
--canon-border-danger: #e22b2b;
--canon-border-focus: rgba(0, 0, 0, 0.4);
--canon-border-hover: rgba(0, 0, 0, 0.2);
--canon-border-success: #008000;
--canon-border-warning: #e36d05;
--canon-fg-accent: #000;
/* Background Colors */
--canon-bg: #000000;
--canon-bg-elevated: #191919;
--canon-bg-solid: #9cc9ff;
--canon-bg-solid-hover: #83b9fd;
--canon-bg-solid-pressed: #83b9fd;
--canon-bg-solid-disabled: #222222;
--canon-bg-tint: transparent;
--canon-bg-tint-hover: rgba(156, 201, 255, 0.12);
--canon-bg-tint-pressed: rgba(156, 201, 255, 0.16);
--canon-bg-tint-disabled: transparent;
--canon-bg-danger: #3b1219;
--canon-bg-warning: #302008;
--canon-bg-success: #132d21;
/* Foreground Colors */
--canon-fg-primary: #ffffff;
--canon-fg-secondary: #9e9e9e;
--canon-fg-link: #9cc9ff;
--canon-fg-link-hover: #7eb5f7;
--canon-fg-disabled: #9e9e9e;
--canon-fg-solid: #101821;
--canon-fg-solid-disabled: #575757;
--canon-fg-tint: #9cc9ff;
--canon-fg-tint-disabled: #575757;
--canon-fg-danger: #e22b2b;
--canon-fg-success: #008000;
--canon-fg-warning: #e36d05;
--canon-fg-link: #fff;
--canon-fg-link-hover: #fff;
--canon-fg-text-primary: #000;
--canon-fg-text-secondary: #646464;
--canon-fg-success: #1db954;
/* Border Colors */
--canon-border: rgba(255, 255, 255, 0.2);
--canon-border-hover: rgba(255, 255, 255, 0.4);
--canon-border-focus: rgba(255, 255, 255, 0.5);
--canon-border-disabled: rgba(255, 255, 255, 0.2);
--canon-border-danger: #f87a7a;
--canon-border-warning: #e36d05;
--canon-border-success: #53db83;
}
@@ -20,6 +20,7 @@ import Grid from '@material-ui/core/Grid';
import Typography from '@material-ui/core/Typography';
import React from 'react';
import { useUserProfile } from '../useUserProfileInfo';
import Button from '@material-ui/core/Button';
const Contents = () => {
const { backstageIdentity } = useUserProfile();
@@ -49,6 +50,9 @@ const Contents = () => {
/** @public */
export const UserSettingsIdentityCard = () => (
<InfoCard title="Backstage Identity">
<Button variant="contained" color="primary">
werfg
</Button>
<Contents />
</InfoCard>
);