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)', - }, - }; -});