Skip to content

Commit e1c6e3b

Browse files
add documention for @graphiql/react (#2657)
* add JSDocs for component props and hooks * add JSDocs for context types * add README for `@graphiql/react`
1 parent 11c2778 commit e1c6e3b

30 files changed

Lines changed: 456 additions & 73 deletions

.changeset/chilly-radios-tap.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@graphiql/react': minor
3+
---
4+
5+
BREAKING: The `onHasCompletion` export has been removed as it is only meant to be used internally.

custom-words.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ paas
196196
// these pop up when writing "GraphQL___"
197197
qlapi
198198
qlid
199+
qlide
199200

200201
// other
201202
architecting

packages/graphiql-react/README.md

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,94 @@
11
[Changelog](https://github.com/graphql/graphiql/blob/main/packages/graphiql-react/CHANGELOG.md) | [API Docs](https://graphiql-test.netlify.app/typedoc/modules/graphiql_react.html) | [NPM](https://www.npmjs.com/package/@graphiql/react)
22

3-
A react SDK for building graphql developer experiences for the web
3+
# `@graphiql/react`
44

5-
Used by `graphiql@2` and beyond!
5+
A React SDK for building integrated GraphQL developer experiences for the web.
66

7-
(docs coming soon!)
7+
## Purpose
8+
9+
This package contains a set of building blocks that allow its users to build GraphQL IDEs with ease. It's the set of components that make up Graph*i*QL, the first and official GraphQL IDE, owned and maintained by the GraphQL Foundation.
10+
11+
There are two kinds of building blocks that this package provides: Stateful context providers for state management and simple UI components.
12+
13+
## Getting started
14+
15+
All the state for your GraphQL IDE lives in multiple contexts. The easiest way to get started is by using the `GraphiQLProvider` component that renders all the individual providers.
16+
17+
There is one required prop called `fetcher`. This is a function that performs GraphQL request against a given endpoint. You can easily create a fetcher using the method `createGraphiQLFetcher` from the `@graphiql/toolkit` package.
18+
19+
```jsx
20+
import { GraphiQLProvider } from '@graphiql/react';
21+
import { createGraphiQLFetcher } from '@graphiql/toolkit';
22+
23+
const fetcher = createGraphiQLFetcher({
24+
url: 'https://my.graphql.api/graphql',
25+
});
26+
27+
function MyGraphQLIDE() {
28+
return (
29+
<GraphiQLProvider fetcher={fetcher}>
30+
<div className="graphiql-container">Hello GraphQL</div>
31+
</GraphiQLProvider>
32+
);
33+
}
34+
```
35+
36+
Inside the provider you can now use any UI component provided by `@graphiql/react`. For example, you can render a query editor like this:
37+
38+
```jsx
39+
import { QueryEditor } from '@graphiql/react';
40+
41+
function MyGraphQLIDE() {
42+
return (
43+
<GraphiQLProvider fetcher={fetcher}>
44+
<div className="graphiql-container">
45+
<QueryEditor />
46+
</div>
47+
</GraphiQLProvider>
48+
);
49+
}
50+
```
51+
52+
The package also ships the necessary CSS that all its UI components need. You can import them from `@graphiql/react/dist/style.css`.
53+
54+
**Note**: In order for these styles to apply, the UI components need to be rendered inside an element that has a class name `graphiql-container`.
55+
56+
By default the UI components will try to use the [Roboto](https://fonts.google.com/specimen/Roboto) font for regular text and the [Fira Code](https://fonts.google.com/specimen/Fira+Code) font for mono-space text. If you want to use the default fonts you can load them using these files:
57+
58+
- `@graphiql/react/font/roboto.css`
59+
- `@graphiql/react/font/fira-code.css`.
60+
61+
You can of course use any other method to load these fonts (for example loading them from Google Fonts).
62+
63+
Further details on how to use `@graphiql/react` can be found in the reference implementation of a GraphQL IDE - Graph*i*QL - in the [`graphiql` package](https://github.com/graphql/graphiql/blob/main/packages/graphiql/src/components/GraphiQL.tsx).
64+
65+
## Available contexts
66+
67+
There are multiple contexts that own different parts of the state that make up a complete GraphQL IDE. For each context there is a provider component (`<name>ContextProvider`) that makes sure the context is initialized and managed properly. These components contains all the logic related to state management. In addition, for each context there is also a hook (`use<name>Context`) that allows you to consume its current value.
68+
69+
Here is a list of all contexts that come with `@graphiql/react`
70+
71+
- `StorageContext`: Provides a storage API that can be used to persist state in the browser (by default using `localStorage`)
72+
- `EditorContext`: Manages all the editors and tabs
73+
- `SchemaContext`: Fetches, validates and stores the GraphQL schema
74+
- `ExecutionContext`: Executes GraphQL requests
75+
- `HistoryContext`: Persists executed requests in storage
76+
- `ExplorerContext`: Handles the state for the docs explorer
77+
78+
All context properties are documented using JSDoc comments. If you're using an IDE like VSCode for development these descriptions will show up in auto-complete tooltips. All these descriptions can also be found in the [API Docs](https://graphiql-test.netlify.app/typedoc/modules/graphiql_react.html).
79+
80+
## Theming
81+
82+
All the components from `@graphiql/react` have been designed with customization in mind. We achieve this using CSS variables.
83+
84+
All variables that are available for customization can be found in the [`root.css` file](https://github.com/graphql/graphiql/blob/main/packages/graphiql-react/src/style/root.css).
85+
86+
### Colors
87+
88+
Colors are defined using the [HSL format](https://en.wikipedia.org/wiki/HSL_and_HSV). All CSS variables for colors are defined as a list of the three values that make up HSL (hue, saturation and lightness).
89+
90+
This approach allows `@graphiql/react` to use transparent colors by passing the value of the CSS variable in the `hsla` function. This enables us to provide truly reusable UI elements where good contrasts are preserved regardless of the elements background.
91+
92+
## Development
93+
94+
If you want to develop with `@graphiql/react` locally - in particular when working on the `graphiql` package - all you need to do is run `yarn dev` in the package folder in a separate terminal. This will build the package using Vite. When using it in combination with `yarn start-graphiql` (running in the repo root) this will give you auto-reloading when working on `graphiql` and `@graphiql/react` simultaneously.

packages/graphiql-react/package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,8 @@
2727
"types"
2828
],
2929
"scripts": {
30-
"dev": "vite",
31-
"build": "tsc --emitDeclarationOnly && vite build",
32-
"preview": "vite preview"
30+
"dev": "concurrently 'tsc --emitDeclarationOnly --watch' 'vite build --watch'",
31+
"build": "tsc --emitDeclarationOnly && vite build"
3332
},
3433
"peerDependencies": {
3534
"graphql": "^15.5.0 || ^16.0.0",

packages/graphiql-react/src/editor/components/header-editor.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@ import '../style/codemirror.css';
77
import '../style/fold.css';
88
import '../style/editor.css';
99

10-
type HeaderEditorProps = UseHeaderEditorArgs & { isHidden?: boolean };
10+
type HeaderEditorProps = UseHeaderEditorArgs & {
11+
/**
12+
* Visually hide the header editor.
13+
* @default false
14+
*/
15+
isHidden?: boolean;
16+
};
1117

1218
export function HeaderEditor({ isHidden, ...hookArgs }: HeaderEditorProps) {
1319
const { headerEditor } = useEditorContext({

packages/graphiql-react/src/editor/components/variable-editor.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ import '../style/hint.css';
1010
import '../style/editor.css';
1111

1212
type VariableEditorProps = UseVariableEditorArgs & {
13+
/**
14+
* Visually hide the header editor.
15+
* @default false
16+
*/
1317
isHidden?: boolean;
1418
};
1519

packages/graphiql-react/src/editor/context.tsx

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,35 +34,109 @@ export type CodeMirrorEditorWithOperationFacts = CodeMirrorEditor & {
3434
variableToType: VariableToType | null;
3535
};
3636

37-
export type EditorContextType = {
38-
activeTabIndex: number;
39-
tabs: TabState[];
37+
export type EditorContextType = TabsState & {
38+
/**
39+
* Add a new tab.
40+
*/
4041
addTab(): void;
42+
/**
43+
* Switch to a different tab.
44+
* @param index The index of the tab that should be switched to.
45+
*/
4146
changeTab(index: number): void;
47+
/**
48+
* Close a tab. If the currently active tab is closed the tab before it will
49+
* become active. If there is no tab before the closed one, the tab after it
50+
* will become active.
51+
* @param index The index of the tab that should be closed.
52+
*/
4253
closeTab(index: number): void;
54+
/**
55+
* Update the state for the tab that is currently active. This will be
56+
* reflected in the `tabs` object and the state will be persisted in storage
57+
* (if available).
58+
* @param partialTab A partial tab state object that will override the
59+
* current values. The properties `id`, `hash` and `title` cannot be changed.
60+
*/
4361
updateActiveTabValues(
4462
partialTab: Partial<Omit<TabState, 'id' | 'hash' | 'title'>>,
4563
): void;
4664

65+
/**
66+
* The CodeMirror editor instance for the headers editor.
67+
*/
4768
headerEditor: CodeMirrorEditor | null;
69+
/**
70+
* The CodeMirror editor instance for the query editor. This editor also
71+
* stores the operation facts that are derived from the current editor
72+
* contents.
73+
*/
4874
queryEditor: CodeMirrorEditorWithOperationFacts | null;
75+
/**
76+
* The CodeMirror editor instance for the response editor.
77+
*/
4978
responseEditor: CodeMirrorEditor | null;
79+
/**
80+
* The CodeMirror editor instance for the variables editor.
81+
*/
5082
variableEditor: CodeMirrorEditor | null;
83+
/**
84+
* Set the CodeMirror editor instance for the headers editor.
85+
*/
5186
setHeaderEditor(newEditor: CodeMirrorEditor): void;
87+
/**
88+
* Set the CodeMirror editor instance for the query editor.
89+
*/
5290
setQueryEditor(newEditor: CodeMirrorEditorWithOperationFacts): void;
91+
/**
92+
* Set the CodeMirror editor instance for the response editor.
93+
*/
5394
setResponseEditor(newEditor: CodeMirrorEditor): void;
95+
/**
96+
* Set the CodeMirror editor instance for the variables editor.
97+
*/
5498
setVariableEditor(newEditor: CodeMirrorEditor): void;
5599

100+
/**
101+
* Changes the operation name and invokes the `onEditOperationName` callback.
102+
*/
56103
setOperationName(operationName: string): void;
57104

105+
/**
106+
* The contents of the headers editor when initially rendering the provider
107+
* component.
108+
*/
58109
initialHeaders: string;
110+
/**
111+
* The contents of the query editor when initially rendering the provider
112+
* component.
113+
*/
59114
initialQuery: string;
115+
/**
116+
* The contents of the response editor when initially rendering the provider
117+
* component.
118+
*/
60119
initialResponse: string;
120+
/**
121+
* The contents of the variables editor when initially rendering the provider
122+
* component.
123+
*/
61124
initialVariables: string;
62125

126+
/**
127+
* A map of fragment definitions using the fragment name as key which are
128+
* made available to include in the query.
129+
*/
63130
externalFragments: Map<string, FragmentDefinitionNode>;
131+
/**
132+
* A list of custom validation rules that are run in addition to the rules
133+
* provided by the GraphQL spec.
134+
*/
64135
validationRules: ValidationRule[];
65136

137+
/**
138+
* If the contents of the headers editor are persisted in storage.
139+
*/
66140
shouldPersistHeaders: boolean;
67141
};
68142

packages/graphiql-react/src/editor/hooks.ts

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,9 @@ export function useChangeHandler(
8989
]);
9090
}
9191

92-
export type OnClickReference = (reference: SchemaReference) => void;
93-
9492
export function useCompletion(
9593
editor: CodeMirrorEditor | null,
96-
callback: OnClickReference | null,
94+
callback: ((reference: SchemaReference) => void) | null,
9795
caller: Function,
9896
) {
9997
const { schema } = useSchemaContext({ nonNull: true, caller });
@@ -150,13 +148,20 @@ export function useKeyMap(
150148
}, [editor, keys, callback]);
151149
}
152150

153-
export function useCopyQuery({
154-
caller,
155-
onCopyQuery,
156-
}: {
151+
export type UseCopyQueryArgs = {
152+
/**
153+
* This is only meant to be used internally in `@graphiql/react`.
154+
*/
157155
caller?: Function;
156+
/**
157+
* Invoked when the current contents of the query editor are copied to the
158+
* clipboard.
159+
* @param query The content that has been copied.
160+
*/
158161
onCopyQuery?: (query: string) => void;
159-
} = {}) {
162+
};
163+
164+
export function useCopyQuery({ caller, onCopyQuery }: UseCopyQueryArgs = {}) {
160165
const { queryEditor } = useEditorContext({
161166
nonNull: true,
162167
caller: caller || useCopyQuery,
@@ -173,7 +178,14 @@ export function useCopyQuery({
173178
}, [queryEditor, onCopyQuery]);
174179
}
175180

176-
export function useMergeQuery({ caller }: { caller?: Function } = {}) {
181+
type UseMergeQueryArgs = {
182+
/**
183+
* This is only meant to be used internally in `@graphiql/react`.
184+
*/
185+
caller?: Function;
186+
};
187+
188+
export function useMergeQuery({ caller }: UseMergeQueryArgs = {}) {
177189
const { queryEditor } = useEditorContext({
178190
nonNull: true,
179191
caller: caller || useMergeQuery,
@@ -190,11 +202,14 @@ export function useMergeQuery({ caller }: { caller?: Function } = {}) {
190202
}, [queryEditor, schema]);
191203
}
192204

193-
export function usePrettifyEditors({
194-
caller,
195-
}: {
205+
type UsePrettifyEditorsArgs = {
206+
/**
207+
* This is only meant to be used internally in `@graphiql/react`.
208+
*/
196209
caller?: Function;
197-
} = {}) {
210+
};
211+
212+
export function usePrettifyEditors({ caller }: UsePrettifyEditorsArgs = {}) {
198213
const { queryEditor, headerEditor, variableEditor } = useEditorContext({
199214
nonNull: true,
200215
caller: caller || usePrettifyEditors,
@@ -244,10 +259,23 @@ export function usePrettifyEditors({
244259
}, [queryEditor, variableEditor, headerEditor]);
245260
}
246261

262+
export type UseAutoCompleteLeafsArgs = {
263+
/**
264+
* A function to determine which field leafs are automatically added when
265+
* trying to execute a query with missing selection sets. It will be called
266+
* with the `GraphQLType` for which fields need to be added.
267+
*/
268+
getDefaultFieldNames?: GetDefaultFieldNamesFn;
269+
/**
270+
* This is only meant to be used internally in `@graphiql/react`.
271+
*/
272+
caller?: Function;
273+
};
274+
247275
export function useAutoCompleteLeafs({
248276
getDefaultFieldNames,
249277
caller,
250-
}: { getDefaultFieldNames?: GetDefaultFieldNamesFn; caller?: Function } = {}) {
278+
}: UseAutoCompleteLeafsArgs = {}) {
251279
const { schema } = useSchemaContext({
252280
nonNull: true,
253281
caller: caller || useAutoCompleteLeafs,

packages/graphiql-react/src/editor/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
export { onHasCompletion } from './completion';
21
export {
32
HeaderEditor,
43
ImagePreview,

0 commit comments

Comments
 (0)