diff --git a/.changeset/bright-hats-unite.md b/.changeset/bright-hats-unite.md new file mode 100644 index 000000000..b8d2ad559 --- /dev/null +++ b/.changeset/bright-hats-unite.md @@ -0,0 +1,5 @@ +--- +'@channel.io/bezier-react': patch +--- + +Add `AlphaStatusBadge` component. diff --git a/packages/bezier-react/src/components/AlphaStatusBadge/AlphaStatusBadge.stories.tsx b/packages/bezier-react/src/components/AlphaStatusBadge/AlphaStatusBadge.stories.tsx new file mode 100644 index 000000000..e6b0daa4a --- /dev/null +++ b/packages/bezier-react/src/components/AlphaStatusBadge/AlphaStatusBadge.stories.tsx @@ -0,0 +1,39 @@ +import React from 'react' + +import { type Meta, type StoryFn, type StoryObj } from '@storybook/react' + +import { Center } from '~/src/components/Center' + +import { StatusBadge } from './StatusBadge' +import { type StatusBadgeProps } from './StatusBadge.types' + +const meta: Meta = { + component: StatusBadge, +} + +export default meta + +const Template: StoryFn = (args) => ( +
+ +
+) + +export const Primary: StoryObj = { + render: Template, + args: { + size: 'm', + online: true, + doNotDisturb: false, + }, + parameters: { + design: { + type: 'link', + url: 'https://www.figma.com/design/KyhPPZeeC0JBmTclJGe3nn/Status?node-id=0-1&t=jHTuLNWLSHKGQjYX-1', + }, + }, +} diff --git a/packages/bezier-react/src/components/AlphaStatusBadge/StatusBadge.module.scss b/packages/bezier-react/src/components/AlphaStatusBadge/StatusBadge.module.scss new file mode 100644 index 000000000..4d54b9e54 --- /dev/null +++ b/packages/bezier-react/src/components/AlphaStatusBadge/StatusBadge.module.scss @@ -0,0 +1,50 @@ +@use '../../styles/mixins/position'; + +.StatusBadge { + --b-status-size: 0; + --b-status-border-width: 0; + --b-status-bg-color: initial; + + position: relative; + z-index: var(--z-index-base); + + box-sizing: content-box; + width: var(--b-status-size); + height: var(--b-status-size); + + background-color: var(--alpha-color-bg-white-highest); + border: var(--b-status-border-width) solid var(--alpha-color-bg-white-highest); + border-radius: 50%; + + &::after { + content: ''; + + position: absolute; + top: 0; + left: 0; + + display: block; + + width: var(--b-status-size); + height: var(--b-status-size); + + background-color: var(--b-status-bg-color); + border-radius: 50%; + } + + &:where(.size-m) { + --b-status-size: 8px; + --b-status-border-width: 2px; + } + + &:where(.size-l) { + --b-status-size: 14px; + --b-status-border-width: 3px; + } +} + +.Icon { + @include position.absolute-center; + + z-index: var(--z-index-floating); +} diff --git a/packages/bezier-react/src/components/AlphaStatusBadge/StatusBadge.tsx b/packages/bezier-react/src/components/AlphaStatusBadge/StatusBadge.tsx new file mode 100644 index 000000000..0922b5bd4 --- /dev/null +++ b/packages/bezier-react/src/components/AlphaStatusBadge/StatusBadge.tsx @@ -0,0 +1,77 @@ +import React, { type CSSProperties, forwardRef } from 'react' + +import { MoonFilledIcon } from '@channel.io/bezier-icons' +import classNames from 'classnames' + +import { type SemanticColor } from '~/src/types/tokens' +import { cssVar } from '~/src/utils/style' + +import { Icon } from '~/src/components/Icon' + +import { type StatusBadgeProps } from './StatusBadge.types' + +import styles from './StatusBadge.module.scss' + +// TODO: Change to use AlphaIcon and alpha color tokens + +/** + * `StatusBadge` is a component to indicate user status. + * @example + * + * ```tsx + * + * ``` + */ +export const StatusBadge = forwardRef( + function StatusBadge( + { + size = 'm', + online = false, + doNotDisturb = false, + style, + className, + ...rest + }, + forwardedRef + ) { + const iconColor: SemanticColor = online + ? 'bgtxt-green-normal' + : doNotDisturb + ? 'bgtxt-yellow-normal' + : 'bg-black-dark' + const backgroundColor: SemanticColor = doNotDisturb + ? 'bg-white-high' + : iconColor + + return ( +
+ {doNotDisturb && ( + + )} +
+ ) + } +) diff --git a/packages/bezier-react/src/components/AlphaStatusBadge/StatusBadge.types.ts b/packages/bezier-react/src/components/AlphaStatusBadge/StatusBadge.types.ts new file mode 100644 index 000000000..fd480bc30 --- /dev/null +++ b/packages/bezier-react/src/components/AlphaStatusBadge/StatusBadge.types.ts @@ -0,0 +1,26 @@ +import type { BezierComponentProps, SizeProps } from '~/src/types/props' + +export type StatusBadgeSize = 'm' | 'l' + +interface StatusBadgeOwnProps { + /** + * `online` is a boolean value that determines the color of the badge. + * If `online` is true, badge will be green. + * If `online` is false, badge will be gray (when `doNotDisturb` is false) + * or yellow (when `doNotDisturb` is true). + * @default false + */ + online?: boolean + /** + * `doNotDisturb` is a boolean value that determines the shape of the badge. + * If `doNotDisturb` is true, badge will be a crescent moon. + * If `doNotDisturb` is false, badge will be a full circle. + * @default false + */ + doNotDisturb?: boolean +} + +export interface StatusBadgeProps + extends BezierComponentProps<'div'>, + SizeProps, + StatusBadgeOwnProps {} diff --git a/packages/bezier-react/src/components/AlphaStatusBadge/index.ts b/packages/bezier-react/src/components/AlphaStatusBadge/index.ts new file mode 100644 index 000000000..6a245ea3c --- /dev/null +++ b/packages/bezier-react/src/components/AlphaStatusBadge/index.ts @@ -0,0 +1,5 @@ +export { StatusBadge as AlphaStatusBadge } from './StatusBadge' +export type { + StatusBadgeProps as AlphaStatusBadgeProps, + StatusBadgeSize as AlphaStatusBadgeSize, +} from './StatusBadge.types' diff --git a/packages/bezier-react/src/index.ts b/packages/bezier-react/src/index.ts index 8dd1416c3..b6484b3e0 100644 --- a/packages/bezier-react/src/index.ts +++ b/packages/bezier-react/src/index.ts @@ -13,6 +13,7 @@ export * from '~/src/components/AlphaFloatingButton' export * from '~/src/components/AlphaFloatingIconButton' export * from '~/src/components/AlphaIconButton' export * from '~/src/components/AlphaLoader' +export * from '~/src/components/AlphaStatusBadge' export * from '~/src/components/AlphaToggleButton' export * from '~/src/components/AlphaToggleButtonGroup' export * from '~/src/components/AlphaTooltipPrimitive'