From d52f3468ca334e9c8061fd3de13265f5ec762208 Mon Sep 17 00:00:00 2001 From: Thomas Heyenbrock Date: Fri, 22 Jul 2022 07:19:59 +0200 Subject: [PATCH] extract loading spinner to `@graphiql/react` (#2581) --- .changeset/smooth-countries-shout.md | 5 ++ packages/graphiql-react/src/ui/index.ts | 1 + packages/graphiql-react/src/ui/spinner.css | 27 +++++++++++ packages/graphiql-react/src/ui/spinner.tsx | 5 ++ .../graphiql/__mocks__/@graphiql/react.tsx | 47 ++++++++++--------- .../graphiql/src/components/DocExplorer.tsx | 6 +-- packages/graphiql/src/components/GraphiQL.tsx | 3 +- packages/graphiql/src/style.css | 29 ------------ 8 files changed, 69 insertions(+), 54 deletions(-) create mode 100644 .changeset/smooth-countries-shout.md create mode 100644 packages/graphiql-react/src/ui/spinner.css create mode 100644 packages/graphiql-react/src/ui/spinner.tsx diff --git a/.changeset/smooth-countries-shout.md b/.changeset/smooth-countries-shout.md new file mode 100644 index 00000000000..87e4ced66ac --- /dev/null +++ b/.changeset/smooth-countries-shout.md @@ -0,0 +1,5 @@ +--- +'@graphiql/react': minor +--- + +Add `Spinner` component to `@graphiql/react` diff --git a/packages/graphiql-react/src/ui/index.ts b/packages/graphiql-react/src/ui/index.ts index 7ef3616b216..0399c089591 100644 --- a/packages/graphiql-react/src/ui/index.ts +++ b/packages/graphiql-react/src/ui/index.ts @@ -1,2 +1,3 @@ export * from './button'; export * from './dropdown'; +export * from './spinner'; diff --git a/packages/graphiql-react/src/ui/spinner.css b/packages/graphiql-react/src/ui/spinner.css new file mode 100644 index 00000000000..40cb82a23f4 --- /dev/null +++ b/packages/graphiql-react/src/ui/spinner.css @@ -0,0 +1,27 @@ +.graphiql-spinner { + height: 56px; + margin: auto; + margin-top: var(--px-16); + width: 56px; + + &::after { + animation: rotation 0.6s infinite linear; + border: 4px solid transparent; + border-radius: 100%; + border-top: 4px solid var(--color-neutral-40); + content: ''; + display: inline-block; + height: 46px; + vertical-align: middle; + width: 46px; + } +} + +@keyframes rotation { + from { + transform: rotate(0deg); + } + to { + transform: rotate(359deg); + } +} diff --git a/packages/graphiql-react/src/ui/spinner.tsx b/packages/graphiql-react/src/ui/spinner.tsx new file mode 100644 index 00000000000..a70fff94fe1 --- /dev/null +++ b/packages/graphiql-react/src/ui/spinner.tsx @@ -0,0 +1,5 @@ +import './spinner.css'; + +export function Spinner() { + return
; +} diff --git a/packages/graphiql/__mocks__/@graphiql/react.tsx b/packages/graphiql/__mocks__/@graphiql/react.tsx index 1e00c64ccb2..0f65bb6ac1a 100644 --- a/packages/graphiql/__mocks__/@graphiql/react.tsx +++ b/packages/graphiql/__mocks__/@graphiql/react.tsx @@ -37,6 +37,7 @@ export { SchemaContext, SchemaContextProvider, SettingsIcon, + Spinner, StopIcon, StorageContext, StorageContextProvider, @@ -52,7 +53,6 @@ export { useMergeQuery, usePrettifyEditors, useSchemaContext, - useSelectHistoryItem, useStorageContext, } from '@graphiql/react'; @@ -92,15 +92,20 @@ function useMockedEditor( onEdit?: (newValue: string) => void, ) { const editorContext = useEditorContext({ nonNull: true }); - const [code, setCode] = useState( - value ?? editorContext[NAME_TO_INITIAL_VALUE[name]], - ); + const [code, setCode] = useState(() => { + const initialValueProp = NAME_TO_INITIAL_VALUE[name]; + return ( + value ?? + (initialValueProp ? editorContext[initialValueProp] : undefined) ?? + '' + ); + }); const ref = useRef(null); const setEditor = editorContext[`set${name.slice(0, 1).toUpperCase()}${name.slice(1)}Editor`]; - const getValueRef = useRef<() => string>(); + const getValueRef = useRef<() => string>(() => code); useEffect(() => { getValueRef.current = () => code; }, [code]); @@ -179,28 +184,28 @@ function useMockedEditor( return ref; } -export const useHeaderEditor: typeof _useHeaderEditor = function useHeaderEditor({ - onEdit, -}) { - return useMockedEditor('header', undefined, onEdit); +export const useHeaderEditor: typeof _useHeaderEditor = function useHeaderEditor( + props, +) { + return useMockedEditor('header', undefined, props?.onEdit); }; -export const useQueryEditor: typeof _useQueryEditor = function useQueryEditor({ - onEdit, -}) { - return useMockedEditor('query', undefined, onEdit); +export const useQueryEditor: typeof _useQueryEditor = function useQueryEditor( + props, +) { + return useMockedEditor('query', undefined, props?.onEdit); }; -export const useResponseEditor: typeof _useResponseEditor = function useResponseEditor({ - value, -}) { - return useMockedEditor('response', value); +export const useResponseEditor: typeof _useResponseEditor = function useResponseEditor( + props, +) { + return useMockedEditor('response', props?.value); }; -export const useVariableEditor: typeof _useVariableEditor = function useVariableEditor({ - onEdit, -}) { - return useMockedEditor('variable', undefined, onEdit); +export const useVariableEditor: typeof _useVariableEditor = function useVariableEditor( + props, +) { + return useMockedEditor('variable', undefined, props?.onEdit); }; export const HeaderEditor: typeof _HeaderEditor = function HeaderEditor(props) { diff --git a/packages/graphiql/src/components/DocExplorer.tsx b/packages/graphiql/src/components/DocExplorer.tsx index 86205f9b778..865f920a829 100644 --- a/packages/graphiql/src/components/DocExplorer.tsx +++ b/packages/graphiql/src/components/DocExplorer.tsx @@ -5,9 +5,9 @@ * LICENSE file in the root directory of this source tree. */ -import React, { ReactNode } from 'react'; +import { Spinner, useExplorerContext, useSchemaContext } from '@graphiql/react'; import { GraphQLSchema, isType } from 'graphql'; -import { useExplorerContext, useSchemaContext } from '@graphiql/react'; +import React, { ReactNode } from 'react'; import FieldDoc from './DocExplorer/FieldDoc'; import SchemaDoc from './DocExplorer/SchemaDoc'; @@ -60,7 +60,7 @@ export function DocExplorer(props: DocExplorerProps) { ); } else if (isFetching) { // Schema is undefined when it is being loaded via introspection. - content =
; + content = ; } else if (!schema) { // Schema is null when it explicitly does not exist, typically due to // an error during introspection. diff --git a/packages/graphiql/src/components/GraphiQL.tsx b/packages/graphiql/src/components/GraphiQL.tsx index dcbd7032c89..52eb919edb3 100644 --- a/packages/graphiql/src/components/GraphiQL.tsx +++ b/packages/graphiql/src/components/GraphiQL.tsx @@ -42,6 +42,7 @@ import { ResponseEditor, SchemaContextProvider, SettingsIcon, + Spinner, StorageContextProvider, ToolbarButton, UnStyledButton, @@ -958,7 +959,7 @@ class GraphiQLWithContext extends React.Component<
{this.props.executionContext.isFetching ? ( -
+ ) : null}