@channel.io/bezier-react 4.0.0-next.3 → 4.0.0-next.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/dist/cjs/styles.css +1 -1
  2. package/dist/cjs/types/props-helpers.js +8 -0
  3. package/dist/cjs/types/props-helpers.js.map +1 -1
  4. package/dist/cjs/v3/BaseStack/BaseStack.js +46 -0
  5. package/dist/cjs/v3/BaseStack/BaseStack.js.map +1 -0
  6. package/dist/cjs/v3/BaseStack/BaseStack.module.scss.js +8 -0
  7. package/dist/cjs/v3/BaseStack/BaseStack.module.scss.js.map +1 -0
  8. package/dist/cjs/v3/Box/Box.js +56 -0
  9. package/dist/cjs/v3/Box/Box.js.map +1 -0
  10. package/dist/cjs/v3/Box/Box.module.scss.js +8 -0
  11. package/dist/cjs/v3/Box/Box.module.scss.js.map +1 -0
  12. package/dist/cjs/v3/Divider/Divider.js +32 -0
  13. package/dist/cjs/v3/Divider/Divider.js.map +1 -0
  14. package/dist/cjs/v3/Divider/Divider.module.scss.js +8 -0
  15. package/dist/cjs/v3/Divider/Divider.module.scss.js.map +1 -0
  16. package/dist/cjs/v3/HStack/HStack.js +19 -0
  17. package/dist/cjs/v3/HStack/HStack.js.map +1 -0
  18. package/dist/cjs/v3/Icon/Icon.js +51 -0
  19. package/dist/cjs/v3/Icon/Icon.js.map +1 -0
  20. package/dist/cjs/v3/Icon/Icon.module.scss.js +8 -0
  21. package/dist/cjs/v3/Icon/Icon.module.scss.js.map +1 -0
  22. package/dist/cjs/v3/SmoothCornersBox/SmoothCornersBox.js +53 -0
  23. package/dist/cjs/v3/SmoothCornersBox/SmoothCornersBox.js.map +1 -0
  24. package/dist/cjs/v3/SmoothCornersBox/SmoothCornersBox.module.scss.js +8 -0
  25. package/dist/cjs/v3/SmoothCornersBox/SmoothCornersBox.module.scss.js.map +1 -0
  26. package/dist/cjs/v3/Spinner/Spinner.js +45 -0
  27. package/dist/cjs/v3/Spinner/Spinner.js.map +1 -0
  28. package/dist/cjs/v3/Spinner/Spinner.module.scss.js +8 -0
  29. package/dist/cjs/v3/Spinner/Spinner.module.scss.js.map +1 -0
  30. package/dist/cjs/v3/Text/Text.js +60 -0
  31. package/dist/cjs/v3/Text/Text.js.map +1 -0
  32. package/dist/cjs/v3/Text/Text.module.scss.js +8 -0
  33. package/dist/cjs/v3/Text/Text.module.scss.js.map +1 -0
  34. package/dist/cjs/v3/VStack/VStack.js +19 -0
  35. package/dist/cjs/v3/VStack/VStack.js.map +1 -0
  36. package/dist/cjs/v3/index.js +22 -0
  37. package/dist/cjs/v3/index.js.map +1 -0
  38. package/dist/esm/styles.css +1 -1
  39. package/dist/esm/types/props-helpers.mjs +5 -1
  40. package/dist/esm/types/props-helpers.mjs.map +1 -1
  41. package/dist/esm/v3/BaseStack/BaseStack.mjs +44 -0
  42. package/dist/esm/v3/BaseStack/BaseStack.mjs.map +1 -0
  43. package/dist/esm/v3/BaseStack/BaseStack.module.scss.mjs +4 -0
  44. package/dist/esm/v3/BaseStack/BaseStack.module.scss.mjs.map +1 -0
  45. package/dist/esm/v3/Box/Box.mjs +54 -0
  46. package/dist/esm/v3/Box/Box.mjs.map +1 -0
  47. package/dist/esm/v3/Box/Box.module.scss.mjs +4 -0
  48. package/dist/esm/v3/Box/Box.module.scss.mjs.map +1 -0
  49. package/dist/esm/v3/Divider/Divider.mjs +30 -0
  50. package/dist/esm/v3/Divider/Divider.mjs.map +1 -0
  51. package/dist/esm/v3/Divider/Divider.module.scss.mjs +4 -0
  52. package/dist/esm/v3/Divider/Divider.module.scss.mjs.map +1 -0
  53. package/dist/esm/v3/HStack/HStack.mjs +17 -0
  54. package/dist/esm/v3/HStack/HStack.mjs.map +1 -0
  55. package/dist/esm/v3/Icon/Icon.mjs +49 -0
  56. package/dist/esm/v3/Icon/Icon.mjs.map +1 -0
  57. package/dist/esm/v3/Icon/Icon.module.scss.mjs +4 -0
  58. package/dist/esm/v3/Icon/Icon.module.scss.mjs.map +1 -0
  59. package/dist/esm/v3/SmoothCornersBox/SmoothCornersBox.mjs +51 -0
  60. package/dist/esm/v3/SmoothCornersBox/SmoothCornersBox.mjs.map +1 -0
  61. package/dist/esm/v3/SmoothCornersBox/SmoothCornersBox.module.scss.mjs +4 -0
  62. package/dist/esm/v3/SmoothCornersBox/SmoothCornersBox.module.scss.mjs.map +1 -0
  63. package/dist/esm/v3/Spinner/Spinner.mjs +43 -0
  64. package/dist/esm/v3/Spinner/Spinner.mjs.map +1 -0
  65. package/dist/esm/v3/Spinner/Spinner.module.scss.mjs +4 -0
  66. package/dist/esm/v3/Spinner/Spinner.module.scss.mjs.map +1 -0
  67. package/dist/esm/v3/Text/Text.mjs +58 -0
  68. package/dist/esm/v3/Text/Text.mjs.map +1 -0
  69. package/dist/esm/v3/Text/Text.module.scss.mjs +4 -0
  70. package/dist/esm/v3/Text/Text.module.scss.mjs.map +1 -0
  71. package/dist/esm/v3/VStack/VStack.mjs +17 -0
  72. package/dist/esm/v3/VStack/VStack.mjs.map +1 -0
  73. package/dist/esm/v3/index.mjs +9 -0
  74. package/dist/esm/v3/index.mjs.map +1 -0
  75. package/dist/types/types/beta-tokens.d.ts +4 -0
  76. package/dist/types/types/beta-tokens.d.ts.map +1 -1
  77. package/dist/types/types/props-helpers.d.ts +48 -1
  78. package/dist/types/types/props-helpers.d.ts.map +1 -1
  79. package/dist/types/types/props.d.ts +44 -0
  80. package/dist/types/types/props.d.ts.map +1 -1
  81. package/dist/types/v3/BaseStack/BaseStack.d.ts +6 -0
  82. package/dist/types/v3/BaseStack/BaseStack.d.ts.map +1 -0
  83. package/dist/types/v3/BaseStack/BaseStack.types.d.ts +45 -0
  84. package/dist/types/v3/BaseStack/BaseStack.types.d.ts.map +1 -0
  85. package/dist/types/v3/Box/Box.d.ts +19 -0
  86. package/dist/types/v3/Box/Box.d.ts.map +1 -0
  87. package/dist/types/v3/Box/Box.types.d.ts +12 -0
  88. package/dist/types/v3/Box/Box.types.d.ts.map +1 -0
  89. package/dist/types/v3/Box/index.d.ts +3 -0
  90. package/dist/types/v3/Box/index.d.ts.map +1 -0
  91. package/dist/types/v3/Divider/Divider.d.ts +13 -0
  92. package/dist/types/v3/Divider/Divider.d.ts.map +1 -0
  93. package/dist/types/v3/Divider/Divider.types.d.ts +27 -0
  94. package/dist/types/v3/Divider/Divider.types.d.ts.map +1 -0
  95. package/dist/types/v3/Divider/index.d.ts +3 -0
  96. package/dist/types/v3/Divider/index.d.ts.map +1 -0
  97. package/dist/types/v3/HStack/HStack.d.ts +7 -0
  98. package/dist/types/v3/HStack/HStack.d.ts.map +1 -0
  99. package/dist/types/v3/HStack/HStack.types.d.ts +2 -0
  100. package/dist/types/v3/HStack/HStack.types.d.ts.map +1 -0
  101. package/dist/types/v3/HStack/index.d.ts +3 -0
  102. package/dist/types/v3/HStack/index.d.ts.map +1 -0
  103. package/dist/types/v3/Icon/Icon.d.ts +19 -0
  104. package/dist/types/v3/Icon/Icon.d.ts.map +1 -0
  105. package/dist/types/v3/Icon/Icon.types.d.ts +21 -0
  106. package/dist/types/v3/Icon/Icon.types.d.ts.map +1 -0
  107. package/dist/types/v3/Icon/index.d.ts +3 -0
  108. package/dist/types/v3/Icon/index.d.ts.map +1 -0
  109. package/dist/types/v3/SmoothCornersBox/SmoothCornersBox.d.ts +15 -0
  110. package/dist/types/v3/SmoothCornersBox/SmoothCornersBox.d.ts.map +1 -0
  111. package/dist/types/v3/SmoothCornersBox/SmoothCornersBox.types.d.ts +61 -0
  112. package/dist/types/v3/SmoothCornersBox/SmoothCornersBox.types.d.ts.map +1 -0
  113. package/dist/types/v3/SmoothCornersBox/index.d.ts +3 -0
  114. package/dist/types/v3/SmoothCornersBox/index.d.ts.map +1 -0
  115. package/dist/types/v3/Spinner/Spinner.d.ts +15 -0
  116. package/dist/types/v3/Spinner/Spinner.d.ts.map +1 -0
  117. package/dist/types/v3/Spinner/Spinner.types.d.ts +5 -0
  118. package/dist/types/v3/Spinner/Spinner.types.d.ts.map +1 -0
  119. package/dist/types/v3/Spinner/index.d.ts +3 -0
  120. package/dist/types/v3/Spinner/index.d.ts.map +1 -0
  121. package/dist/types/v3/Text/Text.d.ts +16 -0
  122. package/dist/types/v3/Text/Text.d.ts.map +1 -0
  123. package/dist/types/v3/Text/Text.types.d.ts +44 -0
  124. package/dist/types/v3/Text/Text.types.d.ts.map +1 -0
  125. package/dist/types/v3/Text/index.d.ts +3 -0
  126. package/dist/types/v3/Text/index.d.ts.map +1 -0
  127. package/dist/types/v3/VStack/VStack.d.ts +7 -0
  128. package/dist/types/v3/VStack/VStack.d.ts.map +1 -0
  129. package/dist/types/v3/VStack/VStack.types.d.ts +2 -0
  130. package/dist/types/v3/VStack/VStack.types.d.ts.map +1 -0
  131. package/dist/types/v3/VStack/index.d.ts +3 -0
  132. package/dist/types/v3/VStack/index.d.ts.map +1 -0
  133. package/dist/types/v3/index.d.ts +9 -0
  134. package/dist/types/v3/index.d.ts.map +1 -0
  135. package/package.json +6 -1
  136. package/src/types/beta-tokens.ts +8 -0
  137. package/src/types/props-helpers.ts +22 -1
  138. package/src/types/props.ts +52 -0
  139. package/src/v3/BaseStack/BaseStack.module.scss +73 -0
  140. package/src/v3/BaseStack/BaseStack.test.tsx +83 -0
  141. package/src/v3/BaseStack/BaseStack.tsx +72 -0
  142. package/src/v3/BaseStack/BaseStack.types.ts +59 -0
  143. package/src/v3/Box/Box.module.scss +13 -0
  144. package/src/v3/Box/Box.stories.tsx +27 -0
  145. package/src/v3/Box/Box.test.tsx +57 -0
  146. package/src/v3/Box/Box.tsx +77 -0
  147. package/src/v3/Box/Box.types.ts +24 -0
  148. package/src/v3/Box/index.ts +2 -0
  149. package/src/v3/Divider/Divider.module.scss +52 -0
  150. package/src/v3/Divider/Divider.stories.tsx +95 -0
  151. package/src/v3/Divider/Divider.test.tsx +47 -0
  152. package/src/v3/Divider/Divider.tsx +57 -0
  153. package/src/v3/Divider/Divider.types.ts +32 -0
  154. package/src/v3/Divider/index.ts +2 -0
  155. package/src/v3/HStack/HStack.stories.tsx +58 -0
  156. package/src/v3/HStack/HStack.test.tsx +14 -0
  157. package/src/v3/HStack/HStack.tsx +21 -0
  158. package/src/v3/HStack/HStack.types.ts +1 -0
  159. package/src/v3/HStack/index.ts +2 -0
  160. package/src/v3/Icon/Icon.module.scss +20 -0
  161. package/src/v3/Icon/Icon.stories.tsx +173 -0
  162. package/src/v3/Icon/Icon.test.tsx +64 -0
  163. package/src/v3/Icon/Icon.tsx +67 -0
  164. package/src/v3/Icon/Icon.types.ts +32 -0
  165. package/src/v3/Icon/index.ts +2 -0
  166. package/src/v3/SmoothCornersBox/SmoothCornersBox.module.scss +48 -0
  167. package/src/v3/SmoothCornersBox/SmoothCornersBox.stories.tsx +41 -0
  168. package/src/v3/SmoothCornersBox/SmoothCornersBox.test.tsx +83 -0
  169. package/src/v3/SmoothCornersBox/SmoothCornersBox.tsx +84 -0
  170. package/src/v3/SmoothCornersBox/SmoothCornersBox.types.ts +69 -0
  171. package/src/v3/SmoothCornersBox/index.ts +2 -0
  172. package/src/v3/Spinner/Spinner.module.scss +58 -0
  173. package/src/v3/Spinner/Spinner.stories.tsx +28 -0
  174. package/src/v3/Spinner/Spinner.test.tsx +65 -0
  175. package/src/v3/Spinner/Spinner.tsx +61 -0
  176. package/src/v3/Spinner/Spinner.types.ts +12 -0
  177. package/src/v3/Spinner/index.ts +2 -0
  178. package/src/v3/Text/Text.module.scss +69 -0
  179. package/src/v3/Text/Text.stories.tsx +52 -0
  180. package/src/v3/Text/Text.test.tsx +84 -0
  181. package/src/v3/Text/Text.tsx +81 -0
  182. package/src/v3/Text/Text.types.ts +70 -0
  183. package/src/v3/Text/index.ts +2 -0
  184. package/src/v3/VStack/VStack.stories.tsx +58 -0
  185. package/src/v3/VStack/VStack.test.tsx +14 -0
  186. package/src/v3/VStack/VStack.tsx +21 -0
  187. package/src/v3/VStack/VStack.types.ts +1 -0
  188. package/src/v3/VStack/index.ts +2 -0
  189. package/src/v3/index.ts +10 -0
@@ -0,0 +1,57 @@
1
+ import * as React from 'react'
2
+
3
+ import { render } from '~/src/utils/test'
4
+
5
+ import { Box } from './Box'
6
+ import { type BoxProps } from './Box.types'
7
+
8
+ import styles from './Box.module.scss'
9
+
10
+ describe('Box', () => {
11
+ const renderBox = (props?: Partial<BoxProps>) =>
12
+ render(<Box {...props}>Hello, Channel!</Box>)
13
+
14
+ it('should render with default style', () => {
15
+ const { getByText } = renderBox()
16
+ const rendered = getByText('Hello, Channel!')
17
+
18
+ expect(rendered).toHaveClass(styles.Box)
19
+ })
20
+
21
+ it('should render as the given element', () => {
22
+ const { getByText } = renderBox({ as: 'section' })
23
+ const rendered = getByText('Hello, Channel!')
24
+
25
+ expect(rendered.tagName).toBe('SECTION')
26
+ })
27
+
28
+ it('should forward ref', () => {
29
+ const ref = React.createRef<HTMLElement>()
30
+
31
+ render(<Box ref={ref} />)
32
+
33
+ expect(ref.current).toBeInTheDocument()
34
+ })
35
+
36
+ it('should receive display style', () => {
37
+ const { getByText } = renderBox({ display: 'inline-block' })
38
+ const rendered = getByText('Hello, Channel!')
39
+
40
+ expect(rendered).toHaveClass(styles['display-inline-block'])
41
+ })
42
+
43
+ it('should receive layout and margin styles', () => {
44
+ const { getByText } = renderBox({
45
+ width: '100px',
46
+ marginTop: 10,
47
+ style: { backgroundColor: 'red' },
48
+ className: 'test-class',
49
+ })
50
+ const rendered = getByText('Hello, Channel!')
51
+
52
+ expect(rendered).toHaveStyle('--b-width: 100px')
53
+ expect(rendered).toHaveStyle('--b-margin-top: 10px')
54
+ expect(rendered).toHaveStyle('background-color: red')
55
+ expect(rendered).toHaveClass('test-class')
56
+ })
57
+ })
@@ -0,0 +1,77 @@
1
+ 'use client'
2
+
3
+ import { createElement, forwardRef } from 'react'
4
+ import type { CSSProperties } from 'react'
5
+
6
+ import classNames from 'classnames'
7
+
8
+ import {
9
+ getV3LayoutStyles,
10
+ getV3MarginStyles,
11
+ splitByV3LayoutProps,
12
+ splitByV3MarginProps,
13
+ } from '~/src/types/props-helpers'
14
+
15
+ import type { BoxProps } from './Box.types'
16
+
17
+ import styles from './Box.module.scss'
18
+
19
+ /**
20
+ * `Box` is a primitive layout component. It provides an easy way to access design tokens.
21
+ * @example
22
+ *
23
+ * ```tsx
24
+ * <Box
25
+ * width="100px"
26
+ * height="100px"
27
+ * padding="6px"
28
+ * margin="6px"
29
+ * backgroundColor="fill-neutral"
30
+ * >
31
+ * <div>{ ... }</div>
32
+ * </Box>
33
+ * ```
34
+ */
35
+ export const Box = forwardRef<HTMLElement, BoxProps>(
36
+ function Box(props, forwardedRef) {
37
+ const [marginProps, marginRest] = splitByV3MarginProps(props)
38
+ const [layoutProps, layoutRest] = splitByV3LayoutProps(marginRest)
39
+ const marginStyles = getV3MarginStyles(marginProps)
40
+ const layoutStyles = getV3LayoutStyles(layoutProps)
41
+
42
+ const {
43
+ children,
44
+ style,
45
+ className,
46
+ as = 'div',
47
+ display,
48
+ ...rest
49
+ } = layoutRest
50
+
51
+ /**
52
+ * NOTE: Keep the existing loose polymorphic Box pattern for API parity.
53
+ * TODO: Replace this with a typed polymorphic helper when ref inference is standardized.
54
+ */
55
+ return createElement(
56
+ as,
57
+ {
58
+ ref: forwardedRef,
59
+ style: {
60
+ ...marginStyles.style,
61
+ ...layoutStyles.style,
62
+ ...style,
63
+ } as CSSProperties,
64
+ className: classNames(
65
+ styles.Box,
66
+ display && styles[`display-${display}`],
67
+ marginStyles.className,
68
+ layoutStyles.className,
69
+ className
70
+ ),
71
+ 'data-testid': 'bezier-box',
72
+ ...rest,
73
+ },
74
+ children
75
+ )
76
+ }
77
+ )
@@ -0,0 +1,24 @@
1
+ import type {
2
+ BezierComponentProps,
3
+ ChildrenProps,
4
+ PolymorphicProps,
5
+ V3LayoutProps,
6
+ V3MarginProps,
7
+ } from '~/src/types/props'
8
+
9
+ type Display = 'block' | 'inline' | 'inline-block'
10
+
11
+ interface BoxOwnProps {
12
+ /**
13
+ * Display type of the box.
14
+ */
15
+ display?: Display
16
+ }
17
+
18
+ export interface BoxProps
19
+ extends Omit<BezierComponentProps<'div'>, keyof BoxOwnProps>,
20
+ PolymorphicProps,
21
+ ChildrenProps,
22
+ V3MarginProps,
23
+ V3LayoutProps,
24
+ BoxOwnProps {}
@@ -0,0 +1,2 @@
1
+ export { Box } from './Box'
2
+ export type { BoxProps } from './Box.types'
@@ -0,0 +1,52 @@
1
+ .Divider {
2
+ --b-v3-divider-indent-size: 6px;
3
+ --b-v3-divider-thickness: 1px;
4
+
5
+ flex-shrink: 0;
6
+ background-color: var(--color-border-neutral);
7
+ border-radius: var(--b-v3-divider-thickness);
8
+
9
+ &:where(.horizontal) {
10
+ width: calc(100% - 2 * var(--b-v3-divider-indent-size));
11
+ height: var(--b-v3-divider-thickness);
12
+ margin: var(--b-v3-divider-indent-size);
13
+
14
+ &:where(.without-indent) {
15
+ width: 100%;
16
+ margin: 0;
17
+ }
18
+
19
+ &:where(.without-side-indent) {
20
+ width: 100%;
21
+ margin-right: 0;
22
+ margin-left: 0;
23
+ }
24
+
25
+ &:where(.without-parallel-indent) {
26
+ margin-top: 0;
27
+ margin-bottom: 0;
28
+ }
29
+ }
30
+
31
+ &:where(.vertical) {
32
+ width: var(--b-v3-divider-thickness);
33
+ height: calc(100% - 2 * var(--b-v3-divider-indent-size));
34
+ margin: var(--b-v3-divider-indent-size);
35
+
36
+ &:where(.without-indent) {
37
+ height: 100%;
38
+ margin: 0;
39
+ }
40
+
41
+ &:where(.without-side-indent) {
42
+ height: 100%;
43
+ margin-top: 0;
44
+ margin-bottom: 0;
45
+ }
46
+
47
+ &:where(.without-parallel-indent) {
48
+ margin-right: 0;
49
+ margin-left: 0;
50
+ }
51
+ }
52
+ }
@@ -0,0 +1,95 @@
1
+ import type { Meta, StoryFn, StoryObj } from '@storybook/react'
2
+
3
+ import { Divider } from './Divider'
4
+ import { type DividerProps } from './Divider.types'
5
+
6
+ const meta = {
7
+ title: 'V3 components/Divider',
8
+ component: Divider,
9
+ argTypes: {
10
+ orientation: {
11
+ control: {
12
+ type: 'radio',
13
+ },
14
+ options: ['horizontal', 'vertical'],
15
+ },
16
+ withoutSideIndent: {
17
+ control: {
18
+ type: 'boolean',
19
+ },
20
+ },
21
+ withoutParallelIndent: {
22
+ control: {
23
+ type: 'boolean',
24
+ },
25
+ },
26
+ withoutIndent: {
27
+ control: {
28
+ type: 'boolean',
29
+ },
30
+ },
31
+ },
32
+ } satisfies Meta<typeof Divider>
33
+
34
+ export default meta
35
+
36
+ const Template: StoryFn<DividerProps> = (props) => (
37
+ <div
38
+ style={{
39
+ display: 'flex',
40
+ alignItems: 'center',
41
+ justifyContent: 'center',
42
+ width: 200,
43
+ height: 200,
44
+ }}
45
+ >
46
+ <Divider {...props} />
47
+ </div>
48
+ )
49
+
50
+ export const Primary: StoryObj<DividerProps> = {
51
+ render: Template,
52
+
53
+ args: {
54
+ orientation: 'horizontal',
55
+ },
56
+ }
57
+
58
+ export const Vertical: StoryObj<DividerProps> = {
59
+ render: Template,
60
+
61
+ args: {
62
+ orientation: 'vertical',
63
+ },
64
+ }
65
+
66
+ const CompositionTemplate: StoryFn<DividerProps> = ({
67
+ orientation,
68
+ ...rest
69
+ }) => (
70
+ <div
71
+ style={{
72
+ display: 'flex',
73
+ flexDirection: orientation === 'horizontal' ? 'column' : 'row',
74
+ alignItems: 'center',
75
+ justifyContent: 'center',
76
+ width: 200,
77
+ height: 200,
78
+ }}
79
+ >
80
+ <div>Channel</div>
81
+ <Divider
82
+ orientation={orientation}
83
+ {...rest}
84
+ />
85
+ <div>Bezier</div>
86
+ </div>
87
+ )
88
+
89
+ export const Composition: StoryObj<DividerProps> = {
90
+ render: CompositionTemplate,
91
+
92
+ args: {
93
+ orientation: 'horizontal',
94
+ },
95
+ }
@@ -0,0 +1,47 @@
1
+ import { render } from '~/src/utils/test'
2
+
3
+ import { Divider } from './Divider'
4
+ import { type DividerProps } from './Divider.types'
5
+
6
+ import styles from './Divider.module.scss'
7
+
8
+ describe('Divider', () => {
9
+ const renderDivider = (props?: Partial<DividerProps>) =>
10
+ render(<Divider {...props} />)
11
+
12
+ it('should render default Divider', () => {
13
+ const { getByRole } = renderDivider()
14
+ const divider = getByRole('separator')
15
+
16
+ expect(divider).toHaveClass(styles.Divider)
17
+ expect(divider).toHaveClass(styles.horizontal)
18
+ })
19
+
20
+ it('should render vertical divider with aria-orientation attribute', () => {
21
+ const { getByRole } = renderDivider({ orientation: 'vertical' })
22
+ const divider = getByRole('separator')
23
+
24
+ expect(divider).toHaveClass(styles.vertical)
25
+ expect(divider).toHaveAttribute('aria-orientation', 'vertical')
26
+ })
27
+
28
+ it('should receive indent styles', () => {
29
+ const { getByRole } = renderDivider({
30
+ withoutIndent: true,
31
+ withoutParallelIndent: true,
32
+ withoutSideIndent: true,
33
+ })
34
+ const divider = getByRole('separator')
35
+
36
+ expect(divider).toHaveClass(styles['without-indent'])
37
+ expect(divider).toHaveClass(styles['without-parallel-indent'])
38
+ expect(divider).toHaveClass(styles['without-side-indent'])
39
+ })
40
+
41
+ it('should not have aria attributes when decorative is true', () => {
42
+ const { getByRole } = renderDivider({ decorative: true })
43
+ const divider = getByRole('separator')
44
+
45
+ expect(divider).not.toHaveAttribute('aria-orientation')
46
+ })
47
+ })
@@ -0,0 +1,57 @@
1
+ 'use client'
2
+
3
+ import { forwardRef } from 'react'
4
+
5
+ import * as SeparatorPrimitive from '@radix-ui/react-separator'
6
+ import classNames from 'classnames'
7
+
8
+ import type { DividerProps } from './Divider.types'
9
+
10
+ import styles from './Divider.module.scss'
11
+
12
+ /**
13
+ * `Divider` is a component to visually or semantically separate content.
14
+ * @example
15
+ *
16
+ * ```tsx
17
+ * <Divider
18
+ * withoutSideIndent
19
+ * />
20
+ * ```
21
+ */
22
+ export const Divider = forwardRef<HTMLDivElement, DividerProps>(
23
+ (
24
+ {
25
+ orientation = 'horizontal',
26
+ decorative,
27
+ withoutSideIndent = false,
28
+ withoutParallelIndent = false,
29
+ withoutIndent = false,
30
+ style,
31
+ className,
32
+ ...rest
33
+ },
34
+ forwardedRef
35
+ ) => (
36
+ <SeparatorPrimitive.Root
37
+ asChild
38
+ orientation={orientation}
39
+ decorative={decorative}
40
+ >
41
+ <div
42
+ ref={forwardedRef}
43
+ style={style}
44
+ className={classNames(
45
+ styles.Divider,
46
+ styles[orientation],
47
+ withoutIndent && styles['without-indent'],
48
+ withoutParallelIndent && styles['without-parallel-indent'],
49
+ withoutSideIndent && styles['without-side-indent'],
50
+ className
51
+ )}
52
+ role="separator"
53
+ {...rest}
54
+ />
55
+ </SeparatorPrimitive.Root>
56
+ )
57
+ )
@@ -0,0 +1,32 @@
1
+ import type { SeparatorProps as SeparatorPrimitiveProps } from '@radix-ui/react-separator'
2
+
3
+ import type { BezierComponentProps } from '~/src/types/props'
4
+
5
+ interface DividerOwnProps {
6
+ /**
7
+ * If true, the divider will be rendered without side padding,
8
+ * which stands for the padding on the left and right sides of the horizontal divider,
9
+ * and the top and bottom sides of the vertical divider.
10
+ * @default false
11
+ */
12
+ withoutSideIndent?: boolean
13
+
14
+ /**
15
+ * If true, the divider will be rendered without parallel padding,
16
+ * which stands for the padding on the top and bottom sides of the horizontal divider,
17
+ * and the left and right sides of the vertical divider.
18
+ * @default false
19
+ */
20
+ withoutParallelIndent?: boolean
21
+
22
+ /**
23
+ * If true, the divider will be rendered without padding,
24
+ * @default false
25
+ */
26
+ withoutIndent?: boolean
27
+ }
28
+
29
+ export interface DividerProps
30
+ extends BezierComponentProps<'div'>,
31
+ SeparatorPrimitiveProps,
32
+ DividerOwnProps {}
@@ -0,0 +1,2 @@
1
+ export { Divider } from './Divider'
2
+ export type { DividerProps } from './Divider.types'
@@ -0,0 +1,58 @@
1
+ import React from 'react'
2
+
3
+ import { type Meta, type StoryFn, type StoryObj } from '@storybook/react'
4
+
5
+ import { range } from '~/src/utils/number'
6
+ import { Box } from '~/src/v3/Box'
7
+ import { Text } from '~/src/v3/Text'
8
+
9
+ import { HStack } from './HStack'
10
+
11
+ const meta = {
12
+ title: 'V3 components/HStack',
13
+ component: HStack,
14
+ } satisfies Meta<typeof HStack>
15
+
16
+ type Story = StoryObj<typeof meta>
17
+
18
+ function DecorativeBox({ children }: React.PropsWithChildren<{}>) {
19
+ return (
20
+ <Box
21
+ width={50}
22
+ height={50}
23
+ backgroundColor="fill-neutral"
24
+ borderRadius="8"
25
+ borderWidth={1}
26
+ borderColor="border-neutral"
27
+ >
28
+ <Text>{children}</Text>
29
+ </Box>
30
+ )
31
+ }
32
+
33
+ const Template: StoryFn<typeof HStack> = (args) => (
34
+ <HStack
35
+ {...args}
36
+ borderColor="border-neutral"
37
+ borderWidth={1}
38
+ >
39
+ {range(4).map((i) => (
40
+ <DecorativeBox key={`item-${i}`}>{i + 1}</DecorativeBox>
41
+ ))}
42
+ </HStack>
43
+ )
44
+
45
+ export const Primary: Story = {
46
+ render: Template,
47
+ args: {
48
+ justify: 'start',
49
+ align: 'start',
50
+ reverse: false,
51
+ wrap: true,
52
+ width: 300,
53
+ height: 300,
54
+ spacing: 6,
55
+ },
56
+ }
57
+
58
+ export default meta
@@ -0,0 +1,14 @@
1
+ import { render } from '~/src/utils/test'
2
+ import styles from '~/src/v3/BaseStack/BaseStack.module.scss'
3
+
4
+ import { HStack } from './HStack'
5
+
6
+ describe('HStack', () => {
7
+ it('should render horizontal stack', () => {
8
+ const { getByText } = render(<HStack>Hello, Channel!</HStack>)
9
+ const rendered = getByText('Hello, Channel!')
10
+
11
+ expect(rendered).toHaveClass(styles.BaseStack)
12
+ expect(rendered).toHaveClass(styles['direction-horizontal'])
13
+ })
14
+ })
@@ -0,0 +1,21 @@
1
+ 'use client'
2
+
3
+ import { createElement, forwardRef } from 'react'
4
+
5
+ import { BaseStack } from '~/src/v3/BaseStack/BaseStack'
6
+
7
+ import type { HStackProps } from './HStack.types'
8
+
9
+ /**
10
+ * `HStack` is a shorthand component equivalent to `Stack` with a horizontal direction property.
11
+ * @see BaseStack
12
+ */
13
+ export const HStack = forwardRef<HTMLElement, HStackProps>(
14
+ function HStack(props, forwardedRef) {
15
+ return createElement(BaseStack, {
16
+ ...props,
17
+ direction: 'horizontal',
18
+ ref: forwardedRef,
19
+ })
20
+ }
21
+ )
@@ -0,0 +1 @@
1
+ export type { HStackProps } from '~/src/v3/BaseStack/BaseStack.types'
@@ -0,0 +1,2 @@
1
+ export { HStack } from './HStack'
2
+ export type { HStackProps } from './HStack.types'
@@ -0,0 +1,20 @@
1
+ @use '../../styles/mixins/dimension';
2
+
3
+ $icon-sizes: '10', '12', '16', '20', '24', '36', '44';
4
+
5
+ .Icon {
6
+ --b-v3-icon-size: initial;
7
+ --b-v3-icon-color: initial;
8
+
9
+ @include dimension.square(var(--b-v3-icon-size));
10
+
11
+ flex: 0 0 auto;
12
+ color: var(--b-v3-icon-color);
13
+ transition: color var(--motion-transition-fast);
14
+
15
+ @each $size in $icon-sizes {
16
+ &:where(.size-#{$size}) {
17
+ --b-v3-icon-size: #{$size}px;
18
+ }
19
+ }
20
+ }