Commit 28d52130 authored by tom's avatar tom

loading skeleton state for button

parent ba2a3e2e
...@@ -13,6 +13,7 @@ import { Skeleton } from './skeleton'; ...@@ -13,6 +13,7 @@ import { Skeleton } from './skeleton';
interface ButtonLoadingProps { interface ButtonLoadingProps {
loading?: boolean; loading?: boolean;
loadingText?: React.ReactNode; loadingText?: React.ReactNode;
loadingSkeleton?: boolean;
} }
export interface ButtonProps extends ChakraButtonProps, ButtonLoadingProps { export interface ButtonProps extends ChakraButtonProps, ButtonLoadingProps {
...@@ -23,7 +24,7 @@ export interface ButtonProps extends ChakraButtonProps, ButtonLoadingProps { ...@@ -23,7 +24,7 @@ export interface ButtonProps extends ChakraButtonProps, ButtonLoadingProps {
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
function Button(props, ref) { function Button(props, ref) {
const { loading, disabled, loadingText, children, expanded, selected, highlighted, ...rest } = props; const { loading, disabled, loadingText, children, expanded, selected, highlighted, loadingSkeleton = false, ...rest } = props;
const content = (() => { const content = (() => {
if (loading && !loadingText) { if (loading && !loadingText) {
...@@ -50,17 +51,20 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( ...@@ -50,17 +51,20 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
})(); })();
return ( return (
<ChakraButton <Skeleton loading={ loadingSkeleton } asChild>
{ ...(expanded ? { 'data-expanded': true } : {}) } <ChakraButton
{ ...(selected ? { 'data-selected': true } : {}) } { ...(expanded ? { 'data-expanded': true } : {}) }
{ ...(highlighted ? { 'data-highlighted': true } : {}) } { ...(selected ? { 'data-selected': true } : {}) }
{ ...(loading ? { 'data-loading': true } : {}) } { ...(highlighted ? { 'data-highlighted': true } : {}) }
disabled={ loading || disabled } { ...(loading ? { 'data-loading': true } : {}) }
ref={ ref } { ...(loadingSkeleton ? { 'data-loading-skeleton': true } : {}) }
{ ...rest } disabled={ !loadingSkeleton && (loading || disabled) }
> ref={ ref }
{ content } { ...rest }
</ChakraButton> >
{ content }
</ChakraButton>
</Skeleton>
); );
}, },
); );
......
import React from 'react'; import React from 'react';
import { Button, type ButtonProps } from './button'; import { Button, type ButtonProps } from './button';
import { Skeleton } from './skeleton';
export interface IconButtonProps extends ButtonProps {} export interface IconButtonProps extends ButtonProps {}
// TODO @tom2drum variants for icon buttons: prev-next, top-bar, copy-to-clipboard, filter column // TODO @tom2drum variants for icon buttons: prev-next, top-bar, copy-to-clipboard, filter column
// TODO @tom2drum fix loading state for outlined variant
export const IconButton = React.forwardRef<HTMLDivElement, IconButtonProps>( export const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(
function IconButton(props, ref) { function IconButton(props, ref) {
const { loading, size, variant = 'plain', ...rest } = props; const { size, variant = 'plain', ...rest } = props;
return ( return (
<Skeleton loading={ loading } ref={ ref } asChild> <Button
<Button ref={ ref }
display="inline-flex" display="inline-flex"
justifyContent="center" justifyContent="center"
px="0" px="0"
py="0" py="0"
{ ...(size ? { size } : { height: 'auto', minW: 'auto' }) } { ...(size ? { size } : { height: 'auto', minW: 'auto' }) }
flexShrink="0" flexShrink="0"
variant={ variant } variant={ variant }
{ ...rest } { ...rest }
/> />
</Skeleton>
); );
}, },
); );
...@@ -15,12 +15,18 @@ export const recipe = defineRecipe({ ...@@ -15,12 +15,18 @@ export const recipe = defineRecipe({
'& svg': { '& svg': {
boxSize: 'auto', boxSize: 'auto',
}, },
_loading: {
bgColor: 'unset',
},
}, },
variants: { variants: {
variant: { variant: {
solid: { solid: {
bg: 'blue.600', bg: 'blue.600',
color: 'white', color: 'white',
'&:not([data-loading-skeleton])': {
bgColor: 'blue.600',
},
_hover: { _hover: {
bg: 'blue.400', bg: 'blue.400',
}, },
...@@ -34,11 +40,14 @@ export const recipe = defineRecipe({ ...@@ -34,11 +40,14 @@ export const recipe = defineRecipe({
}, },
}, },
outline: { outline: {
borderWidth: '2px', borderWidth: '0px',
borderStyle: 'solid', borderStyle: 'solid',
bg: 'transparent', bg: 'transparent',
color: 'button.outline.fg', color: 'button.outline.fg',
borderColor: 'button.outline.fg', borderColor: 'button.outline.fg',
'&:not([data-loading-skeleton])': {
borderWidth: '2px',
},
_hover: { _hover: {
bg: 'transparent', bg: 'transparent',
color: 'blue.400', color: 'blue.400',
...@@ -46,11 +55,14 @@ export const recipe = defineRecipe({ ...@@ -46,11 +55,14 @@ export const recipe = defineRecipe({
}, },
}, },
dropdown: { dropdown: {
borderWidth: '2px', borderWidth: '0px',
borderStyle: 'solid', borderStyle: 'solid',
bg: 'transparent', bg: 'transparent',
color: 'button.dropdown.fg', color: 'button.dropdown.fg',
borderColor: 'button.dropdown.border', borderColor: 'button.dropdown.border',
'&:not([data-loading-skeleton])': {
borderWidth: '2px',
},
_hover: { _hover: {
bg: 'transparent', bg: 'transparent',
color: 'blue.400', color: 'blue.400',
...@@ -111,6 +123,9 @@ export const recipe = defineRecipe({ ...@@ -111,6 +123,9 @@ export const recipe = defineRecipe({
hero: { hero: {
bg: 'button.hero.bg', bg: 'button.hero.bg',
color: 'button.hero.fg', color: 'button.hero.fg',
'&:not([data-loading-skeleton])': {
bg: 'button.hero.bg',
},
_loading: { _loading: {
'& .chakra-spinner': { '& .chakra-spinner': {
borderColor: 'white', borderColor: 'white',
...@@ -172,7 +187,7 @@ export const recipe = defineRecipe({ ...@@ -172,7 +187,7 @@ export const recipe = defineRecipe({
subtle: { subtle: {
bg: 'button.subtle.bg', bg: 'button.subtle.bg',
color: 'button.subtle.fg', color: 'button.subtle.fg',
'&:not([data-loading], [aria-busy=true])': { '&:not([data-loading-skeleton])': {
bg: 'button.subtle.bg', bg: 'button.subtle.bg',
}, },
_hover: { _hover: {
......
...@@ -10,6 +10,8 @@ interface Props { ...@@ -10,6 +10,8 @@ interface Props {
} }
const AdditionalInfoButton = (props: Props, ref: React.ForwardedRef<HTMLButtonElement>) => { const AdditionalInfoButton = (props: Props, ref: React.ForwardedRef<HTMLButtonElement>) => {
const { loading, ...rest } = props;
return ( return (
<IconButton <IconButton
ref={ ref } ref={ ref }
...@@ -22,7 +24,8 @@ const AdditionalInfoButton = (props: Props, ref: React.ForwardedRef<HTMLButtonEl ...@@ -22,7 +24,8 @@ const AdditionalInfoButton = (props: Props, ref: React.ForwardedRef<HTMLButtonEl
borderRadius="base" borderRadius="base"
aria-label="Transaction info" aria-label="Transaction info"
boxSize={ 6 } boxSize={ 6 }
{ ...props } loadingSkeleton={ loading }
{ ...rest }
> >
<IconSvg name="info" boxSize={ 5 }/> <IconSvg name="info" boxSize={ 5 }/>
</IconButton> </IconButton>
......
...@@ -61,7 +61,7 @@ const CopyToClipboard = (props: Props) => { ...@@ -61,7 +61,7 @@ const CopyToClipboard = (props: Props) => {
onClick={ handleClick } onClick={ handleClick }
ml={ 2 } ml={ 2 }
borderRadius="sm" borderRadius="sm"
loading={ isLoading } loadingSkeleton={ isLoading }
color="icon.info" color="icon.info"
_hover={{ color: 'link.primary.hover' }} _hover={{ color: 'link.primary.hover' }}
{ ...rest } { ...rest }
......
...@@ -26,7 +26,7 @@ const Hint = ({ label, className, tooltipProps, isLoading, as }: Props) => { ...@@ -26,7 +26,7 @@ const Hint = ({ label, className, tooltipProps, isLoading, as }: Props) => {
aria-label="hint" aria-label="hint"
boxSize={ 5 } boxSize={ 5 }
className={ className } className={ className }
loading={ isLoading } loadingSkeleton={ isLoading }
borderRadius="sm" borderRadius="sm"
as={ as } as={ as }
> >
......
...@@ -23,7 +23,7 @@ const TableItemActionButtons = ({ onEditClick, onDeleteClick, isLoading }: Props ...@@ -23,7 +23,7 @@ const TableItemActionButtons = ({ onEditClick, onDeleteClick, isLoading }: Props
variant="link" variant="link"
onClick={ onEditClick } onClick={ onEditClick }
onFocusCapture={ onFocusCapture } onFocusCapture={ onFocusCapture }
loading={ isLoading } loadingSkeleton={ isLoading }
display="inline-block" display="inline-block"
flexShrink={ 0 } flexShrink={ 0 }
borderRadius="none" borderRadius="none"
...@@ -37,7 +37,7 @@ const TableItemActionButtons = ({ onEditClick, onDeleteClick, isLoading }: Props ...@@ -37,7 +37,7 @@ const TableItemActionButtons = ({ onEditClick, onDeleteClick, isLoading }: Props
variant="link" variant="link"
onClick={ onDeleteClick } onClick={ onDeleteClick }
onFocusCapture={ onFocusCapture } onFocusCapture={ onFocusCapture }
loading={ isLoading } loadingSkeleton={ isLoading }
display="inline-block" display="inline-block"
flexShrink={ 0 } flexShrink={ 0 }
borderRadius="none" borderRadius="none"
......
...@@ -119,7 +119,7 @@ const ChartMenu = ({ ...@@ -119,7 +119,7 @@ const ChartMenu = ({
<> <>
<MenuRoot> <MenuRoot>
<MenuTrigger asChild> <MenuTrigger asChild>
<IconButton variant="dropdown" size="sm" aria-label="Open chart options menu" loading={ isLoading } borderRadius="base" borderWidth="0"> <IconButton variant="dropdown" size="sm" aria-label="Open chart options menu" loadingSkeleton={ isLoading } borderRadius="base" borderWidth="0">
<IconSvg name="dots" boxSize={ 4 } transform="rotate(-90deg)"/> <IconSvg name="dots" boxSize={ 4 } transform="rotate(-90deg)"/>
</IconButton> </IconButton>
</MenuTrigger> </MenuTrigger>
......
...@@ -43,7 +43,7 @@ const Pagination = (props: Props) => { ...@@ -43,7 +43,7 @@ const Pagination = (props: Props) => {
size="sm" size="sm"
onClick={ onPrevPageClick } onClick={ onPrevPageClick }
disabled={ !canGoBackwards || isLoading || page === 1 } disabled={ !canGoBackwards || isLoading || page === 1 }
loading={ showSkeleton } loadingSkeleton={ showSkeleton }
> >
<IconSvg name="arrows/east-mini" boxSize={ 5 }/> <IconSvg name="arrows/east-mini" boxSize={ 5 }/>
</IconButton> </IconButton>
...@@ -71,7 +71,7 @@ const Pagination = (props: Props) => { ...@@ -71,7 +71,7 @@ const Pagination = (props: Props) => {
size="sm" size="sm"
onClick={ onNextPageClick } onClick={ onNextPageClick }
disabled={ !hasNextPage || isLoading } disabled={ !hasNextPage || isLoading }
loading={ showSkeleton } loadingSkeleton={ showSkeleton }
> >
<IconSvg name="arrows/east-mini" boxSize={ 5 } transform="rotate(180deg)"/> <IconSvg name="arrows/east-mini" boxSize={ 5 } transform="rotate(180deg)"/>
</IconButton> </IconButton>
......
...@@ -21,7 +21,7 @@ const Sort = (props: Props) => { ...@@ -21,7 +21,7 @@ const Sort = (props: Props) => {
return ( return (
<SelectControl { ...controlProps } triggerProps={{ asChild: true }} noIndicator> <SelectControl { ...controlProps } triggerProps={{ asChild: true }} noIndicator>
<IconButton <IconButton
loading={ isLoading } loadingSkeleton={ isLoading }
aria-label="sort" aria-label="sort"
size="sm" size="sm"
variant="outline" variant="outline"
......
...@@ -11,7 +11,6 @@ import IconSvg from 'ui/shared/IconSvg'; ...@@ -11,7 +11,6 @@ import IconSvg from 'ui/shared/IconSvg';
import { Section, Container, SectionHeader, SamplesStack, Sample, SectionSubHeader } from './parts'; import { Section, Container, SectionHeader, SamplesStack, Sample, SectionSubHeader } from './parts';
// ?? buttons on marketplace card
const ButtonShowcase = () => { const ButtonShowcase = () => {
return ( return (
<Container value="button"> <Container value="button">
...@@ -186,6 +185,10 @@ const ButtonShowcase = () => { ...@@ -186,6 +185,10 @@ const ButtonShowcase = () => {
<Button variant="subtle" size="xs" disabled>Disabled: Now+1h</Button> <Button variant="subtle" size="xs" disabled>Disabled: Now+1h</Button>
</Sample> </Sample>
<Sample label="variant: ??? marketplace card???">
TBD
</Sample>
<Sample label="variant: plain"> <Sample label="variant: plain">
<Button variant="plain">Default</Button> <Button variant="plain">Default</Button>
<Button variant="plain" data-hover>Hovered</Button> <Button variant="plain" data-hover>Hovered</Button>
...@@ -203,6 +206,12 @@ const ButtonShowcase = () => { ...@@ -203,6 +206,12 @@ const ButtonShowcase = () => {
<Sample label="loading: true, loadingText: undefined"> <Sample label="loading: true, loadingText: undefined">
<Button loading>Content</Button> <Button loading>Content</Button>
</Sample> </Sample>
<Sample label="loadingSkeleton: true">
<Button loadingSkeleton>Content</Button>
<Button loadingSkeleton variant="outline">Content</Button>
<Button loadingSkeleton variant="dropdown">Content</Button>
<Button loadingSkeleton variant="subtle">Content</Button>
</Sample>
</SamplesStack> </SamplesStack>
</Section> </Section>
......
...@@ -10,7 +10,7 @@ interface Props { ...@@ -10,7 +10,7 @@ interface Props {
className?: string; className?: string;
} }
const NetworkMenuButton = ({ isActive, onClick, className, ...rest }: Props, ref: React.ForwardedRef<HTMLDivElement>) => { const NetworkMenuButton = ({ isActive, onClick, className, ...rest }: Props, ref: React.ForwardedRef<HTMLButtonElement>) => {
return ( return (
<IconButton <IconButton
className={ className } className={ className }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment