-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ColorScheme] Update from avatar menu (#161214)
- Loading branch information
Showing
29 changed files
with
1,126 additions
and
201 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
...lugins/cloud_integrations/cloud_links/public/maybe_add_cloud_links/theme_darkmode_hook.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import { useCallback, useEffect, useState } from 'react'; | ||
import { i18n } from '@kbn/i18n'; | ||
import type { SecurityPluginStart } from '@kbn/security-plugin/public'; | ||
import { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; | ||
|
||
interface Deps { | ||
uiSettingsClient: IUiSettingsClient; | ||
security: SecurityPluginStart; | ||
} | ||
|
||
export const useThemeDarkmodeToggle = ({ uiSettingsClient, security }: Deps) => { | ||
const [isDarkModeOn, setIsDarkModeOn] = useState(false); | ||
// If a value is set in kibana.yml (uiSettings.overrides.theme:darkMode) | ||
// we don't allow the user to change the theme color. | ||
const valueSetInKibanaConfig = uiSettingsClient.isOverridden('theme:darkMode'); | ||
|
||
const { userProfileData, isLoading, update } = security.hooks.useUpdateUserProfile({ | ||
notificationSuccess: { | ||
title: i18n.translate('xpack.cloudLinks.userMenuLinks.darkMode.successNotificationTitle', { | ||
defaultMessage: 'Color theme updated', | ||
}), | ||
pageReloadText: i18n.translate( | ||
'xpack.cloudLinks.userMenuLinks.darkMode.successNotificationText', | ||
{ | ||
defaultMessage: 'Reload the page to see the changes', | ||
} | ||
), | ||
}, | ||
pageReloadChecker: (prev, next) => { | ||
return prev?.userSettings?.darkMode !== next.userSettings?.darkMode; | ||
}, | ||
}); | ||
|
||
const { userSettings: { darkMode: colorScheme } = { darkMode: undefined } } = | ||
userProfileData ?? {}; | ||
|
||
const toggle = useCallback( | ||
(on: boolean) => { | ||
if (isLoading) { | ||
return; | ||
} | ||
update({ | ||
userSettings: { | ||
darkMode: on ? 'dark' : 'light', | ||
}, | ||
}); | ||
}, | ||
[isLoading, update] | ||
); | ||
|
||
useEffect(() => { | ||
let updatedValue = false; | ||
|
||
if (typeof colorScheme !== 'string') { | ||
// User profile does not have yet any preference -> default to space dark mode value | ||
updatedValue = uiSettingsClient.get('theme:darkMode') ?? false; | ||
} else { | ||
updatedValue = colorScheme === 'dark'; | ||
} | ||
|
||
setIsDarkModeOn(updatedValue); | ||
}, [colorScheme, uiSettingsClient]); | ||
|
||
return { | ||
isVisible: valueSetInKibanaConfig ? false : Boolean(userProfileData), | ||
toggle, | ||
isDarkModeOn, | ||
colorScheme, | ||
}; | ||
}; |
57 changes: 57 additions & 0 deletions
57
...loud_integrations/cloud_links/public/maybe_add_cloud_links/theme_darkmode_toggle.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import React from 'react'; | ||
import { render, fireEvent } from '@testing-library/react'; | ||
import '@testing-library/jest-dom'; | ||
import { coreMock } from '@kbn/core/public/mocks'; | ||
import { securityMock } from '@kbn/security-plugin/public/mocks'; | ||
|
||
import { ThemDarkModeToggle } from './theme_darkmode_toggle'; | ||
|
||
describe('ThemDarkModeToggle', () => { | ||
const mockUseUpdateUserProfile = jest.fn(); | ||
const mockGetSpaceDarkModeValue = jest.fn(); | ||
|
||
it('renders correctly and toggles dark mode', () => { | ||
const security = { | ||
...securityMock.createStart(), | ||
hooks: { useUpdateUserProfile: mockUseUpdateUserProfile }, | ||
}; | ||
const { uiSettings } = coreMock.createStart(); | ||
|
||
const mockUpdate = jest.fn(); | ||
mockUseUpdateUserProfile.mockReturnValue({ | ||
userProfileData: { userSettings: { darkMode: 'light' } }, | ||
isLoading: false, | ||
update: mockUpdate, | ||
}); | ||
|
||
mockGetSpaceDarkModeValue.mockReturnValue(false); | ||
|
||
const { getByTestId, rerender } = render( | ||
<ThemDarkModeToggle security={security} uiSettingsClient={uiSettings} /> | ||
); | ||
|
||
const toggleSwitch = getByTestId('darkModeToggleSwitch'); | ||
fireEvent.click(toggleSwitch); | ||
expect(mockUpdate).toHaveBeenCalledWith({ userSettings: { darkMode: 'dark' } }); | ||
|
||
// Now we want to simulate toggling back to light | ||
mockUseUpdateUserProfile.mockReturnValue({ | ||
userProfileData: { userSettings: { darkMode: 'dark' } }, | ||
isLoading: false, | ||
update: mockUpdate, | ||
}); | ||
|
||
// Rerender the component to apply the new props | ||
rerender(<ThemDarkModeToggle security={security} uiSettingsClient={uiSettings} />); | ||
|
||
fireEvent.click(toggleSwitch); | ||
expect(mockUpdate).toHaveBeenLastCalledWith({ userSettings: { darkMode: 'light' } }); | ||
}); | ||
}); |
Oops, something went wrong.