From 5e91eccd68793dcda8ec7f2efa34089576e5311a Mon Sep 17 00:00:00 2001 From: IRBorisov <8611739+IRBorisov@users.noreply.github.com> Date: Sat, 9 Mar 2024 16:40:10 +0300 Subject: [PATCH] Improve tooltips --- .../src/app/Navigation/NavigationButton.tsx | 8 +- rsconcept/frontend/src/components/props.d.ts | 26 +++--- .../frontend/src/components/ui/Button.tsx | 4 +- .../frontend/src/components/ui/Checkbox.tsx | 15 +++- .../src/components/ui/CheckboxTristate.tsx | 3 +- .../src/components/ui/DropdownButton.tsx | 3 +- .../frontend/src/components/ui/MiniButton.tsx | 4 +- .../frontend/src/components/ui/Modal.tsx | 7 +- .../src/components/ui/SelectorButton.tsx | 2 - .../frontend/src/components/ui/TabLabel.tsx | 8 +- .../ConstituentaToolbar.tsx | 9 +- .../EditorRSExpression/RSLocalButton.tsx | 10 ++- .../EditorRSExpression/RSTokenButton.tsx | 2 +- .../EditorRSExpression/StatusBar.tsx | 4 +- .../RSFormPage/EditorRSForm/RSFormToolbar.tsx | 5 +- .../RSFormPage/EditorRSList/RSListToolbar.tsx | 14 +-- .../src/pages/UserProfilePage/UserTabs.tsx | 2 +- rsconcept/frontend/src/utils/labels.ts | 85 ++++++++++--------- 18 files changed, 120 insertions(+), 91 deletions(-) diff --git a/rsconcept/frontend/src/app/Navigation/NavigationButton.tsx b/rsconcept/frontend/src/app/Navigation/NavigationButton.tsx index bfb7c62a..348fe27e 100644 --- a/rsconcept/frontend/src/app/Navigation/NavigationButton.tsx +++ b/rsconcept/frontend/src/app/Navigation/NavigationButton.tsx @@ -1,16 +1,15 @@ import clsx from 'clsx'; +import { CProps } from '@/components/props'; import { globalIDs } from '@/utils/constants'; -interface NavigationButtonProps { +interface NavigationButtonProps extends CProps.Titled { text?: string; icon: React.ReactNode; - title?: string; - titleHtml?: string; onClick?: () => void; } -function NavigationButton({ icon, title, titleHtml, onClick, text }: NavigationButtonProps) { +function NavigationButton({ icon, title, titleHtml, hideTitle, onClick, text }: NavigationButtonProps) { return ( diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorRSExpression/StatusBar.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorRSExpression/StatusBar.tsx index 66cc7e2b..ebe746fa 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorRSExpression/StatusBar.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorRSExpression/StatusBar.tsx @@ -12,7 +12,7 @@ import { inferStatus } from '@/models/rsformAPI'; import { IExpressionParse, ParsingStatus } from '@/models/rslang'; import { colorBgCstStatus } from '@/styling/color'; import { globalIDs } from '@/utils/constants'; -import { labelExpressionStatus } from '@/utils/labels'; +import { labelExpressionStatus, prepareTooltip } from '@/utils/labels'; import StatusIcon from './StatusIcon'; @@ -49,7 +49,7 @@ function StatusBar({ isModified, processing, constituenta, parseData, onAnalyze )} style={{ backgroundColor: processing ? colors.bgDefault : colorBgCstStatus(status, colors) }} data-tooltip-id={globalIDs.tooltip} - data-tooltip-content='Проверить определение [Ctrl + Q]' + data-tooltip-html={prepareTooltip('Проверить определение', 'Ctrl + Q')} onClick={onAnalyze} > diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorRSForm/RSFormToolbar.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorRSForm/RSFormToolbar.tsx index 1b1630b5..61e486cd 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorRSForm/RSFormToolbar.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorRSForm/RSFormToolbar.tsx @@ -9,6 +9,7 @@ import HelpButton from '@/components/Help/HelpButton'; import MiniButton from '@/components/ui/MiniButton'; import Overlay from '@/components/ui/Overlay'; import { HelpTopic } from '@/models/miscellaneous'; +import { prepareTooltip } from '@/utils/labels'; import { useRSEdit } from '../RSEditContext'; @@ -28,7 +29,7 @@ function RSFormToolbar({ modified, anonymous, subscribed, claimable, onSubmit, o {controller.isContentEditable || controller.isProcessing ? ( } onClick={onSubmit} @@ -46,7 +47,7 @@ function RSFormToolbar({ modified, anonymous, subscribed, claimable, onSubmit, o /> {!anonymous ? ( ${subscribed ? 'включено' : 'выключено'}`} disabled={controller.isProcessing} icon={ subscribed ? ( diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorRSList/RSListToolbar.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorRSList/RSListToolbar.tsx index 12f82c71..ccaa29b3 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorRSList/RSListToolbar.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorRSList/RSListToolbar.tsx @@ -13,7 +13,7 @@ import { HelpTopic } from '@/models/miscellaneous'; import { CstType } from '@/models/rsform'; import { getCstTypePrefix } from '@/models/rsformAPI'; import { prefixes } from '@/utils/constants'; -import { getCstTypeShortcut, labelCstType } from '@/utils/labels'; +import { getCstTypeShortcut, labelCstType, prepareTooltip } from '@/utils/labels'; import { useRSEdit } from '../RSEditContext'; @@ -29,25 +29,25 @@ function RSListToolbar({ selectedCount }: RSListToolbarProps) { return ( } disabled={!controller.isMutable || nothingSelected} onClick={controller.moveUp} /> } disabled={!controller.isMutable || nothingSelected} onClick={controller.moveDown} /> } disabled={!controller.isMutable || selectedCount !== 1} onClick={controller.cloneCst} /> } disabled={!controller.isMutable} onClick={() => controller.createCst(undefined, false)} @@ -66,13 +66,13 @@ function RSListToolbar({ selectedCount }: RSListToolbarProps) { key={`${prefixes.csttype_list}${typeStr}`} text={`${getCstTypePrefix(typeStr as CstType)}1 — ${labelCstType(typeStr as CstType)}`} onClick={() => controller.createCst(typeStr as CstType, true)} - title={getCstTypeShortcut(typeStr as CstType)} + titleHtml={getCstTypeShortcut(typeStr as CstType)} /> ))} } disabled={!controller.isMutable || nothingSelected} onClick={controller.deleteCst} diff --git a/rsconcept/frontend/src/pages/UserProfilePage/UserTabs.tsx b/rsconcept/frontend/src/pages/UserProfilePage/UserTabs.tsx index 94628277..72bb825e 100644 --- a/rsconcept/frontend/src/pages/UserProfilePage/UserTabs.tsx +++ b/rsconcept/frontend/src/pages/UserProfilePage/UserTabs.tsx @@ -38,7 +38,7 @@ function UserTabs() {
diff --git a/rsconcept/frontend/src/utils/labels.ts b/rsconcept/frontend/src/utils/labels.ts index f35c461a..ff5b4ff6 100644 --- a/rsconcept/frontend/src/utils/labels.ts +++ b/rsconcept/frontend/src/utils/labels.ts @@ -136,50 +136,50 @@ export function getCstTypeShortcut(type: CstType) { } } -/** +/**
* Generates description for {@link TokenID}. */ export function describeToken(id: TokenID): string { // prettier-ignore switch (id) { - case TokenID.BOOLEAN: return 'Булеан [Alt + E / Shift + B]'; - case TokenID.DECART: return 'Декартово произведение [Alt + Shift + E / Shift + 8]'; - case TokenID.PUNCTUATION_PL: return 'Скобки вокруг выражения [Alt + Shift + 9 ]'; - case TokenID.PUNCTUATION_SL: return 'Скобки вокруг выражения [Alt + [ ]'; - case TokenID.QUANTOR_UNIVERSAL: return 'Квантор всеобщности [`]'; - case TokenID.QUANTOR_EXISTS: return 'Квантор существования [Shift + `]'; - case TokenID.LOGIC_NOT: return 'Отрицание [Alt + `]'; - case TokenID.LOGIC_AND: return 'Конъюнкция [Alt + 3 ~ Shift + 7]'; - case TokenID.LOGIC_OR: return 'Дизъюнкция [Alt + Shift + 3]'; - case TokenID.LOGIC_IMPLICATION: return 'Импликация [Alt + 4]'; - case TokenID.LOGIC_EQUIVALENT: return 'Эквивалентность [Alt + Shift + 4]'; - case TokenID.LIT_EMPTYSET: return 'Пустое множество [Alt + X]'; - case TokenID.LIT_WHOLE_NUMBERS: return 'Целые числа [Alt + Z]'; - case TokenID.EQUAL: return 'Равенство'; - case TokenID.NOTEQUAL: return 'Неравенство [Alt + Shift + `]'; - case TokenID.GREATER_OR_EQ: return 'Больше или равно [Alt + Shift + 7]'; - case TokenID.LESSER_OR_EQ: return 'Меньше или равно [Alt + Shift + 8]'; - case TokenID.SET_IN: return 'Быть элементом (принадлежит) [Alt + 1]'; - case TokenID.SET_NOT_IN: return 'Не принадлежит [Alt + Shift + 1]'; - case TokenID.SUBSET_OR_EQ: return 'Быть частью (нестрогое подмножество) [Alt + 2]'; - case TokenID.SUBSET: return 'Строгое подмножество [Alt + 7]'; - case TokenID.NOT_SUBSET: return 'Не подмножество [Alt + Shift + 2]'; - case TokenID.SET_INTERSECTION: return 'Пересечение [Alt + A]'; - case TokenID.SET_UNION: return 'Объединение [Alt + S]'; - case TokenID.SET_MINUS: return 'Разность множеств [Alt + 5]'; - case TokenID.SET_SYMMETRIC_MINUS: return 'Симметрическая разность [Alt + Shift + 5]'; - case TokenID.NT_DECLARATIVE_EXPR: return 'Декларативная форма определения терма [Alt + D]'; - case TokenID.NT_IMPERATIVE_EXPR: return 'Императивная форма определения терма [Alt + G]'; - case TokenID.NT_RECURSIVE_FULL: return 'Рекурсивная (цикличная) форма определения терма [Alt + T]'; - case TokenID.BIGPR: return 'Большая проекция [Alt + Q]'; - case TokenID.SMALLPR: return 'Малая проекция [Alt + W]'; - case TokenID.FILTER: return 'Фильтр [Alt + F]'; - case TokenID.REDUCE: return 'Множество-сумма [Alt + R]'; - case TokenID.CARD: return 'Мощность [Alt + C]'; - case TokenID.BOOL: return 'Синглетон [Alt + B]'; - case TokenID.DEBOOL: return 'Десинглетон [Alt + V]'; - case TokenID.PUNCTUATION_ASSIGN: return 'Присвоение (императивный синтаксис) [Alt + Shift + 6]'; - case TokenID.PUNCTUATION_ITERATE: return 'Перебор элементов множества (императивный синтаксис) [Alt + 6]'; + case TokenID.BOOLEAN: return prepareTooltip('Булеан', 'Alt + E / Shift + B'); + case TokenID.DECART: return prepareTooltip('Декартово произведение', 'Alt + Shift + E / Shift + 8'); + case TokenID.PUNCTUATION_PL: return prepareTooltip('Скобки () вокруг выражения', 'Alt + Shift + 9'); + case TokenID.PUNCTUATION_SL: return prepareTooltip('Скобки [] вокруг выражения', 'Alt + ['); + case TokenID.QUANTOR_UNIVERSAL: return prepareTooltip('Квантор всеобщности', '`'); + case TokenID.QUANTOR_EXISTS: return prepareTooltip('Квантор существования', 'Shift + `'); + case TokenID.LOGIC_NOT: return prepareTooltip('Отрицание', 'Alt + `'); + case TokenID.LOGIC_AND: return prepareTooltip('Конъюнкция', 'Alt + 3 ~ Shift + 7'); + case TokenID.LOGIC_OR: return prepareTooltip('Дизъюнкция', 'Alt + Shift + 3'); + case TokenID.LOGIC_IMPLICATION: return prepareTooltip('Импликация', 'Alt + 4'); + case TokenID.LOGIC_EQUIVALENT: return prepareTooltip('Эквивалентность', 'Alt + Shift + 4'); + case TokenID.LIT_EMPTYSET: return prepareTooltip('Пустое множество', 'Alt + X'); + case TokenID.LIT_WHOLE_NUMBERS: return prepareTooltip('Целые числа', 'Alt + Z'); + case TokenID.EQUAL: return prepareTooltip('Равенство'); + case TokenID.NOTEQUAL: return prepareTooltip('Неравенство', 'Alt + Shift + `'); + case TokenID.GREATER_OR_EQ: return prepareTooltip('Больше или равно', 'Alt + Shift + 7'); + case TokenID.LESSER_OR_EQ: return prepareTooltip('Меньше или равно', 'Alt + Shift + 8'); + case TokenID.SET_IN: return prepareTooltip('Быть элементом (принадлежит)', 'Alt + 1'); + case TokenID.SET_NOT_IN: return prepareTooltip('Не принадлежит', 'Alt + Shift + 1'); + case TokenID.SUBSET_OR_EQ: return prepareTooltip('Быть частью (нестрогое подмножество)', 'Alt + 2'); + case TokenID.SUBSET: return prepareTooltip('Строгое подмножество', 'Alt + 7'); + case TokenID.NOT_SUBSET: return prepareTooltip('Не подмножество', 'Alt + Shift + 2'); + case TokenID.SET_INTERSECTION: return prepareTooltip('Пересечение', 'Alt + A'); + case TokenID.SET_UNION: return prepareTooltip('Объединение', 'Alt + S'); + case TokenID.SET_MINUS: return prepareTooltip('Разность множеств', 'Alt + 5'); + case TokenID.SET_SYMMETRIC_MINUS: return prepareTooltip('Симметрическая разность', 'Alt + Shift + 5'); + case TokenID.NT_DECLARATIVE_EXPR: return prepareTooltip('Декларативное определение', 'Alt + D'); + case TokenID.NT_IMPERATIVE_EXPR: return prepareTooltip('Императивное определение', 'Alt + G'); + case TokenID.NT_RECURSIVE_FULL: return prepareTooltip('Рекурсивное определение (цикл)', 'Alt + T'); + case TokenID.BIGPR: return prepareTooltip('Большая проекция', 'Alt + Q'); + case TokenID.SMALLPR: return prepareTooltip('Малая проекция', 'Alt + W'); + case TokenID.FILTER: return prepareTooltip('Фильтр', 'Alt + F'); + case TokenID.REDUCE: return prepareTooltip('Множество-сумма', 'Alt + R'); + case TokenID.CARD: return prepareTooltip('Мощность', 'Alt + C'); + case TokenID.BOOL: return prepareTooltip('Синглетон', 'Alt + B'); + case TokenID.DEBOOL: return prepareTooltip('Десинглетон', 'Alt + V'); + case TokenID.PUNCTUATION_ASSIGN: return prepareTooltip('Присвоение', 'Alt + Shift + 6'); + case TokenID.PUNCTUATION_ITERATE: return prepareTooltip('Перебор элементов множества', 'Alt + 6'); } return `no description: ${id}`; } @@ -743,3 +743,10 @@ export function describeAccessMode(mode: UserAccessMode): string { return 'Режим редактирования администратором'; } } + +/** + * Generate HTML wrapper for control description including hotkey. + */ +export function prepareTooltip(text: string, hotkey?: string) { + return hotkey ? `[${hotkey}]
${text}` : text; +}