diff --git a/.changeset/five-pillows-fail.md b/.changeset/five-pillows-fail.md index bae5935e230..e98c1fdc646 100644 --- a/.changeset/five-pillows-fail.md +++ b/.changeset/five-pillows-fail.md @@ -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`) diff --git a/packages/graphiql-react/package.json b/packages/graphiql-react/package.json index fe6768692b9..f9fecea485b 100644 --- a/packages/graphiql-react/package.json +++ b/packages/graphiql-react/package.json @@ -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.2", diff --git a/packages/graphiql-react/src/editor/context.tsx b/packages/graphiql-react/src/editor/context.tsx index d900126bafa..3e60e7b432d 100644 --- a/packages/graphiql-react/src/editor/context.tsx +++ b/packages/graphiql-react/src/editor/context.tsx @@ -296,13 +296,13 @@ const DEFAULT_QUERY = `# Welcome to GraphiQL # # Keyboard shortcuts: # -# Prettify Query: Shift-Ctrl-P (or press the prettify button above) +# Prettify query: Shift-Ctrl-P (or press the prettify button) # -# Merge Query: Shift-Ctrl-M (or press the merge button above) +# Merge fragments: Shift-Ctrl-M (or press the merge button) # -# Run Query: Ctrl-Enter (or press the play button above) +# Run Query: Ctrl-Enter (or press the play button) # -# Auto Complete: Ctrl-Space (or just start typing) +# Auto Complete: Ctrl-Space (or just start typing) # `; diff --git a/packages/graphiql-react/src/history/__tests__/components.spec.tsx b/packages/graphiql-react/src/history/__tests__/components.spec.tsx index 9366c4b67bc..180287b0175 100644 --- a/packages/graphiql-react/src/history/__tests__/components.spec.tsx +++ b/packages/graphiql-react/src/history/__tests__/components.spec.tsx @@ -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( , ); - 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( diff --git a/packages/graphiql-react/src/history/components.tsx b/packages/graphiql-react/src/history/components.tsx index 921e0a68523..ab6ad9efaff 100644 --- a/packages/graphiql-react/src/history/components.tsx +++ b/packages/graphiql-react/src/history/components.tsx @@ -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'; @@ -112,24 +112,35 @@ export function HistoryItem(props: QueryHistoryItemProps) { }}> {displayName} - { - e.stopPropagation(); - setIsEditable(true); - }}> - - - { - e.stopPropagation(); - toggleFavorite(props.item); - }} - title={props.item.favorite ? 'Remove favorite' : 'Add favorite'}> - {props.item.favorite ? : } - + + { + e.stopPropagation(); + setIsEditable(true); + }} + aria-label="Edit label"> + + + + { + e.stopPropagation(); + toggleFavorite(props.item); + }} + aria-label={ + props.item.favorite ? 'Remove favorite' : 'Add favorite' + }> + {props.item.favorite ? ( + + )} diff --git a/packages/graphiql-react/src/history/style.css b/packages/graphiql-react/src/history/style.css index 804fd158ede..f29c5830f65 100644 --- a/packages/graphiql-react/src/history/style.css +++ b/packages/graphiql-react/src/history/style.css @@ -81,7 +81,6 @@ button.graphiql-history-item-action { & > svg { height: 14px; - pointer-events: none; width: 14px; } } diff --git a/packages/graphiql-react/src/toolbar/button.css b/packages/graphiql-react/src/toolbar/button.css index 44fb55d3e96..d4773bd50c3 100644 --- a/packages/graphiql-react/src/toolbar/button.css +++ b/packages/graphiql-react/src/toolbar/button.css @@ -6,8 +6,4 @@ button.graphiql-toolbar-button { &.error { background: hsla(var(--color-error), 0.15); } - - & > svg { - pointer-events: none; - } } diff --git a/packages/graphiql-react/src/toolbar/button.tsx b/packages/graphiql-react/src/toolbar/button.tsx index c3a1969f273..e4f4fc5cb99 100644 --- a/packages/graphiql-react/src/toolbar/button.tsx +++ b/packages/graphiql-react/src/toolbar/button.tsx @@ -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(null); return ( - { - 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']} - /> + + { + 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']} + /> + ); }); ToolbarButton.displayName = 'ToolbarButton'; diff --git a/packages/graphiql-react/src/toolbar/execute.css b/packages/graphiql-react/src/toolbar/execute.css index 546ff3ae03b..b277dd3241b 100644 --- a/packages/graphiql-react/src/toolbar/execute.css +++ b/packages/graphiql-react/src/toolbar/execute.css @@ -24,7 +24,6 @@ button.graphiql-execute-button { display: block; height: var(--px-16); margin: auto; - pointer-events: none; width: var(--px-16); } } diff --git a/packages/graphiql-react/src/toolbar/execute.tsx b/packages/graphiql-react/src/toolbar/execute.tsx index 306bdbd0760..2cac6367556 100644 --- a/packages/graphiql-react/src/toolbar/execute.tsx +++ b/packages/graphiql-react/src/toolbar/execute.tsx @@ -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'; @@ -19,16 +19,20 @@ export function ExecuteButton() { const operations = queryEditor?.operations || []; const hasOptions = operations.length > 1; + const label = `${isRunning ? 'Stop' : 'Execute'} query (Ctrl-Enter)`; const buttonProps = { type: 'button' as const, className: 'graphiql-execute-button', - title: 'Execute Query (Ctrl-Enter)', children: isRunning ? : , + 'aria-label': label, }; return hasOptions ? ( - + + + + {operations.map((operation, i) => { const opName = operation.name @@ -47,15 +51,17 @@ export function ExecuteButton() { ) : ( -