Skip to content

Commit

Permalink
chore(Portal): eliminate flickering on theme switch (#2281)
Browse files Browse the repository at this point in the history
  • Loading branch information
tujoworker committed May 31, 2023
1 parent 2e3d790 commit 02656a7
Show file tree
Hide file tree
Showing 17 changed files with 280 additions and 167 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

describe('Grid', () => {
beforeEach(() => {
cy.visit('/uilib')
cy.visit('/uilib?data-visual-test') // skip animation

// Check if app is mounted
cy.get('#dnb-drawer-list__portal', { timeout: 10000 }).should('exist')
Expand Down
89 changes: 89 additions & 0 deletions packages/dnb-design-system-portal/cypress/e2e/themeSwitch.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/**
* Cypress e2e Test
*
*/

describe('Theme', () => {
beforeEach(() => {
cy.visit('/uilib?data-visual-test') // skip animation

// Check if app is mounted
cy.get('#dnb-drawer-list__portal', { timeout: 10000 }).should('exist')
})

afterEach(() => {
cy.clearLocalStorage('eufemia-theme')
})

it('should have preload link', () => {
cy.get('link[href^="/ui."][rel="preload"]')
.should('exist')
.its('length')
.should('equal', 1)
})

it('should load css file', () => {
cy.get('#portal-tools').click()

// Choose last one
cy.get('#change-theme').click()
cy.get('#change-theme-portal ul li').eq(2).click()

cy.get('link[href^="/sbanken."]', { timeout: 10000 })
.should('exist')
.its('length')
.should('equal', 1)
})

it('should set local storage', () => {
cy.get('#portal-tools').click()

// Choose last one
cy.get('#change-theme').click()
cy.get('#change-theme-portal ul li').eq(2).click()

cy.getAllLocalStorage().then((result) => {
expect(Object.values(result)[0]['eufemia-theme']).to.equal(
'{"name":"sbanken"}'
)
})
})

it('should switch back and forth', () => {
cy.get('#portal-tools').click()

// Choose last one
cy.get('#change-theme').click()
cy.get('#change-theme-portal ul li').eq(2).click()

// Choose first one again
cy.get('#change-theme').click()
cy.get('#change-theme-portal ul li').eq(0).click()

cy.get('link[href^="/ui."][rel="stylesheet"]', { timeout: 10000 })
.should('exist')
.its('length')
.should('equal', 1)
})

it('should load css file after template', () => {
cy.get('#portal-tools').click()

// Choose last one
cy.get('#change-theme').click()
cy.get('#change-theme-portal ul li').eq(2).click()

cy.get(
'#eufemia-style-theme + link[href^="/sbanken."][rel="stylesheet"]',
{ timeout: 10000 }
).should('exist')

// Choose first one again
cy.get('#change-theme').click()
cy.get('#change-theme-portal ul li').eq(0).click()

cy.get('#eufemia-style-theme + link[href^="/ui."][rel="stylesheet"]', {
timeout: 10000,
}).should('exist')
})
})
5 changes: 1 addition & 4 deletions packages/dnb-design-system-portal/gatsby-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,7 @@ const plugins = [
themes: {
ui: { name: 'DNB' }, // universal identity
eiendom: { name: 'DNB Eiendom' },
sbanken: {
name: 'Sbanken (WIP)',
hide: /release|beta|portal/.test(currentBranch),
},
sbanken: { name: 'Sbanken (WIP)' },
},
filesGlob: shouldUsePrebuild()
? '**/build/style/themes/**/*-theme-*.min.css'
Expand Down
4 changes: 4 additions & 0 deletions packages/dnb-design-system-portal/raw-loader.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
declare module '!raw-loader!terser-loader!*' {
const contents: string
export = contents
}
17 changes: 11 additions & 6 deletions packages/dnb-design-system-portal/src/core/ChangeStyleTheme.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import React from 'react'
import { Dropdown, Switch } from '@dnb/eufemia/src'

import { Context } from '@dnb/eufemia/src/shared'
import {
getThemes,
getTheme,
setTheme,
} from 'gatsby-plugin-eufemia-theme-handler'

export default function ChangeStyleTheme() {
const themes: Array<{ name: string; hide?: boolean }> = getThemes()
const themes = getThemes()
const { name } = getTheme()
const { update } = React.useContext(Context)

const date = Object.entries(themes).reduce((acc, [key, value]) => {
if (!value?.hide) {
Expand All @@ -20,10 +21,14 @@ export default function ChangeStyleTheme() {

return (
<Dropdown
id="change-theme"
value={name}
data={date}
on_change={({ data: { value } }) => {
setTheme({ name: value })
update({ skeleton: true })
setTheme({ name: value }, () => {
update({ skeleton: false })
})
}}
/>
)
Expand All @@ -32,14 +37,14 @@ export default function ChangeStyleTheme() {
ChangeStyleTheme.ColorMapping = ColorMapping

function ColorMapping({ enabled, ...props }) {
const { colors } = getTheme()
const { colorMapping } = getTheme()
return (
<Switch
top
label="Toggle Color Mapping"
checked={colors || enabled}
checked={colorMapping === 'basis' || enabled}
on_change={({ checked }) => {
setTheme({ colors: checked })
setTheme({ colorMapping: checked ? 'basis' : null })
}}
{...props}
/>
Expand Down
16 changes: 0 additions & 16 deletions packages/dnb-design-system-portal/src/core/PortalProviders.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,22 +62,6 @@ export const rootElement =
function ThemeProvider({ children }) {
const themeName = useThemeName()

// Deprecated (can be removed when we are full and 100% officially using Reavt v18)
// When using React v17,
// we need to ovecome a hydration issue.
// The JS app gets the correct themeName,
// but React does not change it in the HTML
React.useLayoutEffect(() => {
const element = document.querySelector('.eufemia-theme')
const htmlName = element?.getAttribute('data-name')

if (htmlName !== themeName) {
element.setAttribute('data-name', themeName)
element.classList.remove(`eufemia-theme__${htmlName}`)
element.classList.add(`eufemia-theme__${themeName}`)
}
}, [themeName])

return <Theme name={themeName}>{children}</Theme>
}

Expand Down
4 changes: 4 additions & 0 deletions packages/dnb-design-system-portal/src/docs_dummy/dummy.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,12 @@ redirect_from:
- /other-dummy
---

import ChangeStyleTheme from '../core/ChangeStyleTheme'

# What is this?

This file contains all required GraphQL Frontmatter fields

Have a nice day!

<ChangeStyleTheme />
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,7 @@ export default function PortalToolsMenu({
{theme.name === 'sbanken' && (
<Space top="large">
<H2 size="small">Map colors</H2>
<Space top>
<ChangeStyleTheme.ColorMapping
enabled={theme.colorMapping}
/>
</Space>
<ChangeStyleTheme.ColorMapping enabled={theme.colorMapping} />
</Space>
)}

Expand Down
2 changes: 2 additions & 0 deletions packages/dnb-eufemia/src/shared/Theme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ import { DynamicElement } from './types'
export type ThemeNames = 'ui' | 'eiendom' | 'sbanken'
export type ThemeVariants = string
export type ThemeSizes = 'basis'
export type ColorMapping = 'basis'

export type ThemeProps = {
name?: ThemeNames
variant?: ThemeVariants
size?: ThemeSizes
colorMapping?: ColorMapping
element?: DynamicElement
}

Expand Down
4 changes: 2 additions & 2 deletions packages/gatsby-plugin-eufemia-theme-handler/gatsby-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ exports.onCreateWebpackConfig = (

config.plugins.push(
plugins.define({
'process.env.EUFEMIA_THEME_defaultTheme': JSON.stringify(
'globalThis.EUFEMIA_THEME_defaultTheme': JSON.stringify(
pluginOptions.defaultTheme
),
'process.env.EUFEMIA_THEME_themes': JSON.stringify(
'globalThis.EUFEMIA_THEME_themes': JSON.stringify(
pluginOptions.themes
),
})
Expand Down
51 changes: 0 additions & 51 deletions packages/gatsby-plugin-eufemia-theme-handler/inlineScriptDev.js

This file was deleted.

23 changes: 23 additions & 0 deletions packages/gatsby-plugin-eufemia-theme-handler/inlineScriptDev.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
if (typeof window !== 'undefined') {
try {
const headElement = document.querySelector('html head')
const logMutations = (mutations) => {
for (const mutation of mutations) {
const element = mutation.nextSibling
if (
element &&
(element.src || element.href || '').includes('/commons.')
) {
const themeName = globalThis.__getEufemiaThemeName()
globalThis.__updateEufemiaThemeFile(themeName, true)
break
}
}
}

const observer = new MutationObserver(logMutations)
observer.observe(headElement, { childList: true })
} catch (e) {
console.error(e)
}
}
70 changes: 0 additions & 70 deletions packages/gatsby-plugin-eufemia-theme-handler/inlineScriptProd.js

This file was deleted.

Loading

0 comments on commit 02656a7

Please sign in to comment.