Skip to content

Commit

Permalink
[redesign]: editor in new design (#2513)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
thomasheyenbrock committed Jul 14, 2022
1 parent 65df5b8 commit e2c9c5f
Show file tree
Hide file tree
Showing 45 changed files with 1,392 additions and 1,164 deletions.
5 changes: 5 additions & 0 deletions .changeset/five-pillows-fail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphiql/react': minor
---

Add editor components and implement styles for the new GraphiQL design
10 changes: 10 additions & 0 deletions .changeset/gentle-forks-rule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'codemirror-graphql': major
---

BREAKING: Change the implementation of the info popup when hovering items in the code editor:
- For fields the type prefix was removed, i.e. `MyType.myField` -> `myField`
- For args, the type and field was removed, i.e. `MyType.myField(myArg: MyArgType)` -> `myArg: MyArgType`
- The DOM structure of the info tooltip changed to enable more flexible styling:
- The first section (i.e. the clickable parts like type and field name) are wrapped in an additional div
- The markdown content for deprecation reasons is wrapped in an additional div
5 changes: 5 additions & 0 deletions .changeset/lazy-clouds-lay.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'graphiql': major
---

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.
5 changes: 5 additions & 0 deletions .changeset/perfect-flowers-hunt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'graphiql': minor
---

Consume the editor components from `@graphiql/react`
8 changes: 8 additions & 0 deletions custom-words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -106,23 +106,29 @@ eslintignore
filesfor
flowtests
foldgutter
foldmarker
ghapi
graphqlconfig
graphqlrc
graphqls
invalidchar
languageservice
linenumber
linenumbers
linkify
listvalues
matchingbracket
modulemap
myschema
newhope
nocheck
nocursor
nonmatchingbracket
nrtbf
nulltype
nvim
objectvalues
orche
outdir
outlineable
postbuild
Expand All @@ -147,7 +153,9 @@ websockets


// fonts
fira
menlo
roboto

// locations
givatayim
Expand Down
91 changes: 58 additions & 33 deletions packages/codemirror-graphql/src/info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,36 +74,51 @@ CodeMirror.registerHelper(
(kind === 'Field' && step === 0 && typeInfo.fieldDef) ||
(kind === 'AliasedField' && step === 2 && typeInfo.fieldDef)
) {
const header = document.createElement('div');
header.className = 'CodeMirror-info-header';
renderField(header, typeInfo, options);
const into = document.createElement('div');
renderField(into, typeInfo, options);
into.appendChild(header);
renderDescription(into, options, typeInfo.fieldDef as any);
return into;
} else if (kind === 'Directive' && step === 1 && typeInfo.directiveDef) {
const header = document.createElement('div');
header.className = 'CodeMirror-info-header';
renderDirective(header, typeInfo, options);
const into = document.createElement('div');
renderDirective(into, typeInfo, options);
into.appendChild(header);
renderDescription(into, options, typeInfo.directiveDef);
return into;
} else if (kind === 'Argument' && step === 0 && typeInfo.argDef) {
const header = document.createElement('div');
header.className = 'CodeMirror-info-header';
renderArg(header, typeInfo, options);
const into = document.createElement('div');
renderArg(into, typeInfo, options);
into.appendChild(header);
renderDescription(into, options, typeInfo.argDef);
return into;
} else if (
kind === 'EnumValue' &&
typeInfo.enumValue &&
typeInfo.enumValue.description
) {
const header = document.createElement('div');
header.className = 'CodeMirror-info-header';
renderEnumValue(header, typeInfo, options);
const into = document.createElement('div');
renderEnumValue(into, typeInfo, options);
into.appendChild(header);
renderDescription(into, options, typeInfo.enumValue);
return into;
} else if (
kind === 'NamedType' &&
typeInfo.type &&
(typeInfo.type as GraphQLObjectType).description
) {
const header = document.createElement('div');
header.className = 'CodeMirror-info-header';
renderType(header, typeInfo, options, typeInfo.type);
const into = document.createElement('div');
renderType(into, typeInfo, options, typeInfo.type);
into.appendChild(header);
renderDescription(into, options, typeInfo.type);
return into;
}
Expand All @@ -125,10 +140,6 @@ function renderQualifiedField(
options: GraphQLInfoOptions,
) {
const fieldName = typeInfo.fieldDef?.name || '';
if (fieldName.slice(0, 2) !== '__') {
renderType(into, typeInfo, options, typeInfo.parentType);
text(into, '.');
}
text(into, fieldName, 'field-name', options, getFieldReference(typeInfo));
}

Expand All @@ -146,38 +157,47 @@ function renderArg(
typeInfo: TypeInfo,
options: GraphQLInfoOptions,
) {
if (typeInfo.directiveDef) {
renderDirective(into, typeInfo, options);
} else if (typeInfo.fieldDef) {
renderQualifiedField(into, typeInfo, options);
}

const name = typeInfo.argDef?.name || '';
text(into, '(');
text(into, name, 'arg-name', options, getArgumentReference(typeInfo));
renderTypeAnnotation(into, typeInfo, options, typeInfo.inputType);
text(into, ')');
}

function renderTypeAnnotation(
function renderEnumValue(
into: HTMLElement,
typeInfo: TypeInfo,
options: GraphQLInfoOptions,
t: Maybe<GraphQLType>,
) {
text(into, ': ');
renderType(into, typeInfo, options, t);
const name = typeInfo.enumValue?.name || '';
renderType(into, typeInfo, options, typeInfo.inputType);
text(into, '.');
text(into, name, 'enum-value', options, getEnumValueReference(typeInfo));
}

function renderEnumValue(
function renderTypeAnnotation(
into: HTMLElement,
typeInfo: TypeInfo,
options: GraphQLInfoOptions,
t: Maybe<GraphQLType>,
) {
const name = typeInfo.enumValue?.name || '';
renderType(into, typeInfo, options, typeInfo.inputType);
text(into, '.');
text(into, name, 'enum-value', options, getEnumValueReference(typeInfo));
const typeSpan = document.createElement('span');
typeSpan.className = 'type-name-pill';
if (t instanceof GraphQLNonNull) {
renderType(typeSpan, typeInfo, options, t.ofType);
text(typeSpan, '!');
} else if (t instanceof GraphQLList) {
text(typeSpan, '[');
renderType(typeSpan, typeInfo, options, t.ofType);
text(typeSpan, ']');
} else {
text(
typeSpan,
t?.name || '',
'type-name',
options,
getTypeReference(typeInfo, t),
);
}
into.appendChild(typeSpan);
}

function renderType(
Expand Down Expand Up @@ -243,16 +263,21 @@ function renderDeprecation(
if (reason) {
const deprecationDiv = document.createElement('div');
deprecationDiv.className = 'info-deprecation';
into.appendChild(deprecationDiv);

const label = document.createElement('span');
label.className = 'info-deprecation-label';
label.appendChild(document.createTextNode('Deprecated'));
deprecationDiv.appendChild(label);

const reasonDiv = document.createElement('div');
reasonDiv.className = 'info-deprecation-reason';
if (options.renderDescription) {
deprecationDiv.innerHTML = options.renderDescription(reason);
reasonDiv.innerHTML = options.renderDescription(reason);
} else {
deprecationDiv.appendChild(document.createTextNode(reason));
reasonDiv.appendChild(document.createTextNode(reason));
}
const label = document.createElement('span');
label.className = 'info-deprecation-label';
label.appendChild(document.createTextNode('Deprecated: '));
deprecationDiv.insertBefore(label, deprecationDiv.firstChild);
into.appendChild(deprecationDiv);
deprecationDiv.appendChild(reasonDiv);
}
}

Expand Down
58 changes: 58 additions & 0 deletions packages/graphiql-react/font/fira-code.css

Large diffs are not rendered by default.

272 changes: 272 additions & 0 deletions packages/graphiql-react/font/roboto.css

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions packages/graphiql-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
],
"files": [
"dist",
"font",
"src",
"types"
],
Expand All @@ -40,17 +41,16 @@
"codemirror": "^5.65.3",
"codemirror-graphql": "^1.3.2",
"copy-to-clipboard": "^3.2.0",
"escape-html": "^1.0.3",
"graphql-language-service": "^5.0.6",
"markdown-it": "^12.2.0",
"set-value": "^4.1.0"
},
"devDependencies": {
"@types/codemirror": "^5.60.5",
"@types/escape-html": "^1.0.1",
"@types/set-value": "^4.0.1",
"@vitejs/plugin-react": "^1.3.0",
"graphql": "^16.4.0",
"postcss-nesting": "^10.1.7",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"typescript": "^4.6.3",
Expand Down
3 changes: 3 additions & 0 deletions packages/graphiql-react/postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
plugins: [require('postcss-nesting')],
};
Loading

0 comments on commit e2c9c5f

Please sign in to comment.