aboutsummaryrefslogtreecommitdiffstats
path: root/packages/renderer/src/components/locationBar/LocationOverlayInput.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/renderer/src/components/locationBar/LocationOverlayInput.tsx')
-rw-r--r--packages/renderer/src/components/locationBar/LocationOverlayInput.tsx114
1 files changed, 114 insertions, 0 deletions
diff --git a/packages/renderer/src/components/locationBar/LocationOverlayInput.tsx b/packages/renderer/src/components/locationBar/LocationOverlayInput.tsx
new file mode 100644
index 0000000..cbb5b06
--- /dev/null
+++ b/packages/renderer/src/components/locationBar/LocationOverlayInput.tsx
@@ -0,0 +1,114 @@
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
21import { styled } from '@mui/material/styles';
22import React, { forwardRef, ForwardedRef } from 'react';
23
24const inputClassName = 'LocationOverlayInput-Input';
25
26const overlayClassName = 'LocationOverlayInput-Overlay';
27
28const clipClassName = 'LocationOverlayInput-Clip';
29
30const LocationOverlayInputRoot = styled('div', {
31 name: 'LocationOverlayInput',
32 slot: 'Root',
33 shouldForwardProp: (prop) => prop !== 'overlayVisible',
34})<{ overlayVisible: boolean }>(({ theme, overlayVisible }) => {
35 const itemStyle = {
36 padding: '6px 0 7px 0',
37 // Set text alignment explicitly so it can be flipped by `stylis-plugin-rtl`.
38 textAlign: 'left',
39 };
40 return {
41 display: 'flex',
42 position: 'relative',
43 flex: 1,
44 [`.${inputClassName}`]: {
45 ...itemStyle,
46 color: overlayVisible ? 'transparent' : 'inherit',
47 },
48 [`.${overlayClassName}`]: {
49 ...itemStyle,
50 display: 'flex',
51 position: 'absolute',
52 left: 0,
53 right: 0,
54 top: 0,
55 bottom: 0,
56 // Text rendering with selected transparent text works better on the bottom in light mode.
57 zIndex: theme.palette.mode === 'dark' ? 999 : -999,
58 pointerEvents: 'none',
59 width: 'auto',
60 },
61 [`.${clipClassName}`]: {
62 flex: 1,
63 overflow: 'hidden',
64 whiteSpace: 'nowrap',
65 textOverflow: 'clip',
66 },
67 };
68});
69
70export interface LocationOverlayInputProps
71 extends React.HTMLProps<HTMLInputElement> {
72 className?: string | undefined;
73
74 overlayVisible?: boolean;
75
76 overlay?: JSX.Element | undefined;
77}
78
79const LocationOverlayInput = forwardRef(
80 (
81 { overlayVisible, overlay, className, ...props }: LocationOverlayInputProps,
82 ref: ForwardedRef<HTMLInputElement>,
83 ) => (
84 <LocationOverlayInputRoot overlayVisible={overlayVisible ?? false}>
85 {/* eslint-disable react/jsx-props-no-spreading --
86 Deliberately passing props through to the actual input element.
87 */}
88 <input
89 ref={ref}
90 className={`${className ?? ''} ${inputClassName}`}
91 dir="ltr"
92 {...props}
93 />
94 {/* eslint-enable react/jsx-props-no-spreading */}
95 {overlayVisible && (
96 <div aria-hidden className={`${className ?? ''} ${overlayClassName}`}>
97 <div className={clipClassName} dir="ltr">
98 {overlay}
99 </div>
100 </div>
101 )}
102 </LocationOverlayInputRoot>
103 ),
104);
105
106LocationOverlayInput.displayName = 'LocationOverlayInput';
107
108LocationOverlayInput.defaultProps = {
109 className: undefined,
110 overlayVisible: false,
111 overlay: undefined,
112};
113
114export default LocationOverlayInput;