Skip to content

Commit

Permalink
better tooltips
Browse files Browse the repository at this point in the history
  • Loading branch information
thomasheyenbrock committed Aug 4, 2022
1 parent d0ce3f2 commit 74820ca
Show file tree
Hide file tree
Showing 21 changed files with 327 additions and 212 deletions.
2 changes: 1 addition & 1 deletion .changeset/five-pillows-fail.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
---

Add new components:
- UI components (`Button`, `ButtonGroup`, `Dialog`, `Menu`, `Spinner`, `Tab`, `Tabs`, `UnStyledButton` and lots of icon components)
- UI components (`Button`, `ButtonGroup`, `Dialog`, `Menu`, `Spinner`, `Tab`, `Tabs`, `Tooltip`, `UnStyledButton` and lots of icon components)
- Editor components (`QueryEditor`, `VariableEditor`, `HeaderEditor` and `ResponseEditor`)
- Toolbar components (`ExecuteButton`, `ToolbarButton`, `ToolbarMenu` and `ToolbarSelect`)
- Docs components (`Argument`, `DefaultValue`, `DeprecationReason`, `Directive`, `DocExplorer`, `ExplorerSection`, `FieldDocumentation`, `FieldLink`, `SchemaDocumentation`, `Search`, `TypeDocumentation` and `TypeLink`)
Expand Down
1 change: 1 addition & 0 deletions packages/graphiql-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"@reach/dialog": "^0.17.0",
"@reach/listbox": "^0.17.0",
"@reach/menu-button": "^0.17.0",
"@reach/tooltip": "^0.17.0",
"@reach/visually-hidden": "^0.17.0",
"codemirror": "^5.65.3",
"codemirror-graphql": "^2.0.0-next.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,10 @@ describe('QueryHistoryItem', () => {
});

it('renders label input if the edit label button is clicked', () => {
const { container, getByTitle } = render(
const { container, getByLabelText } = render(
<QueryHistoryItemWithContext {...getMockProps()} />,
);
fireEvent.click(getByTitle('Edit label'));
fireEvent.click(getByLabelText('Edit label'));
expect(container.querySelectorAll('li.editable').length).toBe(1);
expect(container.querySelectorAll('input').length).toBe(1);
expect(
Expand Down
49 changes: 30 additions & 19 deletions packages/graphiql-react/src/history/components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Fragment, useEffect, useRef, useState } from 'react';

import { useEditorContext } from '../editor';
import { CloseIcon, PenIcon, StarFilledIcon, StarIcon } from '../icons';
import { UnStyledButton } from '../ui';
import { Tooltip, UnStyledButton } from '../ui';
import { useHistoryContext } from './context';

import './style.css';
Expand Down Expand Up @@ -112,24 +112,35 @@ export function HistoryItem(props: QueryHistoryItemProps) {
}}>
{displayName}
</UnStyledButton>
<UnStyledButton
className="graphiql-history-item-action"
title="Edit label"
onClick={e => {
e.stopPropagation();
setIsEditable(true);
}}>
<PenIcon />
</UnStyledButton>
<UnStyledButton
className="graphiql-history-item-action"
onClick={e => {
e.stopPropagation();
toggleFavorite(props.item);
}}
title={props.item.favorite ? 'Remove favorite' : 'Add favorite'}>
{props.item.favorite ? <StarFilledIcon /> : <StarIcon />}
</UnStyledButton>
<Tooltip label="Edit label">
<UnStyledButton
className="graphiql-history-item-action"
onClick={e => {
e.stopPropagation();
setIsEditable(true);
}}
aria-label="Edit label">
<PenIcon aria-hidden="true" />
</UnStyledButton>
</Tooltip>
<Tooltip
label={props.item.favorite ? 'Remove favorite' : 'Add favorite'}>
<UnStyledButton
className="graphiql-history-item-action"
onClick={e => {
e.stopPropagation();
toggleFavorite(props.item);
}}
aria-label={
props.item.favorite ? 'Remove favorite' : 'Add favorite'
}>
{props.item.favorite ? (
<StarFilledIcon aria-hidden="true" />
) : (
<StarIcon aria-hidden="true" />
)}
</UnStyledButton>
</Tooltip>
</>
)}
</li>
Expand Down
1 change: 0 additions & 1 deletion packages/graphiql-react/src/history/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ button.graphiql-history-item-action {

& > svg {
height: 14px;
pointer-events: none;
width: 14px;
}
}
Expand Down
4 changes: 0 additions & 4 deletions packages/graphiql-react/src/toolbar/button.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,4 @@ button.graphiql-toolbar-button {
&.error {
background: var(--color-red-background);
}

& > svg {
pointer-events: none;
}
}
59 changes: 32 additions & 27 deletions packages/graphiql-react/src/toolbar/button.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,44 @@
import { forwardRef, useState } from 'react';

import { UnStyledButton } from '../ui';
import { Tooltip, UnStyledButton } from '../ui';
import { compose } from '../utility/compose';

import './button.css';

type ToolbarButtonProps = {
label: string;
};

export const ToolbarButton = forwardRef<
HTMLButtonElement,
JSX.IntrinsicElements['button']
>((props, ref) => {
ToolbarButtonProps & JSX.IntrinsicElements['button']
>(({ label, ...props }, ref) => {
const [error, setError] = useState<Error | null>(null);
return (
<UnStyledButton
{...props}
ref={ref}
className={compose(
'graphiql-toolbar-button',
error ? 'error' : '',
props.className,
)}
onClick={event => {
try {
props.onClick?.(event);
setError(null);
} catch (err) {
setError(
err instanceof Error
? err
: new Error(`Toolbar button click failed: ${err}`),
);
}
}}
title={error ? error.message : props.title}
aria-invalid={error ? 'true' : props['aria-invalid']}
/>
<Tooltip label={label}>
<UnStyledButton
{...props}
ref={ref}
className={compose(
'graphiql-toolbar-button',
error ? 'error' : '',
props.className,
)}
onClick={event => {
try {
props.onClick?.(event);
setError(null);
} catch (err) {
setError(
err instanceof Error
? err
: new Error(`Toolbar button click failed: ${err}`),
);
}
}}
aria-label={error ? error.message : label}
aria-invalid={error ? 'true' : props['aria-invalid']}
/>
</Tooltip>
);
});
ToolbarButton.displayName = 'ToolbarButton';
1 change: 0 additions & 1 deletion packages/graphiql-react/src/toolbar/execute.css
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ button.graphiql-execute-button {
display: block;
height: var(--px-16);
margin: auto;
pointer-events: none;
width: var(--px-16);
}
}
10 changes: 7 additions & 3 deletions packages/graphiql-react/src/toolbar/execute.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEditorContext } from '../editor';
import { useExecutionContext } from '../execution';
import { PlayIcon, StopIcon } from '../icons';
import { Menu } from '../ui';
import { Menu, Tooltip } from '../ui';

import './execute.css';

Expand All @@ -19,16 +19,20 @@ export function ExecuteButton() {
const operations = queryEditor?.operations || [];
const hasOptions = operations.length > 1;

const label = 'Execute Query (Ctrl-Enter)';
const buttonProps = {
type: 'button' as const,
className: 'graphiql-execute-button',
title: 'Execute Query (Ctrl-Enter)',
children: isRunning ? <StopIcon /> : <PlayIcon />,
'aria-label': label,
};

return hasOptions ? (
<Menu>
<Menu.Button {...buttonProps} />
<Tooltip label="Execute Query (Ctrl-Enter)">
<Menu.Button {...buttonProps} />
</Tooltip>

<Menu.List>
{operations.map((operation, i) => {
const opName = operation.name
Expand Down
27 changes: 17 additions & 10 deletions packages/graphiql-react/src/toolbar/listbox.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
import { ComponentProps, forwardRef, ReactNode } from 'react';
import { Listbox } from '../ui';
import { Listbox, Tooltip } from '../ui';
import { createComponentGroup } from '../utility/component-group';
import { compose } from '../utility/compose';

import './listbox.css';

type ToolbarListboxProps = {
button: ReactNode;
label: string;
};

const ToolbarListboxRoot = forwardRef<
HTMLDivElement,
ToolbarListboxProps & ComponentProps<typeof Listbox.Input>
>(({ button, children, ...props }, ref) => (
<Listbox.Input
{...props}
ref={ref}
className={compose('graphiql-toolbar-listbox', props.className)}>
<Listbox.Button>{button}</Listbox.Button>
<Listbox.Popover>{children}</Listbox.Popover>
</Listbox.Input>
));
>(({ button, children, label, ...props }, ref) => {
const labelWithValue = `${label}${props.value ? `: ${props.value}` : ''}`;
return (
<Listbox.Input
{...props}
ref={ref}
className={compose('graphiql-toolbar-listbox', props.className)}
aria-label={labelWithValue}>
<Tooltip label={labelWithValue}>
<Listbox.Button>{button}</Listbox.Button>
</Tooltip>
<Listbox.Popover>{children}</Listbox.Popover>
</Listbox.Input>
);
});
ToolbarListboxRoot.displayName = 'ToolbarListbox';

export const ToolbarListbox = createComponentGroup(ToolbarListboxRoot, {
Expand Down
22 changes: 13 additions & 9 deletions packages/graphiql-react/src/toolbar/menu.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
import { forwardRef, ReactNode } from 'react';
import { Menu } from '../ui';
import { Menu, Tooltip } from '../ui';
import { createComponentGroup } from '../utility/component-group';
import { compose } from '../utility/compose';

import './menu.css';

type ToolbarMenuProps = {
button: ReactNode;
label: string;
};

const ToolbarMenuRoot = forwardRef<
HTMLDivElement,
ToolbarMenuProps & JSX.IntrinsicElements['div']
>(({ button, children, ...props }, ref) => (
>(({ button, children, label, ...props }, ref) => (
<Menu {...props} ref={ref}>
<Menu.Button
className={compose(
'graphiql-un-styled graphiql-toolbar-menu',
props.className,
)}>
{button}
</Menu.Button>
<Tooltip label={label}>
<Menu.Button
className={compose(
'graphiql-un-styled graphiql-toolbar-menu',
props.className,
)}
aria-label={label}>
{button}
</Menu.Button>
</Tooltip>
<Menu.List>{children}</Menu.List>
</Menu>
));
Expand Down
1 change: 1 addition & 0 deletions packages/graphiql-react/src/ui/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from './dropdown';
export * from './markdown';
export * from './spinner';
export * from './tabs';
export * from './tooltip';
20 changes: 11 additions & 9 deletions packages/graphiql-react/src/ui/tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { CloseIcon } from '../icons';
import { createComponentGroup } from '../utility/component-group';
import { compose } from '../utility/compose';
import { UnStyledButton } from './button';
import { Tooltip } from './tooltip';

import './tabs.css';

Expand Down Expand Up @@ -45,15 +46,16 @@ TabButton.displayName = 'Tab.Button';

const TabClose = forwardRef<HTMLButtonElement, JSX.IntrinsicElements['button']>(
(props, ref) => (
<UnStyledButton
aria-label="Close Tab"
title="Close Tab"
{...props}
ref={ref}
type="button"
className={compose('graphiql-tab-close', props.className)}>
<CloseIcon />
</UnStyledButton>
<Tooltip label="Close Tab">
<UnStyledButton
aria-label="Close Tab"
{...props}
ref={ref}
type="button"
className={compose('graphiql-tab-close', props.className)}>
<CloseIcon />
</UnStyledButton>
</Tooltip>
),
);
TabClose.displayName = 'Tab.Close';
Expand Down
10 changes: 10 additions & 0 deletions packages/graphiql-react/src/ui/tooltip.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@import url('@reach/tooltip/styles.css');

[data-reach-tooltip] {
background: var(--color-neutral-7);
border: none;
border-radius: var(--border-radius-4);
box-shadow: var(--box-shadow);
font-size: inherit;
padding: var(--px-6) var(--px-4);
}
3 changes: 3 additions & 0 deletions packages/graphiql-react/src/ui/tooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import './tooltip.css';

export { Tooltip } from '@reach/tooltip';
6 changes: 5 additions & 1 deletion packages/graphiql/__mocks__/@graphiql/react.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export {
DirectiveIcon,
DocExplorer,
DocsIcon,
Dropdown,
EditorContext,
EditorContextProvider,
EnumValueIcon,
Expand All @@ -51,8 +50,10 @@ export {
ImagePreview,
ImplementsIcon,
KeyboardShortcutIcon,
Listbox,
MagnifyingGlassIcon,
MarkdownContent,
Menu,
MergeIcon,
onHasCompletion,
PenIcon,
Expand All @@ -75,6 +76,9 @@ export {
Tab,
Tabs,
ToolbarButton,
ToolbarListbox,
ToolbarMenu,
Tooltip,
TypeDocumentation,
TypeIcon,
TypeLink,
Expand Down
2 changes: 1 addition & 1 deletion packages/graphiql/cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Cypress.Commands.add('clickExecuteQuery', () => {
});

Cypress.Commands.add('clickPrettify', () => {
return cy.get('[title="Prettify Query (Shift-Ctrl-P)"]').click();
return cy.get('[aria-label="Prettify Query (Shift-Ctrl-P)"]').click();
});

Cypress.Commands.add('visitWithOp', ({ query, variables, variablesString }) => {
Expand Down
Loading

0 comments on commit 74820ca

Please sign in to comment.