settings: change tooltips to help buttons

This is more friendly for touch screen users.
This commit is contained in:
David Lechner
2022-05-14 11:09:41 -05:00
parent fb681e06ec
commit 728e7c3b26
4 changed files with 121 additions and 78 deletions
+78 -56
View File
@@ -7,25 +7,26 @@ import {
ButtonGroup,
ControlGroup,
FormGroup,
IRef,
Icon,
InputGroup,
Intent,
Label,
Switch,
} from '@blueprintjs/core';
import { Tooltip2 } from '@blueprintjs/popover2';
import { Classes as Classes2, Popover2 } from '@blueprintjs/popover2';
import { useI18n } from '@shopify/react-i18n';
import React, { useState } from 'react';
import React, { useCallback, useState } from 'react';
import { useDispatch } from 'react-redux';
import { useTernaryDarkMode } from 'usehooks-ts';
import AboutDialog from '../about/AboutDialog';
import { appCheckForUpdate, appReload, appShowInstallPrompt } from '../app/actions';
import {
appName,
pybricksBugReportsUrl,
pybricksGitterUrl,
pybricksProjectsUrl,
pybricksSupportUrl,
tooltipDelay,
} from '../app/constants';
import { pseudolocalize } from '../i18n';
import { useSelector } from '../reducers';
@@ -39,6 +40,43 @@ import {
import { I18nId } from './i18n';
import './settings.scss';
type HelpButtonProps = {
label: string;
content: string | JSX.Element;
};
const HelpButton: React.VoidFunctionComponent<HelpButtonProps> = ({
label,
content,
}) => {
const handleOpening = useCallback((node: HTMLElement) => {
// role must match aria-haspopup
node.setAttribute('role', 'dialog');
}, []);
return (
<Popover2
onOpening={handleOpening}
placement="right"
shouldReturnFocusOnClose
popoverClassName={Classes2.POPOVER2_CONTENT_SIZING}
content={content}
renderTarget={({ isOpen, ref, ...targetProps }) => (
<Button
aria-label={label}
aria-expanded={isOpen}
minimal
icon="help"
elementRef={ref as IRef<HTMLButtonElement>}
{...targetProps}
// override targetProps
aria-haspopup="dialog"
/>
)}
/>
);
};
const Settings: React.VoidFunctionComponent = () => {
const { isSettingShowDocsEnabled, setIsSettingShowDocsEnabled } =
useSettingIsShowDocsEnabled();
@@ -65,7 +103,7 @@ const Settings: React.VoidFunctionComponent = () => {
const [i18n] = useI18n();
return (
<div aria-label={i18n.translate(I18nId.Title)}>
<div className="pb-settings" aria-label={i18n.translate(I18nId.Title)}>
<FormGroup
label={i18n.translate(I18nId.AppearanceTitle)}
helperText={i18n.translate(I18nId.AppearanceZoomHelp, {
@@ -73,13 +111,7 @@ const Settings: React.VoidFunctionComponent = () => {
out: <span>{isMacOS() ? 'Cmd' : 'Ctrl'}--</span>,
})}
>
<Tooltip2
content={i18n.translate(I18nId.AppearanceDocumentationTooltip)}
rootBoundary="document"
placement="left"
targetTagName="div"
hoverOpenDelay={tooltipDelay}
>
<ControlGroup>
<Switch
label={i18n.translate(I18nId.AppearanceDocumentationLabel)}
checked={isSettingShowDocsEnabled}
@@ -89,14 +121,14 @@ const Settings: React.VoidFunctionComponent = () => {
)
}
/>
</Tooltip2>
<Tooltip2
content={i18n.translate(I18nId.AppearanceDarkModeTooltip)}
rootBoundary="document"
placement="left"
targetTagName="div"
hoverOpenDelay={tooltipDelay}
>
<HelpButton
label={i18n.translate(I18nId.AppearanceDocumentationHelpLabel)}
content={i18n.translate(
I18nId.AppearanceDocumentationHelpContent,
)}
/>
</ControlGroup>
<ControlGroup>
<Switch
label={i18n.translate(I18nId.AppearanceDarkModeLabel)}
checked={isDarkMode}
@@ -108,16 +140,14 @@ const Settings: React.VoidFunctionComponent = () => {
)
}
/>
</Tooltip2>
<HelpButton
label={i18n.translate(I18nId.AppearanceDarkModeHelpLabel)}
content={i18n.translate(I18nId.AppearanceDarkModeHelpContent)}
/>
</ControlGroup>
</FormGroup>
<FormGroup label={i18n.translate(I18nId.FirmwareTitle)}>
<Tooltip2
content={i18n.translate(I18nId.FirmwareCurrentProgramTooltip)}
rootBoundary="document"
placement="left"
targetTagName="div"
hoverOpenDelay={tooltipDelay}
>
<ControlGroup>
<Switch
label={i18n.translate(I18nId.FirmwareCurrentProgramLabel)}
checked={isFlashCurrentProgramEnabled}
@@ -127,47 +157,39 @@ const Settings: React.VoidFunctionComponent = () => {
)
}
/>
</Tooltip2>
<ControlGroup vertical={true}>
<Tooltip2
content={i18n.translate(I18nId.FirmwareHubNameTooltip)}
rootBoundary="document"
placement="left"
targetTagName="div"
hoverOpenDelay={tooltipDelay}
openOnTargetFocus={false}
>
<Label htmlFor="hub-name-input">
{i18n.translate(I18nId.FirmwareHubNameLabel)}
</Label>
</Tooltip2>
<HelpButton
label={i18n.translate(I18nId.FirmwareCurrentProgramHelpLabel)}
content={i18n.translate(
I18nId.FirmwareCurrentProgramHelpContent,
{ appName },
)}
/>
</ControlGroup>
<Label htmlFor="hub-name-input">
{i18n.translate(I18nId.FirmwareHubNameLabel)}
</Label>
<ControlGroup>
<InputGroup
id="hub-name-input"
value={hubName}
onChange={(e) => setHubName(e.currentTarget.value)}
onMouseOver={(e) => e.preventDefault()}
className="pb-hub-name-input"
intent={isHubNameValid ? Intent.NONE : Intent.DANGER}
placeholder="Pybricks Hub"
rightElement={
isHubNameValid ? undefined : (
<Tooltip2
content={i18n.translate(
I18nId.FirmwareHubNameErrorTooltip,
)}
rootBoundary="document"
placement="bottom"
targetTagName="div"
>
<Icon
icon="error"
intent={Intent.DANGER}
itemType="div"
/>
</Tooltip2>
<Icon
icon="error"
intent={Intent.DANGER}
itemType="div"
/>
)
}
/>
<HelpButton
label={i18n.translate(I18nId.FirmwareHubNameHelpLabel)}
content={i18n.translate(I18nId.FirmwareHubNameHelpContent)}
/>
</ControlGroup>
</FormGroup>
<FormGroup label={i18n.translate(I18nId.HelpTitle)}>
+12 -8
View File
@@ -7,16 +7,20 @@ export enum I18nId {
Title = 'title',
AppearanceTitle = 'appearance.title',
AppearanceDocumentationLabel = 'appearance.documentation.label',
AppearanceDocumentationTooltip = 'appearance.documentation.tooltip',
AppearanceDarkModeLabel = 'appearance.dark-mode.label',
AppearanceDarkModeTooltip = 'appearance.dark-mode.tooltip',
AppearanceDocumentationHelpLabel = 'appearance.documentation.help.label',
AppearanceDocumentationHelpContent = 'appearance.documentation.help.content',
AppearanceDarkModeLabel = 'appearance.darkMode.label',
AppearanceDarkModeHelpLabel = 'appearance.darkMode.help.label',
AppearanceDarkModeHelpContent = 'appearance.darkMode.help.content',
AppearanceZoomHelp = 'appearance.zoom.help',
FirmwareTitle = 'firmware.title',
FirmwareCurrentProgramLabel = 'firmware.flash-current-program.label',
FirmwareCurrentProgramTooltip = 'firmware.flash-current-program.tooltip',
FirmwareHubNameLabel = 'firmware.hub-name.label',
FirmwareHubNameTooltip = 'firmware.hub-name.tooltip',
FirmwareHubNameErrorTooltip = 'firmware.hub-name.error.tooltip',
FirmwareCurrentProgramLabel = 'firmware.flashCurrentProgram.label',
FirmwareCurrentProgramHelpLabel = 'firmware.flashCurrentProgram.help.label',
FirmwareCurrentProgramHelpContent = 'firmware.flashCurrentProgram.help.content',
FirmwareHubNameLabel = 'firmware.hubName.label',
FirmwareHubNameHelpLabel = 'firmware.hubName.help.label',
FirmwareHubNameHelpContent = 'firmware.hubName.help.content',
FirmwareHubNameError = 'firmware.hubName.error',
HelpTitle = 'help.title',
HelpProjectsLabel = 'help.projects.label',
HelpSupportLabel = 'help.support.label',
+10 -3
View File
@@ -5,7 +5,14 @@
@use '@blueprintjs/core/lib/scss/variables' as bp;
.pb-hub-name-input .#{bp.$ns}-input {
width: 200px;
margin-left: 8px;
.pb-settings {
.#{bp.$ns}-control-group {
.#{bp.$ns}-button {
margin-bottom: 3px;
}
.#{bp.$ns}-input-group {
width: bp.$pt-grid-size * 20;
}
}
}
+21 -11
View File
@@ -4,11 +4,17 @@
"title": "Appearance",
"documentation": {
"label": "Documentation",
"tooltip": "Show or hide the documentation pane."
"help": {
"label": "Show help for documentation toggle.",
"content": "Enable to show the documentation and disable to hide the documentation."
}
},
"dark-mode": {
"darkMode": {
"label": "Dark mode",
"tooltip": "Enable or disable dark mode."
"help": {
"label": "Show help for dark mode toggle.",
"content": "Enable to set theme to dark mode and disable to set theme to light mode."
}
},
"zoom": {
"help": "Use {in} and {out} to zoom."
@@ -16,16 +22,20 @@
},
"firmware": {
"title": "Firmware",
"flash-current-program": {
"flashCurrentProgram": {
"label": "Include current program",
"tooltip": "Select to include your program when installing the firmware."
},
"hub-name": {
"label": "Hub name",
"tooltip": "Hub name to use when flashing the firmware.",
"error": {
"tooltip": "The name is too long."
"help": {
"label": "Show help for include current program toggle.",
"content": "Enable to include your program when flashing the firmware or disable to use the default program. Flashing your program along with the firmware will allow you to run your program without being connected to {appName}"
}
},
"hubName": {
"label": "Hub name",
"help": {
"label": "Show help on hub name input",
"content": "Enter a name here to customize the hub name when flashing the firmware. This name will be used in the Bluetooth advertising data and can be used to identify the hub when connecting."
},
"error": "The name is too long."
}
},
"help": {