Commit 28d52130 authored by tom's avatar tom

loading skeleton state for button

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