chore(html): add html settings dialog (#37565)
This commit is contained in:
parent
ef9ce58723
commit
888da0f89d
|
|
@ -454,8 +454,12 @@ SOFTWARE. */
|
||||||
--color-scale-coral-9: #510901
|
--color-scale-coral-9: #510901
|
||||||
}
|
}
|
||||||
|
|
||||||
@media(prefers-color-scheme: dark) {
|
:root.light-mode {
|
||||||
:root {
|
color-scheme: light;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark-mode {
|
||||||
|
color-scheme: dark;
|
||||||
--color-canvas-default-transparent: rgba(13,17,23,0);
|
--color-canvas-default-transparent: rgba(13,17,23,0);
|
||||||
--color-marketing-icon-primary: #79c0ff;
|
--color-marketing-icon-primary: #79c0ff;
|
||||||
--color-marketing-icon-secondary: #1f6feb;
|
--color-marketing-icon-secondary: #1f6feb;
|
||||||
|
|
@ -887,5 +891,4 @@ SOFTWARE. */
|
||||||
--color-scale-coral-7: #872012;
|
--color-scale-coral-7: #872012;
|
||||||
--color-scale-coral-8: #640D04;
|
--color-scale-coral-8: #640D04;
|
||||||
--color-scale-coral-9: #460701
|
--color-scale-coral-9: #460701
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,12 @@ svg {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cursor-pointer,
|
||||||
|
.cursor-pointer > * {
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
.hbox {
|
.hbox {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: auto;
|
flex: auto;
|
||||||
|
|
@ -296,6 +302,22 @@ article, aside, details, figcaption, figure, footer, header, main, menu, nav, se
|
||||||
background-color: var(--color-btn-hover-bg);
|
background-color: var(--color-btn-hover-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
outline: var(--color-focus-border);
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog {
|
||||||
|
background-color: var(--color-canvas-subtle);
|
||||||
|
border: 1px solid var(--color-border-default);
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subnav-item .octicon.octicon-settings {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 600px) {
|
@media only screen and (max-width: 600px) {
|
||||||
.subnav-item, .form-control {
|
.subnav-item, .form-control {
|
||||||
border-radius: 0 !important;
|
border-radius: 0 !important;
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ import { Link, navigate, SearchParamsContext } from './links';
|
||||||
import { statusIcon } from './statusIcon';
|
import { statusIcon } from './statusIcon';
|
||||||
import { filterWithQuery } from './filter';
|
import { filterWithQuery } from './filter';
|
||||||
import { linkifyText } from '@web/renderUtils';
|
import { linkifyText } from '@web/renderUtils';
|
||||||
|
import { Dialog } from '@web/shared/dialog';
|
||||||
|
import { useDarkModeSetting } from '@web/theme';
|
||||||
|
|
||||||
export const HeaderView: React.FC<{
|
export const HeaderView: React.FC<{
|
||||||
title: string | undefined,
|
title: string | undefined,
|
||||||
|
|
@ -90,6 +92,7 @@ const StatsNavView: React.FC<{
|
||||||
<NavLink token='failed' count={stats.unexpected} />
|
<NavLink token='failed' count={stats.unexpected} />
|
||||||
<NavLink token='flaky' count={stats.flaky} />
|
<NavLink token='flaky' count={stats.flaky} />
|
||||||
<NavLink token='skipped' count={stats.skipped} />
|
<NavLink token='skipped' count={stats.skipped} />
|
||||||
|
<SettingsButton />
|
||||||
</nav>;
|
</nav>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -112,3 +115,42 @@ const NavLink: React.FC<{
|
||||||
<span className='d-inline counter'>{count}</span>
|
<span className='d-inline counter'>{count}</span>
|
||||||
</Link>;
|
</Link>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const SettingsButton: React.FC = () => {
|
||||||
|
const settingsRef = React.useRef<HTMLAnchorElement>(null);
|
||||||
|
const [settingsOpen, setSettingsOpen] = React.useState(false);
|
||||||
|
const [darkMode, setDarkMode] = useDarkModeSetting();
|
||||||
|
|
||||||
|
return <>
|
||||||
|
<Dialog
|
||||||
|
open={settingsOpen}
|
||||||
|
width={200}
|
||||||
|
verticalOffset={8}
|
||||||
|
requestClose={() => setSettingsOpen(false)}
|
||||||
|
anchor={settingsRef}
|
||||||
|
dataTestId='settings-dialog'
|
||||||
|
>
|
||||||
|
<div className='hbox cursor-pointer' style={{ alignItems: 'center' }}>
|
||||||
|
<input type='checkbox' id='dark-mode-setting' checked={darkMode} onChange={() => setDarkMode(!darkMode)}></input>
|
||||||
|
<label htmlFor='dark-mode-setting'>Dark mode</label>
|
||||||
|
</div>
|
||||||
|
</Dialog>
|
||||||
|
<a
|
||||||
|
ref={settingsRef}
|
||||||
|
style={{ cursor: 'pointer' }}
|
||||||
|
className='subnav-item'
|
||||||
|
title='Settings'
|
||||||
|
onClick={e => {
|
||||||
|
setSettingsOpen(!settingsOpen);
|
||||||
|
e.preventDefault();
|
||||||
|
}}
|
||||||
|
onMouseDown={preventDefault}>
|
||||||
|
{icons.settings()}
|
||||||
|
</a>
|
||||||
|
</>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const preventDefault = (e: any) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -103,3 +103,9 @@ export const copy = () => {
|
||||||
<path d='M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z'></path>
|
<path d='M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z'></path>
|
||||||
</svg>;
|
</svg>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const settings = () => {
|
||||||
|
return <svg className='octicon octicon-settings' viewBox='0 0 16 16' width='16' height='16' aria-hidden='true'>
|
||||||
|
<path d='M8 0a8.2 8.2 0 0 1 .701.031C9.444.095 9.99.645 10.16 1.29l.288 1.107c.018.066.079.158.212.224.231.114.454.243.668.386.123.082.233.09.299.071l1.103-.303c.644-.176 1.392.021 1.82.63.27.385.506.792.704 1.218.315.675.111 1.422-.364 1.891l-.814.806c-.049.048-.098.147-.088.294.016.257.016.515 0 .772-.01.147.038.246.088.294l.814.806c.475.469.679 1.216.364 1.891a7.977 7.977 0 0 1-.704 1.217c-.428.61-1.176.807-1.82.63l-1.102-.302c-.067-.019-.177-.011-.3.071a5.909 5.909 0 0 1-.668.386c-.133.066-.194.158-.211.224l-.29 1.106c-.168.646-.715 1.196-1.458 1.26a8.006 8.006 0 0 1-1.402 0c-.743-.064-1.289-.614-1.458-1.26l-.289-1.106c-.018-.066-.079-.158-.212-.224a5.738 5.738 0 0 1-.668-.386c-.123-.082-.233-.09-.299-.071l-1.103.303c-.644.176-1.392-.021-1.82-.63a8.12 8.12 0 0 1-.704-1.218c-.315-.675-.111-1.422.363-1.891l.815-.806c.05-.048.098-.147.088-.294a6.214 6.214 0 0 1 0-.772c.01-.147-.038-.246-.088-.294l-.815-.806C.635 6.045.431 5.298.746 4.623a7.92 7.92 0 0 1 .704-1.217c.428-.61 1.176-.807 1.82-.63l1.102.302c.067.019.177.011.3-.071.214-.143.437-.272.668-.386.133-.066.194-.158.211-.224l.29-1.106C6.009.645 6.556.095 7.299.03 7.53.01 7.764 0 8 0Zm-.571 1.525c-.036.003-.108.036-.137.146l-.289 1.105c-.147.561-.549.967-.998 1.189-.173.086-.34.183-.5.29-.417.278-.97.423-1.529.27l-1.103-.303c-.109-.03-.175.016-.195.045-.22.312-.412.644-.573.99-.014.031-.021.11.059.19l.815.806c.411.406.562.957.53 1.456a4.709 4.709 0 0 0 0 .582c.032.499-.119 1.05-.53 1.456l-.815.806c-.081.08-.073.159-.059.19.162.346.353.677.573.989.02.03.085.076.195.046l1.102-.303c.56-.153 1.113-.008 1.53.27.161.107.328.204.501.29.447.222.85.629.997 1.189l.289 1.105c.029.109.101.143.137.146a6.6 6.6 0 0 0 1.142 0c.036-.003.108-.036.137-.146l.289-1.105c.147-.561.549-.967.998-1.189.173-.086.34-.183.5-.29.417-.278.97-.423 1.529-.27l1.103.303c.109.029.175-.016.195-.045.22-.313.411-.644.573-.99.014-.031.021-.11-.059-.19l-.815-.806c-.411-.406-.562-.957-.53-1.456a4.709 4.709 0 0 0 0-.582c-.032-.499.119-1.05.53-1.456l.815-.806c.081-.08.073-.159.059-.19a6.464 6.464 0 0 0-.573-.989c-.02-.03-.085-.076-.195-.046l-1.102.303c-.56.153-1.113.008-1.53-.27a4.44 4.44 0 0 0-.501-.29c-.447-.222-.85-.629-.997-1.189l-.289-1.105c-.029-.11-.101-.143-.137-.146a6.6 6.6 0 0 0-1.142 0ZM11 8a3 3 0 1 1-6 0 3 3 0 0 1 6 0ZM9.5 8a1.5 1.5 0 1 0-3.001.001A1.5 1.5 0 0 0 9.5 8Z'></path>
|
||||||
|
</svg>;
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,8 @@ const zipjs = zipImport as typeof zip;
|
||||||
|
|
||||||
import logo from '@web/assets/playwright-logo.svg';
|
import logo from '@web/assets/playwright-logo.svg';
|
||||||
import { SearchParamsProvider } from './links';
|
import { SearchParamsProvider } from './links';
|
||||||
|
import { applyTheme } from '@web/theme';
|
||||||
|
|
||||||
const link = document.createElement('link');
|
const link = document.createElement('link');
|
||||||
link.rel = 'shortcut icon';
|
link.rel = 'shortcut icon';
|
||||||
link.href = logo;
|
link.href = logo;
|
||||||
|
|
@ -49,6 +51,7 @@ const ReportLoader: React.FC = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
window.onload = () => {
|
window.onload = () => {
|
||||||
|
applyTheme();
|
||||||
ReactDOM.createRoot(document.querySelector('#root')!).render(<ReportLoader />);
|
ReactDOM.createRoot(document.querySelector('#root')!).render(<ReportLoader />);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
color: var(--color-fg-default);
|
color: var(--color-fg-default);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media(prefers-color-scheme: light) {
|
:root.light-mode {
|
||||||
.label-color-0 {
|
.label-color-0 {
|
||||||
background-color: var(--color-scale-blue-0);
|
background-color: var(--color-scale-blue-0);
|
||||||
color: var(--color-scale-blue-6);
|
color: var(--color-scale-blue-6);
|
||||||
|
|
@ -68,7 +68,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media(prefers-color-scheme: dark) {
|
:root.dark-mode {
|
||||||
.label-color-0 {
|
.label-color-0 {
|
||||||
background-color: var(--color-scale-blue-9);
|
background-color: var(--color-scale-blue-9);
|
||||||
color: var(--color-scale-blue-2);
|
color: var(--color-scale-blue-2);
|
||||||
|
|
|
||||||
|
|
@ -45,13 +45,13 @@
|
||||||
padding: 2px 8px;
|
padding: 2px 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media(prefers-color-scheme: light) {
|
:root.light-mode {
|
||||||
.test-result-counter {
|
.test-result-counter {
|
||||||
background: var(--color-scale-gray-5);
|
background: var(--color-scale-gray-5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media(prefers-color-scheme: dark) {
|
:root.dark-mode {
|
||||||
.test-result-counter {
|
.test-result-counter {
|
||||||
background: var(--color-scale-gray-3);
|
background: var(--color-scale-gray-3);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
color: #a1260d;
|
color: #a1260d;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.dark-mode .recorder .toolbar-button.toggled.circle-large-filled {
|
:root:dark-mode .recorder .toolbar-button.toggled.circle-large-filled {
|
||||||
color: #f48771;
|
color: #f48771;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ import { useDarkModeSetting } from '@web/theme';
|
||||||
import { copy, useSetting } from '@web/uiUtils';
|
import { copy, useSetting } from '@web/uiUtils';
|
||||||
import yaml from 'yaml';
|
import yaml from 'yaml';
|
||||||
import { parseAriaSnapshot } from '@isomorphic/ariaSnapshot';
|
import { parseAriaSnapshot } from '@isomorphic/ariaSnapshot';
|
||||||
import { Dialog } from '@web/components/dialog';
|
import { Dialog } from '@web/shared/dialog';
|
||||||
|
|
||||||
export interface RecorderProps {
|
export interface RecorderProps {
|
||||||
sources: Source[],
|
sources: Source[],
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@
|
||||||
height: var(--browser-frame-header-height);
|
height: var(--browser-frame-header-height);
|
||||||
}
|
}
|
||||||
|
|
||||||
body.dark-mode .browser-frame-header {
|
:root:dark-mode .browser-frame-header {
|
||||||
background: #444950;
|
background: #444950;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@
|
||||||
--action-background-color: #1a85ff66;
|
--action-background-color: #1a85ff66;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.dark-mode .timeline-bar.action.error {
|
:root:dark-mode .timeline-bar.action.error {
|
||||||
--action-color: var(--vscode-errorForeground);
|
--action-color: var(--vscode-errorForeground);
|
||||||
--action-background-color: #f4877166;
|
--action-background-color: #f4877166;
|
||||||
}
|
}
|
||||||
|
|
@ -162,7 +162,7 @@ body.dark-mode .timeline-bar.action.error {
|
||||||
background-color: #3879d91a;
|
background-color: #3879d91a;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.dark-mode .timeline-window-curtain {
|
:root:dark-mode .timeline-window-curtain {
|
||||||
background-color: #161718bf;
|
background-color: #161718bf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ import type { HighlightedElement } from './snapshotTab';
|
||||||
import type { TestAnnotation } from '@playwright/test';
|
import type { TestAnnotation } from '@playwright/test';
|
||||||
import { MetadataWithCommitInfo } from '@testIsomorphic/types';
|
import { MetadataWithCommitInfo } from '@testIsomorphic/types';
|
||||||
import type { ActionGroup } from '@isomorphic/protocolFormatter';
|
import type { ActionGroup } from '@isomorphic/protocolFormatter';
|
||||||
import { DialogToolbarButton } from '@web/components/dialog';
|
import { DialogToolbarButton } from '@web/components/dialogToolbarButton';
|
||||||
import { SettingsView } from './settingsView';
|
import { SettingsView } from './settingsView';
|
||||||
|
|
||||||
export const Workbench: React.FunctionComponent<{
|
export const Workbench: React.FunctionComponent<{
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ body .drop-target {
|
||||||
background: rgba(255, 255, 255, 0.8);
|
background: rgba(255, 255, 255, 0.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
body.dark-mode .drop-target {
|
:root:dark-mode .drop-target {
|
||||||
background: rgba(0, 0, 0, 0.8);
|
background: rgba(0, 0, 0, 0.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,8 @@ import { MultiTraceModel } from './modelUtil';
|
||||||
import './workbenchLoader.css';
|
import './workbenchLoader.css';
|
||||||
import { Workbench } from './workbench';
|
import { Workbench } from './workbench';
|
||||||
import { TestServerConnection, WebSocketTestServerTransport } from '@testIsomorphic/testServerConnection';
|
import { TestServerConnection, WebSocketTestServerTransport } from '@testIsomorphic/testServerConnection';
|
||||||
import { Dialog, DialogToolbarButton } from '@web/components/dialog';
|
import { DialogToolbarButton } from '@web/components/dialogToolbarButton';
|
||||||
|
import { Dialog } from '@web/shared/dialog';
|
||||||
import { DefaultSettingsView } from './defaultSettingsView';
|
import { DefaultSettingsView } from './defaultSettingsView';
|
||||||
|
|
||||||
export const WorkbenchLoader: React.FunctionComponent<{
|
export const WorkbenchLoader: React.FunctionComponent<{
|
||||||
|
|
|
||||||
|
|
@ -79,33 +79,33 @@
|
||||||
color: #267f99;
|
color: #267f99;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.dark-mode .CodeMirror span.cm-def,
|
:root:dark-mode .CodeMirror span.cm-def,
|
||||||
body.dark-mode .CodeMirror span.cm-tag {
|
:root:dark-mode .CodeMirror span.cm-tag {
|
||||||
color: var(--vscode-debugView-valueChangedHighlight);
|
color: var(--vscode-debugView-valueChangedHighlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
body.dark-mode .CodeMirror span.cm-comment,
|
:root:dark-mode .CodeMirror span.cm-comment,
|
||||||
body.dark-mode .CodeMirror span.cm-link {
|
:root:dark-mode .CodeMirror span.cm-link {
|
||||||
color: #6a9955;
|
color: #6a9955;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.dark-mode .CodeMirror span.cm-variable,
|
:root:dark-mode .CodeMirror span.cm-variable,
|
||||||
body.dark-mode .CodeMirror span.cm-variable-2,
|
:root:dark-mode .CodeMirror span.cm-variable-2,
|
||||||
body.dark-mode .CodeMirror span.cm-atom {
|
:root:dark-mode .CodeMirror span.cm-atom {
|
||||||
color: #4fc1ff;
|
color: #4fc1ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.dark-mode .CodeMirror span.cm-property {
|
:root:dark-mode .CodeMirror span.cm-property {
|
||||||
color: #dcdcaa;
|
color: #dcdcaa;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.dark-mode .CodeMirror span.cm-qualifier,
|
:root:dark-mode .CodeMirror span.cm-qualifier,
|
||||||
body.dark-mode .CodeMirror span.cm-attribute {
|
:root:dark-mode .CodeMirror span.cm-attribute {
|
||||||
color: #9cdcfe;
|
color: #9cdcfe;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.dark-mode .CodeMirror span.cm-variable-3,
|
:root:dark-mode .CodeMirror span.cm-variable-3,
|
||||||
body.dark-mode .CodeMirror span.cm-type {
|
:root:dark-mode .CodeMirror span.cm-type {
|
||||||
color: #4ec9b0;
|
color: #4ec9b0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) Microsoft Corporation.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
import { ToolbarButton } from './toolbarButton';
|
||||||
|
import { Dialog } from '../shared/dialog';
|
||||||
|
|
||||||
|
export interface DialogToolbarButtonProps {
|
||||||
|
title?: string;
|
||||||
|
icon?: string;
|
||||||
|
dialogDataTestId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DialogToolbarButton: React.FC<React.PropsWithChildren<DialogToolbarButtonProps>> = ({ title, icon, dialogDataTestId, children }) => {
|
||||||
|
const hostingRef = React.useRef<HTMLButtonElement>(null);
|
||||||
|
const [open, setOpen] = React.useState(false);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ToolbarButton
|
||||||
|
ref={hostingRef}
|
||||||
|
icon={icon}
|
||||||
|
title={title}
|
||||||
|
onClick={() => setOpen(current => !current)}
|
||||||
|
/>
|
||||||
|
<Dialog
|
||||||
|
style={{
|
||||||
|
backgroundColor: 'var(--vscode-sideBar-background)',
|
||||||
|
padding: '4px 8px'
|
||||||
|
}}
|
||||||
|
open={open}
|
||||||
|
width={200}
|
||||||
|
// TODO: Temporary spacing until design of toolbar buttons is revisited
|
||||||
|
verticalOffset={8}
|
||||||
|
requestClose={() => setOpen(false)}
|
||||||
|
anchor={hostingRef}
|
||||||
|
dataTestId={dialogDataTestId}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Dialog>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { ToolbarButton } from './toolbarButton';
|
|
||||||
|
|
||||||
export interface DialogProps {
|
export interface DialogProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
|
|
@ -164,39 +163,3 @@ const buildTopLeftCoordWithAlignment = (
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface DialogToolbarButtonProps {
|
|
||||||
title?: string;
|
|
||||||
icon?: string;
|
|
||||||
dialogDataTestId?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const DialogToolbarButton: React.FC<React.PropsWithChildren<DialogToolbarButtonProps>> = ({ title, icon, dialogDataTestId, children }) => {
|
|
||||||
const hostingRef = React.useRef<HTMLButtonElement>(null);
|
|
||||||
const [open, setOpen] = React.useState(false);
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<ToolbarButton
|
|
||||||
ref={hostingRef}
|
|
||||||
icon={icon}
|
|
||||||
title={title}
|
|
||||||
onClick={() => setOpen(current => !current)}
|
|
||||||
/>
|
|
||||||
<Dialog
|
|
||||||
style={{
|
|
||||||
backgroundColor: 'var(--vscode-sideBar-background)',
|
|
||||||
padding: '4px 8px'
|
|
||||||
}}
|
|
||||||
open={open}
|
|
||||||
width={200}
|
|
||||||
// TODO: Temporary spacing until design of toolbar buttons is revisited
|
|
||||||
verticalOffset={8}
|
|
||||||
requestClose={() => setOpen(false)}
|
|
||||||
anchor={hostingRef}
|
|
||||||
dataTestId={dialogDataTestId}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Dialog>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -41,7 +41,9 @@ export function applyTheme() {
|
||||||
|
|
||||||
const currentTheme = settings.getString('theme', defaultTheme);
|
const currentTheme = settings.getString('theme', defaultTheme);
|
||||||
if (currentTheme === 'dark-mode')
|
if (currentTheme === 'dark-mode')
|
||||||
document.body.classList.add('dark-mode');
|
document.documentElement.classList.add('dark-mode');
|
||||||
|
else
|
||||||
|
document.documentElement.classList.add('light-mode');
|
||||||
}
|
}
|
||||||
|
|
||||||
type Theme = 'dark-mode' | 'light-mode';
|
type Theme = 'dark-mode' | 'light-mode';
|
||||||
|
|
@ -52,8 +54,8 @@ export function toggleTheme() {
|
||||||
const newTheme = oldTheme === 'dark-mode' ? 'light-mode' : 'dark-mode';
|
const newTheme = oldTheme === 'dark-mode' ? 'light-mode' : 'dark-mode';
|
||||||
|
|
||||||
if (oldTheme)
|
if (oldTheme)
|
||||||
document.body.classList.remove(oldTheme);
|
document.documentElement.classList.remove(oldTheme);
|
||||||
document.body.classList.add(newTheme);
|
document.documentElement.classList.add(newTheme);
|
||||||
settings.setString('theme', newTheme);
|
settings.setString('theme', newTheme);
|
||||||
for (const listener of listeners)
|
for (const listener of listeners)
|
||||||
listener(newTheme);
|
listener(newTheme);
|
||||||
|
|
@ -68,7 +70,7 @@ export function removeThemeListener(listener: (theme: Theme) => void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function currentTheme(): Theme {
|
export function currentTheme(): Theme {
|
||||||
return document.body.classList.contains('dark-mode') ? 'dark-mode' : 'light-mode';
|
return document.documentElement.classList.contains('dark-mode') ? 'dark-mode' : 'light-mode';
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useDarkModeSetting(): [boolean, (value: boolean) => void] {
|
export function useDarkModeSetting(): [boolean, (value: boolean) => void] {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
body {
|
:root {
|
||||||
--vscode-font-family: system-ui, "Ubuntu", "Droid Sans", sans-serif;
|
--vscode-font-family: system-ui, "Ubuntu", "Droid Sans", sans-serif;
|
||||||
--vscode-font-weight: normal;
|
--vscode-font-weight: normal;
|
||||||
--vscode-font-size: 13px;
|
--vscode-font-size: 13px;
|
||||||
|
|
@ -544,13 +544,12 @@ body {
|
||||||
--vscode-gitDecoration-submoduleResourceForeground: #1258a7;
|
--vscode-gitDecoration-submoduleResourceForeground: #1258a7;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.light-mode {
|
:root.light-mode {
|
||||||
color-scheme: light;
|
color-scheme: light;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.dark-mode {
|
:root.dark-mode {
|
||||||
color-scheme: dark;
|
color-scheme: dark;
|
||||||
|
|
||||||
--vscode-font-family: system-ui, "Ubuntu", "Droid Sans", sans-serif;
|
--vscode-font-family: system-ui, "Ubuntu", "Droid Sans", sans-serif;
|
||||||
--vscode-font-weight: normal;
|
--vscode-font-weight: normal;
|
||||||
--vscode-font-size: 13px;
|
--vscode-font-size: 13px;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue