diff --git a/packages/trace-viewer/src/ui/defaultSettingsView.tsx b/packages/trace-viewer/src/ui/defaultSettingsView.tsx
new file mode 100644
index 0000000000..c36ddd1458
--- /dev/null
+++ b/packages/trace-viewer/src/ui/defaultSettingsView.tsx
@@ -0,0 +1,29 @@
+/**
+ * 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 { SettingsView } from './settingsView';
+import { useDarkModeSetting } from '@web/theme';
+
+export const DefaultSettingsView: React.FC<{}> = () => {
+ const [darkMode, setDarkMode] = useDarkModeSetting();
+
+ return (
+
+ );
+};
diff --git a/packages/trace-viewer/src/ui/settingsToolbar.css b/packages/trace-viewer/src/ui/settingsToolbar.css
new file mode 100644
index 0000000000..6ef44cd8de
--- /dev/null
+++ b/packages/trace-viewer/src/ui/settingsToolbar.css
@@ -0,0 +1,21 @@
+/*
+ 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.
+*/
+
+.settings-toolbar-dialog {
+ background-color: var(--vscode-sideBar-background);
+
+ padding: 4px 8px;
+}
\ No newline at end of file
diff --git a/packages/trace-viewer/src/ui/settingsToolbar.tsx b/packages/trace-viewer/src/ui/settingsToolbar.tsx
new file mode 100644
index 0000000000..c83dde7d66
--- /dev/null
+++ b/packages/trace-viewer/src/ui/settingsToolbar.tsx
@@ -0,0 +1,47 @@
+/*
+ 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 { Dialog } from './shared/dialog';
+import { ToolbarButton } from '@web/components/toolbarButton';
+import { DefaultSettingsView } from './defaultSettingsView';
+import './settingsToolbar.css';
+
+export const SettingsToolbar: React.FC<{}> = () => {
+ const hostingRef = React.useRef(null);
+
+ const [open, setOpen] = React.useState(false);
+
+ return (
+ <>
+ setOpen(current => !current)}
+ />
+
+ >
+ );
+};
diff --git a/packages/trace-viewer/src/ui/settingsView.css b/packages/trace-viewer/src/ui/settingsView.css
index 3ac8597e35..816c1038e3 100644
--- a/packages/trace-viewer/src/ui/settingsView.css
+++ b/packages/trace-viewer/src/ui/settingsView.css
@@ -16,7 +16,7 @@
.settings-view {
flex: none;
- margin-top: 4px;
+ user-select: none;
}
.settings-view .setting label {
@@ -24,6 +24,7 @@
flex-direction: row;
align-items: center;
margin: 4px 2px;
+ cursor: pointer;
}
.settings-view .setting:first-of-type label {
diff --git a/packages/trace-viewer/src/ui/shared/dialog.tsx b/packages/trace-viewer/src/ui/shared/dialog.tsx
new file mode 100644
index 0000000000..8e74c97b85
--- /dev/null
+++ b/packages/trace-viewer/src/ui/shared/dialog.tsx
@@ -0,0 +1,147 @@
+/*
+ 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';
+
+export interface DialogProps {
+ className?: string;
+
+ open: boolean;
+ width: number;
+
+ requestClose?: () => void;
+
+ hostingElement?: React.RefObject;
+}
+
+export const Dialog: React.FC> = ({
+ className,
+ open,
+ width,
+ requestClose,
+ hostingElement,
+ children,
+}) => {
+ const dialogRef = React.useRef(null);
+
+ let style: React.CSSProperties | undefined = undefined;
+
+ if (hostingElement?.current) {
+ // For now, always place dialog below hosting element
+ const bounds = hostingElement.current.getBoundingClientRect();
+
+ style = {
+ // Override default `