diff options
Diffstat (limited to 'packages')
-rw-r--r-- | packages/renderer/src/components/locationBar/ButtonAdornment.tsx | 69 | ||||
-rw-r--r-- | packages/renderer/src/components/locationBar/GoButton.tsx (renamed from packages/renderer/src/components/locationBar/GoAdornment.tsx) | 26 | ||||
-rw-r--r-- | packages/renderer/src/components/locationBar/LocationInputAdornment.tsx (renamed from packages/renderer/src/components/locationBar/IconAdornment.tsx) | 28 | ||||
-rw-r--r-- | packages/renderer/src/components/locationBar/LocationTextField.tsx | 14 | ||||
-rw-r--r-- | packages/renderer/src/components/locationBar/SecurityLabel.tsx (renamed from packages/renderer/src/components/locationBar/UrlAdornment.tsx) | 77 | ||||
-rw-r--r-- | packages/renderer/src/components/locationBar/UrlOverlay.tsx | 3 | ||||
-rw-r--r-- | packages/renderer/src/components/locationBar/getAlertColor.ts | 28 |
7 files changed, 115 insertions, 130 deletions
diff --git a/packages/renderer/src/components/locationBar/ButtonAdornment.tsx b/packages/renderer/src/components/locationBar/ButtonAdornment.tsx deleted file mode 100644 index 2cf230b..0000000 --- a/packages/renderer/src/components/locationBar/ButtonAdornment.tsx +++ /dev/null | |||
@@ -1,69 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2022 Kristóf Marussy <kristof@marussy.com> | ||
3 | * | ||
4 | * This file is part of Sophie. | ||
5 | * | ||
6 | * Sophie is free software: you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU Affero General Public License as | ||
8 | * published by the Free Software Foundation, version 3. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Affero General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Affero General Public License | ||
16 | * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
17 | * | ||
18 | * SPDX-License-Identifier: AGPL-3.0-only | ||
19 | */ | ||
20 | |||
21 | import InputAdornment from '@mui/material/InputAdornment'; | ||
22 | import { styled } from '@mui/material/styles'; | ||
23 | |||
24 | export const NO_LABEL_BUTTON_CLASS_NAME = 'ButtonAdornment-NoLabel'; | ||
25 | |||
26 | const ButtonAdornment = styled(InputAdornment, { | ||
27 | name: 'ButtonAdornment', | ||
28 | })(({ theme, position }) => { | ||
29 | const { direction } = theme; | ||
30 | const left = direction === 'ltr' ? 'start' : 'end'; | ||
31 | return { | ||
32 | ...(position === left | ||
33 | ? { | ||
34 | marginRight: 2, | ||
35 | marginLeft: -8, | ||
36 | } | ||
37 | : { | ||
38 | marginLeft: 2, | ||
39 | marginRight: -8, | ||
40 | }), | ||
41 | '.MuiButton-root': { | ||
42 | minWidth: 32, | ||
43 | height: 32, | ||
44 | paddingLeft: 6, | ||
45 | paddingRight: 6, | ||
46 | borderRadius: 16, | ||
47 | }, | ||
48 | ...(direction === 'ltr' | ||
49 | ? { | ||
50 | '.MuiButton-startIcon': { | ||
51 | marginLeft: 0, | ||
52 | }, | ||
53 | [`.${NO_LABEL_BUTTON_CLASS_NAME} .MuiButton-startIcon`]: { | ||
54 | marginRight: 0, | ||
55 | }, | ||
56 | } | ||
57 | : { | ||
58 | '.MuiButton-startIcon': { | ||
59 | marginRight: 0, | ||
60 | marginLeft: theme.spacing(1), | ||
61 | }, | ||
62 | [`.${NO_LABEL_BUTTON_CLASS_NAME} .MuiButton-startIcon`]: { | ||
63 | marginLeft: 0, | ||
64 | }, | ||
65 | }), | ||
66 | }; | ||
67 | }); | ||
68 | |||
69 | export default ButtonAdornment; | ||
diff --git a/packages/renderer/src/components/locationBar/GoAdornment.tsx b/packages/renderer/src/components/locationBar/GoButton.tsx index f049b8e..32f715e 100644 --- a/packages/renderer/src/components/locationBar/GoAdornment.tsx +++ b/packages/renderer/src/components/locationBar/GoButton.tsx | |||
@@ -19,25 +19,33 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | import IconGo from '@mui/icons-material/Send'; | 21 | import IconGo from '@mui/icons-material/Send'; |
22 | import Button from '@mui/material/Button'; | 22 | import IconButton from '@mui/material/IconButton'; |
23 | import React, { MouseEventHandler } from 'react'; | 23 | import React, { MouseEventHandler } from 'react'; |
24 | 24 | ||
25 | import ButtonAdornment, { NO_LABEL_BUTTON_CLASS_NAME } from './ButtonAdornment'; | 25 | import LocationInputAdornment from './LocationInputAdornment'; |
26 | 26 | ||
27 | export default function GoAdornment({ | 27 | export default function GoButton({ |
28 | onClick, | 28 | onClick, |
29 | position, | ||
29 | }: { | 30 | }: { |
30 | onClick: MouseEventHandler<HTMLButtonElement>; | 31 | onClick: MouseEventHandler<HTMLButtonElement>; |
32 | position: 'start' | 'end'; | ||
31 | }): JSX.Element { | 33 | }): JSX.Element { |
32 | return ( | 34 | return ( |
33 | <ButtonAdornment position="end"> | 35 | <LocationInputAdornment position={position}> |
34 | <Button | 36 | <IconButton |
35 | aria-label="Go" | 37 | aria-label="Go" |
36 | color="inherit" | 38 | color="inherit" |
37 | startIcon={<IconGo />} | ||
38 | className={NO_LABEL_BUTTON_CLASS_NAME} | ||
39 | onClick={onClick} | 39 | onClick={onClick} |
40 | /> | 40 | sx={{ |
41 | </ButtonAdornment> | 41 | minWidth: '32px', |
42 | height: '32px', | ||
43 | paddingX: '6px', | ||
44 | borderRadius: '16px', | ||
45 | }} | ||
46 | > | ||
47 | <IconGo fontSize="small" /> | ||
48 | </IconButton> | ||
49 | </LocationInputAdornment> | ||
42 | ); | 50 | ); |
43 | } | 51 | } |
diff --git a/packages/renderer/src/components/locationBar/IconAdornment.tsx b/packages/renderer/src/components/locationBar/LocationInputAdornment.tsx index 1a2fa83..a3cd2c5 100644 --- a/packages/renderer/src/components/locationBar/IconAdornment.tsx +++ b/packages/renderer/src/components/locationBar/LocationInputAdornment.tsx | |||
@@ -21,21 +21,21 @@ | |||
21 | import InputAdornment from '@mui/material/InputAdornment'; | 21 | import InputAdornment from '@mui/material/InputAdornment'; |
22 | import { styled } from '@mui/material/styles'; | 22 | import { styled } from '@mui/material/styles'; |
23 | 23 | ||
24 | const IconAdornment = styled(InputAdornment, { | 24 | const LocationInputAdornment = styled(InputAdornment, { |
25 | name: 'IconAdornment', | 25 | name: 'LocationInputAdornment', |
26 | })(({ theme: { direction }, position }) => { | 26 | })(({ theme: { direction }, position }) => { |
27 | const left = direction === 'ltr' ? 'start' : 'end'; | 27 | const left = direction === 'ltr' ? 'start' : 'end'; |
28 | return { | 28 | const marginStart = -8; |
29 | ...(position === left | 29 | const marginEnd = 2; |
30 | ? { | 30 | return position === left |
31 | marginLeft: -2, | 31 | ? { |
32 | marginRight: 8, | 32 | marginLeft: marginStart, |
33 | } | 33 | marginRight: marginEnd, |
34 | : { | 34 | } |
35 | marginLeft: 8, | 35 | : { |
36 | marginRight: -2, | 36 | marginLeft: marginEnd, |
37 | }), | 37 | marginRight: marginStart, |
38 | }; | 38 | }; |
39 | }); | 39 | }); |
40 | 40 | ||
41 | export default IconAdornment; | 41 | export default LocationInputAdornment; |
diff --git a/packages/renderer/src/components/locationBar/LocationTextField.tsx b/packages/renderer/src/components/locationBar/LocationTextField.tsx index e711abc..3a4f7f5 100644 --- a/packages/renderer/src/components/locationBar/LocationTextField.tsx +++ b/packages/renderer/src/components/locationBar/LocationTextField.tsx | |||
@@ -26,9 +26,9 @@ import React, { useCallback, useEffect, useState } from 'react'; | |||
26 | 26 | ||
27 | import Service from '../../stores/Service'; | 27 | import Service from '../../stores/Service'; |
28 | 28 | ||
29 | import GoAdornment from './GoAdornment'; | 29 | import GoButton from './GoButton'; |
30 | import LocationOverlayInput from './LocationOverlayInput'; | 30 | import LocationOverlayInput from './LocationOverlayInput'; |
31 | import UrlAdornment from './UrlAdornment'; | 31 | import SecurityLabel from './SecurityLabel'; |
32 | import UrlOverlay from './UrlOverlay'; | 32 | import UrlOverlay from './UrlOverlay'; |
33 | import splitUrl from './splitUrl'; | 33 | import splitUrl from './splitUrl'; |
34 | 34 | ||
@@ -113,10 +113,16 @@ function LocationTextField({ | |||
113 | hiddenLabel | 113 | hiddenLabel |
114 | disableUnderline | 114 | disableUnderline |
115 | startAdornment={ | 115 | startAdornment={ |
116 | <UrlAdornment changed={changed} splitResult={splitResult} /> | 116 | <SecurityLabel |
117 | changed={changed} | ||
118 | splitResult={splitResult} | ||
119 | position="start" | ||
120 | /> | ||
117 | } | 121 | } |
118 | endAdornment={ | 122 | endAdornment={ |
119 | changed ? <GoAdornment onClick={() => service?.go(value)} /> : undefined | 123 | changed ? ( |
124 | <GoButton onClick={() => service?.go(value)} position="end" /> | ||
125 | ) : undefined | ||
120 | } | 126 | } |
121 | value={value} | 127 | value={value} |
122 | /> | 128 | /> |
diff --git a/packages/renderer/src/components/locationBar/UrlAdornment.tsx b/packages/renderer/src/components/locationBar/SecurityLabel.tsx index 6ede378..6e27e6b 100644 --- a/packages/renderer/src/components/locationBar/UrlAdornment.tsx +++ b/packages/renderer/src/components/locationBar/SecurityLabel.tsx | |||
@@ -19,68 +19,79 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | import IconHttps from '@mui/icons-material/HttpsOutlined'; | 21 | import IconHttps from '@mui/icons-material/HttpsOutlined'; |
22 | import IconHttp from '@mui/icons-material/NoEncryption'; | ||
22 | import IconGlobe from '@mui/icons-material/Public'; | 23 | import IconGlobe from '@mui/icons-material/Public'; |
23 | import IconWarning from '@mui/icons-material/Warning'; | 24 | import IconWarning from '@mui/icons-material/Warning'; |
24 | import { styled } from '@mui/material'; | 25 | import { styled } from '@mui/material/styles'; |
25 | import Button from '@mui/material/Button'; | ||
26 | import React from 'react'; | 26 | import React from 'react'; |
27 | 27 | ||
28 | import ButtonAdornment, { NO_LABEL_BUTTON_CLASS_NAME } from './ButtonAdornment'; | 28 | import LocationInputAdornment from './LocationInputAdornment'; |
29 | import IconAdornment from './IconAdornment'; | 29 | import getAlertColor from './getAlertColor'; |
30 | import type { SplitResult } from './splitUrl'; | 30 | import type { SplitResult } from './splitUrl'; |
31 | 31 | ||
32 | const FastColorChangingButton = styled(Button)(({ theme }) => ({ | 32 | const SecurityLabelRoot = styled(LocationInputAdornment, { |
33 | transition: theme.transitions.create( | 33 | name: 'SecurityLabel', |
34 | ['background-color', 'box-shadow', 'border-color'], | 34 | slot: 'Root', |
35 | { | 35 | shouldForwardProp: (prop) => prop !== 'alert', |
36 | duration: theme.transitions.duration.short, | 36 | })<{ alert: boolean }>(({ theme, alert }) => ({ |
37 | easing: theme.transitions.easing.easeInOut, | 37 | padding: 6, |
38 | }, | 38 | color: getAlertColor(theme, alert), |
39 | ), | 39 | // Clicking on the security label should focus the text field instead. |
40 | pointerEvents: 'none', | ||
40 | })); | 41 | })); |
41 | 42 | ||
42 | export default function UrlAdornment({ | 43 | const SecurityLabelText = styled('span', { |
44 | name: 'SecurityLabel', | ||
45 | slot: 'Text', | ||
46 | })(({ theme }) => ({ | ||
47 | marginInlineStart: theme.spacing(1), | ||
48 | // Keep the same baseline as the input box text. | ||
49 | paddingBottom: 1, | ||
50 | fontWeight: theme.typography.fontWeightMedium, | ||
51 | userSelect: 'none', | ||
52 | })); | ||
53 | |||
54 | export default function SecurityLabel({ | ||
43 | splitResult, | 55 | splitResult, |
44 | changed, | 56 | changed, |
57 | position, | ||
45 | }: { | 58 | }: { |
46 | splitResult: SplitResult; | 59 | splitResult: SplitResult; |
47 | changed: boolean; | 60 | changed: boolean; |
61 | position: 'start' | 'end'; | ||
48 | }): JSX.Element { | 62 | }): JSX.Element { |
49 | const { type } = splitResult; | 63 | const { type } = splitResult; |
50 | if (changed || type === 'empty') { | 64 | if (changed || type === 'empty') { |
51 | return ( | 65 | return ( |
52 | <IconAdornment position="start"> | 66 | <SecurityLabelRoot alert={false} position={position} aria-hidden> |
53 | <IconGlobe fontSize="small" /> | 67 | <IconGlobe fontSize="small" /> |
54 | </IconAdornment> | 68 | </SecurityLabelRoot> |
55 | ); | 69 | ); |
56 | } | 70 | } |
57 | switch (type) { | 71 | switch (type) { |
58 | case 'valid': { | 72 | case 'valid': { |
59 | const { secure } = splitResult; | 73 | const { secure } = splitResult; |
60 | return secure ? ( | 74 | return secure ? ( |
61 | <ButtonAdornment position="start"> | 75 | <SecurityLabelRoot |
62 | <FastColorChangingButton | 76 | alert={false} |
63 | aria-label="Show certificate" | 77 | position={position} |
64 | color="inherit" | 78 | aria-label="Secure connection" |
65 | className={NO_LABEL_BUTTON_CLASS_NAME} | 79 | > |
66 | startIcon={<IconHttps />} | 80 | <IconHttps fontSize="small" /> |
67 | /> | 81 | </SecurityLabelRoot> |
68 | </ButtonAdornment> | ||
69 | ) : ( | 82 | ) : ( |
70 | <ButtonAdornment position="start"> | 83 | <SecurityLabelRoot alert position={position}> |
71 | <FastColorChangingButton color="error" startIcon={<IconWarning />}> | 84 | <IconHttp fontSize="small" /> |
72 | Not secure | 85 | <SecurityLabelText>Not secure</SecurityLabelText> |
73 | </FastColorChangingButton> | 86 | </SecurityLabelRoot> |
74 | </ButtonAdornment> | ||
75 | ); | 87 | ); |
76 | } | 88 | } |
77 | case 'invalid': | 89 | case 'invalid': |
78 | return ( | 90 | return ( |
79 | <ButtonAdornment position="start"> | 91 | <SecurityLabelRoot alert position={position}> |
80 | <FastColorChangingButton color="error" startIcon={<IconWarning />}> | 92 | <IconWarning fontSize="small" /> |
81 | Unknown site | 93 | <SecurityLabelText>Unknown site</SecurityLabelText> |
82 | </FastColorChangingButton> | 94 | </SecurityLabelRoot> |
83 | </ButtonAdornment> | ||
84 | ); | 95 | ); |
85 | default: | 96 | default: |
86 | /* eslint-disable-next-line @typescript-eslint/restrict-template-expressions -- | 97 | /* eslint-disable-next-line @typescript-eslint/restrict-template-expressions -- |
diff --git a/packages/renderer/src/components/locationBar/UrlOverlay.tsx b/packages/renderer/src/components/locationBar/UrlOverlay.tsx index f7a3c4c..d590709 100644 --- a/packages/renderer/src/components/locationBar/UrlOverlay.tsx +++ b/packages/renderer/src/components/locationBar/UrlOverlay.tsx | |||
@@ -21,6 +21,7 @@ | |||
21 | import { styled } from '@mui/material/styles'; | 21 | import { styled } from '@mui/material/styles'; |
22 | import React from 'react'; | 22 | import React from 'react'; |
23 | 23 | ||
24 | import getAlertColor from './getAlertColor'; | ||
24 | import type { SplitResult } from './splitUrl'; | 25 | import type { SplitResult } from './splitUrl'; |
25 | 26 | ||
26 | const PrimaryFragment = styled('span', { | 27 | const PrimaryFragment = styled('span', { |
@@ -28,7 +29,7 @@ const PrimaryFragment = styled('span', { | |||
28 | slot: 'PrimaryFragment', | 29 | slot: 'PrimaryFragment', |
29 | shouldForwardProp: (prop) => prop !== 'alert', | 30 | shouldForwardProp: (prop) => prop !== 'alert', |
30 | })<{ alert: boolean }>(({ theme, alert }) => ({ | 31 | })<{ alert: boolean }>(({ theme, alert }) => ({ |
31 | color: alert ? theme.palette.error.main : theme.palette.text.primary, | 32 | color: getAlertColor(theme, alert), |
32 | })); | 33 | })); |
33 | 34 | ||
34 | const SecondaryFragment = styled('span', { | 35 | const SecondaryFragment = styled('span', { |
diff --git a/packages/renderer/src/components/locationBar/getAlertColor.ts b/packages/renderer/src/components/locationBar/getAlertColor.ts new file mode 100644 index 0000000..82b5f55 --- /dev/null +++ b/packages/renderer/src/components/locationBar/getAlertColor.ts | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2022 Kristóf Marussy <kristof@marussy.com> | ||
3 | * | ||
4 | * This file is part of Sophie. | ||
5 | * | ||
6 | * Sophie is free software: you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU Affero General Public License as | ||
8 | * published by the Free Software Foundation, version 3. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Affero General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Affero General Public License | ||
16 | * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
17 | * | ||
18 | * SPDX-License-Identifier: AGPL-3.0-only | ||
19 | */ | ||
20 | |||
21 | import { Theme } from '@mui/material/styles'; | ||
22 | |||
23 | export default function getAlertColor({ palette }: Theme, alert: boolean) { | ||
24 | if (alert) { | ||
25 | return palette.mode === 'dark' ? palette.error.light : palette.error.main; | ||
26 | } | ||
27 | return palette.text.primary; | ||
28 | } | ||