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;
 | 
				
			||||||
| 
						 | 
					@ -888,4 +892,3 @@ SOFTWARE. */
 | 
				
			||||||
  --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