From ad688dcca7dbf804b9d20d13863510f1b2bd34c3 Mon Sep 17 00:00:00 2001 From: andrew Date: Thu, 23 May 2024 16:43:12 +0900 Subject: [PATCH 1/8] feat(spinner): implement `AlphaSpinner` component --- .../AlphaSpinner/Spinner.module.scss | 66 +++++++++++++++++++ .../src/components/AlphaSpinner/Spinner.tsx | 50 ++++++++++++++ .../components/AlphaSpinner/Spinner.types.ts | 20 ++++++ 3 files changed, 136 insertions(+) create mode 100644 packages/bezier-react/src/components/AlphaSpinner/Spinner.module.scss create mode 100644 packages/bezier-react/src/components/AlphaSpinner/Spinner.tsx create mode 100644 packages/bezier-react/src/components/AlphaSpinner/Spinner.types.ts diff --git a/packages/bezier-react/src/components/AlphaSpinner/Spinner.module.scss b/packages/bezier-react/src/components/AlphaSpinner/Spinner.module.scss new file mode 100644 index 0000000000..36e73b9437 --- /dev/null +++ b/packages/bezier-react/src/components/AlphaSpinner/Spinner.module.scss @@ -0,0 +1,66 @@ +@use '../../styles/mixins/dimension'; + +@keyframes rotate { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} + +.Spinner { + --b-spinner-size: initial; + --b-spinner-track-color: initial; + --b-spinner-fill-color: initial; + --b-spinner-stroke-width: initial; + --b-spinner-stroke-dasharray: initial; + + @include dimension.square(var(--b-spinner-size)); + + display: inline-flex; + animation: rotate 1s linear infinite; + + & .track { + fill: none; + stroke: var(--b-spinner-track-color); + stroke-linecap: round; + stroke-width: var(--b-spinner-stroke-width); + } + + & .fill { + fill: none; + stroke: var(--b-spinner-fill-color); + stroke-dasharray: var(--b-spinner-stroke-dasharray); + stroke-linecap: round; + stroke-width: var(--b-spinner-stroke-width); + } + + &:where(.size-s) { + --b-spinner-size: 28px; + --b-spinner-stroke-width: 4px; + --b-spinner-stroke-dasharray: 40 9999; + } + + &:where(.size-m) { + --b-spinner-size: 50px; + --b-spinner-stroke-width: 6px; + --b-spinner-stroke-dasharray: 60 9999; + } + + &:where(.variant-primary) { + --b-spinner-track-color: var(--alpha-color-primary-bg-lightest); + --b-spinner-fill-color: var(--alpha-color-fg-blue-normal); + } + + &:where(.variant-secondary) { + --b-spinner-track-color: var(--alpha-color-bg-black-light); + --b-spinner-fill-color: var(--alpha-color-fg-black-light); + } + + &:where(.variant-on-overlay) { + --b-spinner-track-color: var(--alpha-color-bg-absolute-white-lightest); + --b-spinner-fill-color: var(--alpha-color-fg-absolute-white-light); + } +} diff --git a/packages/bezier-react/src/components/AlphaSpinner/Spinner.tsx b/packages/bezier-react/src/components/AlphaSpinner/Spinner.tsx new file mode 100644 index 0000000000..0ded522f6e --- /dev/null +++ b/packages/bezier-react/src/components/AlphaSpinner/Spinner.tsx @@ -0,0 +1,50 @@ +import React, { forwardRef } from 'react' + +import classNames from 'classnames' + +import { type SpinnerProps } from './Spinner.types' + +import styles from './Spinner.module.scss' + +export const SPINNER_TEST_ID = 'bezier-spinner' + +export const Spinner = forwardRef( + function Spinner( + { className, size = 'm', variant = 'secondary', ...rest }, + forwardedRef + ) { + return ( + + + + + + + + ) + } +) diff --git a/packages/bezier-react/src/components/AlphaSpinner/Spinner.types.ts b/packages/bezier-react/src/components/AlphaSpinner/Spinner.types.ts new file mode 100644 index 0000000000..e82251598f --- /dev/null +++ b/packages/bezier-react/src/components/AlphaSpinner/Spinner.types.ts @@ -0,0 +1,20 @@ +import { + type BezierComponentProps, + type ColorProps, + type SizeProps, +} from '~/src/types/props' + +type SpinnerSize = 's' | 'm' + +interface SpinnerOwnProps { + /** + * The style variant of Spinner. + */ + variant?: 'primary' | 'secondary' | 'on-overlay' +} + +export interface SpinnerProps + extends Omit, keyof ColorProps>, + SizeProps, + ColorProps, + SpinnerOwnProps {} From cc7b7512255ae74f36f730d86e9f5d43ce4acd88 Mon Sep 17 00:00:00 2001 From: andrew Date: Thu, 23 May 2024 16:43:36 +0900 Subject: [PATCH 2/8] feat(spinner): test and storybook --- .../AlphaSpinner/AlphaSpinner.stories.tsx | 23 +++++++++++++ .../components/AlphaSpinner/Spinner.test.tsx | 34 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 packages/bezier-react/src/components/AlphaSpinner/AlphaSpinner.stories.tsx create mode 100644 packages/bezier-react/src/components/AlphaSpinner/Spinner.test.tsx diff --git a/packages/bezier-react/src/components/AlphaSpinner/AlphaSpinner.stories.tsx b/packages/bezier-react/src/components/AlphaSpinner/AlphaSpinner.stories.tsx new file mode 100644 index 0000000000..67479e56ba --- /dev/null +++ b/packages/bezier-react/src/components/AlphaSpinner/AlphaSpinner.stories.tsx @@ -0,0 +1,23 @@ +import React from 'react' + +import { type Meta, type StoryFn } from '@storybook/react' + +import { Spinner } from './Spinner' +import { type SpinnerProps } from './Spinner.types' + +const meta: Meta = { + component: Spinner, +} + +export default meta + +const Template: StoryFn = ({ ...args }) => + +export const Primary = { + render: Template, + + args: { + size: 'm', + variant: 'secondary', + }, +} diff --git a/packages/bezier-react/src/components/AlphaSpinner/Spinner.test.tsx b/packages/bezier-react/src/components/AlphaSpinner/Spinner.test.tsx new file mode 100644 index 0000000000..0dfecc84e3 --- /dev/null +++ b/packages/bezier-react/src/components/AlphaSpinner/Spinner.test.tsx @@ -0,0 +1,34 @@ +import React from 'react' + +import { render } from '~/src/utils/test' + +import { SPINNER_TEST_ID, Spinner } from './Spinner' + +describe('Spinner >', () => { + const renderSpinner = (props?: React.ComponentProps) => + render() + + it('should render', () => { + const { getByTestId } = renderSpinner() + const renderedSpinner = getByTestId(SPINNER_TEST_ID) + expect(renderedSpinner).toBeInTheDocument() + }) + + it('should render as a div by default', () => { + const { getByTestId } = renderSpinner() + const renderedSpinner = getByTestId(SPINNER_TEST_ID) + expect(renderedSpinner.tagName).toBe('SPAN') + }) + + it('should forward ref', () => { + const ref = React.createRef() + renderSpinner({ ref }) + expect(ref.current).toBeInTheDocument() + }) + + it('should receive size', () => { + const { getByTestId } = renderSpinner({ size: 'm' }) + const renderedSpinner = getByTestId(SPINNER_TEST_ID) + expect(renderedSpinner).toHaveClass('size-m') + }) +}) From 2471584dde653528cc5cb7ccc2ba5828ad286bdc Mon Sep 17 00:00:00 2001 From: andrew Date: Thu, 23 May 2024 16:43:48 +0900 Subject: [PATCH 3/8] feat(spinner): export --- packages/bezier-react/src/components/AlphaSpinner/index.ts | 2 ++ packages/bezier-react/src/index.ts | 1 + 2 files changed, 3 insertions(+) create mode 100644 packages/bezier-react/src/components/AlphaSpinner/index.ts diff --git a/packages/bezier-react/src/components/AlphaSpinner/index.ts b/packages/bezier-react/src/components/AlphaSpinner/index.ts new file mode 100644 index 0000000000..a45a7b9962 --- /dev/null +++ b/packages/bezier-react/src/components/AlphaSpinner/index.ts @@ -0,0 +1,2 @@ +export { Spinner as AlphaSpinner } from './Spinner' +export { type SpinnerProps as AlphaSpinnerProps } from './Spinner.types' diff --git a/packages/bezier-react/src/index.ts b/packages/bezier-react/src/index.ts index 70ff6b8b4d..acc1807223 100644 --- a/packages/bezier-react/src/index.ts +++ b/packages/bezier-react/src/index.ts @@ -12,6 +12,7 @@ export * from '~/src/components/AlphaDialogPrimitive' export * from '~/src/components/AlphaFloatingButton' export * from '~/src/components/AlphaFloatingIconButton' export * from '~/src/components/AlphaIconButton' +export * from '~/src/components/AlphaSpinner' export * from '~/src/components/AlphaTooltipPrimitive' export * from '~/src/components/AppProvider' export * from '~/src/components/AutoFocus' From 0c7fc76a2d410f730e8adc08b97e949d9b814076 Mon Sep 17 00:00:00 2001 From: andrew Date: Thu, 23 May 2024 16:44:16 +0900 Subject: [PATCH 4/8] chore(changeset): add --- .changeset/sweet-knives-divide.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/sweet-knives-divide.md diff --git a/.changeset/sweet-knives-divide.md b/.changeset/sweet-knives-divide.md new file mode 100644 index 0000000000..cb36173d73 --- /dev/null +++ b/.changeset/sweet-knives-divide.md @@ -0,0 +1,5 @@ +--- +"@channel.io/bezier-react": patch +--- + +Add `AlphaSpinner` component From c3ff1852a90300c2a4ac9081d141e494b96d4e47 Mon Sep 17 00:00:00 2001 From: andrew Date: Thu, 23 May 2024 17:12:20 +0900 Subject: [PATCH 5/8] refactor(spinner): change classname according to figma --- .../src/components/AlphaSpinner/Spinner.module.scss | 2 +- packages/bezier-react/src/components/AlphaSpinner/Spinner.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/bezier-react/src/components/AlphaSpinner/Spinner.module.scss b/packages/bezier-react/src/components/AlphaSpinner/Spinner.module.scss index 36e73b9437..f30c1185f2 100644 --- a/packages/bezier-react/src/components/AlphaSpinner/Spinner.module.scss +++ b/packages/bezier-react/src/components/AlphaSpinner/Spinner.module.scss @@ -29,7 +29,7 @@ stroke-width: var(--b-spinner-stroke-width); } - & .fill { + & .indicator { fill: none; stroke: var(--b-spinner-fill-color); stroke-dasharray: var(--b-spinner-stroke-dasharray); diff --git a/packages/bezier-react/src/components/AlphaSpinner/Spinner.tsx b/packages/bezier-react/src/components/AlphaSpinner/Spinner.tsx index 0ded522f6e..77f3d8913e 100644 --- a/packages/bezier-react/src/components/AlphaSpinner/Spinner.tsx +++ b/packages/bezier-react/src/components/AlphaSpinner/Spinner.tsx @@ -40,7 +40,7 @@ export const Spinner = forwardRef( cx="8" cy="8" r="7" - className={styles.fill} + className={styles.indicator} vectorEffect="non-scaling-stroke" /> From 7b9f34a111419e4a953f18ea56dd73343aa581cb Mon Sep 17 00:00:00 2001 From: andrew Date: Fri, 24 May 2024 09:38:04 +0900 Subject: [PATCH 6/8] feat(spinner): make size optional --- packages/bezier-react/src/components/AlphaSpinner/Spinner.tsx | 4 ++-- .../bezier-react/src/components/AlphaSpinner/Spinner.types.ts | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/bezier-react/src/components/AlphaSpinner/Spinner.tsx b/packages/bezier-react/src/components/AlphaSpinner/Spinner.tsx index 77f3d8913e..1aaa6c1c82 100644 --- a/packages/bezier-react/src/components/AlphaSpinner/Spinner.tsx +++ b/packages/bezier-react/src/components/AlphaSpinner/Spinner.tsx @@ -10,14 +10,14 @@ export const SPINNER_TEST_ID = 'bezier-spinner' export const Spinner = forwardRef( function Spinner( - { className, size = 'm', variant = 'secondary', ...rest }, + { className, size, variant = 'secondary', ...rest }, forwardedRef ) { return ( Date: Fri, 24 May 2024 13:45:09 +0900 Subject: [PATCH 7/8] feat(spinner): change variable name to indicator --- .../src/components/AlphaSpinner/Spinner.module.scss | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/bezier-react/src/components/AlphaSpinner/Spinner.module.scss b/packages/bezier-react/src/components/AlphaSpinner/Spinner.module.scss index f30c1185f2..77b004b1cd 100644 --- a/packages/bezier-react/src/components/AlphaSpinner/Spinner.module.scss +++ b/packages/bezier-react/src/components/AlphaSpinner/Spinner.module.scss @@ -13,7 +13,7 @@ .Spinner { --b-spinner-size: initial; --b-spinner-track-color: initial; - --b-spinner-fill-color: initial; + --b-spinner-indicator-color: initial; --b-spinner-stroke-width: initial; --b-spinner-stroke-dasharray: initial; @@ -31,7 +31,7 @@ & .indicator { fill: none; - stroke: var(--b-spinner-fill-color); + stroke: var(--b-spinner-indicator-color); stroke-dasharray: var(--b-spinner-stroke-dasharray); stroke-linecap: round; stroke-width: var(--b-spinner-stroke-width); @@ -51,16 +51,16 @@ &:where(.variant-primary) { --b-spinner-track-color: var(--alpha-color-primary-bg-lightest); - --b-spinner-fill-color: var(--alpha-color-fg-blue-normal); + --b-spinner-indicator-color: var(--alpha-color-fg-blue-normal); } &:where(.variant-secondary) { --b-spinner-track-color: var(--alpha-color-bg-black-light); - --b-spinner-fill-color: var(--alpha-color-fg-black-light); + --b-spinner-indicator-color: var(--alpha-color-fg-black-light); } &:where(.variant-on-overlay) { --b-spinner-track-color: var(--alpha-color-bg-absolute-white-lightest); - --b-spinner-fill-color: var(--alpha-color-fg-absolute-white-light); + --b-spinner-indicator-color: var(--alpha-color-fg-absolute-white-light); } } From 4682f95f3d3ab1e36fb51d219496ed4f3a3d7c07 Mon Sep 17 00:00:00 2001 From: andrew Date: Wed, 29 May 2024 10:12:20 +0900 Subject: [PATCH 8/8] fix(spinner): typo fix --- .../bezier-react/src/components/AlphaSpinner/Spinner.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bezier-react/src/components/AlphaSpinner/Spinner.test.tsx b/packages/bezier-react/src/components/AlphaSpinner/Spinner.test.tsx index 0dfecc84e3..96ec2697ea 100644 --- a/packages/bezier-react/src/components/AlphaSpinner/Spinner.test.tsx +++ b/packages/bezier-react/src/components/AlphaSpinner/Spinner.test.tsx @@ -14,7 +14,7 @@ describe('Spinner >', () => { expect(renderedSpinner).toBeInTheDocument() }) - it('should render as a div by default', () => { + it('should render as a span element by default', () => { const { getByTestId } = renderSpinner() const renderedSpinner = getByTestId(SPINNER_TEST_ID) expect(renderedSpinner.tagName).toBe('SPAN')