diff --git a/src/frontend/apps/impress/src/features/docs/doc-tree/components/ButtonAddChildDoc.tsx b/src/frontend/apps/impress/src/features/docs/doc-tree/components/ButtonAddChildDoc.tsx
new file mode 100644
index 00000000..522905f6
--- /dev/null
+++ b/src/frontend/apps/impress/src/features/docs/doc-tree/components/ButtonAddChildDoc.tsx
@@ -0,0 +1,76 @@
+import { useCallback } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import { BoxButton, Icon } from '@/components';
+
+type ButtonAddChildDocProps = {
+ onCreateChild: (params: { parentId: string }) => void;
+ parentId: string;
+ title?: string | null;
+};
+
+export const ButtonAddChildDoc = ({
+ onCreateChild,
+ parentId,
+ title,
+}: ButtonAddChildDocProps) => {
+ const { t } = useTranslation();
+
+ const preventDefaultAndStopPropagation = useCallback(
+ (e: React.MouseEvent | React.KeyboardEvent) => {
+ e.stopPropagation();
+ e.preventDefault();
+ },
+ [],
+ );
+
+ const isValidKeyEvent = useCallback((e: React.KeyboardEvent) => {
+ return e.key === 'Enter' || e.key === ' ';
+ }, []);
+
+ const handleClick = useCallback(
+ (e: React.MouseEvent) => {
+ preventDefaultAndStopPropagation(e);
+ void onCreateChild({ parentId });
+ },
+ [onCreateChild, parentId, preventDefaultAndStopPropagation],
+ );
+
+ const handleKeyDown = useCallback(
+ (e: React.KeyboardEvent) => {
+ if (isValidKeyEvent(e)) {
+ preventDefaultAndStopPropagation(e);
+ void onCreateChild({ parentId });
+ }
+ },
+ [
+ onCreateChild,
+ parentId,
+ preventDefaultAndStopPropagation,
+ isValidKeyEvent,
+ ],
+ );
+
+ return (
+
+
+
+ );
+};
diff --git a/src/frontend/apps/impress/src/features/docs/doc-tree/components/ButtonMoreOptions.tsx b/src/frontend/apps/impress/src/features/docs/doc-tree/components/ButtonMoreOptions.tsx
new file mode 100644
index 00000000..73a38a79
--- /dev/null
+++ b/src/frontend/apps/impress/src/features/docs/doc-tree/components/ButtonMoreOptions.tsx
@@ -0,0 +1,73 @@
+import { useCallback } from 'react';
+import { useTranslation } from 'react-i18next';
+import { css } from 'styled-components';
+
+import { Icon } from '@/components';
+
+type ButtonMoreOptionsProps = {
+ isOpen?: boolean;
+ onOpenChange?: (isOpen: boolean) => void;
+ title?: string | null;
+ className?: string;
+};
+
+export const ButtonMoreOptions = ({
+ isOpen,
+ onOpenChange,
+ title,
+ className = 'icon-button',
+}: ButtonMoreOptionsProps) => {
+ const { t } = useTranslation();
+
+ const preventDefaultAndStopPropagation = useCallback(
+ (e: React.MouseEvent | React.KeyboardEvent) => {
+ e.stopPropagation();
+ e.preventDefault();
+ },
+ [],
+ );
+
+ const isValidKeyEvent = useCallback((e: React.KeyboardEvent) => {
+ return e.key === 'Enter' || e.key === ' ';
+ }, []);
+
+ const handleClick = useCallback(
+ (e: React.MouseEvent) => {
+ preventDefaultAndStopPropagation(e);
+ onOpenChange?.(!isOpen);
+ },
+ [isOpen, onOpenChange, preventDefaultAndStopPropagation],
+ );
+
+ const handleKeyDown = useCallback(
+ (e: React.KeyboardEvent) => {
+ if (isValidKeyEvent(e)) {
+ preventDefaultAndStopPropagation(e);
+ onOpenChange?.(!isOpen);
+ }
+ },
+ [isOpen, onOpenChange, preventDefaultAndStopPropagation, isValidKeyEvent],
+ );
+
+ return (
+
+ );
+};
diff --git a/src/frontend/apps/impress/src/features/docs/doc-tree/components/DocTreeItemActions.tsx b/src/frontend/apps/impress/src/features/docs/doc-tree/components/DocTreeItemActions.tsx
index 0ceaa192..1c1e3ccb 100644
--- a/src/frontend/apps/impress/src/features/docs/doc-tree/components/DocTreeItemActions.tsx
+++ b/src/frontend/apps/impress/src/features/docs/doc-tree/components/DocTreeItemActions.tsx
@@ -8,9 +8,7 @@ import { useRouter } from 'next/router';
import { useTranslation } from 'react-i18next';
import { css } from 'styled-components';
-import { Box, BoxButton, Icon } from '@/components';
-import { useDocTreeItemHandlers } from '@/features/docs/doc-tree/hooks/useDocTreeItemHandlers';
-import { useDropdownFocusManagement } from '@/features/docs/doc-tree/hooks/useDropdownFocusManagement';
+import { Box, Icon } from '@/components';
import {
Doc,
ModalRemoveDoc,
@@ -19,6 +17,9 @@ import {
useCreateChildDoc,
useDuplicateDoc,
} from '@/docs/doc-management';
+import { ButtonAddChildDoc } from '@/features/docs/doc-tree/components/ButtonAddChildDoc';
+import { ButtonMoreOptions } from '@/features/docs/doc-tree/components/ButtonMoreOptions';
+import { useDropdownFocusManagement } from '@/features/docs/doc-tree/hooks/useDropdownFocusManagement';
import { useDetachDoc } from '../api/useDetach';
import MoveDocIcon from '../assets/doc-extract-bold.svg';
@@ -149,18 +150,6 @@ export const DocTreeItemActions = ({
}
};
- const {
- handleMoreOptionsClick,
- handleMoreOptionsKeyDown,
- handleAddChildClick,
- handleAddChildKeyDown,
- } = useDocTreeItemHandlers({
- isOpen,
- onOpenChange,
- createChildDoc,
- docId: doc.id,
- });
-
useDropdownFocusManagement({
isOpen: isOpen || false,
docId: doc.id,
@@ -202,45 +191,18 @@ export const DocTreeItemActions = ({
isOpen={isOpen}
onOpenChange={onOpenChange}
>
-
{doc.abilities.children_create && (
-
-
-
+
)}
{deleteModal.isOpen && (
diff --git a/src/frontend/apps/impress/src/features/docs/doc-tree/hooks/useDocTreeItemHandlers.ts b/src/frontend/apps/impress/src/features/docs/doc-tree/hooks/useDocTreeItemHandlers.ts
deleted file mode 100644
index b22b7026..00000000
--- a/src/frontend/apps/impress/src/features/docs/doc-tree/hooks/useDocTreeItemHandlers.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-import { useCallback } from 'react';
-
-interface UseDocTreeItemHandlersProps {
- isOpen?: boolean;
- onOpenChange?: (isOpen: boolean) => void;
- createChildDoc: (params: { parentId: string }) => void;
- docId: string;
-}
-
-export const useDocTreeItemHandlers = ({
- isOpen,
- onOpenChange,
- createChildDoc,
- docId,
-}: UseDocTreeItemHandlersProps) => {
- const preventDefaultAndStopPropagation = useCallback(
- (e: React.MouseEvent | React.KeyboardEvent) => {
- e.stopPropagation();
- e.preventDefault();
- },
- [],
- );
-
- const isValidKeyEvent = useCallback((e: React.KeyboardEvent) => {
- return e.key === 'Enter' || e.key === ' ';
- }, []);
-
- const handleMoreOptionsClick = useCallback(
- (e: React.MouseEvent) => {
- preventDefaultAndStopPropagation(e);
- onOpenChange?.(!isOpen);
- },
- [isOpen, onOpenChange, preventDefaultAndStopPropagation],
- );
-
- const handleMoreOptionsKeyDown = useCallback(
- (e: React.KeyboardEvent) => {
- if (isValidKeyEvent(e)) {
- preventDefaultAndStopPropagation(e);
- onOpenChange?.(!isOpen);
- }
- },
- [isOpen, onOpenChange, preventDefaultAndStopPropagation, isValidKeyEvent],
- );
-
- const handleAddChildClick = useCallback(
- (e: React.MouseEvent) => {
- preventDefaultAndStopPropagation(e);
- void createChildDoc({
- parentId: docId,
- });
- },
- [createChildDoc, docId, preventDefaultAndStopPropagation],
- );
-
- const handleAddChildKeyDown = useCallback(
- (e: React.KeyboardEvent) => {
- if (isValidKeyEvent(e)) {
- preventDefaultAndStopPropagation(e);
- void createChildDoc({
- parentId: docId,
- });
- }
- },
- [createChildDoc, docId, preventDefaultAndStopPropagation, isValidKeyEvent],
- );
-
- return {
- handleMoreOptionsClick,
- handleMoreOptionsKeyDown,
- handleAddChildClick,
- handleAddChildKeyDown,
- };
-};