Skip to content

Commit

Permalink
GraphiQL component: forcedTheme (#3407)
Browse files Browse the repository at this point in the history
* GraphiQL component: `showThemeSettings`

changeset

change prop to enforceTheme

clean

change prop name

cypress theme tests

delete onEditForceTheme

fix some

new changeset

fix

fix

Update packages/graphiql/cypress/e2e/theme.cy.ts

Co-authored-by: Dimitri POSTOLOV <en3m@ya.ru>

Update packages/graphiql/cypress/e2e/theme.cy.ts

Co-authored-by: Dimitri POSTOLOV <en3m@ya.ru>

Update packages/graphiql/cypress/e2e/theme.cy.ts

Co-authored-by: Dimitri POSTOLOV <en3m@ya.ru>

Update packages/graphiql/resources/renderExample.js

Co-authored-by: Dimitri POSTOLOV <en3m@ya.ru>

Update packages/graphiql/src/components/GraphiQL.tsx

Co-authored-by: Dimitri POSTOLOV <en3m@ya.ru>

Update packages/graphiql/src/components/GraphiQL.tsx

Co-authored-by: Dimitri POSTOLOV <en3m@ya.ru>

Update packages/graphiql/cypress/e2e/theme.cy.ts

Co-authored-by: Dimitri POSTOLOV <en3m@ya.ru>

Update .changeset/famous-shirts-mate.md

Co-authored-by: Dimitri POSTOLOV <en3m@ya.ru>

Update packages/graphiql/cypress/e2e/theme.cy.ts

Co-authored-by: Dimitri POSTOLOV <en3m@ya.ru>

Update packages/graphiql/cypress/e2e/theme.cy.ts

Co-authored-by: Dimitri POSTOLOV <en3m@ya.ru>

Update packages/graphiql/cypress/e2e/theme.cy.ts

Co-authored-by: Dimitri POSTOLOV <en3m@ya.ru>

* Update packages/graphiql/src/components/GraphiQL.tsx

Co-authored-by: Ted Thibodeau Jr <tthibodeau@openlinksw.com>

* Update packages/graphiql/src/components/GraphiQL.tsx

Co-authored-by: Ted Thibodeau Jr <tthibodeau@openlinksw.com>

* simplify

* fix cypress

---------

Co-authored-by: Dimitri POSTOLOV <en3m@ya.ru>
Co-authored-by: Ted Thibodeau Jr <tthibodeau@openlinksw.com>
Co-authored-by: Dimitri POSTOLOV <dmytropostolov@gmail.com>
  • Loading branch information
4 people authored Jun 17, 2024
1 parent c126878 commit 115c1c0
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 33 deletions.
5 changes: 5 additions & 0 deletions .changeset/famous-shirts-mate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'graphiql': minor
---

Add a new prop to GraphiQL component: `forcedTheme` to force the theme and hide the theme switcher.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ module.exports = {
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/non-nullable-type-assertion-style': 'error',
'@typescript-eslint/consistent-type-assertions': 'error',
'@typescript-eslint/no-duplicate-type-constituents': 'error',
// TODO: Fix all errors for the following rules included in recommended config
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
Expand Down
17 changes: 17 additions & 0 deletions packages/graphiql/cypress/e2e/theme.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
describe('Theme', () => {
it('Switches to light theme when `forcedTheme` is light', () => {
cy.visit('/?query={test}&forcedTheme=light');
cy.get('body').should('have.class', 'graphiql-light');
});

it('Switches to dark theme when `forcedTheme` is dark', () => {
cy.visit('/?query={test}&forcedTheme=dark');
cy.get('body').should('have.class', 'graphiql-dark');
});

it('Defaults to light theme when `forcedTheme` value is invalid', () => {
cy.visit('/?query={test}&forcedTheme=invalid');
cy.get('[data-value=settings]').click();
cy.get('.graphiql-dialog-section-title').eq(1).should('have.text', 'Theme'); // Check for the presence of the theme dialog
});
});
1 change: 1 addition & 0 deletions packages/graphiql/resources/renderExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,6 @@ root.render(
shouldPersistHeaders: true,
inputValueDeprecation: GraphQLVersion.includes('15.5') ? undefined : true,
onTabChange,
forcedTheme: parameters.forcedTheme,
}),
);
94 changes: 61 additions & 33 deletions packages/graphiql/src/components/GraphiQL.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import React, {
ReactElement,
useCallback,
useState,
useEffect,
useMemo,
} from 'react';

import {
Expand Down Expand Up @@ -168,6 +170,7 @@ export function GraphiQL({
<GraphiQLInterface
showPersistHeadersSettings={shouldPersistHeaders !== false}
disableTabs={props.disableTabs ?? false}
forcedTheme={props.forcedTheme}
{...props}
/>
</GraphiQLProvider>
Expand Down Expand Up @@ -216,22 +219,45 @@ export type GraphiQLInterfaceProps = WriteableEditorProps &
*/
showPersistHeadersSettings?: boolean;
disableTabs?: boolean;
/**
* forcedTheme allows enforcement of a specific theme for GraphiQL.
* This is useful when you want to make sure that GraphiQL is always
* rendered with a specific theme
*/
forcedTheme?: (typeof THEMES)[number];
};

const THEMES = ['light', 'dark', 'system'] as const;

export function GraphiQLInterface(props: GraphiQLInterfaceProps) {
const isHeadersEditorEnabled = props.isHeadersEditorEnabled ?? true;
const editorContext = useEditorContext({ nonNull: true });
const executionContext = useExecutionContext({ nonNull: true });
const schemaContext = useSchemaContext({ nonNull: true });
const storageContext = useStorageContext();
const pluginContext = usePluginContext();
const forcedTheme = useMemo(
() =>
props.forcedTheme && THEMES.includes(props.forcedTheme)
? props.forcedTheme
: undefined,
[props.forcedTheme],
);

const copy = useCopyQuery({ onCopyQuery: props.onCopyQuery });
const merge = useMergeQuery();
const prettify = usePrettifyEditors();

const { theme, setTheme } = useTheme();

useEffect(() => {
if (forcedTheme === 'system') {
setTheme(null);
} else if (forcedTheme === 'light' || forcedTheme === 'dark') {
setTheme(forcedTheme);
}
}, [forcedTheme, setTheme]);

const PluginContent = pluginContext?.visiblePlugin?.content;

const pluginResize = useDragResize({
Expand Down Expand Up @@ -317,7 +343,7 @@ export function GraphiQLInterface(props: GraphiQLInterfaceProps) {
<ToolbarButton onClick={copy} label="Copy query (Shift-Ctrl-C)">
<CopyIcon className="graphiql-toolbar-icon" aria-hidden="true" />
</ToolbarButton>
{props.toolbar?.additionalContent && props.toolbar.additionalContent}
{props.toolbar?.additionalContent}
{props.toolbar?.additionalComponent && (
<props.toolbar.additionalComponent />
)}
Expand Down Expand Up @@ -520,7 +546,7 @@ export function GraphiQLInterface(props: GraphiQLInterfaceProps) {
)}
<div ref={pluginResize.secondRef} className="graphiql-sessions">
<div className="graphiql-session-header">
{props.disableTabs ? null : (
{!props.disableTabs && (
<Tabs
values={editorContext.tabs}
onReorder={handleReorder}
Expand Down Expand Up @@ -772,39 +798,41 @@ export function GraphiQLInterface(props: GraphiQLInterfaceProps) {
</ButtonGroup>
</div>
) : null}
<div className="graphiql-dialog-section">
<div>
<div className="graphiql-dialog-section-title">Theme</div>
<div className="graphiql-dialog-section-caption">
Adjust how the interface looks like.
{!forcedTheme && (
<div className="graphiql-dialog-section">
<div>
<div className="graphiql-dialog-section-title">Theme</div>
<div className="graphiql-dialog-section-caption">
Adjust how the interface appears.
</div>
</div>
<ButtonGroup>
<Button
type="button"
className={theme === null ? 'active' : ''}
onClick={handleChangeTheme}
>
System
</Button>
<Button
type="button"
className={theme === 'light' ? 'active' : ''}
data-theme="light"
onClick={handleChangeTheme}
>
Light
</Button>
<Button
type="button"
className={theme === 'dark' ? 'active' : ''}
data-theme="dark"
onClick={handleChangeTheme}
>
Dark
</Button>
</ButtonGroup>
</div>
<ButtonGroup>
<Button
type="button"
className={theme === null ? 'active' : ''}
onClick={handleChangeTheme}
>
System
</Button>
<Button
type="button"
className={theme === 'light' ? 'active' : ''}
data-theme="light"
onClick={handleChangeTheme}
>
Light
</Button>
<Button
type="button"
className={theme === 'dark' ? 'active' : ''}
data-theme="dark"
onClick={handleChangeTheme}
>
Dark
</Button>
</ButtonGroup>
</div>
)}
{storageContext ? (
<div className="graphiql-dialog-section">
<div>
Expand Down

0 comments on commit 115c1c0

Please sign in to comment.