UI refactor (#418)

button refactor

Co-authored-by: Jamie Pine <32987599+jamiepine@users.noreply.github.com>
This commit is contained in:
Brendan Allan 2022-10-19 12:24:47 +08:00 committed by GitHub
parent cf39b6fcc9
commit 21e156c517
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 123 additions and 184 deletions

View file

@ -9,9 +9,11 @@ import { Discord, Github } from '@icons-pack/react-simple-icons';
import AppLogo from '@sd/assets/images/logo.png';
import { Dropdown, DropdownItem } from '@sd/ui';
import clsx from 'clsx';
import { DotsThreeVertical, List } from 'phosphor-react';
import { DotsThreeVertical } from 'phosphor-react';
import { PropsWithChildren, useEffect, useState } from 'react';
import { positions } from '../pages/careers.page';
import { getWindow } from '../utils';

View file

@ -72,12 +72,12 @@ export const Inspector = (props: Props) => {
<FavoriteButton data={objectData} />
</Tooltip>
<Tooltip label="Share">
<Button size="sm" noPadding>
<Button size="sm" padding="sm">
<ShareIcon className="w-[18px] h-[18px]" />
</Button>
</Tooltip>
<Tooltip label="Link">
<Button size="sm" noPadding>
<Button size="sm" padding="sm">
<Link className="w-[18px] h-[18px]" />
</Button>
</Tooltip>

View file

@ -30,7 +30,7 @@ export default function FavoriteButton(props: Props) {
};
return (
<Button onClick={toggleFavorite} size="sm" noPadding>
<Button onClick={toggleFavorite} size="sm" padding="sm">
<Heart weight={favorite ? 'fill' : 'regular'} className="w-[18px] h-[18px]" />
</Button>
);

View file

@ -48,7 +48,7 @@ export function JobsManager() {
{/* <div className="z-10 flex flex-row w-full h-10 bg-gray-500 border-b border-gray-700 bg-opacity-30"></div> */}
<div className="h-full mr-1 overflow-x-hidden custom-scroll inspector-scroll">
<div className="py-1 pl-2">
<div className="fixed flex items-center h-10 ">
<div className="fixed flex items-center h-10">
<h3 className="mt-1.5 ml-2 text-md font-medium opacity-40">Recent Jobs</h3>
</div>
<div className="h-10"></div>
@ -64,31 +64,28 @@ export function JobsManager() {
<Tooltip label={job.status}>
<niceData.icon className={clsx('w-5 mr-3', color)} />
</Tooltip>
<div className="flex flex-col">
<span className="flex mt-0.5 items-center font-semibold">{niceData.name}</span>
<div className="flex items-center">
<span className="text-xs opacity-60">
<div className="flex flex-1 flex-col">
<span className="mt-0.5 font-semibold">{niceData.name}</span>
<div className="flex items-center opacity-60">
<span className="text-xs">
{job.status === 'Failed' ? 'Failed after' : 'Took'}{' '}
{job.seconds_elapsed
? dayjs.duration({ seconds: job.seconds_elapsed }).humanize()
: 'less than a second'}
</span>
<span className="mx-1 opacity-30">&#8226;</span>
<span className="text-xs opacity-60">
{dayjs(job.date_created).toNow(true)} ago
</span>
<span className="mx-1 opacity-50">&#8226;</span>
<span className="text-xs">{dayjs(job.date_created).toNow(true)} ago</span>
</div>
<span className="text-xs opacity-60">{job.data}</span>
<span className="text-xs">{job.data}</span>
</div>
<div className="flex-grow" />
<div className="flex space-x-2">
<div className="space-x-2">
{job.status === 'Failed' && (
<Button className="!p-0 w-7 h-7 flex items-center" variant="gray">
<ArrowsClockwise className="w-4" />
<Button padding="thin" variant="gray">
<ArrowsClockwise className="w-4 h-4" />
</Button>
)}
<Button className="!p-0 w-7 h-7 flex items-center" variant="gray">
<XMarkIcon className="w-4" />
<Button padding="thin" variant="gray">
<XMarkIcon className="w-4 h-4" />
</Button>
</div>
</div>

View file

@ -11,10 +11,10 @@ export function KeyManager(props: KeyManagerProps) {
<div>
<Tabs.Root defaultValue="mount">
<Tabs.List>
<Tabs.Trigger className="text-sm font-medium text-gray-300" value="mount">
<Tabs.Trigger className="text-sm font-medium " value="mount">
Mount
</Tabs.Trigger>
<Tabs.Trigger className="text-sm font-medium text-gray-300" value="keys">
<Tabs.Trigger className="text-sm font-medium " value="keys">
Keys
</Tabs.Trigger>
</Tabs.List>

View file

@ -168,7 +168,7 @@ export function Sidebar() {
<Dropdown
buttonProps={{
justifyLeft: true,
justify: 'left',
className: clsx(
`flex w-full text-left max-w-full mb-1 mt-1 -mr-0.5 shadow-xs rounded !bg-gray-50 border-gray-150 hover:!bg-gray-1000 dark:!bg-gray-500 dark:hover:!bg-gray-500 dark:!border-gray-550 dark:hover:!border-gray-500`,
macOnly(
@ -233,14 +233,10 @@ export function Sidebar() {
{library && <RunningJobsWidget />}
<div className="mt-2 mb-2">
<div className="mt-2 mb-3">
<NavLink to="/settings/general">
{({ isActive }) => (
<Button
noPadding
variant={'default'}
className={clsx('px-[4px] hover:!bg-opacity-20 mb-1')}
>
<Button padding="sm" variant="default" className={clsx('hover:!bg-opacity-20')}>
<CogIcon className="w-5 h-5" />
</Button>
)}
@ -251,9 +247,9 @@ export function Sidebar() {
disabled={!library}
trigger={
<Button
noPadding
padding="sm"
className={clsx(
'px-[4px] !outline-none hover:!bg-opacity-20 disabled:opacity-50 disabled:cursor-not-allowed'
'!outline-none hover:!bg-opacity-20 disabled:opacity-50 disabled:cursor-not-allowed'
)}
>
<CheckCircle className="w-5 h-5" />

View file

@ -14,7 +14,7 @@ import { SettingsHeader } from '../../../components/settings/SettingsHeader';
function LibraryListItem(props: { library: LibraryConfigWrapped }) {
const [openDeleteModal, setOpenDeleteModal] = useState(false);
const { mutate: deleteLib, isLoading: libDeletePending } = useBridgeMutation('library.delete', {
const deleteLibrary = useBridgeMutation('library.delete', {
onSuccess: () => {
setOpenDeleteModal(false);
}
@ -23,16 +23,16 @@ function LibraryListItem(props: { library: LibraryConfigWrapped }) {
return (
<Card>
<DotsSixVertical weight="bold" className="mt-[15px] mr-3 opacity-30" />
<div className="flex-grow my-0.5">
<div className="flex-1 my-0.5">
<h3 className="font-semibold">{props.library.config.name}</h3>
<p className="mt-0.5 text-xs text-gray-200">{props.library.uuid}</p>
</div>
<div className="mt-2 space-x-2">
<ButtonLink to="/settings/library" variant="gray" className="!p-1.5">
<div className="flex flex-row space-x-2 items-center">
<ButtonLink to="/settings/library" variant="gray" padding="sm">
<PencilIcon className="w-4 h-4" />
</ButtonLink>
<DeleteLibraryDialog libraryUuid={props.library.uuid}>
<Button variant="gray" className="!p-1.5">
<Button variant="gray" padding="sm">
<TrashIcon className="w-4 h-4" />
</Button>
</DeleteLibraryDialog>

View file

@ -1,95 +1,10 @@
import { VariantProps, cva } from 'class-variance-authority';
import clsx from 'clsx';
import { forwardRef } from 'react';
import { Link, LinkProps } from 'react-router-dom';
const sizes = {
default: 'py-1 px-3 text-md font-medium',
sm: 'py-1 px-2 text-xs font-medium'
};
const variants = {
default: `
bg-gray-50
shadow-sm
hover:bg-gray-100
active:bg-gray-50
dark:bg-transparent
dark:active:bg-gray-600
dark:hover:bg-gray-550
dark:active:opacity-80
border-gray-100
hover:border-gray-200
active:border-gray-200
dark:border-transparent
dark:active:border-gray-600
dark:hover:border-gray-500
text-gray-700
hover:text-gray-900
active:text-gray-600
dark:text-gray-200
dark:active:text-white
dark:hover:text-white
`,
gray: `
bg-gray-100
shadow-sm
hover:bg-gray-200
active:bg-gray-100
dark:bg-gray-500
dark:hover:bg-gray-500
dark:bg-opacity-80
dark:hover:bg-opacity-100
dark:active:opacity-80
border-gray-200
hover:border-gray-300
active:border-gray-200
dark:border-gray-500
dark:hover:border-gray-500
text-gray-700
hover:text-gray-900
active:text-gray-600
dark:text-gray-200
dark:active:text-white
dark:hover:text-white
`,
primary: `
bg-primary-600
text-white
shadow-sm
active:bg-primary-600
hover:bg-primary
border-primary-500
hover:border-primary-500
active:border-primary-700
`,
colored: `
text-white
shadow-sm
hover:bg-opacity-90
active:bg-opacity-100
`,
selected: `bg-gray-100 dark:bg-gray-500
text-black hover:text-black active:text-black dark:hover:text-white dark:text-white
`
};
export type ButtonVariant = keyof typeof variants;
export type ButtonSize = keyof typeof sizes;
export interface ButtonBaseProps {
variant?: ButtonVariant;
size?: ButtonSize;
loading?: boolean;
export interface ButtonBaseProps extends VariantProps<typeof styles> {
icon?: React.ReactNode;
noPadding?: boolean;
noBorder?: boolean;
pressEffect?: boolean;
justifyLeft?: boolean;
}
export type ButtonProps = ButtonBaseProps &
@ -109,73 +24,102 @@ type Button = {
const hasHref = (props: ButtonProps | LinkButtonProps): props is LinkButtonProps => 'href' in props;
const styles = cva(
'border rounded-md items-center transition-colors duration-100 cursor-default disabled:opacity-50 disabled:cursor-not-allowed',
{
variants: {
pressEffect: {
true: 'active:translate-y-[1px]'
},
loading: {
true: 'opacity-70'
},
padding: {
thin: '!p-1',
sm: '!p-1.5'
},
noBorder: {
true: 'border-0'
},
size: {
md: 'py-1 px-3 text-md font-medium',
sm: 'py-1 px-2 text-xs font-medium'
},
justify: {
left: 'justify-left',
center: ''
},
variant: {
default: [
'bg-gray-50 shadow-sm hover:bg-gray-100 active:bg-gray-50 dark:bg-transparent',
'dark:active:bg-gray-600 dark:hover:bg-gray-550 dark:active:opacity-80',
'border-gray-100 hover:border-gray-200 active:border-gray-200',
'dark:border-transparent dark:active:border-gray-600 dark:hover:border-gray-500',
'text-gray-700 hover:text-gray-900 active:text-gray-600',
'dark:text-gray-200 dark:active:text-white dark:hover:text-white'
],
gray: [
'bg-gray-100 shadow-sm hover:bg-gray-200 active:bg-gray-100 dark:bg-gray-500 dark:hover:bg-gray-500 dark:bg-opacity-80 dark:hover:bg-opacity-100 dark:active:opacity-80',
'border-gray-200 hover:border-gray-300 active:border-gray-200 dark:border-gray-500 dark:hover:border-gray-500',
'text-gray-700 hover:text-gray-900 active:text-gray-600 dark:text-gray-200 dark:active:text-white dark:hover:text-white'
],
primary: [
'bg-primary-600 text-white shadow-sm active:bg-primary-600 hover:bg-primary border-primary-500 hover:border-primary-500 active:border-primary-700'
],
colored: ['text-white shadow-sm hover:bg-opacity-90 active:bg-opacity-100'],
selected: [
'bg-gray-100 dark:bg-gray-500 text-black hover:text-black active:text-black dark:hover:text-white dark:text-white'
]
}
},
defaultVariants: {
size: 'md',
justify: 'center',
variant: 'default'
}
}
);
export const Button = forwardRef<
HTMLButtonElement | HTMLAnchorElement,
ButtonProps | LinkButtonProps
>(
(
{ loading, justifyLeft, className, pressEffect, noBorder, noPadding, size, variant, ...props },
ref
) => {
className = clsx(
'border rounded-md items-center transition-colors duration-100 cursor-default disabled:opacity-50 disabled:cursor-not-allowed',
{
'opacity-70': loading,
'!p-1': noPadding,
'justify-center': !justifyLeft,
'active:translate-y-[1px]': pressEffect,
'border-0': noBorder
},
sizes[size || 'default'],
variants[variant || 'default'],
className
);
>(({ className, ...props }, ref) => {
className = clsx(styles(props), className);
return hasHref(props) ? (
<a {...props} ref={ref as any} className={clsx(className, 'no-underline')}>
<>
{props.icon}
{props.children}
</>
</a>
) : (
<button {...(props as ButtonProps)} ref={ref as any} className={className}>
<>
{props.icon}
{props.children}
</>
</button>
);
}
);
let children = (
<>
{props.icon}
{props.children}
</>
);
return hasHref(props) ? (
<a {...props} ref={ref as any} className={clsx(className, 'no-underline inline-block')}>
{children}
</a>
) : (
<button {...(props as ButtonProps)} ref={ref as any} className={className}>
{children}
</button>
);
});
export const ButtonLink = forwardRef<
HTMLLinkElement,
ButtonBaseProps & LinkProps & React.RefAttributes<HTMLAnchorElement>
>(
(
{ loading, justifyLeft, className, pressEffect, noBorder, noPadding, size, variant, ...props },
ref
) => {
className = clsx(
'border rounded-md items-center transition-colors duration-100 cursor-default',
{ 'opacity-70': loading, '!p-1': noPadding },
{ 'justify-center': !justifyLeft },
sizes[size || 'default'],
variants[variant || 'default'],
{ 'active:translate-y-[1px]': pressEffect },
{ 'border-0': noBorder },
'disabled:opacity-50 disabled:cursor-not-allowed',
className
);
>(({ className, to, ...props }, ref) => {
className = clsx(
styles(props),
'no-underline disabled:opacity-50 disabled:cursor-not-allowed',
className
);
return (
<Link {...props} ref={ref as any} className={clsx(className, 'no-underline')}>
<>
{props.icon}
{props.children}
</>
</Link>
);
}
);
return (
<Link to={to} ref={ref as any} className={className}>
<>
{props.icon}
{props.children}
</>
</Link>
);
});