From 9aef83a32aeb5f193a3ff0f191c95d09eb0d70b6 Mon Sep 17 00:00:00 2001 From: Jake Harclerode Date: Thu, 15 Aug 2024 08:44:45 -0700 Subject: [PATCH] add defaultTheme prop to specify default theme if no previous value stored (#3619) * add defaultTheme prop to specify default theme if no previous value in storageContext * yoyo --------- Co-authored-by: Dimitri POSTOLOV --- .changeset/orange-cars-glow.md | 6 +++ packages/graphiql-react/src/theme.ts | 4 +- packages/graphiql/cypress/e2e/theme.cy.ts | 37 +++++++++++++------ packages/graphiql/resources/renderExample.js | 1 + packages/graphiql/src/components/GraphiQL.tsx | 4 +- 5 files changed, 38 insertions(+), 14 deletions(-) create mode 100644 .changeset/orange-cars-glow.md diff --git a/.changeset/orange-cars-glow.md b/.changeset/orange-cars-glow.md new file mode 100644 index 00000000000..c829f642a15 --- /dev/null +++ b/.changeset/orange-cars-glow.md @@ -0,0 +1,6 @@ +--- +'@graphiql/react': minor +'graphiql': minor +--- + +add new prop `defaultTheme` to set the default color preference theme diff --git a/packages/graphiql-react/src/theme.ts b/packages/graphiql-react/src/theme.ts index 5dc3b8ea669..a8bd0b7126c 100644 --- a/packages/graphiql-react/src/theme.ts +++ b/packages/graphiql-react/src/theme.ts @@ -7,7 +7,7 @@ import { useStorageContext } from './storage'; */ export type Theme = 'light' | 'dark' | null; -export function useTheme() { +export function useTheme(defaultTheme: Theme = null) { const storageContext = useStorageContext(); const [theme, setThemeInternal] = useState(() => { @@ -26,7 +26,7 @@ export function useTheme() { // Remove the invalid stored value storageContext.set(STORAGE_KEY, ''); } - return null; + return defaultTheme; } }); diff --git a/packages/graphiql/cypress/e2e/theme.cy.ts b/packages/graphiql/cypress/e2e/theme.cy.ts index 456b99511de..e22d2fa4b5d 100644 --- a/packages/graphiql/cypress/e2e/theme.cy.ts +++ b/packages/graphiql/cypress/e2e/theme.cy.ts @@ -1,17 +1,32 @@ 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'); - }); + describe('`forcedTheme`', () => { + it('Switches to light theme when `forcedTheme` is light', () => { + cy.visit('/?forcedTheme=light'); + cy.get('body').should('have.class', 'graphiql-light'); + }); + + it('Switches to dark theme when `forcedTheme` is dark', () => { + cy.visit('/?forcedTheme=dark'); + cy.get('body').should('have.class', 'graphiql-dark'); + }); - 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('/?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 + }); }); - 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 + describe('`defaultTheme`', () => { + it('should have light theme', () => { + cy.visit('/?defaultTheme=light'); + cy.get('body').should('have.class', 'graphiql-light'); + }); + it('should have dark theme', () => { + cy.visit('/?defaultTheme=dark'); + cy.get('body').should('have.class', 'graphiql-dark'); + }); }); }); diff --git a/packages/graphiql/resources/renderExample.js b/packages/graphiql/resources/renderExample.js index b3276303ddb..0bbadd29069 100644 --- a/packages/graphiql/resources/renderExample.js +++ b/packages/graphiql/resources/renderExample.js @@ -95,5 +95,6 @@ root.render( onTabChange, forcedTheme: parameters.forcedTheme, defaultQuery: parameters.defaultQuery, + defaultTheme: parameters.defaultTheme, }), ); diff --git a/packages/graphiql/src/components/GraphiQL.tsx b/packages/graphiql/src/components/GraphiQL.tsx index c108f69624d..470cbd6f2ad 100644 --- a/packages/graphiql/src/components/GraphiQL.tsx +++ b/packages/graphiql/src/components/GraphiQL.tsx @@ -40,6 +40,7 @@ import { Spinner, Tab, Tabs, + Theme, ToolbarButton, Tooltip, UnStyledButton, @@ -219,6 +220,7 @@ export type GraphiQLInterfaceProps = WriteableEditorProps & * settings modal. */ showPersistHeadersSettings?: boolean; + defaultTheme?: Theme; disableTabs?: boolean; /** * `forcedTheme` allows enforcement of a specific theme for GraphiQL. @@ -263,7 +265,7 @@ export function GraphiQLInterface(props: GraphiQLInterfaceProps) { const merge = useMergeQuery(); const prettify = usePrettifyEditors(); - const { theme, setTheme } = useTheme(); + const { theme, setTheme } = useTheme(props.defaultTheme); useEffect(() => { if (forcedTheme === 'system') {