1
1
import type { Interpolation } from "@emotion/react" ;
2
+ import CircularProgress from "@mui/material/CircularProgress" ;
3
+ import FormControl from "@mui/material/FormControl" ;
4
+ import FormControlLabel from "@mui/material/FormControlLabel" ;
5
+ import Radio from "@mui/material/Radio" ;
6
+ import RadioGroup from "@mui/material/RadioGroup" ;
2
7
import { visuallyHidden } from "@mui/utils" ;
3
- import type { UpdateUserAppearanceSettingsRequest } from "api/typesGenerated" ;
8
+ import {
9
+ type TerminalFontName ,
10
+ TerminalFontNames ,
11
+ type UpdateUserAppearanceSettingsRequest ,
12
+ } from "api/typesGenerated" ;
4
13
import { ErrorAlert } from "components/Alert/ErrorAlert" ;
5
14
import { PreviewBadge } from "components/Badges/Badges" ;
6
15
import { Stack } from "components/Stack/Stack" ;
7
16
import { ThemeOverride } from "contexts/ThemeProvider" ;
8
17
import type { FC } from "react" ;
9
- import themes , { DEFAULT_TERMINAL_FONT , DEFAULT_THEME , type Theme } from "theme" ;
18
+ import themes , {
19
+ DEFAULT_TERMINAL_FONT ,
20
+ DEFAULT_THEME ,
21
+ type Theme ,
22
+ } from "theme" ;
23
+ import { Section } from "../Section" ;
10
24
11
25
export interface AppearanceFormProps {
12
26
isUpdating ?: boolean ;
@@ -22,44 +36,107 @@ export const AppearanceForm: FC<AppearanceFormProps> = ({
22
36
initialValues,
23
37
} ) => {
24
38
const currentTheme = initialValues . theme_preference || DEFAULT_THEME ;
25
- const currentTerminalFont = initialValues . terminal_font || DEFAULT_TERMINAL_FONT ;
39
+ const currentTerminalFont =
40
+ initialValues . terminal_font || DEFAULT_TERMINAL_FONT ;
26
41
27
42
const onChangeTheme = async ( theme : string ) => {
28
43
if ( isUpdating ) {
29
44
return ;
30
45
}
46
+ await onSubmit ( {
47
+ theme_preference : theme ,
48
+ terminal_font : currentTerminalFont ,
49
+ } ) ;
50
+ } ;
31
51
32
- await onSubmit ( { theme_preference : theme , terminal_font : currentTerminalFont } ) ;
52
+ const onChangeTerminalFont = async ( terminalFont : TerminalFontName ) => {
53
+ if ( isUpdating ) {
54
+ return ;
55
+ }
56
+ await onSubmit ( {
57
+ theme_preference : currentTheme ,
58
+ terminal_font : terminalFont ,
59
+ } ) ;
33
60
} ;
34
61
35
62
return (
36
63
< form >
37
64
{ Boolean ( error ) && < ErrorAlert error = { error } /> }
38
65
39
- < Stack direction = "row" wrap = "wrap" >
40
- < AutoThemePreviewButton
41
- displayName = "Auto"
42
- active = { currentTheme === "auto" }
43
- themes = { [ themes . dark , themes . light ] }
44
- onSelect = { ( ) => onChangeTheme ( "auto" ) }
45
- />
46
- < ThemePreviewButton
47
- displayName = "Dark"
48
- active = { currentTheme === "dark" }
49
- theme = { themes . dark }
50
- onSelect = { ( ) => onChangeTheme ( "dark" ) }
51
- />
52
- < ThemePreviewButton
53
- displayName = "Light"
54
- active = { currentTheme === "light" }
55
- theme = { themes . light }
56
- onSelect = { ( ) => onChangeTheme ( "light" ) }
57
- />
58
- </ Stack >
66
+ < Section
67
+ title = {
68
+ < Stack direction = "row" alignItems = "center" >
69
+ < span > Theme</ span >
70
+ { isUpdating && < CircularProgress size = { 16 } /> }
71
+ </ Stack >
72
+ }
73
+ layout = "fluid"
74
+ >
75
+ < Stack direction = "row" wrap = "wrap" >
76
+ < AutoThemePreviewButton
77
+ displayName = "Auto"
78
+ active = { currentTheme === "auto" }
79
+ themes = { [ themes . dark , themes . light ] }
80
+ onSelect = { ( ) => onChangeTheme ( "auto" ) }
81
+ />
82
+ < ThemePreviewButton
83
+ displayName = "Dark"
84
+ active = { currentTheme === "dark" }
85
+ theme = { themes . dark }
86
+ onSelect = { ( ) => onChangeTheme ( "dark" ) }
87
+ />
88
+ < ThemePreviewButton
89
+ displayName = "Light"
90
+ active = { currentTheme === "light" }
91
+ theme = { themes . light }
92
+ onSelect = { ( ) => onChangeTheme ( "light" ) }
93
+ />
94
+ </ Stack >
95
+ </ Section >
96
+ < div css = { { marginBottom : 48 } } > </ div >
97
+ < Section
98
+ title = {
99
+ < Stack direction = "row" alignItems = "center" >
100
+ < span > Terminal Font</ span >
101
+ { isUpdating && < CircularProgress size = { 16 } /> }
102
+ </ Stack >
103
+ }
104
+ layout = "fluid"
105
+ >
106
+ < FormControl >
107
+ < RadioGroup
108
+ aria-labelledby = "demo-radio-buttons-group-label"
109
+ defaultValue = { currentTerminalFont }
110
+ name = "radio-buttons-group"
111
+ onChange = { ( _ , value ) =>
112
+ onChangeTerminalFont ( toTerminalFontName ( value ) )
113
+ }
114
+ >
115
+ < FormControlLabel
116
+ value = "ibm-plex-mono"
117
+ control = { < Radio /> }
118
+ label = {
119
+ < div css = { { fontFamily : "IBM Plex Mono" } } > IBM Plex Mono</ div >
120
+ }
121
+ />
122
+ < FormControlLabel
123
+ value = "fira-code"
124
+ control = { < Radio /> }
125
+ label = { < div css = { { fontFamily : "Fira Code" } } > Fira Code</ div > }
126
+ />
127
+ </ RadioGroup >
128
+ </ FormControl >
129
+ </ Section >
59
130
</ form >
60
131
) ;
61
132
} ;
62
133
134
+ export function toTerminalFontName ( value : string ) : TerminalFontName {
135
+ return TerminalFontNames . includes ( value as TerminalFontName )
136
+ ? ( value as TerminalFontName )
137
+ : "" ;
138
+ }
139
+
63
140
interface AutoThemePreviewButtonProps extends Omit < ThemePreviewProps , "theme" > {
64
141
themes : [ Theme , Theme ] ;
65
142
onSelect ?: ( ) => void ;
0 commit comments