feat(ui): update button variants following figma (#482)
* feat(ui): update button variants following figma * feat(ui): separate size prop to allow for regular and small sized button variants * update type to no longer include minimal-small * update uno css config to use new spacing system * add variants and sizes to file upload; update button and file upload stories * add mini button variant and update small button * specify width on icon-only regular variant * update plus buttons to be mini sizes * remove redundant classnames --------- Co-authored-by: doprz <52579214+doprz@users.noreply.github.com>
This commit is contained in:
@@ -35,6 +35,62 @@ export const Default: Story = {
|
||||
},
|
||||
};
|
||||
|
||||
export const Small: Story = {
|
||||
// @ts-ignore
|
||||
args: {
|
||||
children: '',
|
||||
},
|
||||
render: props => (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '15px' }}>
|
||||
<div style={{ display: 'flex', gap: '15px' }}>
|
||||
<Button {...props} variant='filled' color='ut-black' size='small'>
|
||||
Button
|
||||
</Button>
|
||||
<Button {...props} variant='outline' color='ut-black' size='small'>
|
||||
Button
|
||||
</Button>
|
||||
<Button {...props} variant='minimal' color='ut-black' size='small'>
|
||||
Button
|
||||
</Button>
|
||||
</div>
|
||||
<hr />
|
||||
<div style={{ display: 'flex', gap: '15px' }}>
|
||||
<Button {...props} icon={ImageSquare} variant='filled' color='ut-black' size='small' />
|
||||
<Button {...props} icon={ImageSquare} variant='outline' color='ut-black' size='small' />
|
||||
<Button {...props} icon={ImageSquare} variant='minimal' color='ut-black' size='small' />
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
};
|
||||
|
||||
export const Mini: Story = {
|
||||
// @ts-ignore
|
||||
args: {
|
||||
children: '',
|
||||
},
|
||||
render: props => (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '15px' }}>
|
||||
<div style={{ display: 'flex', gap: '15px' }}>
|
||||
<Button {...props} variant='filled' color='ut-black' size='mini'>
|
||||
Button
|
||||
</Button>
|
||||
<Button {...props} variant='outline' color='ut-black' size='mini'>
|
||||
Button
|
||||
</Button>
|
||||
<Button {...props} variant='minimal' color='ut-black' size='mini'>
|
||||
Button
|
||||
</Button>
|
||||
</div>
|
||||
<hr />
|
||||
<div style={{ display: 'flex', gap: '15px' }}>
|
||||
<Button {...props} icon={ImageSquare} variant='filled' color='ut-black' size='mini' />
|
||||
<Button {...props} icon={ImageSquare} variant='outline' color='ut-black' size='mini' />
|
||||
<Button {...props} icon={ImageSquare} variant='minimal' color='ut-black' size='mini' />
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
};
|
||||
|
||||
export const Disabled: Story = {
|
||||
args: {
|
||||
variant: 'filled',
|
||||
@@ -50,7 +106,7 @@ export const Grid: Story = {
|
||||
<div style={{ display: 'flex', gap: '15px' }}>
|
||||
<Button {...props} variant='filled' color='ut-black' />
|
||||
<Button {...props} variant='outline' color='ut-black' />
|
||||
<Button {...props} variant='single' color='ut-black' />
|
||||
<Button {...props} variant='minimal' color='ut-black' />
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
@@ -58,7 +114,7 @@ export const Grid: Story = {
|
||||
<div style={{ display: 'flex', gap: '15px' }}>
|
||||
<Button {...props} variant='filled' color='ut-black' disabled />
|
||||
<Button {...props} variant='outline' color='ut-black' disabled />
|
||||
<Button {...props} variant='single' color='ut-black' disabled />
|
||||
<Button {...props} variant='minimal' color='ut-black' disabled />
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
@@ -82,12 +138,12 @@ export const PrettyColors: Story = {
|
||||
<Button {...props} variant='outline' color={color}>
|
||||
Button
|
||||
</Button>
|
||||
<Button {...props} variant='single' color={color}>
|
||||
<Button {...props} variant='minimal' color={color}>
|
||||
Button
|
||||
</Button>
|
||||
<Button {...props} variant='filled' color={color} />
|
||||
<Button {...props} variant='outline' color={color} />
|
||||
<Button {...props} variant='single' color={color} />
|
||||
<Button {...props} variant='minimal' color={color} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -45,6 +45,62 @@ export const Default: Story = {
|
||||
},
|
||||
};
|
||||
|
||||
export const Small: Story = {
|
||||
// @ts-ignore
|
||||
args: {
|
||||
children: '',
|
||||
},
|
||||
render: props => (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '15px' }}>
|
||||
<div style={{ display: 'flex', gap: '15px' }}>
|
||||
<FileUpload {...props} variant='filled' color='ut-black' size='small'>
|
||||
Upload File
|
||||
</FileUpload>
|
||||
<FileUpload {...props} variant='outline' color='ut-black' size='small'>
|
||||
Upload File
|
||||
</FileUpload>
|
||||
<FileUpload {...props} variant='minimal' color='ut-black' size='small'>
|
||||
Upload File
|
||||
</FileUpload>
|
||||
</div>
|
||||
<hr />
|
||||
<div style={{ display: 'flex', gap: '15px' }}>
|
||||
<FileUpload {...props} icon={ImageSquare} variant='filled' color='ut-black' size='small' />
|
||||
<FileUpload {...props} icon={ImageSquare} variant='outline' color='ut-black' size='small' />
|
||||
<FileUpload {...props} icon={ImageSquare} variant='minimal' color='ut-black' size='small' />
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
};
|
||||
|
||||
export const Mini: Story = {
|
||||
// @ts-ignore
|
||||
args: {
|
||||
children: '',
|
||||
},
|
||||
render: props => (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '15px' }}>
|
||||
<div style={{ display: 'flex', gap: '15px' }}>
|
||||
<FileUpload {...props} variant='filled' color='ut-black' size='mini'>
|
||||
Button
|
||||
</FileUpload>
|
||||
<FileUpload {...props} variant='outline' color='ut-black' size='mini'>
|
||||
Button
|
||||
</FileUpload>
|
||||
<FileUpload {...props} variant='minimal' color='ut-black' size='mini'>
|
||||
Button
|
||||
</FileUpload>
|
||||
</div>
|
||||
<hr />
|
||||
<div style={{ display: 'flex', gap: '15px' }}>
|
||||
<FileUpload {...props} icon={ImageSquare} variant='filled' color='ut-black' size='mini' />
|
||||
<FileUpload {...props} icon={ImageSquare} variant='outline' color='ut-black' size='mini' />
|
||||
<FileUpload {...props} icon={ImageSquare} variant='minimal' color='ut-black' size='mini' />
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
};
|
||||
|
||||
export const Disabled: Story = {
|
||||
args: {
|
||||
variant: 'filled',
|
||||
@@ -60,7 +116,7 @@ export const Grid: Story = {
|
||||
<div style={{ display: 'flex', gap: '15px' }}>
|
||||
<FileUpload {...props} variant='filled' color='ut-black' />
|
||||
<FileUpload {...props} variant='outline' color='ut-black' />
|
||||
<FileUpload {...props} variant='single' color='ut-black' />
|
||||
<FileUpload {...props} variant='minimal' color='ut-black' />
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
@@ -68,7 +124,7 @@ export const Grid: Story = {
|
||||
<div style={{ display: 'flex', gap: '15px' }}>
|
||||
<FileUpload {...props} variant='filled' color='ut-black' disabled />
|
||||
<FileUpload {...props} variant='outline' color='ut-black' disabled />
|
||||
<FileUpload {...props} variant='single' color='ut-black' disabled />
|
||||
<FileUpload {...props} variant='minimal' color='ut-black' disabled />
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
@@ -92,7 +148,7 @@ export const PrettyColors: Story = {
|
||||
<FileUpload {...props} variant='outline' color={color}>
|
||||
Button
|
||||
</FileUpload>
|
||||
<FileUpload {...props} variant='single' color={color}>
|
||||
<FileUpload {...props} variant='minimal' color={color}>
|
||||
Button
|
||||
</FileUpload>
|
||||
</div>
|
||||
|
||||
@@ -56,10 +56,10 @@ export const AreYouSure: StoryObj<PromptDialogProps> = {
|
||||
</Text>
|
||||
),
|
||||
children: [
|
||||
<Button key='yes' variant='single' color='ut-burntorange'>
|
||||
<Button key='yes' variant='minimal' color='ut-burntorange'>
|
||||
Yes
|
||||
</Button>,
|
||||
<Button key='no' variant='single' color='ut-black'>
|
||||
<Button key='no' variant='minimal' color='ut-black'>
|
||||
No
|
||||
</Button>,
|
||||
],
|
||||
@@ -76,7 +76,7 @@ export const YouHave10ActiveSchedules: StoryObj<PromptDialogProps> = {
|
||||
</Text>
|
||||
),
|
||||
children: [
|
||||
<Button key='yes' variant='single' color='ut-black'>
|
||||
<Button key='yes' variant='minimal' color='ut-black'>
|
||||
I understand
|
||||
</Button>,
|
||||
],
|
||||
@@ -94,10 +94,10 @@ export const WelcomeToUTRPV2: StoryObj<PromptDialogProps> = {
|
||||
</Text>
|
||||
),
|
||||
children: [
|
||||
<Button key='migrate' variant='single' color='ut-black'>
|
||||
<Button key='migrate' variant='minimal' color='ut-black'>
|
||||
Don't Migrate
|
||||
</Button>,
|
||||
<Button key='start-fresh' variant='single' color='ut-burntorange'>
|
||||
<Button key='start-fresh' variant='minimal' color='ut-burntorange'>
|
||||
Migrate
|
||||
</Button>,
|
||||
],
|
||||
|
||||
@@ -132,12 +132,11 @@ export default function PopupMain(): JSX.Element {
|
||||
<div className='bottom-0 right-0 mt-2.5 w-full flex justify-end'>
|
||||
<Button
|
||||
variant='filled'
|
||||
size='mini'
|
||||
color='ut-burntorange'
|
||||
className='h-fit p-0 btn'
|
||||
onClick={handleAddSchedule}
|
||||
>
|
||||
<Plus className='h-6 w-6' />
|
||||
</Button>
|
||||
icon={Plus}
|
||||
/>
|
||||
</div>
|
||||
</ScheduleDropdown>
|
||||
</div>
|
||||
|
||||
@@ -60,12 +60,12 @@ export default function CalendarBottomBar({ courseCells, setCourse }: CalendarBo
|
||||
</div>
|
||||
<div className='flex items-center screenshot:hidden'>
|
||||
{displayCourses && <Divider orientation='vertical' size='1rem' className='mx-1.25' />}
|
||||
<Button variant='single' color='ut-black' icon={CalendarDots} onClick={saveAsCal}>
|
||||
<Button variant='minimal' color='ut-black' icon={CalendarDots} onClick={saveAsCal}>
|
||||
Save as .CAL
|
||||
</Button>
|
||||
<Divider orientation='vertical' size='1rem' className='mx-1.25' />
|
||||
<Button
|
||||
variant='single'
|
||||
variant='minimal'
|
||||
color='ut-black'
|
||||
icon={ImageSquare}
|
||||
onClick={() => requestAnimationFrame(() => saveCalAsPng())}
|
||||
|
||||
@@ -57,7 +57,7 @@ export default function CalendarHeader({ onSidebarToggle }: CalendarHeaderProps)
|
||||
return (
|
||||
<div className='flex items-center gap-5 overflow-x-auto overflow-y-hidden border-b border-ut-offwhite px-7 py-4 md:overflow-x-hidden'>
|
||||
<Button
|
||||
variant='single'
|
||||
variant='minimal'
|
||||
icon={Sidebar}
|
||||
color='ut-gray'
|
||||
onClick={onSidebarToggle}
|
||||
@@ -83,7 +83,7 @@ export default function CalendarHeader({ onSidebarToggle }: CalendarHeaderProps)
|
||||
|
||||
{/* <Button variant='single' icon={UndoIcon} color='ut-black' />
|
||||
<Button variant='single' icon={RedoIcon} color='ut-black' /> */}
|
||||
<Button variant='single' icon={GearSix} color='theme-black' onClick={handleOpenOptions} />
|
||||
<Button variant='minimal' icon={GearSix} color='theme-black' onClick={handleOpenOptions} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -31,9 +31,7 @@ export function CalendarSchedules() {
|
||||
<Text variant='h3' className='text-nowrap'>
|
||||
MY SCHEDULES
|
||||
</Text>
|
||||
<Button variant='single' color='theme-black' className='h-fit p-0 btn' onClick={handleAddSchedule}>
|
||||
<Plus className='h-6 w-6' />
|
||||
</Button>
|
||||
<Button size='mini' variant='minimal' color='theme-black' onClick={handleAddSchedule} icon={Plus} />
|
||||
</div>
|
||||
<div className='flex flex-col space-y-2.5'>
|
||||
<List
|
||||
|
||||
@@ -8,7 +8,8 @@ import React from 'react';
|
||||
interface Props {
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
variant: 'filled' | 'outline' | 'single';
|
||||
variant?: 'filled' | 'outline' | 'minimal';
|
||||
size?: 'regular' | 'small' | 'mini';
|
||||
onClick?: () => void;
|
||||
icon?: Icon;
|
||||
iconProps?: IconProps;
|
||||
@@ -24,7 +25,8 @@ interface Props {
|
||||
export function Button({
|
||||
className,
|
||||
style,
|
||||
variant,
|
||||
variant = 'filled',
|
||||
size = 'regular',
|
||||
onClick,
|
||||
icon,
|
||||
iconProps,
|
||||
@@ -52,11 +54,15 @@ export function Button({
|
||||
{
|
||||
'text-white! bg-opacity-100 hover:enabled:shadow-md active:enabled:shadow-sm shadow-black/20':
|
||||
variant === 'filled',
|
||||
'bg-opacity-0 border-current hover:enabled:bg-opacity-8 border': variant === 'outline',
|
||||
'bg-opacity-0 border-none hover:enabled:bg-opacity-8': variant === 'single', // settings is the only "single"
|
||||
'px-2 py-1.25': isIconOnly && variant !== 'outline',
|
||||
'px-1.75 py-1.25': isIconOnly && variant === 'outline',
|
||||
'px-3.75': variant === 'outline' && !isIconOnly,
|
||||
'bg-opacity-0 border-current hover:enabled:bg-opacity-8 border stroke-width-[1px]':
|
||||
variant === 'outline',
|
||||
'bg-opacity-0 border-none hover:enabled:bg-opacity-8': variant === 'minimal',
|
||||
'h-10 gap-spacing-3 px-spacing-5': size === 'regular' && !isIconOnly,
|
||||
'h-10 w-10 p-spacing-2': size === 'regular' && isIconOnly,
|
||||
'h-[35px] gap-spacing-3 px-spacing-3': size === 'small' && !isIconOnly,
|
||||
'h-[35px] w-[35px] p-spacing-2': size === 'small' && isIconOnly,
|
||||
'h-6 p-spacing-2': size === 'mini' && !isIconOnly,
|
||||
'h-6 w-6 p-0': size === 'mini' && isIconOnly,
|
||||
},
|
||||
className
|
||||
)}
|
||||
@@ -66,7 +72,10 @@ export function Button({
|
||||
>
|
||||
{Icon && <Icon {...iconProps} className={clsx('h-6 w-6', iconProps?.className)} />}
|
||||
{!isIconOnly && (
|
||||
<Text variant='h4' className='inline-flex translate-y-0.08 items-center gap-2'>
|
||||
<Text
|
||||
variant={size === 'regular' ? 'h4' : 'small'}
|
||||
className='inline-flex translate-y-0.08 items-center gap-2'
|
||||
>
|
||||
{children}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
@@ -8,7 +8,8 @@ import React from 'react';
|
||||
interface Props {
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
variant: 'filled' | 'outline' | 'single';
|
||||
variant?: 'filled' | 'outline' | 'minimal';
|
||||
size?: 'regular' | 'small' | 'mini';
|
||||
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
icon?: Icon;
|
||||
iconProps?: IconProps;
|
||||
@@ -25,7 +26,8 @@ interface Props {
|
||||
export default function FileUpload({
|
||||
className,
|
||||
style,
|
||||
variant,
|
||||
variant = 'filled',
|
||||
size = 'regular',
|
||||
onChange,
|
||||
icon,
|
||||
iconProps,
|
||||
@@ -53,11 +55,15 @@ export default function FileUpload({
|
||||
{
|
||||
'text-white! bg-opacity-100 hover:enabled:shadow-md active:enabled:shadow-sm shadow-black/20':
|
||||
variant === 'filled',
|
||||
'bg-opacity-0 border-current hover:enabled:bg-opacity-8 border': variant === 'outline',
|
||||
'bg-opacity-0 border-none hover:enabled:bg-opacity-8': variant === 'single', // settings is the only "single"
|
||||
'px-2 py-1.25': isIconOnly && variant !== 'outline',
|
||||
'px-1.75 py-1.25': isIconOnly && variant === 'outline',
|
||||
'px-3.75': variant === 'outline' && !isIconOnly,
|
||||
'bg-opacity-0 border-current hover:enabled:bg-opacity-8 border stroke-width-[1px]':
|
||||
variant === 'outline',
|
||||
'bg-opacity-0 border-none hover:enabled:bg-opacity-8': variant === 'minimal',
|
||||
'h-10 gap-spacing-3 px-spacing-5': size === 'regular' && !isIconOnly,
|
||||
'h-10 w-10 p-spacing-2': size === 'regular' && isIconOnly,
|
||||
'h-[35px] gap-spacing-3 px-spacing-3': size === 'small' && !isIconOnly,
|
||||
'h-[35px] w-[35px] p-spacing-2': size === 'small' && isIconOnly,
|
||||
'h-6 p-spacing-2': size === 'mini' && !isIconOnly,
|
||||
'h-6 w-6 p-0': size === 'mini' && isIconOnly,
|
||||
},
|
||||
className
|
||||
)}
|
||||
@@ -65,7 +71,10 @@ export default function FileUpload({
|
||||
>
|
||||
{Icon && <Icon {...iconProps} className={clsx('h-6 w-6', iconProps?.className)} />}
|
||||
{!isIconOnly && (
|
||||
<Text variant='h4' className='inline-flex translate-y-0.08 items-center gap-2'>
|
||||
<Text
|
||||
variant={size === 'regular' ? 'h4' : 'small'}
|
||||
className='inline-flex translate-y-0.08 items-center gap-2'
|
||||
>
|
||||
{children}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
@@ -53,7 +53,7 @@ function MigrationButtons({ close }: { close: () => void }): JSX.Element {
|
||||
</Text>
|
||||
)}
|
||||
<Button
|
||||
variant='single'
|
||||
variant='minimal'
|
||||
color='ut-black'
|
||||
onClick={() => {
|
||||
close();
|
||||
|
||||
@@ -73,7 +73,7 @@ export default function ScheduleListItem({ schedule, dragHandleProps, onClick }:
|
||||
// eslint-disable-next-line react/no-unstable-nested-components
|
||||
buttons: close => (
|
||||
<>
|
||||
<Button variant='single' color='ut-black' onClick={close}>
|
||||
<Button variant='minimal' color='ut-black' onClick={close}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
|
||||
@@ -107,7 +107,7 @@ export default function HeadingAndActions({ course, activeSchedule, onClose }: H
|
||||
<Text variant='h1' className='flex-1 whitespace-nowrap text-theme-black'>
|
||||
({department} {courseNumber})
|
||||
</Text>
|
||||
<Button color='ut-burntorange' variant='single' icon={Copy} onClick={handleCopy}>
|
||||
<Button color='ut-burntorange' variant='minimal' icon={Copy} onClick={handleCopy}>
|
||||
{formattedUniqueId}
|
||||
</Button>
|
||||
<button className='bg-transparent p-0 text-ut-black btn' onClick={onClose}>
|
||||
|
||||
@@ -260,7 +260,7 @@ export default function Settings(): JSX.Element {
|
||||
UTRP SETTINGS & CREDITS PAGE
|
||||
</Text>
|
||||
<div className='hidden flex-row items-center justify-end gap-6 screenshot:hidden lg:flex'>
|
||||
<Button variant='single' color='theme-black' onClick={handleChangelogOnClick}>
|
||||
<Button variant='minimal' color='theme-black' onClick={handleChangelogOnClick}>
|
||||
<IconoirGitFork className='h-6 w-6 text-ut-gray' />
|
||||
<Text variant='small' className='text-ut-gray font-normal'>
|
||||
v{manifest.version} - {process.env.NODE_ENV}
|
||||
|
||||
@@ -21,7 +21,7 @@ export default function useChangelog(): () => void {
|
||||
<Text variant='h1' className='text-theme-black'>
|
||||
Changelog
|
||||
</Text>
|
||||
<Button variant='single' onClick={close} color='theme-black' className='p-1 text-gray-700'>
|
||||
<Button variant='minimal' onClick={close} color='theme-black' className='p-1 text-gray-700'>
|
||||
<X className='h-6 w-6' />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -26,7 +26,7 @@ export default defineConfig({
|
||||
],
|
||||
shortcuts: {
|
||||
focusable: 'outline-none ring-blue-500/50 dark:ring-blue-400/60 ring-0 focus-visible:ring-4',
|
||||
btn: 'h-10 w-auto flex cursor-pointer justify-center items-center gap-2 rounded-1 px-4 py-0 text-4.5 btn-transition disabled:(cursor-not-allowed opacity-50) active:enabled:scale-96 focusable',
|
||||
btn: 'h-10 w-auto flex cursor-pointer justify-center items-center gap-spacing-3 rounded-1 px-spacing-5 py-0 text-4.5 btn-transition disabled:(cursor-not-allowed opacity-50) active:enabled:scale-96 focusable',
|
||||
link: 'text-ut-burntorange link:text-ut-burntorange underline underline-offset-2 hover:text-ut-orange focus-visible:text-ut-orange focusable btn-transition ease-out-expo',
|
||||
linkanimate:
|
||||
'relative cursor-pointer transition duration-100 ease-out after:(absolute left-0.4 right-0.4 h-2px scale-x-95 bg-ut-orange opacity-0 transition duration-250 ease-out-expo content-empty -bottom-0.75 -translate-y-0.5) active:scale-95 hover:text-ut-orange focus-visible:text-ut-orange hover:after:(opacity-100) !hover:after:translate-y-0 !hover:after:scale-x-100',
|
||||
|
||||
Reference in New Issue
Block a user