mirror of
https://github.com/responsively-org/responsively-app
synced 2024-11-10 14:54:12 +00:00
UI polish
This commit is contained in:
parent
d13edb4abf
commit
f6558e91e6
3 changed files with 93 additions and 122 deletions
|
@ -59,7 +59,7 @@ export function DropDown({ label, options, className }: Props) {
|
|||
option.onClick !== null ? (
|
||||
<button
|
||||
className={cx(
|
||||
'group flex w-full items-center rounded-md px-2 py-2',
|
||||
'group flex w-full items-center rounded-md px-2 py-2 text-sm',
|
||||
{ 'bg-slate-200 dark:bg-slate-800': active }
|
||||
)}
|
||||
type="button"
|
||||
|
@ -70,8 +70,7 @@ export function DropDown({ label, options, className }: Props) {
|
|||
) : (
|
||||
<div
|
||||
className={cx(
|
||||
'group mt-2 flex w-full items-center rounded-md px-2',
|
||||
{ 'bg-slate-200 dark:bg-slate-800': active }
|
||||
'group mt-2 flex w-full items-center rounded-md px-2'
|
||||
)}
|
||||
>
|
||||
{option.label}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Icon } from '@iconify/react';
|
||||
import cx from 'classnames';
|
||||
import { useState } from 'react';
|
||||
import { DropDown } from 'renderer/components/DropDown';
|
||||
|
||||
|
@ -18,7 +19,46 @@ interface Props {
|
|||
webview: Electron.WebviewTag | null;
|
||||
}
|
||||
|
||||
export const AccessibilityTools = ({ webview }: Props) => {
|
||||
const MenuItemLabel = ({
|
||||
label,
|
||||
isActive,
|
||||
}: {
|
||||
label: string;
|
||||
isActive: boolean;
|
||||
}) => {
|
||||
return (
|
||||
<div className="justify-normal flex w-full flex-shrink-0 items-center gap-1 whitespace-nowrap">
|
||||
<Icon
|
||||
icon="ic:round-check"
|
||||
className={cx('opacity-0', {
|
||||
'opacity-100': isActive,
|
||||
})}
|
||||
/>
|
||||
<span
|
||||
className={cx({
|
||||
'font-semibold text-black dark:text-white': isActive,
|
||||
})}
|
||||
>
|
||||
{label}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const MenuItemHeader = ({ label }: { label: string }) => {
|
||||
return (
|
||||
<div className="relative flex w-full min-w-44 items-center justify-between gap-1 whitespace-nowrap">
|
||||
<div className="absolute inset-0 flex items-center" aria-hidden="true">
|
||||
<div className="w-full border-t border-gray-300 dark:border-gray-600" />
|
||||
</div>
|
||||
<span className="mxl-1 z-10 flex-shrink-0 bg-slate-100 pr-2 dark:bg-slate-900">
|
||||
{label}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const ColorBlindnessTools = ({ webview }: Props) => {
|
||||
const [injectCss, setInjectCss] = useState<InjectedCss>();
|
||||
|
||||
const applyCss = async (
|
||||
|
@ -60,6 +100,17 @@ export const AccessibilityTools = ({ webview }: Props) => {
|
|||
}
|
||||
};
|
||||
|
||||
const clearSimulation = async () => {
|
||||
if (webview === null) {
|
||||
return;
|
||||
}
|
||||
if (injectCss === undefined) {
|
||||
return;
|
||||
}
|
||||
await webview.removeInsertedCSS(injectCss.key);
|
||||
setInjectCss(undefined);
|
||||
};
|
||||
|
||||
const applyColorDeficiency = async (colorDeficiency: string) => {
|
||||
const xsltPath =
|
||||
'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgdmVyc2lvbj0iMS4xIj4KICA8ZGVmcz4KICAgIDxmaWx0ZXIgaWQ9InByb3Rhbm9waWEiPgogICAgICA8ZmVDb2xvck1hdHJpeAogICAgICAgIGluPSJTb3VyY2VHcmFwaGljIgogICAgICAgIHR5cGU9Im1hdHJpeCIKICAgICAgICB2YWx1ZXM9IjAuNTY3LCAwLjQzMywgMCwgICAgIDAsIDAKICAgICAgICAgICAgICAgIDAuNTU4LCAwLjQ0MiwgMCwgICAgIDAsIDAKICAgICAgICAgICAgICAgIDAsICAgICAwLjI0MiwgMC43NTgsIDAsIDAKICAgICAgICAgICAgICAgIDAsICAgICAwLCAgICAgMCwgICAgIDEsIDAiLz4KICAgIDwvZmlsdGVyPgogICAgPGZpbHRlciBpZD0icHJvdGFub21hbHkiPgogICAgICA8ZmVDb2xvck1hdHJpeAogICAgICAgIGluPSJTb3VyY2VHcmFwaGljIgogICAgICAgIHR5cGU9Im1hdHJpeCIKICAgICAgICB2YWx1ZXM9IjAuODE3LCAwLjE4MywgMCwgICAgIDAsIDAKICAgICAgICAgICAgICAgIDAuMzMzLCAwLjY2NywgMCwgICAgIDAsIDAKICAgICAgICAgICAgICAgIDAsICAgICAwLjEyNSwgMC44NzUsIDAsIDAKICAgICAgICAgICAgICAgIDAsICAgICAwLCAgICAgMCwgICAgIDEsIDAiLz4KICAgIDwvZmlsdGVyPgogICAgPGZpbHRlciBpZD0iZGV1dGVyYW5vcGlhIj4KICAgICAgPGZlQ29sb3JNYXRyaXgKICAgICAgICBpbj0iU291cmNlR3JhcGhpYyIKICAgICAgICB0eXBlPSJtYXRyaXgiCiAgICAgICAgdmFsdWVzPSIwLjYyNSwgMC4zNzUsIDAsICAgMCwgMAogICAgICAgICAgICAgICAgMC43LCAgIDAuMywgICAwLCAgIDAsIDAKICAgICAgICAgICAgICAgIDAsICAgICAwLjMsICAgMC43LCAwLCAwCiAgICAgICAgICAgICAgICAwLCAgICAgMCwgICAgIDAsICAgMSwgMCIvPgogICAgPC9maWx0ZXI+CiAgICA8ZmlsdGVyIGlkPSJkZXV0ZXJhbm9tYWx5Ij4KICAgICAgPGZlQ29sb3JNYXRyaXgKICAgICAgICBpbj0iU291cmNlR3JhcGhpYyIKICAgICAgICB0eXBlPSJtYXRyaXgiCiAgICAgICAgdmFsdWVzPSIwLjgsICAgMC4yLCAgIDAsICAgICAwLCAwCiAgICAgICAgICAgICAgICAwLjI1OCwgMC43NDIsIDAsICAgICAwLCAwCiAgICAgICAgICAgICAgICAwLCAgICAgMC4xNDIsIDAuODU4LCAwLCAwCiAgICAgICAgICAgICAgICAwLCAgICAgMCwgICAgIDAsICAgICAxLCAwIi8+CiAgICA8L2ZpbHRlcj4KICAgIDxmaWx0ZXIgaWQ9InRyaXRhbm9waWEiPgogICAgICA8ZmVDb2xvck1hdHJpeAogICAgICAgIGluPSJTb3VyY2VHcmFwaGljIgogICAgICAgIHR5cGU9Im1hdHJpeCIKICAgICAgICB2YWx1ZXM9IjAuOTUsIDAuMDUsICAwLCAgICAgMCwgMAogICAgICAgICAgICAgICAgMCwgICAgMC40MzMsIDAuNTY3LCAwLCAwCiAgICAgICAgICAgICAgICAwLCAgICAwLjQ3NSwgMC41MjUsIDAsIDAKICAgICAgICAgICAgICAgIDAsICAgIDAsICAgICAwLCAgICAgMSwgMCIvPgogICAgPC9maWx0ZXI+CiAgICA8ZmlsdGVyIGlkPSJ0cml0YW5vbWFseSI+CiAgICAgIDxmZUNvbG9yTWF0cml4CiAgICAgICAgaW49IlNvdXJjZUdyYXBoaWMiCiAgICAgICAgdHlwZT0ibWF0cml4IgogICAgICAgIHZhbHVlcz0iMC45NjcsIDAuMDMzLCAwLCAgICAgMCwgMAogICAgICAgICAgICAgICAgMCwgICAgIDAuNzMzLCAwLjI2NywgMCwgMAogICAgICAgICAgICAgICAgMCwgICAgIDAuMTgzLCAwLjgxNywgMCwgMAogICAgICAgICAgICAgICAgMCwgICAgIDAsICAgICAwLCAgICAgMSwgMCIvPgogICAgPC9maWx0ZXI+CiAgICA8ZmlsdGVyIGlkPSJhY2hyb21hdG9wc2lhIj4KICAgICAgPGZlQ29sb3JNYXRyaXgKICAgICAgICBpbj0iU291cmNlR3JhcGhpYyIKICAgICAgICB0eXBlPSJtYXRyaXgiCiAgICAgICAgdmFsdWVzPSIwLjI5OSwgMC41ODcsIDAuMTE0LCAwLCAwCiAgICAgICAgICAgICAgICAwLjI5OSwgMC41ODcsIDAuMTE0LCAwLCAwCiAgICAgICAgICAgICAgICAwLjI5OSwgMC41ODcsIDAuMTE0LCAwLCAwCiAgICAgICAgICAgICAgICAwLCAgICAgMCwgICAgIDAsICAgICAxLCAwIi8+CiAgICA8L2ZpbHRlcj4KICAgIDxmaWx0ZXIgaWQ9ImFjaHJvbWF0b21hbHkiPgogICAgICA8ZmVDb2xvck1hdHJpeAogICAgICAgIGluPSJTb3VyY2VHcmFwaGljIgogICAgICAgIHR5cGU9Im1hdHJpeCIKICAgICAgICB2YWx1ZXM9IjAuNjE4LCAwLjMyMCwgMC4wNjIsIDAsIDAKICAgICAgICAgICAgICAgIDAuMTYzLCAwLjc3NSwgMC4wNjIsIDAsIDAKICAgICAgICAgICAgICAgIDAuMTYzLCAwLjMyMCwgMC41MTYsIDAsIDAKICAgICAgICAgICAgICAgIDAsICAgICAwLCAgICAgMCwgICAgIDEsIDAiLz4KICAgIDwvZmlsdGVyPgogIDwvZGVmcz4KPC9zdmc+Cg==';
|
||||
|
@ -137,52 +188,37 @@ export const AccessibilityTools = ({ webview }: Props) => {
|
|||
|
||||
return (
|
||||
<DropDown
|
||||
className="text-xs"
|
||||
label={<Icon icon="codicon:debug-line-by-line" fontSize={18} />}
|
||||
className={cx('rounded-lg text-xs', {
|
||||
'bg-slate-400/60': injectCss?.name != null,
|
||||
})}
|
||||
label={<Icon icon="bx:low-vision" fontSize={18} />}
|
||||
options={[
|
||||
{
|
||||
label: (
|
||||
<div className="flex w-full flex-shrink-0 items-center justify-between gap-12 whitespace-nowrap">
|
||||
<span className="font-bold">A11y Tools</span>
|
||||
</div>
|
||||
),
|
||||
label: <MenuItemHeader label="No deficiency" />,
|
||||
onClick: null,
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<div className="flex w-full flex-shrink-0 items-center justify-between gap-12 whitespace-nowrap">
|
||||
<span>Visual deficiency</span>
|
||||
</div>
|
||||
<MenuItemLabel
|
||||
label="Normal Vision"
|
||||
isActive={injectCss?.name == null}
|
||||
/>
|
||||
),
|
||||
onClick: null,
|
||||
onClick: () => {
|
||||
clearSimulation();
|
||||
},
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<div className="flex w-full flex-shrink-0 items-center justify-start gap-12 whitespace-nowrap">
|
||||
<span className="ml-1 font-semibold">Red-green deficiency</span>
|
||||
</div>
|
||||
),
|
||||
label: <MenuItemHeader label="Red-green deficiency" />,
|
||||
onClick: null,
|
||||
},
|
||||
...redgreen.map((x: string) => {
|
||||
return {
|
||||
label: (
|
||||
<div className="justify-normal flex w-full flex-shrink-0 items-center gap-1 whitespace-nowrap">
|
||||
{injectCss?.name === x.toLowerCase() ? (
|
||||
<Icon icon="ic:round-check" />
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
<span
|
||||
className={`ml-2 ${
|
||||
injectCss?.name === x.toLowerCase()
|
||||
? 'font-semibold text-black'
|
||||
: ''
|
||||
}`}
|
||||
>
|
||||
{x}
|
||||
</span>
|
||||
</div>
|
||||
<MenuItemLabel
|
||||
label={x}
|
||||
isActive={injectCss?.name === x.toLowerCase()}
|
||||
/>
|
||||
),
|
||||
onClick: () => {
|
||||
applyColorDeficiency(x.toLowerCase());
|
||||
|
@ -190,32 +226,16 @@ export const AccessibilityTools = ({ webview }: Props) => {
|
|||
};
|
||||
}),
|
||||
{
|
||||
label: (
|
||||
<div className="flex w-full flex-shrink-0 items-center justify-between gap-12 whitespace-nowrap">
|
||||
<span className="ml-1 font-semibold">Blue-yellow deficiency</span>
|
||||
</div>
|
||||
),
|
||||
label: <MenuItemHeader label="Blue-yellow deficiency" />,
|
||||
onClick: null,
|
||||
},
|
||||
...blueyellow.map((x: string) => {
|
||||
return {
|
||||
label: (
|
||||
<div className="justify-normal flex w-full flex-shrink-0 items-center gap-1 whitespace-nowrap">
|
||||
{injectCss?.name === x.toLowerCase() ? (
|
||||
<Icon icon="ic:round-check" />
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
<span
|
||||
className={`ml-2 ${
|
||||
injectCss?.name === x.toLowerCase()
|
||||
? 'font-semibold text-black'
|
||||
: ''
|
||||
}`}
|
||||
>
|
||||
{x}
|
||||
</span>
|
||||
</div>
|
||||
<MenuItemLabel
|
||||
label={x}
|
||||
isActive={injectCss?.name === x.toLowerCase()}
|
||||
/>
|
||||
),
|
||||
onClick: () => {
|
||||
applyColorDeficiency(x.toLowerCase());
|
||||
|
@ -223,32 +243,16 @@ export const AccessibilityTools = ({ webview }: Props) => {
|
|||
};
|
||||
}),
|
||||
{
|
||||
label: (
|
||||
<div className="flex w-full flex-shrink-0 items-center justify-between gap-1 whitespace-nowrap">
|
||||
<span className="ml-1 font-semibold">Full color deficiency</span>
|
||||
</div>
|
||||
),
|
||||
label: <MenuItemHeader label="Full color deficiency" />,
|
||||
onClick: null,
|
||||
},
|
||||
...full.map((x: string) => {
|
||||
return {
|
||||
label: (
|
||||
<div className="justify-normal flex w-full flex-shrink-0 items-center gap-1 whitespace-nowrap">
|
||||
{injectCss?.name === x.toLowerCase() ? (
|
||||
<Icon icon="ic:round-check" />
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
<span
|
||||
className={`ml-2 ${
|
||||
injectCss?.name === x.toLowerCase()
|
||||
? 'font-semibold text-black'
|
||||
: ''
|
||||
}`}
|
||||
>
|
||||
{x}
|
||||
</span>
|
||||
</div>
|
||||
<MenuItemLabel
|
||||
label={x}
|
||||
isActive={injectCss?.name === x.toLowerCase()}
|
||||
/>
|
||||
),
|
||||
onClick: () => {
|
||||
applyColorDeficiency(x.toLowerCase());
|
||||
|
@ -256,32 +260,16 @@ export const AccessibilityTools = ({ webview }: Props) => {
|
|||
};
|
||||
}),
|
||||
{
|
||||
label: (
|
||||
<div className="flex w-full flex-shrink-0 items-center justify-between gap-1 whitespace-nowrap">
|
||||
<span className="ml-1 font-semibold">Visual impairment</span>
|
||||
</div>
|
||||
),
|
||||
label: <MenuItemHeader label="Visual impairment" />,
|
||||
onClick: null,
|
||||
},
|
||||
...visualimpairments.map((x: string) => {
|
||||
return {
|
||||
label: (
|
||||
<div className="justify-normal flex w-full flex-shrink-0 items-center gap-1 whitespace-nowrap">
|
||||
{injectCss?.name === x.toLowerCase() ? (
|
||||
<Icon icon="ic:round-check" />
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
<span
|
||||
className={`ml-2 ${
|
||||
injectCss?.name === x.toLowerCase()
|
||||
? 'font-semibold text-black'
|
||||
: ''
|
||||
}`}
|
||||
>
|
||||
{x}
|
||||
</span>
|
||||
</div>
|
||||
<MenuItemLabel
|
||||
label={x}
|
||||
isActive={injectCss?.name === x.toLowerCase()}
|
||||
/>
|
||||
),
|
||||
onClick: () => {
|
||||
applyVisualImpairment(x.toLowerCase());
|
||||
|
@ -289,32 +277,16 @@ export const AccessibilityTools = ({ webview }: Props) => {
|
|||
};
|
||||
}),
|
||||
{
|
||||
label: (
|
||||
<div className="flex w-full flex-shrink-0 items-center justify-between gap-1 whitespace-nowrap">
|
||||
<span className="ml-1 font-semibold">Temporary impairment</span>
|
||||
</div>
|
||||
),
|
||||
label: <MenuItemHeader label="Temporary impairment" />,
|
||||
onClick: null,
|
||||
},
|
||||
...sunlight.map((x: string) => {
|
||||
return {
|
||||
label: (
|
||||
<div className="justify-normal flex w-full flex-shrink-0 items-center gap-1 whitespace-nowrap">
|
||||
{injectCss?.name === x.toLowerCase() ? (
|
||||
<Icon icon="ic:round-check" />
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
<span
|
||||
className={`ml-2 ${
|
||||
injectCss?.name === x.toLowerCase()
|
||||
? 'font-semibold text-black'
|
||||
: ''
|
||||
}`}
|
||||
>
|
||||
{x}
|
||||
</span>
|
||||
</div>
|
||||
<MenuItemLabel
|
||||
label={x}
|
||||
isActive={injectCss?.name === x.toLowerCase()}
|
||||
/>
|
||||
),
|
||||
onClick: () => {
|
||||
applySunlight(x.toLowerCase());
|
|
@ -8,7 +8,7 @@ import WebPage from 'main/screenshot/webpage';
|
|||
|
||||
import screenshotSfx from 'renderer/assets/sfx/screenshot.mp3';
|
||||
import { updateWebViewHeightAndScale } from 'common/webViewUtils';
|
||||
import { AccessibilityTools } from './AccessibilityTools';
|
||||
import { ColorBlindnessTools } from './ColorBlindnessTools';
|
||||
|
||||
interface Props {
|
||||
webview: Electron.WebviewTag | null;
|
||||
|
@ -178,7 +178,7 @@ const Toolbar = ({
|
|||
}
|
||||
/>
|
||||
</Button>
|
||||
<AccessibilityTools webview={webview} />
|
||||
<ColorBlindnessTools webview={webview} />
|
||||
</div>
|
||||
<Button
|
||||
onClick={() => onIndividualLayoutHandler(device)}
|
||||
|
|
Loading…
Reference in a new issue