You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NextUI Drawer侧边栏打开时输入框无法获取焦点的问题求助

NextUI Drawer侧边栏打开时输入框无法获取焦点的问题求助

我在开发React应用时,使用@nextui-org/react库的Drawer组件实现了侧边栏,但遇到了一个头疼的问题:当侧边栏打开时,点击主内容区的输入框,输入框没法获得焦点,反而侧边栏导航列表里的某个项会被聚焦。这直接导致用户在侧边栏显示时没法和输入框交互。

我发现如果把Sidebar实现里的DrawerContent组件去掉,问题就解决了,说明问题出在这个组件或者它和Drawer的交互上。打开侧边栏时,页面里会出现<span data-focus-scope-start="true" hidden="" aria-hidden="true"></span>这个元素,我怀疑这和焦点管理的错误有关。

一开始我以为是portalContainer属性影响了事件处理,就把它去掉了,但问题还是存在。我还用浏览器开发者工具检查了相关元素的z-index,排除了层级堆叠的问题。

经过测试,我确定问题就出在DrawerContent组件上。我的预期是侧边栏打开时点击输入框,输入框能获得焦点让用户输入,但实际情况是输入框没焦点,侧边栏的导航项反而被聚焦。那个带data-focus-scope-start的span元素看起来就是罪魁祸首,它应该是在错误地管理焦点。

LayoutPanel.js:

import React from "react";
import { Outlet, useLocation, useNavigate } from "react-router";
import Sidebar from "../components/Sidebar";
import {
  Button,
  Card,
  CardBody,
  CardHeader,
  Divider,
  useDisclosure,
} from "@nextui-org/react";
import { Icon } from "@iconify/react";
import { images } from "../utils/images";

const LayoutPanel = () => {
  const { isOpen, onOpen, onOpenChange } = useDisclosure();

  const navigate = useNavigate();
  const location = useLocation();

  return (
    <div>
      {/* <HeaderNavigation /> */}
      <div className="flex w-full">
        <Sidebar isOpen={isOpen} onOpenChange={onOpenChange} />
        <Card className="flex-1 m-3 min-h-[calc(100vh-24px)]">
          <CardHeader className="h-[76px]">
            <div className="flex items-center gap-2">
              {!isOpen && (
                <Button isIconOnly variant="light" onPress={onOpenChange}>
                  <Icon icon="solar:siderbar-outline" width={24} />
                </Button>
              )}
              <img
                src={images.logo}
                alt="logo"
                className="object-contain h-6 dark:invert"
              />
            </div>
          </CardHeader>
          <Divider />
          <CardBody className="container mx-auto max-w-7xl text-start">
            <Outlet />
          </CardBody>
        </Card>
      </div>
      {/* <Footer /> */}
    </div>
  );
};

export default LayoutPanel;

Sidebar.js:

import React from "react";
import {
  Drawer,
  DrawerContent,
  DrawerHeader,
  DrawerBody,
  Listbox,
  ListboxItem,
  Accordion,
  Button,
  AccordionItem,
  cn,
  Divider,
} from "@nextui-org/react";
import sidebarNavigation from "../utils/sidebarNavigation";
import { Icon } from "@iconify/react";

const Sidebar = ({ isOpen, onOpenChange }) => {
  return (
    <div
      id="sidebar"
      className={cn(
        "transition-all absolute md:relative duration-300 ease-in-out overflow-hidden",
        isOpen ? "w-[336px]" : "w-0"
      )}
    >
      <Drawer
        isDismissable={false}
        hideCloseButton
        isKeyboardDismissDisabled={false}
        portalContainer={document.getElementById("sidebar") || undefined}
        backdrop={window.innerWidth < 768 && isOpen ? "blur" : "transparent"}
        classNames={{
          wrapper: "!items-stretch w-auto relative",
          base: "data-[placement=right]:sm:my-3 data-[placement=left]:sm:my-3 rounded-e-large rounded-s-none",
          body: "pe-0",
          header: "p-[calc(1rem+2px)] ",
        }}
        shouldBlockScroll
        isOpen={isOpen}
        onOpenChange={onOpenChange}
      >
        <DrawerContent>
          <DrawerHeader className="flex justify-between gap-3 ">
            <h3>賲賳賵</h3>
            <Button isIconOnly variant="light" onPress={onOpenChange}>
              <Icon icon="solar:siderbar-outline" width={24} />
            </Button>
          </DrawerHeader>
          <Divider />
          <DrawerBody>
            <Listbox
              variant="flat"
              className="overflow-y-auto pe-3 ps-0"
            >
              {sidebarNavigation.map((menuItem) =>
                menuItem.subItems ? (
                  <ListboxItem key={menuItem.title}>
                    <Accordion showDivider={false} className="space-y-3">
                      <AccordionItem
                        key={menuItem.title}
                        aria-label={menuItem.title}
                        startContent={
                          <div
                            className={`flex items-center rounded-small justify-center ${menuItem.color} w-9 h-9`}
                          >
                            <img
                              src={menuItem.icon}
                              className="object-contain invert"
                              width={24}
                              alt={menuItem.title}
                            />
                          </div>
                        }
                        subtitle={menuItem.subtitle}
                        classNames={{
                          trigger: "p-0",
                          content: "py-0 ps-3",
                        }}
                        title={menuItem.title}
                      >
                        <Listbox
                          variant="flat"
                          aria-label={`夭蹖乇賲賳賵 ${menuItem.title}`}
                          classNames={{
                            list: cn("border-s border-default-200 ps-4"),
                          }}
                        >
                          {menuItem.subItems.map((subItem) => (
                            <ListboxItem
                              key={subItem.title}
                              textValue={subItem.title}
                              href={subItem.path}
                              startContent={
                                <div
                                  className={`flex items-center rounded-small justify-center ${menuItem.color} w-7 h-7`}
                                >
                                  <img
                                    src={subItem.icon}
                                    width={20}
                                    className="object-contain"
                                    alt={subItem.title}
                                  />
                                </div>
                              }
                            >
                              <span>{subItem.title}</span>
                            </ListboxItem>
                          ))}
                        </Listbox>
                      </AccordionItem>
                    </Accordion>
                  </ListboxItem>
                ) : (
                  <ListboxItem
                    title={menuItem.title}
                    description={menuItem.subtitle}
                    classNames={{
                      base: "gap-3",
                    }}
                    startContent={
                      <div className="ms-2">
                        <div
                          className={`flex items-center rounded-small justify-center ${menuItem.color} w-9 h-9`}
                        >
                          <img
                            src={menuItem.icon}
                            width={20}
                            className="invert"
                            alt={menuItem.title}
                          />
                        </div>
                      </div>
                    }
                  >
                    {menuItem.title}
                  </ListboxItem>
                )
              )}
            </Listbox>
          </DrawerBody>
        </DrawerContent>
      </Drawer>
    </div>
  );
};

export default Sidebar;

FormFastGroup.js:

import { Controller, useForm } from "react-hook-form";
import { Button, Form, Input } from "@nextui-org/react";

const FormFastGroup = () => {
  const { handleSubmit, control } = useForm();

  const onSubmit = (data) => {
    console.log(data);
  };

  return (
    <Form
      className="w-full max-w-xs flex flex-col gap-4"
      onSubmit={handleSubmit(onSubmit)}
    >
      <Controller
        name="groupName"
        control={control}
        defaultValue=""
        render={({ field }) => (
          <Input
            {...field}
            label="分组名称"
            placeholder="请输入分组名称"
            variant="bordered"
          />
        )}
      />
      <Button type="submit" color="primary">
        提交
      </Button>
    </Form>
  );
};

export default FormFastGroup;

备注:内容来源于stack exchange,提问作者Parsa Amirabadi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 17:03:01