diff --git a/packages/component/src/index.ts b/packages/component/src/index.ts
index c639b16950..2031c16b8c 100644
--- a/packages/component/src/index.ts
+++ b/packages/component/src/index.ts
@@ -3,7 +3,6 @@ export * from './styles';
export * from './ui/breadcrumbs';
export * from './ui/button';
export * from './ui/confirm';
-export * from './ui/divider';
export * from './ui/empty';
export * from './ui/input';
export * from './ui/layout';
diff --git a/packages/component/src/ui/divider/index.ts b/packages/component/src/ui/divider/index.ts
deleted file mode 100644
index 8a7925fd93..0000000000
--- a/packages/component/src/ui/divider/index.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import MuiDivider from '@mui/material/Divider';
-
-import { styled } from '../../styles';
-
-export const Divider = styled(MuiDivider)(() => {
- return {
- borderColor: 'var(--affine-border-color)',
- };
-});
diff --git a/packages/component/src/ui/empty/empty-svg.tsx b/packages/component/src/ui/empty/empty-svg.tsx
index b18ad5624e..bf29ee34f8 100644
--- a/packages/component/src/ui/empty/empty-svg.tsx
+++ b/packages/component/src/ui/empty/empty-svg.tsx
@@ -1,7 +1,7 @@
-import type { SvgIconProps } from '@mui/material/SvgIcon';
import SvgIcon from '@mui/material/SvgIcon';
+import { memo } from 'react';
-export const EmptySvg = (_props: SvgIconProps) => {
+export const EmptySvg = memo(function EmptySvg() {
return (
{
);
-};
+});
diff --git a/packages/component/src/ui/input/index.css.ts b/packages/component/src/ui/input/index.css.ts
new file mode 100644
index 0000000000..84ca25ad5d
--- /dev/null
+++ b/packages/component/src/ui/input/index.css.ts
@@ -0,0 +1,34 @@
+import { createVar, style } from '@vanilla-extract/css';
+
+export const heightVar = createVar('heightVar');
+export const widthVar = createVar('widthVar');
+
+export const inputStyle = style({
+ vars: {
+ [heightVar]: 'unset',
+ [widthVar]: '100%',
+ },
+ width: widthVar,
+ height: heightVar,
+ lineHeight: '22px',
+ padding: '8px 12px',
+ color: 'var(--affine-text-primary-color)',
+ border: '1px solid',
+ borderColor: 'var(--affine-border-color)', // TODO: check out disableColor,
+ backgroundColor: 'var(--affine-white)',
+ borderRadius: '10px',
+ selectors: {
+ '&[data-no-border="true"]': {
+ border: 'unset',
+ },
+ '&[data-disabled="true"]': {
+ color: 'var(--affine-text-disable-color)',
+ },
+ '&::placeholder': {
+ color: 'var(--affine-placeholder-color)',
+ },
+ '&:focus': {
+ borderColor: 'var(--affine-primary-color)',
+ },
+ },
+});
diff --git a/packages/component/src/ui/input/index.stories.tsx b/packages/component/src/ui/input/index.stories.tsx
new file mode 100644
index 0000000000..c5a12bcc3f
--- /dev/null
+++ b/packages/component/src/ui/input/index.stories.tsx
@@ -0,0 +1,39 @@
+import { expect } from '@storybook/jest';
+import type { Meta, StoryFn } from '@storybook/react';
+import { userEvent, within } from '@storybook/testing-library';
+
+import { Input } from '.';
+
+export default {
+ title: 'AFFiNE/Input',
+ component: Input,
+} satisfies Meta;
+
+export const Basic: StoryFn = () => {
+ return ;
+};
+
+Basic.play = async ({ canvasElement }) => {
+ const element = within(canvasElement);
+ const item = element.getByTestId('test-input') as HTMLInputElement;
+ expect(item).toBeTruthy();
+ expect(item.value).toBe('test');
+ userEvent.clear(item);
+ userEvent.type(item, 'test 2');
+ expect(item.value).toBe('test 2');
+};
+
+export const DynamicHeight: StoryFn = () => {
+ return ;
+};
+
+DynamicHeight.play = async ({ canvasElement }) => {
+ const element = within(canvasElement);
+ const item = element.getByTestId('test-input') as HTMLInputElement;
+ expect(item).toBeTruthy();
+ expect(item.getBoundingClientRect().width).toBe(200);
+};
+
+export const NoBorder: StoryFn = () => {
+ return ;
+};
diff --git a/packages/component/src/ui/input/input.tsx b/packages/component/src/ui/input/input.tsx
index 43e8e2d15e..b97e6a475d 100644
--- a/packages/component/src/ui/input/input.tsx
+++ b/packages/component/src/ui/input/input.tsx
@@ -1,14 +1,16 @@
+import { assignInlineVars } from '@vanilla-extract/dynamic';
+import clsx from 'clsx';
import type {
+ ChangeEventHandler,
CSSProperties,
FocusEventHandler,
ForwardedRef,
HTMLAttributes,
- InputHTMLAttributes,
KeyboardEventHandler,
} from 'react';
-import { forwardRef, useEffect, useState } from 'react';
+import { forwardRef, useCallback } from 'react';
-import { StyledInput } from './style';
+import { heightVar, inputStyle, widthVar } from './index.css';
type inputProps = {
value?: string;
@@ -27,39 +29,35 @@ type inputProps = {
export const Input = forwardRef(function Input(
{
disabled,
- value: valueProp,
+ value,
placeholder,
maxLength,
minLength,
height,
width,
onChange,
- onBlur,
- onKeyDown,
noBorder = false,
...otherProps
}: inputProps,
ref: ForwardedRef
) {
- const [value, setValue] = useState(valueProp || '');
- const handleChange: InputHTMLAttributes['onChange'] = e => {
- const { value } = e.target;
- setValue(value);
- onChange && onChange(value);
- };
-
- const handleBlur: InputHTMLAttributes['onBlur'] = e => {
- onBlur && onBlur(e);
- };
- const handleKeyDown: InputHTMLAttributes['onKeyDown'] =
+ const handleChange = useCallback>(
e => {
- onKeyDown && onKeyDown(e);
- };
- useEffect(() => {
- setValue(valueProp || '');
- }, [valueProp]);
+ const { value } = e.target;
+ onChange && onChange(value);
+ },
+ [onChange]
+ );
+
return (
- (function Input(
maxLength={maxLength}
minLength={minLength}
onChange={handleChange}
- onBlur={handleBlur}
- onKeyDown={handleKeyDown}
height={height}
- noBorder={noBorder}
{...otherProps}
/>
);
diff --git a/packages/component/src/ui/input/style.ts b/packages/component/src/ui/input/style.ts
deleted file mode 100644
index 123bf45a62..0000000000
--- a/packages/component/src/ui/input/style.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import type { CSSProperties } from 'react';
-
-import { styled } from '../../styles';
-
-export const StyledInput = styled('input')<{
- disabled?: boolean;
- value?: string;
- width?: CSSProperties['width'];
- height?: CSSProperties['height'];
- noBorder?: boolean;
-}>(({ width, disabled, height, noBorder }) => {
- return {
- width: width || '100%',
- height,
- lineHeight: '22px',
- padding: '8px 12px',
- color: disabled
- ? 'var(--affine-text-disable-color)'
- : 'var(--affine-text-primary-color)',
- border: noBorder ? 'unset' : `1px solid`,
- borderColor: 'var(--affine-border-color)', // TODO: check out disableColor,
- backgroundColor: 'var(--affine-white)',
- borderRadius: '10px',
- '&::placeholder': {
- color: 'var(--affine-placeholder-color)',
- },
- '&:focus': {
- borderColor: 'var(--affine-primary-color)',
- },
- };
-});