Skip to content

Commit ff65086

Browse files
[redesign]: editor in new design (graphql#2513)
* add postcss config to allow nesting * avoid processing css from `@graphiql/react` with postcss * add css files for default fonts * add long description with markdown to dev schema * rewrite completion tooltip * move editor css to @graphiql/react * git mv editor components to `@graphiql/react` * adjust editor components after moving to `@graphiql/react` * move styles for auto-inserted leads * make dynamic padding more resilient and add explanatory comment * add extra color to avoid conflicts * colocate markdown and deprecation styles * add changesets * fix spell checking * add changeset for graphiql@2 * don't enter pre-release mode in changeset * more elaborate changeset message
1 parent 8ce3a90 commit ff65086

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1392
-1164
lines changed

.changeset/five-pillows-fail.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@graphiql/react': minor
3+
---
4+
5+
Add editor components and implement styles for the new GraphiQL design

.changeset/gentle-forks-rule.md

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'codemirror-graphql': major
3+
---
4+
5+
BREAKING: Change the implementation of the info popup when hovering items in the code editor:
6+
- For fields the type prefix was removed, i.e. `MyType.myField` -> `myField`
7+
- For args, the type and field was removed, i.e. `MyType.myField(myArg: MyArgType)` -> `myArg: MyArgType`
8+
- The DOM structure of the info tooltip changed to enable more flexible styling:
9+
- The first section (i.e. the clickable parts like type and field name) are wrapped in an additional div
10+
- The markdown content for deprecation reasons is wrapped in an additional div

.changeset/lazy-clouds-lay.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'graphiql': major
3+
---
4+
5+
BREAKING: Implement a new design for the GraphiQL UI. This changes both DOM structure and class names. We consider this a breaking change as custom GraphQL IDEs built on top of GraphiQL relied on these internals, e.g. overriding styles using certain class names.

.changeset/perfect-flowers-hunt.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'graphiql': minor
3+
---
4+
5+
Consume the editor components from `@graphiql/react`

custom-words.txt

+8
Original file line numberDiff line numberDiff line change
@@ -140,23 +140,29 @@ eslintignore
140140
filesfor
141141
flowtests
142142
foldgutter
143+
foldmarker
143144
ghapi
144145
graphqlconfig
145146
graphqlrc
146147
graphqls
148+
invalidchar
147149
languageservice
150+
linenumber
148151
linenumbers
149152
linkify
150153
listvalues
154+
matchingbracket
151155
modulemap
152156
myschema
153157
newhope
154158
nocheck
155159
nocursor
160+
nonmatchingbracket
156161
nrtbf
157162
nulltype
158163
nvim
159164
objectvalues
165+
orche
160166
outdir
161167
outlineable
162168
postbuild
@@ -181,7 +187,9 @@ websockets
181187

182188

183189
// fonts
190+
fira
184191
menlo
192+
roboto
185193

186194
// locations
187195
givatayim

packages/codemirror-graphql/src/info.ts

+58-33
Original file line numberDiff line numberDiff line change
@@ -74,36 +74,51 @@ CodeMirror.registerHelper(
7474
(kind === 'Field' && step === 0 && typeInfo.fieldDef) ||
7575
(kind === 'AliasedField' && step === 2 && typeInfo.fieldDef)
7676
) {
77+
const header = document.createElement('div');
78+
header.className = 'CodeMirror-info-header';
79+
renderField(header, typeInfo, options);
7780
const into = document.createElement('div');
78-
renderField(into, typeInfo, options);
81+
into.appendChild(header);
7982
renderDescription(into, options, typeInfo.fieldDef as any);
8083
return into;
8184
} else if (kind === 'Directive' && step === 1 && typeInfo.directiveDef) {
85+
const header = document.createElement('div');
86+
header.className = 'CodeMirror-info-header';
87+
renderDirective(header, typeInfo, options);
8288
const into = document.createElement('div');
83-
renderDirective(into, typeInfo, options);
89+
into.appendChild(header);
8490
renderDescription(into, options, typeInfo.directiveDef);
8591
return into;
8692
} else if (kind === 'Argument' && step === 0 && typeInfo.argDef) {
93+
const header = document.createElement('div');
94+
header.className = 'CodeMirror-info-header';
95+
renderArg(header, typeInfo, options);
8796
const into = document.createElement('div');
88-
renderArg(into, typeInfo, options);
97+
into.appendChild(header);
8998
renderDescription(into, options, typeInfo.argDef);
9099
return into;
91100
} else if (
92101
kind === 'EnumValue' &&
93102
typeInfo.enumValue &&
94103
typeInfo.enumValue.description
95104
) {
105+
const header = document.createElement('div');
106+
header.className = 'CodeMirror-info-header';
107+
renderEnumValue(header, typeInfo, options);
96108
const into = document.createElement('div');
97-
renderEnumValue(into, typeInfo, options);
109+
into.appendChild(header);
98110
renderDescription(into, options, typeInfo.enumValue);
99111
return into;
100112
} else if (
101113
kind === 'NamedType' &&
102114
typeInfo.type &&
103115
(typeInfo.type as GraphQLObjectType).description
104116
) {
117+
const header = document.createElement('div');
118+
header.className = 'CodeMirror-info-header';
119+
renderType(header, typeInfo, options, typeInfo.type);
105120
const into = document.createElement('div');
106-
renderType(into, typeInfo, options, typeInfo.type);
121+
into.appendChild(header);
107122
renderDescription(into, options, typeInfo.type);
108123
return into;
109124
}
@@ -125,10 +140,6 @@ function renderQualifiedField(
125140
options: GraphQLInfoOptions,
126141
) {
127142
const fieldName = typeInfo.fieldDef?.name || '';
128-
if (fieldName.slice(0, 2) !== '__') {
129-
renderType(into, typeInfo, options, typeInfo.parentType);
130-
text(into, '.');
131-
}
132143
text(into, fieldName, 'field-name', options, getFieldReference(typeInfo));
133144
}
134145

@@ -146,38 +157,47 @@ function renderArg(
146157
typeInfo: TypeInfo,
147158
options: GraphQLInfoOptions,
148159
) {
149-
if (typeInfo.directiveDef) {
150-
renderDirective(into, typeInfo, options);
151-
} else if (typeInfo.fieldDef) {
152-
renderQualifiedField(into, typeInfo, options);
153-
}
154-
155160
const name = typeInfo.argDef?.name || '';
156-
text(into, '(');
157161
text(into, name, 'arg-name', options, getArgumentReference(typeInfo));
158162
renderTypeAnnotation(into, typeInfo, options, typeInfo.inputType);
159-
text(into, ')');
160163
}
161164

162-
function renderTypeAnnotation(
165+
function renderEnumValue(
163166
into: HTMLElement,
164167
typeInfo: TypeInfo,
165168
options: GraphQLInfoOptions,
166-
t: Maybe<GraphQLType>,
167169
) {
168-
text(into, ': ');
169-
renderType(into, typeInfo, options, t);
170+
const name = typeInfo.enumValue?.name || '';
171+
renderType(into, typeInfo, options, typeInfo.inputType);
172+
text(into, '.');
173+
text(into, name, 'enum-value', options, getEnumValueReference(typeInfo));
170174
}
171175

172-
function renderEnumValue(
176+
function renderTypeAnnotation(
173177
into: HTMLElement,
174178
typeInfo: TypeInfo,
175179
options: GraphQLInfoOptions,
180+
t: Maybe<GraphQLType>,
176181
) {
177-
const name = typeInfo.enumValue?.name || '';
178-
renderType(into, typeInfo, options, typeInfo.inputType);
179-
text(into, '.');
180-
text(into, name, 'enum-value', options, getEnumValueReference(typeInfo));
182+
const typeSpan = document.createElement('span');
183+
typeSpan.className = 'type-name-pill';
184+
if (t instanceof GraphQLNonNull) {
185+
renderType(typeSpan, typeInfo, options, t.ofType);
186+
text(typeSpan, '!');
187+
} else if (t instanceof GraphQLList) {
188+
text(typeSpan, '[');
189+
renderType(typeSpan, typeInfo, options, t.ofType);
190+
text(typeSpan, ']');
191+
} else {
192+
text(
193+
typeSpan,
194+
t?.name || '',
195+
'type-name',
196+
options,
197+
getTypeReference(typeInfo, t),
198+
);
199+
}
200+
into.appendChild(typeSpan);
181201
}
182202

183203
function renderType(
@@ -243,16 +263,21 @@ function renderDeprecation(
243263
if (reason) {
244264
const deprecationDiv = document.createElement('div');
245265
deprecationDiv.className = 'info-deprecation';
266+
into.appendChild(deprecationDiv);
267+
268+
const label = document.createElement('span');
269+
label.className = 'info-deprecation-label';
270+
label.appendChild(document.createTextNode('Deprecated'));
271+
deprecationDiv.appendChild(label);
272+
273+
const reasonDiv = document.createElement('div');
274+
reasonDiv.className = 'info-deprecation-reason';
246275
if (options.renderDescription) {
247-
deprecationDiv.innerHTML = options.renderDescription(reason);
276+
reasonDiv.innerHTML = options.renderDescription(reason);
248277
} else {
249-
deprecationDiv.appendChild(document.createTextNode(reason));
278+
reasonDiv.appendChild(document.createTextNode(reason));
250279
}
251-
const label = document.createElement('span');
252-
label.className = 'info-deprecation-label';
253-
label.appendChild(document.createTextNode('Deprecated: '));
254-
deprecationDiv.insertBefore(label, deprecationDiv.firstChild);
255-
into.appendChild(deprecationDiv);
280+
deprecationDiv.appendChild(reasonDiv);
256281
}
257282
}
258283

packages/graphiql-react/font/fira-code.css

+58
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/graphiql-react/font/roboto.css

+272
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/graphiql-react/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"types": "types/index.d.ts",
1717
"files": [
1818
"dist",
19+
"font",
1920
"src",
2021
"types"
2122
],
@@ -34,17 +35,16 @@
3435
"codemirror": "^5.65.3",
3536
"codemirror-graphql": "^1.3.2",
3637
"copy-to-clipboard": "^3.2.0",
37-
"escape-html": "^1.0.3",
3838
"graphql-language-service": "^5.0.6",
3939
"markdown-it": "^12.2.0",
4040
"set-value": "^4.1.0"
4141
},
4242
"devDependencies": {
4343
"@types/codemirror": "^5.60.5",
44-
"@types/escape-html": "^1.0.1",
4544
"@types/set-value": "^4.0.1",
4645
"@vitejs/plugin-react": "^1.3.0",
4746
"graphql": "^16.4.0",
47+
"postcss-nesting": "^10.1.7",
4848
"react": "^17.0.2",
4949
"react-dom": "^17.0.2",
5050
"typescript": "^4.6.3",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
plugins: [require('postcss-nesting')],
3+
};

0 commit comments

Comments
 (0)