Skip to content

Commit e56c719

Browse files
committed
frontend/aria: start making autoFocus configurable
1 parent 13bec8c commit e56c719

File tree

10 files changed

+51
-12
lines changed

10 files changed

+51
-12
lines changed

src/packages/frontend/account/account-preferences-appearance.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,16 @@ export function AccountPreferencesAppearance() {
241241
</HelpIcon>
242242
</div>
243243
</LabeledRow>
244+
<Switch
245+
checked={!!other_settings.get("auto_focus")}
246+
onChange={(e) => on_change("auto_focus", e.target.checked)}
247+
>
248+
<FormattedMessage
249+
id="account.other-settings.auto_focus"
250+
defaultMessage={`<strong>Auto Focus Text Input:</strong>
251+
automatically focus text input fields when they appear (e.g., file explorer, projects, ...)`}
252+
/>
253+
</Switch>
244254
<Switch
245255
checked={!!other_settings.get("hide_file_popovers")}
246256
onChange={(e) => on_change("hide_file_popovers", e.target.checked)}

src/packages/frontend/account/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@ export { init } from "./init";
1111
export { show_announce_start, show_announce_end } from "./dates";
1212

1313
export { default_filename } from "./default-file-name-generator";
14+
15+
export { useAutoFocusPreference } from "./use-auto-focus-preference";
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* This file is part of CoCalc: Copyright © 2025 Sagemath, Inc.
3+
* License: MS-RSL – see LICENSE.md for details
4+
*/
5+
6+
import { useTypedRedux } from "@cocalc/frontend/app-framework";
7+
8+
/**
9+
* Hook to get the user's auto focus preference for text input fields.
10+
* Returns false by default (auto focus disabled).
11+
*/
12+
export function useAutoFocusPreference(): boolean {
13+
const other_settings = useTypedRedux("account", "other_settings");
14+
return other_settings?.get("auto_focus") ?? false;
15+
}

src/packages/frontend/app/page.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import BalanceButton from "@cocalc/frontend/purchases/balance-button";
3636
import PayAsYouGoModal from "@cocalc/frontend/purchases/pay-as-you-go/modal";
3737
import openSupportTab from "@cocalc/frontend/support/open";
3838
import { webapp_client } from "@cocalc/frontend/webapp-client";
39-
import { COLORS, SITE_NAME } from "@cocalc/util/theme";
39+
import { COLORS } from "@cocalc/util/theme";
4040
import { IS_IOS, IS_MOBILE, IS_SAFARI } from "../feature";
4141
import { ActiveContent } from "./active-content";
4242
import { ConnectionIndicator } from "./connection-indicator";
@@ -124,7 +124,6 @@ export const Page: React.FC = () => {
124124

125125
const is_commercial = useTypedRedux("customize", "is_commercial");
126126
const insecure_test_mode = useTypedRedux("customize", "insecure_test_mode");
127-
const site_name = useTypedRedux("customize", "site_name") ?? SITE_NAME;
128127

129128
function account_tab_icon(): IconName | React.JSX.Element {
130129
if (is_anonymous) {

src/packages/frontend/components/search-input.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,9 @@ export const SearchInput: React.FC<Props> = React.memo((props) => {
6161
}, []);
6262

6363
useEffect(() => {
64-
if (focus == null) return;
64+
if (props.focus == null) return;
6565
input_ref.current?.focus();
66-
}, [focus]);
66+
}, [props.focus]);
6767

6868
function get_opts(): { ctrl_down: boolean; shift_down: boolean } {
6969
return { ctrl_down, shift_down };

src/packages/frontend/frame-editors/frame-tree/commands/generic-commands.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { debounce } from "lodash";
1010
import { useEffect, useRef } from "react";
1111
import { defineMessage, IntlShape, useIntl } from "react-intl";
1212

13+
import { useAutoFocusPreference } from "@cocalc/frontend/account";
1314
import { set_account_table } from "@cocalc/frontend/account/util";
1415
import { redux } from "@cocalc/frontend/app-framework";
1516
import { Icon } from "@cocalc/frontend/components";
@@ -1578,6 +1579,7 @@ function fileAction(action) {
15781579

15791580
function SearchBox({ setHelpSearch, helpSearch }) {
15801581
const intl = useIntl();
1582+
const shouldAutoFocus = useAutoFocusPreference();
15811583
const didFocus = useRef<boolean>(false);
15821584

15831585
useEffect(() => {
@@ -1591,7 +1593,7 @@ function SearchBox({ setHelpSearch, helpSearch }) {
15911593

15921594
return (
15931595
<Input.Search
1594-
autoFocus
1596+
autoFocus={shouldAutoFocus}
15951597
placeholder={intl.formatMessage(labels.search)}
15961598
allowClear
15971599
value={helpSearch}

src/packages/frontend/project/explorer/search-bar.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import { Alert, Flex } from "antd";
77
import React from "react";
88
import { useIntl } from "react-intl";
9+
10+
import { useAutoFocusPreference } from "@cocalc/frontend/account";
911
import { CSS, redux } from "@cocalc/frontend/app-framework";
1012
import { Icon, SearchInput } from "@cocalc/frontend/components";
1113
import { ProjectActions } from "@cocalc/frontend/project_store";
@@ -73,6 +75,7 @@ export const SearchBar = React.memo((props: Props) => {
7375
} = props;
7476

7577
const intl = useIntl();
78+
const shouldAutoFocus = useAutoFocusPreference();
7679
const { project_id } = useProjectContext();
7780

7881
// edit → run → edit
@@ -300,8 +303,8 @@ export const SearchBar = React.memo((props: Props) => {
300303
return (
301304
<Flex style={{ flex: "1 0 auto", position: "relative" }} vertical={true}>
302305
<SearchInput
303-
autoFocus
304-
autoSelect
306+
autoFocus={shouldAutoFocus}
307+
autoSelect={shouldAutoFocus}
305308
placeholder={intl.formatMessage({
306309
id: "project.explorer.search-bar.placeholder",
307310
defaultMessage: 'Filter files or "/" for terminal...',

src/packages/frontend/project/new/new-file-page.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ import { Button, Input, Modal, Space } from "antd";
77
import { useEffect, useRef, useState } from "react";
88
import { defineMessage, FormattedMessage, useIntl } from "react-intl";
99

10-
import { default_filename } from "@cocalc/frontend/account";
10+
import {
11+
default_filename,
12+
useAutoFocusPreference,
13+
} from "@cocalc/frontend/account";
1114
import { Alert, Col, Row } from "@cocalc/frontend/antd-bootstrap";
1215
import {
1316
ProjectActions,
@@ -54,6 +57,7 @@ interface Props {
5457

5558
export default function NewFilePage(props: Props) {
5659
const intl = useIntl();
60+
const shouldAutoFocus = useAutoFocusPreference();
5761
const [createFolderModal, setCreateFolderModal] = useState<boolean>(false);
5862
const createFolderModalRef = useRef<any>(null);
5963
useEffect(() => {
@@ -392,7 +396,7 @@ export default function NewFilePage(props: Props) {
392396
<Input
393397
ref={createFolderModalRef}
394398
style={{ margin: "15px 0" }}
395-
autoFocus
399+
autoFocus={shouldAutoFocus}
396400
size="large"
397401
value={filename}
398402
onChange={(e) => setFilename(e.target.value)}
@@ -464,7 +468,7 @@ export default function NewFilePage(props: Props) {
464468
<Input
465469
size="large"
466470
ref={inputRef}
467-
autoFocus
471+
autoFocus={shouldAutoFocus}
468472
value={filename}
469473
disabled={extensionWarning}
470474
placeholder={

src/packages/frontend/projects/create-project.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { Button, Card, Col, Form, Input, Modal, Row, Space } from "antd";
1111
import { delay } from "awaiting";
1212
import { FormattedMessage, useIntl } from "react-intl";
1313

14+
import { useAutoFocusPreference } from "@cocalc/frontend/account";
1415
import { Well } from "@cocalc/frontend/antd-bootstrap";
1516
import {
1617
CSS,
@@ -60,6 +61,7 @@ export function NewProjectCreator({
6061
open_trigger,
6162
}: Props) {
6263
const intl = useIntl();
64+
const shouldAutoFocus = useAutoFocusPreference();
6365
// view --> edit --> saving --> view
6466
const [state, set_state] = useState<EditState>(noProjects ? "edit" : "view");
6567
const [title_text, set_title_text] = useState<string>(
@@ -378,7 +380,7 @@ export function NewProjectCreator({
378380
disabled={state === "saving"}
379381
onChange={input_on_change}
380382
onKeyDown={handle_keypress}
381-
autoFocus
383+
autoFocus={shouldAutoFocus}
382384
/>
383385
</Form.Item>
384386
</Form>

src/packages/frontend/projects/projects-table-controls.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { Set } from "immutable";
1717
import { ReactNode, useMemo } from "react";
1818
import { useIntl } from "react-intl";
1919

20+
import { useAutoFocusPreference } from "@cocalc/frontend/account";
2021
import { CSS, useActions, useTypedRedux } from "@cocalc/frontend/app-framework";
2122
import { Icon } from "@cocalc/frontend/components";
2223
import { IS_MOBILE } from "@cocalc/frontend/feature";
@@ -53,6 +54,7 @@ export function ProjectsTableControls({
5354
filtersRef,
5455
}: Props) {
5556
const intl = useIntl();
57+
const shouldAutoFocus = useAutoFocusPreference();
5658
const actions = useActions("projects");
5759

5860
// Redux state
@@ -113,7 +115,7 @@ export function ProjectsTableControls({
113115
id: "projects.table-controls.search.placeholder",
114116
defaultMessage: "Filter projects...",
115117
})}
116-
autoFocus
118+
autoFocus={shouldAutoFocus}
117119
value={search}
118120
onChange={handleSearchChange}
119121
onPressEnter={handlePressEnter}

0 commit comments

Comments
 (0)