From 053831b48c981b2a83a78e8dbcbdbed5869d6595 Mon Sep 17 00:00:00 2001 From: Antoine Clausse Date: Mon, 4 Nov 2024 10:08:43 +0100 Subject: [PATCH] [web] Spelling correction Dropdown to BS5 (#21493) * Split `SpellingSuggestions` into a BS3 and BS5 version * Migrate `B5SpellingSuggestions` to BS5 * Add `.dropdown-menu.dropdown-menu-unpositioned` styles This makes the dropdown position itself without overflows * Make spelling tooltip background transparent * Migrate Cog icon to BS5 * Use `PolymorphicComponent` Co-authored-by: Ilkin Ismailov * Fix formatting --------- Co-authored-by: Ilkin Ismailov GitOrigin-RevId: aaa6c589637971031d13ac099f935fe2052e6989 --- .../extensions/spelling/index.ts | 1 + .../spelling-suggestions-feedback.tsx | 50 +++--- .../spelling-suggestions-language.tsx | 27 +++- .../spelling/spelling-suggestions.tsx | 152 ++++++++++++++++-- .../bootstrap-5/components/dropdown-menu.scss | 9 ++ 5 files changed, 200 insertions(+), 39 deletions(-) diff --git a/services/web/frontend/js/features/source-editor/extensions/spelling/index.ts b/services/web/frontend/js/features/source-editor/extensions/spelling/index.ts index d31befc261..02799b449c 100644 --- a/services/web/frontend/js/features/source-editor/extensions/spelling/index.ts +++ b/services/web/frontend/js/features/source-editor/extensions/spelling/index.ts @@ -61,6 +61,7 @@ const spellingTheme = EditorView.baseTheme({ }, '.cm-tooltip.ol-cm-spelling-context-menu-tooltip': { borderWidth: '0', + background: 'transparent', }, }) diff --git a/services/web/frontend/js/features/source-editor/extensions/spelling/spelling-suggestions-feedback.tsx b/services/web/frontend/js/features/source-editor/extensions/spelling/spelling-suggestions-feedback.tsx index c9f6528303..8143ac343c 100644 --- a/services/web/frontend/js/features/source-editor/extensions/spelling/spelling-suggestions-feedback.tsx +++ b/services/web/frontend/js/features/source-editor/extensions/spelling/spelling-suggestions-feedback.tsx @@ -4,10 +4,12 @@ import OLTooltip from '@/features/ui/components/ol/ol-tooltip' import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' import classnames from 'classnames' import MaterialIcon from '@/shared/components/material-icon' +import { Dropdown } from 'react-bootstrap-5' +import { bsVersion, isBootstrap5 } from '@/features/utils/bootstrap-5' +import PolymorphicComponent from '@/shared/components/polymorphic-component' const SpellingSuggestionsFeedback: FC = () => { const { t } = useTranslation() - return ( { tooltipProps={{ className: 'split-test-badge-tooltip' }} overlayProps={{ placement: 'bottom', delay: 100 }} > - - - } - bs5={ - - } - /> - {t('give_feedback')} - + + + + } + bs5={ + + } + /> + {t('give_feedback')} + + ) } diff --git a/services/web/frontend/js/features/source-editor/extensions/spelling/spelling-suggestions-language.tsx b/services/web/frontend/js/features/source-editor/extensions/spelling/spelling-suggestions-language.tsx index a3352098a3..25bad03b98 100644 --- a/services/web/frontend/js/features/source-editor/extensions/spelling/spelling-suggestions-language.tsx +++ b/services/web/frontend/js/features/source-editor/extensions/spelling/spelling-suggestions-language.tsx @@ -2,6 +2,11 @@ import { memo, useCallback } from 'react' import Icon from '@/shared/components/icon' import { useTranslation } from 'react-i18next' import OLTooltip from '@/features/ui/components/ol/ol-tooltip' +import { bsVersion, isBootstrap5 } from '@/features/utils/bootstrap-5' +import { Dropdown } from 'react-bootstrap-5' +import PolymorphicComponent from '@/shared/components/polymorphic-component' +import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' +import MaterialIcon from '@/shared/components/material-icon' export const SpellingSuggestionsLanguage = memo<{ language: { name: string } @@ -27,12 +32,22 @@ export const SpellingSuggestionsLanguage = memo<{ description={t('change_language')} overlayProps={{ placement: 'right', delay: 100 }} > - + + + } + bs5={} + /> + {language.name} + + ) }) diff --git a/services/web/frontend/js/features/source-editor/extensions/spelling/spelling-suggestions.tsx b/services/web/frontend/js/features/source-editor/extensions/spelling/spelling-suggestions.tsx index 596bafa205..bee819a224 100644 --- a/services/web/frontend/js/features/source-editor/extensions/spelling/spelling-suggestions.tsx +++ b/services/web/frontend/js/features/source-editor/extensions/spelling/spelling-suggestions.tsx @@ -15,6 +15,9 @@ import SpellingSuggestionsFeedback from './spelling-suggestions-feedback' import { SpellingSuggestionsLanguage } from './spelling-suggestions-language' import { captureException } from '@/infrastructure/error-reporter' import { debugConsole } from '@/utils/debugging' +import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' +import { SpellCheckLanguage } from '../../../../../../types/project-settings' +import { Dropdown } from 'react-bootstrap-5' const ITEMS_TO_SHOW = 8 @@ -22,14 +25,16 @@ const ITEMS_TO_SHOW = 8 const wrapArrayIndex = (index: number, length: number) => ((index % length) + length) % length -export const SpellingSuggestions: FC<{ +type SpellingSuggestionsProps = { word: Word spellCheckLanguage?: string spellChecker?: SpellChecker | null handleClose: () => void handleLearnWord: () => void handleCorrectWord: (text: string) => void -}> = ({ +} + +export const SpellingSuggestions: FC = ({ word, spellCheckLanguage, spellChecker, @@ -37,8 +42,6 @@ export const SpellingSuggestions: FC<{ handleLearnWord, handleCorrectWord, }) => { - const { t } = useTranslation() - const [suggestions, setSuggestions] = useState(() => Array.isArray(word.suggestions) ? word.suggestions.slice(0, ITEMS_TO_SHOW) @@ -47,10 +50,6 @@ export const SpellingSuggestions: FC<{ const [waiting, setWaiting] = useState(!word.suggestions) - const [selectedIndex, setSelectedIndex] = useState(0) - - const itemsLength = suggestions.length + 1 - useEffect(() => { if (!word.suggestions) { spellChecker @@ -85,6 +84,46 @@ export const SpellingSuggestions: FC<{ return null } + const innerProps = { + suggestions, + waiting, + handleClose, + handleCorrectWord, + handleLearnWord, + language, + } + + return ( + } + bs5={} + /> + ) +} + +type SpellingSuggestionsInnerProps = { + suggestions: string[] + waiting: boolean + handleClose: () => void + handleCorrectWord: (text: string) => void + handleLearnWord: () => void + language: SpellCheckLanguage +} + +const B3SpellingSuggestions: FC = ({ + suggestions, + waiting, + language, + handleClose, + handleCorrectWord, + handleLearnWord, +}) => { + const { t } = useTranslation() + + const [selectedIndex, setSelectedIndex] = useState(0) + + const itemsLength = suggestions.length + 1 + return (
    {suggestions.map((suggestion, index) => ( - 0 &&
  • } )} - { @@ -155,7 +194,7 @@ export const SpellingSuggestions: FC<{ ) } -const ListItem: FC<{ +const BS3ListItem: FC<{ content: string selected: boolean handleClick: MouseEventHandler @@ -183,3 +222,94 @@ const ListItem: FC<{
  • ) } + +const B5SpellingSuggestions: FC = ({ + suggestions, + waiting, + language, + handleClose, + handleCorrectWord, + handleLearnWord, +}) => { + const { t } = useTranslation() + return ( + + { + switch (event.code) { + case 'Escape': + case 'Tab': + event.preventDefault() + handleClose() + break + } + }} + > + {Array.isArray(suggestions) && + suggestions.map((suggestion, index) => ( + { + event.preventDefault() + handleCorrectWord(suggestion) + }} + // eslint-disable-next-line jsx-a11y/no-autofocus + autoFocus={index === 0} + /> + ))} + {suggestions?.length > 0 && } + { + event.preventDefault() + handleLearnWord() + }} + // eslint-disable-next-line jsx-a11y/no-autofocus + autoFocus={suggestions?.length === 0} + /> + + + + {getMeta('ol-isSaas') && ( + <> + + + + )} + + + ) +} + +const BS5ListItem: FC<{ + content: string + handleClick: MouseEventHandler + autoFocus?: boolean +}> = ({ content, handleClick, autoFocus }) => { + const handleListItem = useCallback( + (node: HTMLElement | null) => { + if (node && autoFocus) node.focus() + }, + [autoFocus] + ) + return ( + + {content} + + ) +} diff --git a/services/web/frontend/stylesheets/bootstrap-5/components/dropdown-menu.scss b/services/web/frontend/stylesheets/bootstrap-5/components/dropdown-menu.scss index 3dc5777795..042251c9a7 100644 --- a/services/web/frontend/stylesheets/bootstrap-5/components/dropdown-menu.scss +++ b/services/web/frontend/stylesheets/bootstrap-5/components/dropdown-menu.scss @@ -9,6 +9,15 @@ var(--spacing-04); } +.dropdown-menu.dropdown-menu-unpositioned { + position: unset; + top: unset; + left: unset; + z-index: unset; + display: block; + float: unset; +} + .dropdown-menu { @include shadow-md;