feat: add tab-index in select

This commit is contained in:
qishaoxuan
2022-07-28 14:06:56 +08:00
parent ec80998b82
commit 56eae05a0f
4 changed files with 92 additions and 85 deletions

View File

@@ -1,4 +1,4 @@
import React, { type CSSProperties, useState } from 'react'; import React, { forwardRef, type CSSProperties, useState } from 'react';
import { Input, styled, InputProps } from '@toeverything/components/ui'; import { Input, styled, InputProps } from '@toeverything/components/ui';
import { StyledHighLightWrapper } from '../StyledComponent'; import { StyledHighLightWrapper } from '../StyledComponent';
import { IconNames } from '../types'; import { IconNames } from '../types';
@@ -29,38 +29,39 @@ export const PendantIcon = ({
); );
}; };
export const IconInput = ({ export const IconInput = forwardRef<HTMLInputElement, IconInputProps>(
iconName, ({ iconName, iconStyle, color, background, ...inputProps }, ref) => {
iconStyle, return (
color, <>
background, <PendantIcon
...inputProps iconName={iconName}
}: IconInputProps) => { iconStyle={iconStyle}
return ( color={color}
<> background={background}
<PendantIcon />
iconName={iconName} <Input
iconStyle={iconStyle} ref={ref}
color={color} style={{
background={background} flexGrow: '1',
/> }}
<Input noBorder
style={{ {...inputProps}
flexGrow: '1', />
border: 'none', </>
}} );
{...inputProps} }
/> );
</>
);
};
type HighLightIconInputProps = { type HighLightIconInputProps = {
startElement?: React.ReactNode; startElement?: React.ReactNode;
endElement?: React.ReactNode; endElement?: React.ReactNode;
tabIndex?: number;
} & IconInputProps; } & IconInputProps;
export const HighLightIconInput = (props: HighLightIconInputProps) => { export const HighLightIconInput = forwardRef<
HTMLInputElement,
HighLightIconInputProps
>((props, ref) => {
const { const {
onFocus, onFocus,
onBlur, onBlur,
@@ -74,6 +75,7 @@ export const HighLightIconInput = (props: HighLightIconInputProps) => {
<StyledHighLightWrapper isFocus={focus}> <StyledHighLightWrapper isFocus={focus}>
{startElement} {startElement}
<IconInput <IconInput
ref={ref}
onFocus={e => { onFocus={e => {
setFocus(true); setFocus(true);
onFocus?.(e); onFocus?.(e);
@@ -87,7 +89,7 @@ export const HighLightIconInput = (props: HighLightIconInputProps) => {
{endElement} {endElement}
</StyledHighLightWrapper> </StyledHighLightWrapper>
); );
}; });
const StyledIconWrapper = styled('div')` const StyledIconWrapper = styled('div')`
display: inline-flex; display: inline-flex;

View File

@@ -5,7 +5,7 @@ import React, {
KeyboardEvent, KeyboardEvent,
useRef, useRef,
} from 'react'; } from 'react';
import { Add, Delete, Close } from '@mui/icons-material'; import { Add, Close } from '@mui/icons-material';
import { ModifyPanelContentProps } from './types'; import { ModifyPanelContentProps } from './types';
import { import {
MultiSelectProperty, MultiSelectProperty,
@@ -38,6 +38,7 @@ type OptionItemType = {
}; };
onEnter?: (e: KeyboardEvent) => void; onEnter?: (e: KeyboardEvent) => void;
focused?: boolean; focused?: boolean;
tabIndex?: number;
}; };
type SelectPropsType = { type SelectPropsType = {
@@ -138,6 +139,7 @@ export const BasicSelect = ({
onEnter={() => { onEnter={() => {
insertOption(options[options.length - 1].id); insertOption(options[options.length - 1].id);
}} }}
tabIndex={index + 1}
/> />
); );
})} })}
@@ -196,6 +198,7 @@ const OptionItem = ({
iconConfig, iconConfig,
onEnter, onEnter,
focused, focused,
tabIndex,
}: OptionItemType) => { }: OptionItemType) => {
const theme = useTheme(); const theme = useTheme();
const inputRef = useRef<HTMLInputElement>(); const inputRef = useRef<HTMLInputElement>();
@@ -204,11 +207,8 @@ const OptionItem = ({
}, [focused]); }, [focused]);
return ( return (
<HighLightIconInput <HighLightIconInput
componentsProps={{ tabIndex={tabIndex}
input: { ref={inputRef}
ref: inputRef,
},
}}
iconName={iconConfig?.name} iconName={iconConfig?.name}
color={iconConfig?.color} color={iconConfig?.color}
background={iconConfig?.background} background={iconConfig?.background}

View File

@@ -8,7 +8,7 @@ export default ({
initialValue, initialValue,
iconConfig, iconConfig,
}: ModifyPanelContentProps) => { }: ModifyPanelContentProps) => {
const [text, setText] = useState(initialValue?.value || ''); const [text, setText] = useState((initialValue?.value as string) || '');
return ( return (
<HighLightIconInput <HighLightIconInput
iconName={iconConfig?.iconName} iconName={iconConfig?.iconName}

View File

@@ -1,57 +1,62 @@
import { forwardRef, type ForwardedRef } from 'react'; import React, {
/* eslint-disable no-restricted-imports */ forwardRef,
import InputUnstyled, { type ForwardedRef,
inputUnstyledClasses, type InputHTMLAttributes,
type InputUnstyledProps, type CSSProperties,
} from '@mui/base/InputUnstyled'; } from 'react';
import { styled } from '../styled'; import { styled } from '../styled';
/** export type InputProps = {
* Input is extend by mui InputUnstyled startAdornment?: React.ReactNode;
* endAdornment?: React.ReactNode;
* InputUnstyled Demos: style?: CSSProperties;
* noBorder?: boolean;
* - [Input](https://mui.com/base/react-input/) } & InputHTMLAttributes<HTMLInputElement>;
*
* InputUnstyled API:
*
* - [InputUnstyled API](https://mui.com/base/api/input-unstyled/)
*
* **/
export type InputProps = InputUnstyledProps;
export const Input = forwardRef(function CustomInput( export const Input = forwardRef(
props: InputUnstyledProps, (props: InputProps, ref: ForwardedRef<HTMLInputElement>) => {
ref: ForwardedRef<HTMLDivElement> // const { getRootProps, getInputProps } = useInput(props);
) { const {
const { components, ...other } = props; style,
return ( startAdornment = null,
<InputUnstyled endAdornment = null,
components={{ onClick,
Root: StyledInputRoot, noBorder = false,
Input: StyledInputElement, ...inputProps
...components, } = props;
}}
{...other}
ref={ref}
/>
);
});
const StyledInputRoot = styled('div')(({ theme }) => ({ return (
height: '32px', <StyledInputRoot
display: 'flex', noBorder={noBorder}
border: `1px solid ${theme.affine.palette.borderColor}`, style={style}
borderRadius: '10px', onClick={onClick}
color: `${theme.affine.palette.secondaryText}`, >
padding: '0 12px', {startAdornment}
fontSize: '14px', <StyledInputElement ref={ref} {...inputProps} />
lineHeight: '1.5', {endAdornment}
transition: 'border .1s', </StyledInputRoot>
[`&.${inputUnstyledClasses.focused}`]: { );
borderColor: `${theme.affine.palette.primary}`, }
}, );
}));
const StyledInputRoot = styled('div')<{ noBorder: boolean }>(
({ noBorder, theme }) => ({
height: '32px',
display: 'flex',
border: noBorder
? 'none'
: `1px solid ${theme.affine.palette.borderColor}`,
borderRadius: '10px',
color: `${theme.affine.palette.secondaryText}`,
padding: '0 12px',
fontSize: '14px',
lineHeight: '1.5',
transition: 'border .1s',
'&:focus-within': {
borderColor: `${theme.affine.palette.primary}`,
},
})
);
const StyledInputElement = styled('input')(({ theme }) => ({ const StyledInputElement = styled('input')(({ theme }) => ({
fontSize: '14px', fontSize: '14px',