Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v13] Connect: Light theme #28277

Merged
merged 3 commits into from Jun 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 9 additions & 3 deletions web/.storybook/preview.js
Expand Up @@ -21,8 +21,11 @@ import { darkTheme, lightTheme } from './../packages/design/src/theme';
import DefaultThemeProvider from '../packages/design/src/ThemeProvider';
import Box from './../packages/design/src/Box';
import '../packages/teleport/src/lib/polyfillRandomUuid';
import { ThemeProvider as TeletermThemeProvider } from './../packages/teleterm/src/ui/ThemeProvider';
import { theme as TeletermTheme } from './../packages/teleterm/src/ui/ThemeProvider/theme';
import { StaticThemeProvider as TeletermThemeProvider } from './../packages/teleterm/src/ui/ThemeProvider';
import {
darkTheme as teletermDarkTheme,
lightTheme as teletermLightTheme,
} from './../packages/teleterm/src/ui/ThemeProvider/theme';
import { handlersTeleport } from './../packages/teleport/src/mocks/handlers';

// Checks we are running non-node environment (browser)
Expand All @@ -41,7 +44,10 @@ const ThemeDecorator = (storyFn, meta) => {

if (meta.title.startsWith('Teleterm/')) {
ThemeProvider = TeletermThemeProvider;
theme = TeletermTheme;
theme =
meta.globals.theme === 'Dark Theme'
? teletermDarkTheme
: teletermLightTheme;
} else {
ThemeProvider = DefaultThemeProvider;
theme = meta.globals.theme === 'Dark Theme' ? darkTheme : lightTheme;
Expand Down
Expand Up @@ -56,10 +56,7 @@ const ChildWrapper = styled.div`
display: flex;
align-items: center;
justify-content: center;
background: ${props =>
props.theme.name === 'dark'
? props.theme.colors.spotBackground[0]
: props.theme.colors.spotBackground[0]};
background: ${props => props.theme.colors.spotBackground[0]};
border-radius: 200px;
`;

Expand Down
12 changes: 10 additions & 2 deletions web/packages/design/src/DataTable/index.ts
Expand Up @@ -22,7 +22,15 @@ import {
LabelCell,
ClickableLabelCell,
} from './Cells';
import { StyledPanel } from './StyledTable';
import { StyledPanel, StyledTableWrapper } from './StyledTable';

export { Cell, TextCell, DateCell, LabelCell, ClickableLabelCell, StyledPanel };
export {
Cell,
TextCell,
DateCell,
LabelCell,
ClickableLabelCell,
StyledPanel,
StyledTableWrapper,
};
export default Table;
26 changes: 25 additions & 1 deletion web/packages/design/src/theme/darkTheme.ts
Expand Up @@ -15,7 +15,7 @@ limitations under the License.
*/

import { fonts } from './fonts';
import { getContrastRatio } from './utils/colorManipulator';
import { getContrastRatio, lighten } from './utils/colorManipulator';
import { blueGrey, lightBlue, yellow } from './palette';
import typography, { fontSizes, fontWeights } from './typography';
import { sharedStyles } from './sharedStyles';
Expand Down Expand Up @@ -148,6 +148,30 @@ const colors = {
disabledBackground: 'rgba(255, 255, 255, 0.12)',
},

terminal: {
foreground: '#F1F2F4',
background: '#010B1C', // bgTerminal
selectionBackground: 'rgba(255, 255, 255, 0.18)',
cursor: '#FFF',
cursorAccent: '#010B1C',
red: '#FF6257',
green: '#00BFA6',
yellow: '#FFAB00',
blue: '#009EFF',
magenta: '#9F85FF',
cyan: '#00D3F0',
brightWhite: lighten('#010B1C', 0.89),
white: lighten('#010B1C', 0.78),
brightBlack: lighten('#010B1C', 0.61),
black: '#000',
brightRed: '#FF948D',
brightGreen: '#2EFFD5',
brightYellow: '#FFD98C',
brightBlue: '#7BCDFF',
brightMagenta: '#B9A6FF',
brightCyan: '#74EEFF',
},

subtle: blueGrey[50],
link: '#009EFF',
bgTerminal: '#010B1C',
Expand Down
26 changes: 25 additions & 1 deletion web/packages/design/src/theme/lightTheme.ts
Expand Up @@ -15,7 +15,7 @@ limitations under the License.
*/

import { fonts } from './fonts';
import { getContrastRatio } from './utils/colorManipulator';
import { darken, getContrastRatio } from './utils/colorManipulator';
import { lightBlue, blueGrey, yellow } from './palette';
import typography, { fontSizes, fontWeights } from './typography';
import { sharedStyles } from './sharedStyles';
Expand Down Expand Up @@ -144,6 +144,30 @@ const colors = {
disabledBackground: 'rgba(255, 255, 255, 0.12)',
},

terminal: {
foreground: '#000',
background: '#F1F2F4', // levels.sunken
selectionBackground: 'rgba(0, 0, 0, 0.18)',
cursor: '#000',
cursorAccent: '#F1F2F4',
red: '#9D0A00',
green: '#005742',
yellow: '#704B00',
blue: '#004B89',
magenta: '#3D1BB2',
cyan: '#015C6E',
brightWhite: darken('#F1F2F4', 0.55),
white: darken('#F1F2F4', 0.68),
brightBlack: darken('#F1F2F4', 0.8),
black: '#000',
brightRed: '#BF372E',
brightGreen: '#007562',
brightYellow: '#8F5F00',
brightBlue: '#006BB8',
brightMagenta: '#5531D4',
brightCyan: '#007282',
},

subtle: blueGrey[50],
link: '#0073BA',
bgTerminal: '#010B1C',
Expand Down
Expand Up @@ -56,10 +56,6 @@ export const PathInput = forwardRef<

const StyledFieldInput = styled(FieldInput)`
input {
border: 1px solid ${props => props.theme.colors.text.muted};
background: transparent;
color: white;
box-shadow: none;
font-size: 14px;
height: 32px;
}
Expand Down
Expand Up @@ -127,7 +127,7 @@ const Dropzone = styled.button`
color: inherit;
background-color: ${props => props.theme.colors.spotBackground[0]};
margin-top: ${props => props.theme.space[3]}px;
border: 1px dashed ${props => props.theme.colors.spotBackground[1]};
border: 1px dashed ${props => props.theme.colors.text.muted};
height: 128px;
text-align: center;
cursor: pointer;
Expand Down
4 changes: 3 additions & 1 deletion web/packages/teleport/src/components/Toggle/Toggle.tsx
Expand Up @@ -22,9 +22,10 @@ export default function Toggle({
onToggle,
children,
disabled,
className,
}: Props) {
return (
<StyledWrapper disabled={disabled}>
<StyledWrapper disabled={disabled} className={className}>
<StyledInput
checked={isToggled}
onChange={onToggle}
Expand All @@ -41,6 +42,7 @@ type Props = {
onToggle: () => void;
children?: ReactNode;
disabled?: boolean;
className?: string;
};

const StyledWrapper = styled.label`
Expand Down
4 changes: 3 additions & 1 deletion web/packages/teleterm/src/main.ts
Expand Up @@ -18,7 +18,7 @@ import { spawn } from 'child_process';

import path from 'path';

import { app, globalShortcut, shell } from 'electron';
import { app, globalShortcut, shell, nativeTheme } from 'electron';

import MainProcess from 'teleterm/mainProcess';
import { getRuntimeSettings } from 'teleterm/mainProcess/runtimeSettings';
Expand Down Expand Up @@ -59,6 +59,8 @@ async function initializeApp(): Promise<void> {
jsonSchemaFile: configJsonSchemaFileStorage,
platform: settings.platform,
});

nativeTheme.themeSource = configService.get('theme').value;
const windowsManager = new WindowsManager(appStateFileStorage, settings);

process.on('uncaughtException', (error, origin) => {
Expand Down
8 changes: 8 additions & 0 deletions web/packages/teleterm/src/mainProcess/fixtures/mocks.ts
Expand Up @@ -68,6 +68,14 @@ export class MockMainProcessClient implements MainProcessClient {
async openConfigFile() {
return '';
}

shouldUseDarkColors() {
return true;
}

subscribeToNativeThemeUpdate() {
return { cleanup: () => undefined };
}
}

export const makeRuntimeSettings = (
Expand Down
5 changes: 5 additions & 0 deletions web/packages/teleterm/src/mainProcess/mainProcess.ts
Expand Up @@ -26,6 +26,7 @@ import {
ipcMain,
Menu,
MenuItemConstructorOptions,
nativeTheme,
shell,
} from 'electron';
import { wait } from 'shared/utils/wait';
Expand Down Expand Up @@ -193,6 +194,10 @@ export default class MainProcess {
event.returnValue = this.settings;
});

ipcMain.on('main-process-should-use-dark-colors', event => {
event.returnValue = nativeTheme.shouldUseDarkColors;
});

ipcMain.handle('main-process-get-resolved-child-process-addresses', () => {
return this.resolvedChildProcessAddresses;
});
Expand Down
14 changes: 13 additions & 1 deletion web/packages/teleterm/src/mainProcess/mainProcessClient.ts
Expand Up @@ -53,8 +53,20 @@ export default function createMainProcessClient(): MainProcessClient {
removeTshSymlinkMacOs() {
return ipcRenderer.invoke('main-process-remove-tsh-symlink-macos');
},
openConfigFile(): Promise<string> {
openConfigFile() {
return ipcRenderer.invoke('main-process-open-config-file');
},
shouldUseDarkColors() {
return ipcRenderer.sendSync('main-process-should-use-dark-colors');
},
subscribeToNativeThemeUpdate: listener => {
const onThemeChange = (_, value: { shouldUseDarkColors: boolean }) =>
listener(value);
const channel = 'main-process-native-theme-update';
ipcRenderer.addListener(channel, onThemeChange);
return {
cleanup: () => ipcRenderer.removeListener(channel, onThemeChange),
};
},
};
}
7 changes: 7 additions & 0 deletions web/packages/teleterm/src/mainProcess/types.ts
Expand Up @@ -75,6 +75,13 @@ export type MainProcessClient = {

/** Opens config file and returns a path to it. */
openConfigFile(): Promise<string>;
shouldUseDarkColors(): boolean;
/** Subscribes to updates of the native theme. Returns a cleanup function. */
subscribeToNativeThemeUpdate: (
listener: (value: { shouldUseDarkColors: boolean }) => void
) => {
cleanup: () => void;
};
};

export type ChildProcessAddresses = {
Expand Down
22 changes: 19 additions & 3 deletions web/packages/teleterm/src/mainProcess/windowsManager.ts
Expand Up @@ -16,11 +16,18 @@

import path from 'path';

import { app, BrowserWindow, Menu, Rectangle, screen } from 'electron';
import {
app,
BrowserWindow,
Menu,
Rectangle,
screen,
nativeTheme,
} from 'electron';

import { FileStorage } from 'teleterm/services/fileStorage';
import { RuntimeSettings } from 'teleterm/mainProcess/types';
import theme from 'teleterm/ui/ThemeProvider/theme';
import { darkTheme, lightTheme } from 'teleterm/ui/ThemeProvider/theme';

type WindowState = Rectangle;

Expand All @@ -47,13 +54,16 @@ export class WindowsManager {
}

createWindow(): void {
const activeTheme = nativeTheme.shouldUseDarkColors
? darkTheme
: lightTheme;
const windowState = this.getWindowState();
const window = new BrowserWindow({
x: windowState.x,
y: windowState.y,
width: windowState.width,
height: windowState.height,
backgroundColor: theme.colors.levels.sunken,
backgroundColor: activeTheme.colors.levels.sunken,
minWidth: 400,
minHeight: 300,
show: false,
Expand Down Expand Up @@ -88,6 +98,12 @@ export class WindowsManager {
this.popupUniversalContextMenu(window, props);
});

nativeTheme.on('updated', () => {
window.webContents.send('main-process-native-theme-update', {
shouldUseDarkColors: nativeTheme.shouldUseDarkColors,
});
});

window.webContents.session.setPermissionRequestHandler(
(webContents, permission, callback) => {
// deny all permissions requests, we currently do not require any
Expand Down
4 changes: 4 additions & 0 deletions web/packages/teleterm/src/services/config/appConfigSchema.ts
Expand Up @@ -106,6 +106,10 @@ export const createAppConfigSchema = (platform: Platform) => {
.max(256)
.default(15)
.describe('Font size for the terminal.'),
theme: z
.enum(['light', 'dark', 'system'])
.default('system')
.describe('Color theme for the app.'),
});
};

Expand Down
Expand Up @@ -48,7 +48,7 @@ export type NavButtonProps = {
const StyledNavButton = styled.button(props => {
return {
color: props.active
? props.theme.colors.light
? props.theme.colors.text.main
: props.theme.colors.text.slightlyMuted,
cursor: 'pointer',
fontFamily: 'inherit',
Expand Down
Expand Up @@ -40,7 +40,7 @@ export default function ClusterResources() {

return (
<StyledMain>
<Flex mt={3} pb={5} flexDirection="column">
<Flex pb={5} flexDirection="column">
<SideNav mb={2} />
<HorizontalSplit>
{clusterCtx.isLocationActive('/resources/servers') && <Servers />}
Expand Down