Skip to content

Commit

Permalink
refactor(theme): style Button
Browse files Browse the repository at this point in the history
  • Loading branch information
Akuukis committed Dec 12, 2024
1 parent 15b3557 commit 40b5316
Show file tree
Hide file tree
Showing 7 changed files with 267 additions and 71 deletions.
150 changes: 86 additions & 64 deletions jsapp/js/components/common/button.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,55 @@
import React from 'react';
import type {ComponentStory, ComponentMeta} from '@storybook/react';
import Button from './button';
import type {ButtonType, ButtonSize, ButtonProps} from './button';
import type {TooltipAlignment} from './tooltip';
import {IconNames} from 'jsapp/fonts/k-icons';
import type {IconName} from 'jsapp/fonts/k-icons';
import type {ButtonProps, MantineSize, PolymorphicComponentProps} from '@mantine/core';
import {Button, MantineProvider} from '@mantine/core';
import Icon from './icon';
import '@mantine/core/styles.css';
import {themeKobo} from 'jsapp/js/theme';

const buttonTypes: ButtonType[] = ['primary', 'secondary', 'danger', 'secondary-danger', 'text'];
const buttonVariants: Array<ButtonProps['variant']> = [
'filled',
'light',
// 'outline',
// 'white',
// 'subtle',
// 'default',
// 'gradient',

const buttonSizes: ButtonSize[] = ['s', 'm', 'l'];
//// Custom:
'danger',
'danger-secondary',

'transparent',
];

const buttonSizes: MantineSize[] = [
// 'xs',
'sm',
'md',
'lg',
// 'xl',
];

const tooltipPositions: TooltipAlignment[] = ['right', 'left', 'center'];

export default {
title: 'common/Button',
component: Button,
argTypes: {
type: {
description: 'Type of button',
options: buttonTypes,
variant: {
description: 'Variant of button',
options: buttonVariants,
control: 'select',
},
size: {
description: 'Size of button',
options: buttonSizes,
control: 'radio',
},
startIcon: {
leftSection: {
description: 'Icon on the beginning (please use only one of the icons)',
options: Object.keys(IconNames),
control: {type: 'select'},
Expand Down Expand Up @@ -57,57 +80,59 @@ export default {
},
} as ComponentMeta<typeof Button>;

const Template: ComponentStory<typeof Button> = (args) => <Button {...args} />;
const Template: ComponentStory<typeof Button> = (args) =>
<MantineProvider theme={themeKobo}><Button {...args} /></MantineProvider>;

export const Primary = Template.bind({});
Primary.args = {
type: 'primary',
size: 'l',
label: 'Click me',
variant: 'filled',
size: 'lg',
children: 'Click me',
};

export const Secondary = Template.bind({});
Secondary.args = {
type: 'secondary',
size: 'l',
label: 'Click me',
variant: 'light',
size: 'lg',
children: 'Click me',
};


export const Danger = Template.bind({});
Danger.args = {
type: 'danger',
size: 'l',
label: 'Click me',
variant: 'danger',
size: 'lg',
children: 'Click me',
};

export const SecondaryDanger = Template.bind({});
SecondaryDanger.args = {
type: 'secondary-danger',
size: 'l',
label: 'Click me',
variant: 'danger-secondary',
size: 'lg',
children: 'Click me',
};

export const Text = Template.bind({});
Text.args = {
type: 'text',
size: 'l',
label: 'Click me',
variant: 'transparent',
size: 'lg',
children: 'Click me',
};

const demoButtons: Array<{label?: string, startIcon?: IconName}> = [
const demoButtons: Array<{label?: string; leftSectionName?: IconName}> = [
{
label: 'Click me',
startIcon: undefined,
leftSectionName: undefined,
},
{
label: 'Click me',
startIcon: 'document',
leftSectionName: 'document',
},
{
label: undefined,
startIcon: 'document',
}
//// For button without text use ActionIcon instead!
// {
// label: undefined,
// leftSectionName: 'document',
// },
];

/**
Expand All @@ -118,37 +143,34 @@ const demoButtons: Array<{label?: string, startIcon?: IconName}> = [
* - and in idle, pending, and disabled states.
*/
export const AllButtons = () => (
<div style={{
display: 'grid',
gridTemplateColumns: 'repeat(9, auto)',
gridAutoFlow: 'row',
gridGap: '30px 15px',
justifyItems: 'start',
padding: '10px',
}}>
{buttonTypes.map((buttonType) => (
buttonSizes.map((buttonSize) => (
demoButtons.map((demoButton) => {
const buttonProps: ButtonProps = {
type: buttonType,
size: buttonSize,
onClick: () => console.info('Clicked!', buttonType, buttonSize, demoButton.label, demoButton.startIcon),
};
if (demoButton.label) {
buttonProps.label = demoButton.label;
}
if (demoButton.startIcon) {
buttonProps.startIcon = demoButton.startIcon;
}
return (
<>
<Button {...buttonProps}/>
<Button {...buttonProps} isPending/>
<Button {...buttonProps} isDisabled/>
</>
);
})
))
))}
</div>
<MantineProvider theme={themeKobo}>
<div style={{
display: 'grid',
gridTemplateColumns: 'repeat(6, auto)',
gridAutoFlow: 'row',
gridGap: '30px 15px',
justifyItems: 'start',
padding: '10px',
}}>
{buttonVariants.map((variant) => (
buttonSizes.map((size) => (
demoButtons.map(({label, leftSectionName}) => {
const buttonProps: PolymorphicComponentProps<'button', ButtonProps> = {
variant,
size: size,
leftSection: leftSectionName ? <Icon name={leftSectionName} size={size as any} /> : undefined,
onClick: () => console.info('Clicked!', variant, size, label, leftSectionName),
};
return (
<>
<Button {...buttonProps}>{label}</Button>
<Button {...buttonProps} loading>{label}</Button>
<Button {...buttonProps} disabled>{label}</Button>
</>
);
})
))
))}
</div>
</MantineProvider>
);
1 change: 0 additions & 1 deletion jsapp/js/components/drawer.es6
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ const FormSidebar = observer(
return (
<>
<Button
variant='primary'
size='lg'
fullWidth
disabled={!sessionStore.isLoggedIn}
Expand Down
3 changes: 2 additions & 1 deletion jsapp/js/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,4 +248,5 @@ declare module 'react-autobind' {
export default autoBind;
}

declare module "*.module.scss";
declare module '*.module.scss';
declare module '*.module.css';
6 changes: 1 addition & 5 deletions jsapp/js/theme/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
import {createTheme} from '@mantine/core';

export const themeKobo = createTheme({
/** Put your mantine theme override here */
});
export {themeKobo} from './kobo';
31 changes: 31 additions & 0 deletions jsapp/js/theme/kobo/Button.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
@use 'js/components/common/icon';

.root {
font-weight: 500;

&[data-size='sm'] {
min-width: 28px;
}
&[data-size='md'] {
min-width: 32px;
}
&[data-size='lg'] {
min-width: 38px;
}

&[data-disabled] {
color: var(--button-color);
background: var(--button-bg);
opacity: 0.5;
}

}

.section {
&[data-position='left'] {
margin-right: calc(var(--button-height) * 0.1);
}
&[data-position='right'] {
margin-left: calc(var(--button-height) * 0.1);
}
}
58 changes: 58 additions & 0 deletions jsapp/js/theme/kobo/Button.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import type {ButtonVariant} from '@mantine/core';
import {Button, rem} from '@mantine/core';
import classes from './Button.module.css';

type ButtonVariantCustom = Extract<ButtonVariant, 'filled' | 'light' | 'transparent'> | 'danger' | 'danger-secondary';

declare module '@mantine/core' {
export interface ButtonProps {
variant?: ButtonVariantCustom;
// size?: ... // Can override ButtonFactory subset of ButtonProps only. TODO: Figure out how to forbid unused sizes.
}
}

export const ButtonThemeKobo = Button.extend({
classNames: classes,
defaultProps: {
variant: 'filled',
},
vars: (theme, props) => {
return {
root: {
'--button-height-sm': rem(28),
'--button-height-md': rem(32),
'--button-height-lg': rem(38),
'--button-padding-x-sm': rem(11.2),
'--button-padding-x-md': rem(12.8),
'--button-padding-x-lg': rem(15.2),
'--button-bd': '0',

// TODO: Consider standardizing global colors, or using them in a more standard way.
...(props.variant === 'filled' && {
'--button-hover': theme.colors.blue[5],
}),
...(props.variant === 'light' && {
'--button-color': theme.colors.blue[5],
'--button-bg': theme.colors.blue[9],
'--button-hover': theme.colors.blue[8],
}),
...(props.variant === 'transparent' && {
'--button-color': theme.colors.blue[4],
'--button-hover-color': theme.colors.blue[5],
}),
...(props.variant === 'danger' && {
'--button-color': 'var(--mantine-color-white)',
'--button-bg': theme.colors.red[6],
'--button-hover': theme.colors.red[5],
}),
...(props.variant === 'danger-secondary' && {
'--button-color': theme.colors.red[6],
'--button-bg': theme.colors.red[9],
'--button-hover': theme.colors.red[8],
}),

},
};
},

});
Loading

0 comments on commit 40b5316

Please sign in to comment.