diff --git a/src/app/core/components/switch-button.tsx b/src/app/core/components/switch-button.tsx
new file mode 100644
index 0000000000..77ce80f441
--- /dev/null
+++ b/src/app/core/components/switch-button.tsx
@@ -0,0 +1,108 @@
+import React from "react"
+import styled from "styled-components"
+
+const Underline = styled.div`
+ position: absolute;
+ bottom: 0;
+ left: -4px;
+ right: -4px;
+ height: 2px;
+ background: var(--primary-color);
+ border-radius: 1px;
+ opacity: 0;
+`
+
+const Button = styled.button`
+ background-color: var(--button-background);
+ border: none;
+ font-size: 11px;
+ font-weight: 500;
+ text-transform: uppercase;
+ min-width: 60px;
+ padding: 0 16px;
+ border-radius: 6px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ span {
+ display: flex;
+ height: 100%;
+ align-items: center;
+ opacity: 0.5;
+ position: relative;
+ }
+
+ &[aria-pressed="true"] {
+ span {
+ opacity: 1;
+ }
+ ${Underline} {
+ opacity: 1;
+ }
+ }
+
+ &:hover:not([aria-pressed="true"]) {
+ background: var(--button-background-hover);
+ span {
+ opacity: 0.7;
+ }
+ }
+
+ &:active:not([aria-pressed="true"]) {
+ background: var(--button-background-active);
+ }
+
+ &:first-child {
+ border-top-right-radius: 0px;
+ border-bottom-right-radius: 0px;
+ }
+ &:last-child {
+ border-top-left-radius: 0px;
+ border-bottom-left-radius: 0px;
+ }
+`
+
+const BG = styled.div<{minWidth: number}>`
+ user-select: none;
+ border-radius: 6px;
+ height: 22px;
+ display: flex;
+ gap: 1px;
+
+ ${Button} {
+ min-width: ${(props) => props.minWidth}px;
+ }
+`
+
+type Option = {
+ label: string
+ click: React.MouseEventHandler
+ active: boolean
+}
+
+function Option(props: Option) {
+ return (
+
+ )
+}
+
+type Props = {
+ options: Option[]
+ minWidth?: number
+}
+
+export function SwitchButton(props: Props) {
+ return (
+
+ {props.options.map((props, i) => (
+
+ ))}
+
+ )
+}
diff --git a/src/app/core/hooks/use-auto-select.ts b/src/app/core/hooks/use-auto-select.ts
new file mode 100644
index 0000000000..e0bc2dc898
--- /dev/null
+++ b/src/app/core/hooks/use-auto-select.ts
@@ -0,0 +1,9 @@
+import {RefObject, useLayoutEffect} from "react"
+
+export function useAutoSelect(ref: RefObject) {
+ useLayoutEffect(() => {
+ if (ref.current) {
+ ref.current.select()
+ }
+ }, [])
+}
diff --git a/src/app/core/hooks/use-select.ts b/src/app/core/hooks/use-select.ts
index 9daa4d5cb4..a95833d64f 100644
--- a/src/app/core/hooks/use-select.ts
+++ b/src/app/core/hooks/use-select.ts
@@ -1,5 +1,5 @@
-import {useCallback} from "react"
import {useStore} from "react-redux"
+import {State} from "src/js/state/types"
/**
* This is useful when you need to select from the state
@@ -8,10 +8,9 @@ import {useStore} from "react-redux"
* needs to grab it once in the event handler.
*/
export default function useSelect() {
- const store = useStore()
- const select = useCallback(
- (selector: any) => selector(store.getState()),
- [store]
- )
+ const store = useStore()
+ function select any>(selector: T): ReturnType {
+ return selector(store.getState())
+ }
return select
}
diff --git a/src/app/core/icons/check.tsx b/src/app/core/icons/check.tsx
new file mode 100644
index 0000000000..a4e60d3c68
--- /dev/null
+++ b/src/app/core/icons/check.tsx
@@ -0,0 +1,12 @@
+import React from "react"
+
+export default function Check(props: any) {
+ return (
+
+ )
+}
diff --git a/src/app/core/icons/chevron-down.tsx b/src/app/core/icons/chevron-down.tsx
index 7c42d773ec..53c9422394 100644
--- a/src/app/core/icons/chevron-down.tsx
+++ b/src/app/core/icons/chevron-down.tsx
@@ -1,15 +1,8 @@
import React from "react"
export default function ChevronDown(props: any) {
return (
-