Merge remote-tracking branch 'origin/autosuggest-input-refactor' into chats
This commit is contained in:
commit
09887130b7
4 changed files with 30 additions and 17 deletions
|
@ -7,6 +7,7 @@ import AutosuggestInput, { AutoSuggestion } from 'soapbox/components/autosuggest
|
||||||
import { useAppDispatch } from 'soapbox/hooks';
|
import { useAppDispatch } from 'soapbox/hooks';
|
||||||
|
|
||||||
import type { Menu } from 'soapbox/components/dropdown_menu';
|
import type { Menu } from 'soapbox/components/dropdown_menu';
|
||||||
|
import type { InputThemes } from 'soapbox/components/ui/input/input';
|
||||||
|
|
||||||
const noOp = () => { };
|
const noOp = () => { };
|
||||||
|
|
||||||
|
@ -20,6 +21,7 @@ interface IAutosuggestAccountInput {
|
||||||
autoSelect?: boolean,
|
autoSelect?: boolean,
|
||||||
menu?: Menu,
|
menu?: Menu,
|
||||||
onKeyDown?: React.KeyboardEventHandler,
|
onKeyDown?: React.KeyboardEventHandler,
|
||||||
|
theme?: InputThemes,
|
||||||
}
|
}
|
||||||
|
|
||||||
const AutosuggestAccountInput: React.FC<IAutosuggestAccountInput> = ({
|
const AutosuggestAccountInput: React.FC<IAutosuggestAccountInput> = ({
|
||||||
|
|
|
@ -6,10 +6,12 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
|
||||||
import AutosuggestEmoji, { Emoji } from 'soapbox/components/autosuggest_emoji';
|
import AutosuggestEmoji, { Emoji } from 'soapbox/components/autosuggest_emoji';
|
||||||
import Icon from 'soapbox/components/icon';
|
import Icon from 'soapbox/components/icon';
|
||||||
|
import { Input } from 'soapbox/components/ui';
|
||||||
import AutosuggestAccount from 'soapbox/features/compose/components/autosuggest_account';
|
import AutosuggestAccount from 'soapbox/features/compose/components/autosuggest_account';
|
||||||
import { isRtl } from 'soapbox/rtl';
|
import { isRtl } from 'soapbox/rtl';
|
||||||
|
|
||||||
import type { Menu, MenuItem } from 'soapbox/components/dropdown_menu';
|
import type { Menu, MenuItem } from 'soapbox/components/dropdown_menu';
|
||||||
|
import type { InputThemes } from 'soapbox/components/ui/input/input';
|
||||||
|
|
||||||
type CursorMatch = [
|
type CursorMatch = [
|
||||||
tokenStart: number | null,
|
tokenStart: number | null,
|
||||||
|
@ -60,6 +62,7 @@ interface IAutosuggestInput extends Pick<React.HTMLAttributes<HTMLInputElement>,
|
||||||
menu?: Menu,
|
menu?: Menu,
|
||||||
resultsPosition: string,
|
resultsPosition: string,
|
||||||
hidePortal?: boolean,
|
hidePortal?: boolean,
|
||||||
|
theme?: InputThemes,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class AutosuggestInput extends ImmutablePureComponent<IAutosuggestInput> {
|
export default class AutosuggestInput extends ImmutablePureComponent<IAutosuggestInput> {
|
||||||
|
@ -285,7 +288,7 @@ export default class AutosuggestInput extends ImmutablePureComponent<IAutosugges
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { hidePortal, value, suggestions, disabled, placeholder, onKeyUp, autoFocus, className, id, maxLength, menu } = this.props;
|
const { hidePortal, value, suggestions, disabled, placeholder, onKeyUp, autoFocus, className, id, maxLength, menu, theme } = this.props;
|
||||||
const { suggestionsHidden } = this.state;
|
const { suggestionsHidden } = this.state;
|
||||||
const style: React.CSSProperties = { direction: 'ltr' };
|
const style: React.CSSProperties = { direction: 'ltr' };
|
||||||
|
|
||||||
|
@ -299,11 +302,10 @@ export default class AutosuggestInput extends ImmutablePureComponent<IAutosugges
|
||||||
<div key='input' className='relative w-full'>
|
<div key='input' className='relative w-full'>
|
||||||
<label className='sr-only'>{placeholder}</label>
|
<label className='sr-only'>{placeholder}</label>
|
||||||
|
|
||||||
<input
|
<Input
|
||||||
type='text'
|
type='text'
|
||||||
className={classNames({
|
className={className}
|
||||||
'block w-full sm:text-sm border-gray-200 dark:border-gray-800 bg-gray-200 dark:bg-gray-800 text-gray-900 dark:text-white placeholder:text-gray-600 dark:placeholder:text-gray-600 focus:border-gray-200 dark:focus-border-gray-800 focus:ring-primary-500 focus:ring-2': true,
|
outerClassName='mt-0'
|
||||||
}, className)}
|
|
||||||
ref={this.setInput}
|
ref={this.setInput}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
@ -319,6 +321,7 @@ export default class AutosuggestInput extends ImmutablePureComponent<IAutosugges
|
||||||
id={id}
|
id={id}
|
||||||
maxLength={maxLength}
|
maxLength={maxLength}
|
||||||
data-testid='autosuggest-input'
|
data-testid='autosuggest-input'
|
||||||
|
theme={theme}
|
||||||
/>
|
/>
|
||||||
</div>,
|
</div>,
|
||||||
<Portal key='portal'>
|
<Portal key='portal'>
|
||||||
|
|
|
@ -11,7 +11,10 @@ const messages = defineMessages({
|
||||||
hidePassword: { id: 'input.password.hide_password', defaultMessage: 'Hide password' },
|
hidePassword: { id: 'input.password.hide_password', defaultMessage: 'Hide password' },
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IInput extends Pick<React.InputHTMLAttributes<HTMLInputElement>, 'maxLength' | 'onChange' | 'onBlur' | 'type' | 'autoComplete' | 'autoCorrect' | 'autoCapitalize' | 'required' | 'disabled' | 'onClick' | 'readOnly' | 'min' | 'pattern'> {
|
/** Possible theme names for an Input. */
|
||||||
|
type InputThemes = 'normal' | 'search' | 'transparent';
|
||||||
|
|
||||||
|
interface IInput extends Pick<React.InputHTMLAttributes<HTMLInputElement>, 'maxLength' | 'onChange' | 'onBlur' | 'type' | 'autoComplete' | 'autoCorrect' | 'autoCapitalize' | 'required' | 'disabled' | 'onClick' | 'readOnly' | 'min' | 'pattern' | 'onKeyDown' | 'onKeyUp' | 'onFocus' | 'style' | 'id'> {
|
||||||
/** Put the cursor into the input on mount. */
|
/** Put the cursor into the input on mount. */
|
||||||
autoFocus?: boolean,
|
autoFocus?: boolean,
|
||||||
/** The initial text in the input. */
|
/** The initial text in the input. */
|
||||||
|
@ -36,8 +39,8 @@ interface IInput extends Pick<React.InputHTMLAttributes<HTMLInputElement>, 'maxL
|
||||||
prepend?: React.ReactElement,
|
prepend?: React.ReactElement,
|
||||||
/** An element to display as suffix to input. Cannot be used with password type. */
|
/** An element to display as suffix to input. Cannot be used with password type. */
|
||||||
append?: React.ReactElement,
|
append?: React.ReactElement,
|
||||||
/** Adds specific styling to denote a searchabe input. */
|
/** Theme to style the input with. */
|
||||||
isSearch?: boolean,
|
theme?: InputThemes,
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Form input element. */
|
/** Form input element. */
|
||||||
|
@ -45,7 +48,7 @@ const Input = React.forwardRef<HTMLInputElement, IInput>(
|
||||||
(props, ref) => {
|
(props, ref) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const { type = 'text', icon, className, outerClassName, hasError, append, prepend, isSearch, ...filteredProps } = props;
|
const { type = 'text', icon, className, outerClassName, hasError, append, prepend, theme = 'normal', ...filteredProps } = props;
|
||||||
|
|
||||||
const [revealed, setRevealed] = React.useState(false);
|
const [revealed, setRevealed] = React.useState(false);
|
||||||
|
|
||||||
|
@ -59,8 +62,8 @@ const Input = React.forwardRef<HTMLInputElement, IInput>(
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
classNames('mt-1 relative shadow-sm', outerClassName, {
|
classNames('mt-1 relative shadow-sm', outerClassName, {
|
||||||
'rounded-md': !isSearch,
|
'rounded-md': theme !== 'search',
|
||||||
'rounded-full': isSearch,
|
'rounded-full': theme === 'search',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
@ -82,9 +85,10 @@ const Input = React.forwardRef<HTMLInputElement, IInput>(
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'text-gray-900 dark:text-gray-100 placeholder:text-gray-600 dark:placeholder:text-gray-600 block w-full sm:text-sm dark:ring-1 dark:ring-gray-800 focus:ring-primary-500 focus:border-primary-500 dark:focus:ring-primary-500 dark:focus:border-primary-500':
|
'text-gray-900 dark:text-gray-100 placeholder:text-gray-600 dark:placeholder:text-gray-600 block w-full sm:text-sm dark:ring-1 dark:ring-gray-800 focus:ring-primary-500 focus:border-primary-500 dark:focus:ring-primary-500 dark:focus:border-primary-500':
|
||||||
true,
|
['normal', 'search'].includes(theme),
|
||||||
'rounded-md bg-white dark:bg-gray-900 border-gray-400 dark:border-gray-800': !isSearch,
|
'rounded-md bg-white dark:bg-gray-900 border-gray-400 dark:border-gray-800': theme === 'normal',
|
||||||
'rounded-full bg-gray-200 border-gray-200 dark:bg-gray-800 dark:border-gray-800 focus:bg-white': isSearch,
|
'rounded-full bg-gray-200 border-gray-200 dark:bg-gray-800 dark:border-gray-800 focus:bg-white': theme === 'search',
|
||||||
|
'bg-transparent border-none': theme === 'transparent',
|
||||||
'pr-7': isPassword || append,
|
'pr-7': isPassword || append,
|
||||||
'text-red-600 border-red-600': hasError,
|
'text-red-600 border-red-600': hasError,
|
||||||
'pl-8': typeof icon !== 'undefined',
|
'pl-8': typeof icon !== 'undefined',
|
||||||
|
@ -127,4 +131,7 @@ const Input = React.forwardRef<HTMLInputElement, IInput>(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
export default Input;
|
export {
|
||||||
|
Input as default,
|
||||||
|
InputThemes,
|
||||||
|
};
|
||||||
|
|
|
@ -15,6 +15,7 @@ import {
|
||||||
submitSearch,
|
submitSearch,
|
||||||
} from 'soapbox/actions/search';
|
} from 'soapbox/actions/search';
|
||||||
import AutosuggestAccountInput from 'soapbox/components/autosuggest_account_input';
|
import AutosuggestAccountInput from 'soapbox/components/autosuggest_account_input';
|
||||||
|
import { Input } from 'soapbox/components/ui';
|
||||||
import SvgIcon from 'soapbox/components/ui/icon/svg-icon';
|
import SvgIcon from 'soapbox/components/ui/icon/svg-icon';
|
||||||
import { useAppSelector } from 'soapbox/hooks';
|
import { useAppSelector } from 'soapbox/hooks';
|
||||||
|
|
||||||
|
@ -117,7 +118,6 @@ const Search = (props: ISearch) => {
|
||||||
|
|
||||||
const hasValue = value.length > 0 || submitted;
|
const hasValue = value.length > 0 || submitted;
|
||||||
const componentProps: any = {
|
const componentProps: any = {
|
||||||
className: 'block w-full pl-3 pr-10 py-2 border border-gray-200 dark:border-gray-800 rounded-full leading-5 bg-gray-200 dark:bg-gray-800 dark:text-white placeholder:text-gray-600 dark:placeholder:text-gray-600 focus:outline-none focus:ring-2 focus:ring-primary-500 sm:text-sm',
|
|
||||||
type: 'text',
|
type: 'text',
|
||||||
id: 'search',
|
id: 'search',
|
||||||
placeholder: intl.formatMessage(messages.placeholder),
|
placeholder: intl.formatMessage(messages.placeholder),
|
||||||
|
@ -126,6 +126,7 @@ const Search = (props: ISearch) => {
|
||||||
onKeyDown: handleKeyDown,
|
onKeyDown: handleKeyDown,
|
||||||
onFocus: handleFocus,
|
onFocus: handleFocus,
|
||||||
autoFocus: autoFocus,
|
autoFocus: autoFocus,
|
||||||
|
theme: 'search',
|
||||||
};
|
};
|
||||||
|
|
||||||
if (autosuggest) {
|
if (autosuggest) {
|
||||||
|
@ -142,7 +143,7 @@ const Search = (props: ISearch) => {
|
||||||
{autosuggest ? (
|
{autosuggest ? (
|
||||||
<AutosuggestAccountInput {...componentProps} />
|
<AutosuggestAccountInput {...componentProps} />
|
||||||
) : (
|
) : (
|
||||||
<input {...componentProps} />
|
<Input {...componentProps} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
|
Loading…
Reference in a new issue