Skip to content

Commit

Permalink
feat(Loading): Add a new component Loading and fix an issue with load…
Browse files Browse the repository at this point in the history
…ing on component Button after upgrade to daisyui version 3 (#358)
  • Loading branch information
trinhquocviet committed Jun 19, 2023
1 parent e5161fd commit 65550d9
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 2 deletions.
5 changes: 3 additions & 2 deletions src/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { forwardRef, ReactNode } from 'react'
import clsx from 'clsx'
import { twMerge } from 'tailwind-merge'

import Loading from '../Loading';
import {
IComponentBaseProps,
ComponentColor,
Expand All @@ -23,7 +24,7 @@ export type ButtonProps = Omit<
fullWidth?: boolean
responsive?: boolean
animation?: boolean
loading?: boolean
loading?: boolean
active?: boolean
startIcon?: ReactNode
endIcon?: ReactNode
Expand Down Expand Up @@ -80,7 +81,6 @@ const Button = forwardRef<HTMLButtonElement, ButtonProps>(
'no-animation': !animation,
'btn-active': active,
'btn-disabled': disabled,
loading: loading,
})
)

Expand All @@ -102,6 +102,7 @@ const Button = forwardRef<HTMLButtonElement, ButtonProps>(
style={style}
disabled={disabled}
>
{!startIcon && loading && (<Loading size={size} />)}
{startIcon && !loading && startIcon}
{children}
{endIcon && endIcon}
Expand Down
69 changes: 69 additions & 0 deletions src/Loading/Loading.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React from 'react'
import { StoryFn as Story, Meta } from '@storybook/react'

import Loading, { LoadingProps } from '.'

const meta: Meta = {
title: 'Data Display/Loading',
component: Loading,
parameters: {
controls: { expanded: true },
},
};

export default meta

const Template: Story<LoadingProps> = (args) => {
return <Loading {...args} />
}
export const Default = Template.bind({})
Default.args = {
variant: 'spinner',
}

export const Colors: Story<LoadingProps> = (args) => {
return (
<div>
<div>
<Loading {...args} />
<Loading {...args} color="primary" />
<Loading {...args} color="secondary" />
<Loading {...args} color="success" />
<Loading {...args} color="warning" />
<Loading {...args} color="error" />
<Loading {...args} color="info" />
<Loading {...args} color="accent" />
<Loading {...args} color="ghost" />
</div>
</div>
)
}
Colors.args = {
className: "m-1"
}

export const Variants: Story<LoadingProps> = (args) => {
return (
<div className="flex gap-x-2">
<Loading {...args} />
<Loading {...args} variant="dots" />
<Loading {...args} variant="ring" />
<Loading {...args} variant="ball" />
<Loading {...args} variant="bars" />
<Loading {...args} variant="infinity" />
</div>
)
}

export const Sizes: Story<LoadingProps> = (args) => {
return (
<div>
<div>
<Loading {...args} size="xs" />
<Loading {...args} size="sm" />
<Loading {...args} size="md" />
<Loading {...args} size="lg" />
</div>
</div>
)
}
30 changes: 30 additions & 0 deletions src/Loading/Loading.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { render } from '@testing-library/react'
import Loading from '.'

describe('Loading', () => {
it('renders a default variant', () => {
const {container} = render(<Loading />)
expect(container.querySelector('.loading')).toHaveClass('loading-spinner')
})

it('renders a variant', () => {
const {container} = render(<Loading variant="infinity" />)
expect(container.querySelector('.loading')).toHaveClass('loading-infinity')
})

it('renders a size', () => {
const {container} = render(<Loading size="xs" />)
expect(container.querySelector('.loading')).toHaveClass('loading-xs')
})

it('renders a color', () => {
const {container} = render(<Loading color="primary" />)
expect(container.querySelector('.loading')).toHaveClass('text-primary')
})

it('renders a variant and size', () => {
const {container} = render(<Loading variant="dots" size="xs" />)
expect(container.querySelector('.loading')).toHaveClass('loading-dots')
expect(container.querySelector('.loading')).toHaveClass('loading-xs')
})
})
72 changes: 72 additions & 0 deletions src/Loading/Loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React, { forwardRef, ReactNode } from 'react'
import clsx from 'clsx'
import { twMerge } from 'tailwind-merge'

import {
IComponentBaseProps,
ComponentColor,
ComponentSize,
} from '../types'

export type LoadingProps =
React.HTMLAttributes<HTMLSpanElement>
& IComponentBaseProps
& {
size?: ComponentSize
color?: ComponentColor
variant?: 'spinner' | 'dots' | 'ring' | 'ball' | 'bars' | 'infinity'
}

const Loading = forwardRef<HTMLSpanElement, LoadingProps>(
(
{
size,
variant = 'spinner',
color,
dataTheme,
className,
style,
...props
},
ref
): JSX.Element => {
const classes = twMerge(
'loading',
className,
clsx({
'loading-lg': size === 'lg',
'loading-md': size === 'md',
'loading-sm': size === 'sm',
'loading-xs': size === 'xs',
'loading-spinner': variant === 'spinner',
'loading-dots': variant === 'dots',
'loading-ring': variant === 'ring',
'loading-ball': variant === 'ball',
'loading-bars': variant === 'bars',
'loading-infinity': variant === 'infinity',
'text-primary': color === 'primary',
'text-secondary': color === 'secondary',
'text-accent': color === 'accent',
'text-info': color === 'info',
'text-success': color === 'success',
'text-warning': color === 'warning',
'text-error': color === 'error',
'text-ghost': color === 'ghost',
})
)

return (
<span
{...props}
ref={ref}
data-theme={dataTheme}
className={classes}
style={style}
/>
)
}
)

Loading.displayName = 'Loading'

export default Loading
3 changes: 3 additions & 0 deletions src/Loading/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Loading, { LoadingProps as TLoadingProps } from './Loading'
export type LoadingProps = TLoadingProps
export default Loading

0 comments on commit 65550d9

Please sign in to comment.