Skip to content

Commit 9836060

Browse files
somebody1234Frizi
authored andcommitted
Remove FocusArea component and associated components (#12789)
- Remove `FocusArea` component and various providers related to it # Important Notes None
1 parent f1aa932 commit 9836060

30 files changed

+461
-1471
lines changed

app/gui/src/dashboard/App.tsx

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ import InputBindingsProvider from '#/providers/InputBindingsProvider'
5151
import LocalStorageProvider, * as localStorageProvider from '#/providers/LocalStorageProvider'
5252
import { useLogger } from '#/providers/LoggerProvider'
5353
import ModalProvider, * as modalProvider from '#/providers/ModalProvider'
54-
import * as navigator2DProvider from '#/providers/Navigator2DProvider'
5554
import * as sessionProvider from '#/providers/SessionProvider'
5655
import * as textProvider from '#/providers/TextProvider'
5756

@@ -230,8 +229,6 @@ function AppRouter(props: React.PropsWithChildren<AppRouterProps>) {
230229
const { localStorage } = localStorageProvider.useLocalStorage()
231230
const { setModal } = modalProvider.useSetModal()
232231

233-
const navigator2D = navigator2DProvider.useNavigator2D()
234-
235232
const localBackend =
236233
projectManagerInstance != null ? new LocalBackend(projectManagerInstance) : null
237234

@@ -256,14 +253,6 @@ function AppRouter(props: React.PropsWithChildren<AppRouterProps>) {
256253
}
257254
}, [setModal])
258255

259-
React.useEffect(() => {
260-
const onKeyDown = navigator2D.onKeyDown.bind(navigator2D)
261-
document.addEventListener('keydown', onKeyDown)
262-
return () => {
263-
document.removeEventListener('keydown', onKeyDown)
264-
}
265-
}, [navigator2D])
266-
267256
React.useEffect(() => {
268257
let isClick = false
269258
const onMouseDown = () => {

app/gui/src/dashboard/components/AriaComponents/Inputs/Dropdown/Dropdown.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import {
3333
import { makeRoundedStyles } from '../../utilities'
3434

3535
const DROPDOWN_STYLES = tv({
36-
base: 'focus-child group relative flex w-max cursor-pointer flex-col items-start whitespace-nowrap rounded-input leading-cozy',
36+
base: 'group relative flex w-max cursor-pointer flex-col items-start whitespace-nowrap rounded-input leading-cozy',
3737
variants: {
3838
isFocused: {
3939
true: {

app/gui/src/dashboard/components/AriaComponents/Inputs/HiddenFile/HiddenFile.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export function HiddenFile<Schema extends TSchema, TFieldName extends FieldPath<
4848
render={({ field }) => (
4949
<Input
5050
type="file"
51-
className="focus-child w-0"
51+
className="w-0"
5252
accept={accept}
5353
onChange={(event) => {
5454
field.onChange(event.target.files?.[0])

app/gui/src/dashboard/components/ColorPicker.tsx

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
/** @file A color picker to select from a predetermined list of colors. */
22
import * as React from 'react'
33

4-
import * as focusHooks from '#/hooks/focusHooks'
5-
6-
import * as focusClassProvider from '#/providers/FocusClassProvider'
7-
import * as focusDirectionProvider from '#/providers/FocusDirectionProvider'
8-
94
import * as aria from '#/components/aria'
105
import FocusRing from '#/components/styled/FocusRing'
116
import RadioGroup from '#/components/styled/RadioGroup'
@@ -23,21 +18,14 @@ export interface InternalColorPickerItemProps {
2318
/** An input in a {@link ColorPicker}. */
2419
function ColorPickerItem(props: InternalColorPickerItemProps) {
2520
const { color } = props
26-
const { focusChildClass } = focusClassProvider.useFocusClasses()
27-
const focusDirection = focusDirectionProvider.useFocusDirection()
28-
const handleFocusMove = focusHooks.useHandleFocusMove(focusDirection)
2921
const cssColor = backend.lChColorToCssColor(color)
3022

3123
return (
3224
<FocusRing within>
3325
<aria.Radio
34-
ref={(element) => {
35-
element?.querySelector('input')?.classList.add(focusChildClass)
36-
}}
3726
value={cssColor}
3827
className="group flex size-radio-button cursor-pointer rounded-full p-radio-button-dot"
3928
style={{ backgroundColor: cssColor }}
40-
onKeyDown={handleFocusMove}
4129
>
4230
<div className="hidden size-radio-button-dot rounded-full bg-selected-frame group-selected:block" />
4331
</aria.Radio>

app/gui/src/dashboard/components/JSONSchemaInput.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ export default function JSONSchemaInput(props: JSONSchemaInputProps) {
106106
value={typeof value === 'string' ? value : ''}
107107
size={1}
108108
className={twMerge(
109-
'focus-child h-6 w-full grow rounded-input border-0.5 border-primary/20 bg-transparent px-2 outline-offset-2 transition-[border-color,outline] duration-200 read-only:read-only focus:border-primary/50 focus:outline focus:outline-2 focus:outline-offset-0 focus:outline-primary',
109+
'h-6 w-full grow rounded-input border-0.5 border-primary/20 bg-transparent px-2 outline-offset-2 transition-[border-color,outline] duration-200 read-only:read-only focus:border-primary/50 focus:outline focus:outline-2 focus:outline-offset-0 focus:outline-primary',
110110
validationErrorClassName,
111111
)}
112112
placeholder={getText('enterText')}
@@ -132,7 +132,7 @@ export default function JSONSchemaInput(props: JSONSchemaInputProps) {
132132
value={typeof value === 'number' ? value : ''}
133133
size={1}
134134
className={twMerge(
135-
'focus-child h-6 w-full grow rounded-input border-0.5 border-primary/20 bg-transparent px-2 outline-offset-2 transition-[border-color,outline] duration-200 read-only:read-only focus:border-primary/50 focus:outline focus:outline-2 focus:outline-offset-0 focus:outline-primary',
135+
'h-6 w-full grow rounded-input border-0.5 border-primary/20 bg-transparent px-2 outline-offset-2 transition-[border-color,outline] duration-200 read-only:read-only focus:border-primary/50 focus:outline focus:outline-2 focus:outline-offset-0 focus:outline-primary',
136136
validationErrorClassName,
137137
)}
138138
placeholder={getText('enterNumber')}
@@ -159,7 +159,7 @@ export default function JSONSchemaInput(props: JSONSchemaInputProps) {
159159
value={typeof value === 'number' ? value : ''}
160160
size={1}
161161
className={twMerge(
162-
'focus-child h-6 w-full grow rounded-input border-0.5 border-primary/20 bg-transparent px-2 outline-offset-2 transition-[border-color,outline] duration-200 read-only:read-only focus:border-primary/50 focus:outline focus:outline-2 focus:outline-offset-0 focus:outline-primary',
162+
'h-6 w-full grow rounded-input border-0.5 border-primary/20 bg-transparent px-2 outline-offset-2 transition-[border-color,outline] duration-200 read-only:read-only focus:border-primary/50 focus:outline focus:outline-2 focus:outline-offset-0 focus:outline-primary',
163163
validationErrorClassName,
164164
)}
165165
placeholder={getText('enterInteger')}

app/gui/src/dashboard/components/Link.tsx

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@ import * as toastify from 'react-toastify'
55
import * as aria from '#/components/aria'
66
import FocusRing from '#/components/styled/FocusRing'
77
import SvgMask from '#/components/SvgMask'
8-
import { useFocusChild } from '#/hooks/focusHooks'
98
import { useText } from '#/providers/TextProvider'
109
import { mergeRefs } from '#/utilities/mergeRefs'
1110
import { forwardRef } from '#/utilities/react'
12-
import { twMerge } from 'tailwind-merge'
1311

1412
/** Props for a {@link Link}. */
1513
export interface LinkProps {
@@ -26,7 +24,6 @@ export default forwardRef(Link)
2624
function Link(props: LinkProps, ref: React.ForwardedRef<HTMLAnchorElement>) {
2725
const { openInBrowser = false, to, icon, text, onPress } = props
2826
const { getText } = useText()
29-
const { className: focusChildClassName, ...focusChildProps } = useFocusChild()
3027
const linkRef = React.useRef<HTMLAnchorElement>(null)
3128

3229
return (
@@ -38,17 +35,13 @@ function Link(props: LinkProps, ref: React.ForwardedRef<HTMLAnchorElement>) {
3835
href={to}
3936
{...(openInBrowser && { target: '_blank' })}
4037
rel="noopener noreferrer"
41-
className={twMerge(
42-
'flex items-center gap-auth-link rounded-full px-auth-link-x py-auth-link-y text-center text-xs font-bold text-blue-500 transition-all duration-auth hover:text-blue-700 focus:text-blue-700',
43-
focusChildClassName,
44-
)}
38+
className="flex items-center gap-auth-link rounded-full px-auth-link-x py-auth-link-y text-center text-xs font-bold text-blue-500 transition-all duration-auth hover:text-blue-700 focus:text-blue-700"
4539
onPress={() => {
4640
if (openInBrowser) {
4741
toastify.toast.success(getText('openedLinkInBrowser'))
4842
}
4943
onPress?.()
5044
}}
51-
{...focusChildProps}
5245
>
5346
<SvgMask src={icon} />
5447
{text}

app/gui/src/dashboard/components/MenuEntry.tsx

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import BlankIcon from '#/assets/blank.svg'
88

99
import type * as inputBindings from '#/configurations/inputBindings'
1010

11-
import * as focusHooks from '#/hooks/focusHooks'
12-
1311
import * as inputBindingsProvider from '#/providers/InputBindingsProvider'
1412
import * as modalProvider from '#/providers/ModalProvider'
1513
import * as textProvider from '#/providers/TextProvider'
@@ -119,7 +117,6 @@ export default function MenuEntry(props: MenuEntryProps) {
119117
const { unsetModal } = modalProvider.useSetModal()
120118
const dialogContext = useDialogContext()
121119
const inputBindings = inputBindingsProvider.useInputBindings()
122-
const focusChildProps = focusHooks.useFocusChild()
123120
const info = inputBindings.metadata[action]
124121
const buttonRef = React.useRef<HTMLButtonElement>(null)
125122
const isDisabledRef = useSyncRef(isDisabled)
@@ -168,19 +165,17 @@ export default function MenuEntry(props: MenuEntryProps) {
168165
<FocusRing>
169166
<aria.Button
170167
ref={buttonRef}
171-
{...aria.mergeProps<aria.ButtonProps>()(focusChildProps, {
172-
isDisabled,
173-
className: 'group flex w-full rounded-menu-entry',
174-
onPress: () => {
175-
if (dialogContext) {
176-
// Closing a dialog takes precedence over unsetting the modal.
177-
dialogContext.close()
178-
} else {
179-
unsetModal()
180-
}
181-
doAction()
182-
},
183-
})}
168+
isDisabled={isDisabled}
169+
className="group flex w-full rounded-menu-entry"
170+
onPress={() => {
171+
if (dialogContext) {
172+
// Closing a dialog takes precedence over unsetting the modal.
173+
dialogContext.close()
174+
} else {
175+
unsetModal()
176+
}
177+
doAction()
178+
}}
184179
>
185180
<div className={MENU_ENTRY_VARIANTS(variantProps)} {...targetProps}>
186181
<div title={title} className="flex items-center gap-menu-entry whitespace-nowrap">

app/gui/src/dashboard/components/Modal.tsx

Lines changed: 21 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ import * as React from 'react'
33

44
import * as modalProvider from '#/providers/ModalProvider'
55

6-
import FocusRoot from '#/components/styled/FocusRoot'
7-
86
import { ClearPressResponder } from '#/components/aria'
97
import * as tailwindVariants from '#/utilities/tailwindVariants'
108

@@ -41,34 +39,28 @@ export default function Modal(props: ModalProps) {
4139
// Required so that `Button`s and `Checkbox`es contained inside do not trigger any
4240
// ancestor `DialogTrigger`s.
4341
<ClearPressResponder>
44-
<FocusRoot active={!hidden}>
45-
{(innerProps) => (
46-
<div
47-
{...(!hidden ? { 'data-testid': 'modal-background' } : {})}
48-
style={style}
49-
className={MODAL_VARIANTS(variantProps)}
50-
onClick={
51-
onClick ??
52-
((event) => {
53-
if (event.currentTarget === event.target && getSelection()?.type !== 'Range') {
54-
event.stopPropagation()
55-
unsetModal()
56-
}
57-
})
42+
<div
43+
{...(!hidden ? { 'data-testid': 'modal-background' } : {})}
44+
style={style}
45+
className={MODAL_VARIANTS(variantProps)}
46+
onClick={
47+
onClick ??
48+
((event) => {
49+
if (event.currentTarget === event.target && getSelection()?.type !== 'Range') {
50+
event.stopPropagation()
51+
unsetModal()
5852
}
59-
onContextMenu={onContextMenu}
60-
{...innerProps}
61-
onKeyDown={(event) => {
62-
innerProps.onKeyDown?.(event)
63-
if (event.key !== 'Escape') {
64-
event.stopPropagation()
65-
}
66-
}}
67-
>
68-
{children}
69-
</div>
70-
)}
71-
</FocusRoot>
53+
})
54+
}
55+
onContextMenu={onContextMenu}
56+
onKeyDown={(event) => {
57+
if (event.key !== 'Escape') {
58+
event.stopPropagation()
59+
}
60+
}}
61+
>
62+
{children}
63+
</div>
7264
</ClearPressResponder>
7365
)
7466
}

app/gui/src/dashboard/components/dashboard/Label.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import type { DragEvent, MouseEvent, PropsWithChildren } from 'react'
44
import type { PressEvent } from '#/components/aria'
55
import { Text } from '#/components/AriaComponents'
66
import FocusRing from '#/components/styled/FocusRing'
7-
import { useHandleFocusMove } from '#/hooks/focusHooks'
8-
import { useFocusDirection } from '#/providers/FocusDirectionProvider'
97
import type { Label as BackendLabel } from '#/services/Backend'
108
import { lChColorToCssColor, type LChColor } from '#/services/Backend'
119
import { twMerge } from '#/utilities/tailwindMerge'
@@ -39,8 +37,6 @@ export default function Label(props: InternalLabelProps) {
3937
const { active = false, isDisabled = false, color, negated = false, draggable, title } = props
4038
const { onPress, onDragStart, onContextMenu, label } = props
4139
const { children: childrenRaw } = props
42-
const focusDirection = useFocusDirection()
43-
const handleFocusMove = useHandleFocusMove(focusDirection)
4440
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
4541
const isLight = color.lightness > 50
4642

@@ -61,7 +57,7 @@ export default function Label(props: InternalLabelProps) {
6157
title={title}
6258
disabled={isDisabled}
6359
className={twMerge(
64-
'focus-child relative flex h-6 items-center whitespace-nowrap rounded-inherit px-[7px] opacity-50 transition-all after:pointer-events-none after:absolute after:inset after:rounded-full hover:opacity-100 focus:opacity-100',
60+
'relative flex h-6 items-center whitespace-nowrap rounded-inherit px-[7px] opacity-50 transition-all after:pointer-events-none after:absolute after:inset after:rounded-full hover:opacity-100 focus:opacity-100',
6561
active && 'active',
6662
negated && 'after:border-2 after:border-delete',
6763
)}
@@ -74,7 +70,6 @@ export default function Label(props: InternalLabelProps) {
7470
onDragStart?.(e)
7571
}}
7672
onContextMenu={onContextMenu}
77-
onKeyDown={handleFocusMove}
7873
>
7974
{typeof childrenRaw !== 'string' ?
8075
childrenRaw

app/gui/src/dashboard/components/dashboard/Permission.tsx

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import * as toastAndLogHooks from '#/hooks/toastAndLogHooks'
1111
import * as textProvider from '#/providers/TextProvider'
1212

1313
import PermissionSelector from '#/components/dashboard/PermissionSelector'
14-
import FocusArea from '#/components/styled/FocusArea'
1514

1615
import type Backend from '#/services/Backend'
1716
import * as backendModule from '#/services/Backend'
@@ -81,26 +80,22 @@ export default function Permission(props: PermissionProps) {
8180
}
8281

8382
return (
84-
<FocusArea active={!isDisabled} direction="horizontal">
85-
{(innerProps) => (
86-
<div className="flex w-full items-center gap-user-permission" {...innerProps}>
87-
<PermissionSelector
88-
showDelete
89-
isDisabled={isDisabled}
90-
error={isOnlyOwner ? getText('needsOwnerError', assetTypeName) : null}
91-
selfPermission={self.permission}
92-
action={permission.permission}
93-
assetType={asset.type}
94-
onChange={async (permissions) => {
95-
await doSetPermission(object.merge(permission, { permission: permissions }))
96-
}}
97-
doDelete={() => {
98-
doDelete(backendModule.getAssetPermissionId(permission))
99-
}}
100-
/>
101-
<Text truncate="1">{backendModule.getAssetPermissionName(permission)}</Text>
102-
</div>
103-
)}
104-
</FocusArea>
83+
<div className="flex w-full items-center gap-user-permission">
84+
<PermissionSelector
85+
showDelete
86+
isDisabled={isDisabled}
87+
error={isOnlyOwner ? getText('needsOwnerError', assetTypeName) : null}
88+
selfPermission={self.permission}
89+
action={permission.permission}
90+
assetType={asset.type}
91+
onChange={async (permissions) => {
92+
await doSetPermission(object.merge(permission, { permission: permissions }))
93+
}}
94+
doDelete={() => {
95+
doDelete(backendModule.getAssetPermissionId(permission))
96+
}}
97+
/>
98+
<Text truncate="1">{backendModule.getAssetPermissionName(permission)}</Text>
99+
</div>
105100
)
106101
}

0 commit comments

Comments
 (0)