diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/TestColors/TestColors.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/TestColors/TestColors.tsx
index e09a062ecd..2a46fb4acb 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/TestColors/TestColors.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/TestColors/TestColors.tsx
@@ -37,6 +37,7 @@ import { SortSvg } from '$app/components/_shared/svg/SortSvg';
import { TextTypeSvg } from '$app/components/_shared/svg/TextTypeSvg';
import { TrashSvg } from '$app/components/_shared/svg/TrashSvg';
import { UrlTypeSvg } from '$app/components/_shared/svg/UrlTypeSvg';
+import { GroupByFieldSvg } from '$app/components/_shared/svg/GroupByFieldSvg';
export const TestColors = () => {
return (
@@ -110,6 +111,9 @@ export const TestColors = () => {
+
+
+
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/Popup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/Popup.tsx
index d317322e17..00806d62f4 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/Popup.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/Popup.tsx
@@ -2,7 +2,7 @@ import { MouseEvent, ReactNode, useRef } from 'react';
import useOutsideClick from './useOutsideClick';
export interface IPopupItem {
- icon: ReactNode;
+ icon: ReactNode | (() => JSX.Element);
title: string;
onClick: () => void;
}
@@ -31,18 +31,20 @@ export const Popup = ({
return (
{items.map((item, index) => (
))}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/svg/GroupByFieldSvg.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/svg/GroupByFieldSvg.tsx
new file mode 100644
index 0000000000..960e1bad2a
--- /dev/null
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/svg/GroupByFieldSvg.tsx
@@ -0,0 +1,26 @@
+export const GroupByFieldSvg = () => {
+ return (
+
+ );
+};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx
index bff32516d8..7cc577632a 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx
@@ -8,6 +8,7 @@ import { DragDropContext } from 'react-beautiful-dnd';
import { useState } from 'react';
import { RowInfo } from '$app/stores/effects/database/row/row_cache';
import { EditRow } from '$app/components/_shared/EditRow/EditRow';
+import { BoardToolbar } from '$app/components/board/BoardToolbar';
export const Board = ({ viewId, title }: { viewId: string; title: string }) => {
const { controller, rows, groups, groupByFieldId, onNewRowClick, onDragEnd } = useDatabase(viewId, ViewLayoutPB.Board);
@@ -22,12 +23,7 @@ export const Board = ({ viewId, title }: { viewId: string; title: string }) => {
return (
<>
-
+
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardFieldsPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardFieldsPopup.tsx
new file mode 100644
index 0000000000..9b8a765bbd
--- /dev/null
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardFieldsPopup.tsx
@@ -0,0 +1,36 @@
+import { useAppSelector } from '$app/stores/store';
+import { FieldTypeIcon } from '$app/components/_shared/EditRow/FieldTypeIcon';
+import { Popup } from '$app/components/_shared/Popup';
+import { useRef } from 'react';
+import useOutsideClick from '$app/components/_shared/useOutsideClick';
+import { EyeOpenSvg } from '$app/components/_shared/svg/EyeOpenSvg';
+
+export const BoardFieldsPopup = ({ hidePopup }: { hidePopup: () => void }) => {
+ const columns = useAppSelector((state) => state.database.columns);
+ const fields = useAppSelector((state) => state.database.fields);
+ const ref = useRef
(null);
+ useOutsideClick(ref, () => hidePopup());
+
+ return (
+
+ {columns.map((column, index) => (
+
+
+
+
+
+ {fields[column.fieldId].title}
+
+
+
+
+
+
+
+ ))}
+
+ );
+};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardGroupFieldsPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardGroupFieldsPopup.tsx
new file mode 100644
index 0000000000..7039bf29b2
--- /dev/null
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardGroupFieldsPopup.tsx
@@ -0,0 +1,3 @@
+export const BoardGroupFieldsPopup = ({ hidePopup }: { hidePopup: () => void }) => {
+ return <>>;
+};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardSettingsPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardSettingsPopup.tsx
new file mode 100644
index 0000000000..3e37ed27c4
--- /dev/null
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardSettingsPopup.tsx
@@ -0,0 +1,48 @@
+import { useEffect, useState } from 'react';
+import { PropertiesSvg } from '$app/components/_shared/svg/PropertiesSvg';
+import { IPopupItem, Popup } from '$app/components/_shared/Popup';
+import { useTranslation } from 'react-i18next';
+import { GroupByFieldSvg } from '$app/components/_shared/svg/GroupByFieldSvg';
+
+export const BoardSettingsPopup = ({
+ hidePopup,
+ onFieldsClick,
+ onGroupClick,
+}: {
+ hidePopup: () => void;
+ onFieldsClick: () => void;
+ onGroupClick: () => void;
+}) => {
+ const [settingsItems, setSettingsItems] = useState([]);
+ const { t } = useTranslation('');
+ useEffect(() => {
+ setSettingsItems([
+ {
+ icon: (
+
+
+
+ ),
+ title: t('grid.settings.Properties'),
+ onClick: onFieldsClick,
+ },
+ {
+ icon: (
+
+
+
+ ),
+ title: t('grid.settings.group'),
+ onClick: onGroupClick,
+ },
+ ]);
+ }, [t]);
+
+ return (
+ hidePopup()}
+ items={settingsItems}
+ className={'absolute top-full left-full z-10'}
+ >
+ );
+};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardToolbar.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardToolbar.hooks.ts
new file mode 100644
index 0000000000..b9fd587734
--- /dev/null
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardToolbar.hooks.ts
@@ -0,0 +1,37 @@
+import { useState } from 'react';
+
+export const useBoardToolbar = () => {
+ const [showSettings, setShowSettings] = useState(false);
+ const [showAllFields, setShowAllFields] = useState(false);
+ const [showGroupFields, setShowGroupFields] = useState(false);
+
+ const onSettingsClick = () => {
+ setShowSettings(!showSettings);
+ };
+
+ const onFieldsClick = () => {
+ setShowSettings(false);
+ setShowAllFields(true);
+ };
+
+ const onGroupClick = () => {
+ setShowSettings(false);
+ setShowGroupFields(true);
+ };
+
+ const hidePopup = () => {
+ setShowSettings(false);
+ setShowAllFields(false);
+ setShowGroupFields(false);
+ };
+
+ return {
+ showSettings,
+ onSettingsClick,
+ onFieldsClick,
+ onGroupClick,
+ hidePopup,
+ showAllFields,
+ showGroupFields,
+ };
+};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardToolbar.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardToolbar.tsx
new file mode 100644
index 0000000000..7459f39857
--- /dev/null
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardToolbar.tsx
@@ -0,0 +1,28 @@
+import { SettingsSvg } from '$app/components/_shared/svg/SettingsSvg';
+import { useBoardToolbar } from '$app/components/board/BoardToolbar.hooks';
+import { BoardSettingsPopup } from '$app/components/board/BoardSettingsPopup';
+import { BoardFieldsPopup } from '$app/components/board/BoardFieldsPopup';
+import { BoardGroupFieldsPopup } from '$app/components/board/BoardGroupFieldsPopup';
+
+export const BoardToolbar = ({ title }: { title: string }) => {
+ const { showSettings, showAllFields, showGroupFields, onSettingsClick, onFieldsClick, onGroupClick, hidePopup } =
+ useBoardToolbar();
+
+ return (
+
+
{title}
+
+ {showSettings && (
+
+ )}
+ {showAllFields &&
}
+ {showGroupFields &&
}
+
+ );
+};