Skip to content

Commit

Permalink
Add AlphaStatusBadge component (#2434)
Browse files Browse the repository at this point in the history
<!--
  How to write a good PR title:
- Follow [the Conventional Commits
specification](https://www.conventionalcommits.org/en/v1.0.0/).
  - Give as much context as necessary and as little as possible
  - Prefix it with [WIP] while it’s a work in progress
-->

## Self Checklist

- [x] I wrote a PR title in **English** and added an appropriate
**label** to the PR.
- [x] I wrote the commit message in **English** and to follow [**the
Conventional Commits
specification**](https://www.conventionalcommits.org/en/v1.0.0/).
- [x] I [added the
**changeset**](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md)
about the changes that needed to be released. (or didn't have to)
- [x] I wrote or updated **documentation** related to the changes. (or
didn't have to)
- [x] I wrote or updated **tests** related to the changes. (or didn't
have to)
- [x] I tested the changes in various browsers. (or didn't have to)
  - Windows: Chrome, Edge, (Optional) Firefox
  - macOS: Chrome, Edge, Safari, (Optional) Firefox

## Related Issue

<!-- Please link to issue if one exists -->

<!-- Fixes #0000 -->

Fixes #2399 

## Summary

<!-- Please brief explanation of the changes made -->

- Implement `StatusBadge` component using v2 design tokens.

## Details

<!-- Please elaborate description of the changes -->

- The type (and shape) of status is determined by the props `online` and
`doNotDisturb`

### Breaking change? (Yes/No)

<!-- If Yes, please describe the impact and migration path for users -->

- No

## References

<!-- Please list any other resources or points the reviewer should be
aware of -->

- [컴포넌트
스펙](https://www.notion.so/channelio/StatusBadge-b821c27b36e04246a6841b30c08026bf?pvs=4)
-
[피그마](https://www.figma.com/design/KyhPPZeeC0JBmTclJGe3nn/Status?node-id=0-1&node-type=CANVAS&m=dev)
  • Loading branch information
babycroc authored Oct 16, 2024
1 parent b25b60c commit f2edf11
Show file tree
Hide file tree
Showing 7 changed files with 203 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/bright-hats-unite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@channel.io/bezier-react': patch
---

Add `AlphaStatusBadge` component.
Original file line number Diff line number Diff line change
@@ -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<typeof StatusBadge> = {
component: StatusBadge,
}

export default meta

const Template: StoryFn<StatusBadgeProps> = (args) => (
<Center
width={200}
height={200}
backgroundColor="bg-grey-light"
>
<StatusBadge {...args} />
</Center>
)

export const Primary: StoryObj<StatusBadgeProps> = {
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',
},
},
}
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
@@ -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
* <StatusBadge
* size="m"
* online
* doNotDisturb
* />
* ```
*/
export const StatusBadge = forwardRef<HTMLDivElement, StatusBadgeProps>(
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 (
<div
ref={forwardedRef}
style={
{
'--b-status-bg-color': cssVar(backgroundColor),
...style,
} as CSSProperties
}
className={classNames(
styles.StatusBadge,
styles[`size-${size}`],
className
)}
{...rest}
>
{doNotDisturb && (
<Icon
source={MoonFilledIcon}
size={size === 'm' ? 'xxxs' : 'xs'}
color={iconColor}
className={styles.Icon}
/>
)}
</div>
)
}
)
Original file line number Diff line number Diff line change
@@ -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<StatusBadgeSize>,
StatusBadgeOwnProps {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export { StatusBadge as AlphaStatusBadge } from './StatusBadge'
export type {
StatusBadgeProps as AlphaStatusBadgeProps,
StatusBadgeSize as AlphaStatusBadgeSize,
} from './StatusBadge.types'
1 change: 1 addition & 0 deletions packages/bezier-react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down

0 comments on commit f2edf11

Please sign in to comment.