diff --git a/src/components/common/AutoComplete.tsx b/src/components/common/AutoComplete.tsx index e384c4bcf7f298b9d9eb649266216878f419a7d9..0e0f399da111e2276555137281e8d6bfa00000cb 100644 --- a/src/components/common/AutoComplete.tsx +++ b/src/components/common/AutoComplete.tsx @@ -4,7 +4,7 @@ import { Channels } from "revolt.js/dist/api/objects"; import { emojiDictionary } from "../../assets/emojis"; import { SYSTEM_USER_ID, User } from "revolt.js"; import UserIcon from "./user/UserIcon"; -import styled from "styled-components"; +import styled, { css } from "styled-components"; import Emoji from "./Emoji"; import ChannelIcon from "./ChannelIcon"; @@ -31,6 +31,7 @@ export type SearchClues = { }; export type AutoCompleteProps = { + detached?: boolean, state: AutoCompleteState, setState: StateUpdater<AutoCompleteState>, @@ -314,7 +315,7 @@ export function useAutoComplete(setValue: (v?: string) => void, searchClues?: Se } } -const Base = styled.div` +const Base = styled.div<{ detached?: boolean }>` position: relative; > div { @@ -348,11 +349,19 @@ const Base = styled.div` background: var(--primary-background); } } + + ${ props => props.detached && css` + bottom: 8px; + + > div { + border-radius: 4px; + } + ` } `; -export default function AutoComplete({ state, setState, onClick }: Pick<AutoCompleteProps, 'state' | 'setState' | 'onClick'>) { +export default function AutoComplete({ detached, state, setState, onClick }: Pick<AutoCompleteProps, 'detached' | 'state' | 'setState' | 'onClick'>) { return ( - <Base> + <Base detached={detached}> <div> {state.type === "emoji" && state.matches.map((match, i) => ( diff --git a/src/pages/settings/panes/Profile.tsx b/src/pages/settings/panes/Profile.tsx index 39902c0c37451d4cab2885131006cb7c2dc83822..941d311d1b3a880de03bddfb8a3895b00b18226e 100644 --- a/src/pages/settings/panes/Profile.tsx +++ b/src/pages/settings/panes/Profile.tsx @@ -8,6 +8,7 @@ import { FileUploader } from "../../../context/revoltjs/FileUploads"; import { useForceUpdate, useSelf } from "../../../context/revoltjs/hooks"; import { UserProfile } from "../../../context/intermediate/popovers/UserProfile"; import { ClientStatus, StatusContext } from "../../../context/revoltjs/RevoltClient"; +import AutoComplete, { useAutoComplete } from "../../../components/common/AutoComplete"; export function Profile() { const { intl } = useContext(IntlContext) as any; @@ -36,6 +37,15 @@ export function Profile() { }, [status]); const [ changed, setChanged ] = useState(false); + function setContent(content?: string) { + setProfile({ ...profile, content }) + if (!changed) setChanged(true) + } + + const { onChange, onKeyUp, onKeyDown, onFocus, onBlur, ...autoCompleteProps } = + useAutoComplete(setContent, { + users: { type: 'all' } + }); return ( <div className={styles.user}> @@ -93,6 +103,7 @@ export function Profile() { <h3> <Text id="app.settings.pages.profile.info" /> </h3> + <AutoComplete detached {...autoCompleteProps} /> <TextAreaAutoSize maxRows={10} minHeight={200} @@ -100,8 +111,8 @@ export function Profile() { value={profile?.content ?? ""} disabled={typeof profile === "undefined"} onChange={ev => { - setProfile({ ...profile, content: ev.currentTarget.value }) - if (!changed) setChanged(true) + onChange(ev); + setContent(ev.currentTarget.value) }} placeholder={translate( `app.settings.pages.profile.${ @@ -112,6 +123,10 @@ export function Profile() { "", intl.dictionary )} + onKeyUp={onKeyUp} + onKeyDown={onKeyDown} + onFocus={onFocus} + onBlur={onBlur} /> <p> <Button contrast