diff --git a/src/components/Box/Box.spec.tsx b/src/components/Box/Box.spec.tsx
index 10f0d1f7..0bb69183 100644
--- a/src/components/Box/Box.spec.tsx
+++ b/src/components/Box/Box.spec.tsx
@@ -35,27 +35,45 @@ describe('Box', () => {
expect(container.firstChild).toMatchSnapshot();
});
- test('it works with default testId', () => {
- setup(Hello world);
- expect(screen.getByTestId('Box')).toBeTruthy();
- });
+ describe('as prop', () => {
+ test('it falls back to div', () => {
+ setup(Hello world);
+ expect(screen.getByTestId('Component').nodeName).toBe('DIV');
+ });
- test('it works with specified testId', () => {
- setup(
-
- Hello world
-
- );
- expect(screen.getByTestId('TestId')).toBeTruthy();
+ test('it works with HTML element', () => {
+ setup(
+
+ Hello world
+
+ );
+ expect(screen.getByTestId('Box').nodeName).toBe('BUTTON');
+ expect(screen.getByRole('button')).toBeTruthy();
+ });
+
+ test('it works with React component', () => {
+ const TestComponent = ({ status }: { status: string }) => (
+
test {status}
+ );
+ setup();
+ expect(screen.getByText('test info')).toBeTruthy();
+ });
});
- test('it works with as', () => {
- setup(
-
- Hello world
-
- );
- expect(screen.getByTestId('Box').nodeName).toBe('SPAN');
+ describe('testId prop', () => {
+ test('it works with default testId', () => {
+ setup(Hello world);
+ expect(screen.getByTestId('Box')).toBeTruthy();
+ });
+
+ test('it works with specified testId', () => {
+ setup(
+
+ Hello world
+
+ );
+ expect(screen.getByTestId('TestId')).toBeTruthy();
+ });
});
test('it works with className', () => {
diff --git a/src/components/Box/index.tsx b/src/components/Box/index.tsx
index ed1874e0..b6059e81 100644
--- a/src/components/Box/index.tsx
+++ b/src/components/Box/index.tsx
@@ -1,41 +1,44 @@
-import React from 'react';
+import React, { ElementType } from 'react';
import cx from 'classnames';
-import type { BaseProps, SizeType } from '../types';
+import type { CommonComponentCombinedProps, SizeType } from '../types';
import styles from './Box.module.scss';
-export interface BoxProps {
- readonly elevation?: SizeType;
- readonly stroke?: SizeType;
- readonly gutter?: SizeType;
- readonly gutterX?: SizeType;
- readonly gutterY?: SizeType;
-}
+export type BoxProps = {
+ elevation?: SizeType;
+ gutter?: SizeType;
+ gutterX?: SizeType;
+ gutterY?: SizeType;
+};
-const Box = ({
+const Box = ({
+ as,
className,
- as: Component = 'div',
testId = 'Box',
elevation = 'none',
gutter = 'none',
gutterX = 'none',
gutterY = 'none',
- ...restProps
-}: BaseProps & BoxProps) => (
-
-);
+ ...props
+}: CommonComponentCombinedProps) => {
+ const PolymorphicComponent = as || 'div';
+ return (
+
+ );
+};
Box.displayName = 'Box';
export default Box;
diff --git a/src/components/Button/index.tsx b/src/components/Button/index.tsx
index 77ed5b51..20e8a27a 100644
--- a/src/components/Button/index.tsx
+++ b/src/components/Button/index.tsx
@@ -1,24 +1,27 @@
-import React from 'react';
+import React, { ElementType } from 'react';
import cx from 'classnames';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import type { IconProp } from '@fortawesome/fontawesome-svg-core';
-import type { BaseProps, LevelType, SizeType } from '../types';
+import type {
+ CommonComponentCombinedProps,
+ LevelType,
+ SizeType
+} from '../types';
import Box from '../Box';
import Text from '../Text';
import styles from './Button.module.scss';
-export interface ButtonProps
- extends Omit, 'size'> {
- readonly level?: LevelType;
- readonly size?: SizeType;
- readonly icon?: IconProp;
- readonly block?: boolean;
- readonly disabled?: boolean;
-}
+export type ButtonProps = {
+ level?: LevelType;
+ size?: SizeType;
+ icon?: IconProp;
+ block?: boolean;
+ disabled?: boolean;
+};
-const Button = ({
+const Button = ({
className,
- as = 'button',
+ as,
testId = 'Button',
level = 'primary',
size = 'medium',
@@ -26,27 +29,30 @@ const Button = ({
icon,
children,
...restProps
-}: BaseProps & ButtonProps) => (
-
- ) => {
+ const PolymorphicComponent = as || 'button';
+ return (
+
- {icon && }
- {children}
-
-
-);
+
+ {icon && }
+ {children}
+
+
+ );
+};
Button.displayName = 'Button';
export default Button;
diff --git a/src/components/types.ts b/src/components/types.ts
index 6a9234a2..c0496d53 100644
--- a/src/components/types.ts
+++ b/src/components/types.ts
@@ -1,16 +1,25 @@
-import React from 'react';
+import {
+ ElementType,
+ ReactNode,
+ CSSProperties,
+ ComponentPropsWithoutRef
+} from 'react';
-export type AsType = keyof JSX.IntrinsicElements;
+export type CommonComponentProps = {
+ as?: T;
+ testId?: string;
+ children?: ReactNode;
+ className?: string;
+ style?: CSSProperties;
+};
+
+export type CommonComponentCombinedProps<
+ T extends ElementType,
+ K
+> = CommonComponentProps &
+ Omit, keyof CommonComponentProps> &
+ K;
export type LevelType = 'primary' | 'secondary' | 'tertiary' | 'danger';
export type SizeType = 'none' | 'small' | 'medium' | 'large';
-
-export type BaseProps = {
- readonly className?: string;
- readonly as?: AsType;
- readonly testId?: string;
- readonly children?: React.ReactNode | React.ReactNode[];
- readonly style?: React.CSSProperties;
- readonly htmlFor?: string;
-};