From cdfb1c7abf02ef7896d6cdcf3566ee0c7dd390d3 Mon Sep 17 00:00:00 2001 From: Ollie H Date: Mon, 8 May 2023 14:09:15 -0700 Subject: Visual improvements to web autocomplete (#591) * Visual improvements to web autocomplete * Remove stray styling --- bskyweb/templates/base.html | 38 ++----- .../com/composer/text-input/web/Autocomplete.tsx | 122 ++++++++++++++++++--- web/index.html | 22 +--- 3 files changed, 118 insertions(+), 64 deletions(-) diff --git a/bskyweb/templates/base.html b/bskyweb/templates/base.html index 3bc8098ae..1d51b4f20 100644 --- a/bskyweb/templates/base.html +++ b/bskyweb/templates/base.html @@ -57,14 +57,6 @@ } }*/ - /* OLLIE: TODO -- this is not accessible */ - /* Remove focus state on inputs */ - .ProseMirror-focused { - outline: 0; - } - input:focus { - outline: 0; - } /* Remove default link styling */ a { color: inherit; @@ -106,28 +98,16 @@ color: #0085ff; cursor: pointer; } + /* OLLIE: TODO -- this is not accessible */ + /* Remove focus state on inputs */ + .ProseMirror-focused { + outline: 0; + } + input:focus { + outline: 0; + } .tippy-content .items { - border-radius: 6px; - background: #F3F3F8; - border: 1px solid #e0d9d9; - padding: 3px 3px; - } - .tippy-content .items .item { - display: block; - background: transparent; - color: #8a8c9a; - border: 0; - font: 17px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; - padding: 7px 10px 8px; - width: 100%; - text-align: left; - box-sizing: border-box; - letter-spacing: 0.2px; - } - .tippy-content .items .item.is-selected { - background: #fff; - border-radius: 4px; - color: #333; + width: fit-content; } {% include "scripts.html" %} diff --git a/src/view/com/composer/text-input/web/Autocomplete.tsx b/src/view/com/composer/text-input/web/Autocomplete.tsx index 7c6f8770b..20dbbbbe8 100644 --- a/src/view/com/composer/text-input/web/Autocomplete.tsx +++ b/src/view/com/composer/text-input/web/Autocomplete.tsx @@ -1,9 +1,12 @@ import React, { forwardRef, + useCallback, useEffect, useImperativeHandle, + useMemo, useState, } from 'react' +import {StyleSheet, View} from 'react-native' import {ReactRenderer} from '@tiptap/react' import tippy, {Instance as TippyInstance} from 'tippy.js' import { @@ -12,6 +15,10 @@ import { SuggestionKeyDownProps, } from '@tiptap/suggestion' import {UserAutocompleteModel} from 'state/models/discovery/user-autocomplete' +import {usePalette} from 'lib/hooks/usePalette' +import Graphemer from 'graphemer' +import {Text} from 'view/com/util/text/Text' +import {UserAvatar} from 'view/com/util/UserAvatar' interface MentionListRef { onKeyDown: (props: SuggestionKeyDownProps) => boolean @@ -26,7 +33,7 @@ export function createSuggestion({ async items({query}) { autocompleteView.setActive(true) await autocompleteView.setPrefix(query) - return autocompleteView.suggestions.slice(0, 8).map(s => s.handle) + return autocompleteView.suggestions.slice(0, 8) }, render: () => { @@ -91,12 +98,14 @@ export function createSuggestion({ const MentionList = forwardRef( (props: SuggestionProps, ref) => { const [selectedIndex, setSelectedIndex] = useState(0) + const pal = usePalette('default') + const splitter = useMemo(() => new Graphemer(), []) const selectItem = (index: number) => { const item = props.items[index] if (item) { - props.command({id: item}) + props.command({id: item.handle}) } } @@ -137,21 +146,106 @@ const MentionList = forwardRef( }, })) + const {items} = props + + const getDisplayedName = useCallback( + (name: string) => { + // Heuristic value based on max display name and handle lengths + const DISPLAY_LIMIT = 30 + if (name.length > DISPLAY_LIMIT) { + const graphemes = splitter.splitGraphemes(name) + + if (graphemes.length > DISPLAY_LIMIT) { + return graphemes.length > DISPLAY_LIMIT + ? `${graphemes.slice(0, DISPLAY_LIMIT).join('')}...` + : name.substring(0, DISPLAY_LIMIT) + } + } + + return name + }, + [splitter], + ) + return (
- {props.items.length ? ( - props.items.map((item, index) => ( - - )) - ) : ( -
No result
- )} + + {items.length > 0 ? ( + items.map((item, index) => { + const displayName = getDisplayedName( + item.displayName ?? item.handle, + ) + const isSelected = selectedIndex === index + + return ( + + + + + {displayName} + + + + {item.handle} + + + ) + }) + ) : ( + + No result + + )} +
) }, ) + +const styles = StyleSheet.create({ + container: { + width: 500, + borderRadius: 6, + borderWidth: 1, + borderStyle: 'solid', + padding: 4, + }, + mentionContainer: { + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', + flexDirection: 'row', + paddingHorizontal: 12, + paddingVertical: 8, + gap: 4, + }, + firstMention: { + borderTopLeftRadius: 2, + borderTopRightRadius: 2, + }, + lastMention: { + borderBottomLeftRadius: 2, + borderBottomRightRadius: 2, + }, + avatarAndDisplayName: { + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + gap: 6, + }, + noResult: { + paddingHorizontal: 12, + paddingVertical: 8, + }, +}) diff --git a/web/index.html b/web/index.html index f88fd727b..f518665ca 100644 --- a/web/index.html +++ b/web/index.html @@ -110,27 +110,7 @@ outline: 0; } .tippy-content .items { - border-radius: 6px; - background: #F3F3F8; - border: 1px solid #e0d9d9; - padding: 3px 3px; - } - .tippy-content .items .item { - display: block; - background: transparent; - color: #8a8c9a; - border: 0; - font: 17px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; - padding: 7px 10px 8px; - width: 100%; - text-align: left; - box-sizing: border-box; - letter-spacing: 0.2px; - } - .tippy-content .items .item.is-selected { - background: #fff; - border-radius: 4px; - color: #333; + width: fit-content; } -- cgit 1.4.1