Compare commits
1 Commits
main
...
fix/react-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2ac3acfb6 |
@@ -4,7 +4,7 @@ import { Button } from "@headlessui/react";
|
|||||||
import { t } from "@lingui/core/macro";
|
import { t } from "@lingui/core/macro";
|
||||||
import { env } from "next-runtime-env";
|
import { env } from "next-runtime-env";
|
||||||
import { useTheme } from "next-themes";
|
import { useTheme } from "next-themes";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import { HiBolt } from "react-icons/hi2";
|
import { HiBolt } from "react-icons/hi2";
|
||||||
import {
|
import {
|
||||||
TbLayoutSidebarLeftCollapse,
|
TbLayoutSidebarLeftCollapse,
|
||||||
@@ -92,56 +92,59 @@ export default function SideNavigation({
|
|||||||
href: string;
|
href: string;
|
||||||
icon: object;
|
icon: object;
|
||||||
keyboardShortcut: KeyboardShortcut;
|
keyboardShortcut: KeyboardShortcut;
|
||||||
}[] = [
|
}[] = useMemo(
|
||||||
{
|
() => [
|
||||||
name: t`Boards`,
|
{
|
||||||
href: "/boards",
|
name: t`Boards`,
|
||||||
icon: isDarkMode ? boardsIconDark : boardsIconLight,
|
href: "/boards",
|
||||||
keyboardShortcut: {
|
icon: isDarkMode ? boardsIconDark : boardsIconLight,
|
||||||
type: "SEQUENCE",
|
keyboardShortcut: {
|
||||||
strokes: [{ key: "G" }, { key: "B" }],
|
type: "SEQUENCE",
|
||||||
action: () => router.push("/boards"),
|
strokes: [{ key: "G" }, { key: "B" }],
|
||||||
group: "NAVIGATION",
|
action: () => router.push("/boards"),
|
||||||
description: t`Go to boards`,
|
group: "NAVIGATION",
|
||||||
|
description: t`Go to boards`,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
name: t`Templates`,
|
||||||
name: t`Templates`,
|
href: "/templates",
|
||||||
href: "/templates",
|
icon: isDarkMode ? templatesIconDark : templatesIconLight,
|
||||||
icon: isDarkMode ? templatesIconDark : templatesIconLight,
|
keyboardShortcut: {
|
||||||
keyboardShortcut: {
|
type: "SEQUENCE",
|
||||||
type: "SEQUENCE",
|
strokes: [{ key: "G" }, { key: "T" }],
|
||||||
strokes: [{ key: "G" }, { key: "T" }],
|
action: () => router.push("/templates"),
|
||||||
action: () => router.push("/templates"),
|
group: "NAVIGATION",
|
||||||
group: "NAVIGATION",
|
description: t`Go to templates`,
|
||||||
description: t`Go to templates`,
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
name: t`Members`,
|
||||||
name: t`Members`,
|
href: "/members",
|
||||||
href: "/members",
|
icon: isDarkMode ? membersIconDark : membersIconLight,
|
||||||
icon: isDarkMode ? membersIconDark : membersIconLight,
|
keyboardShortcut: {
|
||||||
keyboardShortcut: {
|
type: "SEQUENCE",
|
||||||
type: "SEQUENCE",
|
strokes: [{ key: "G" }, { key: "M" }],
|
||||||
strokes: [{ key: "G" }, { key: "M" }],
|
action: () => router.push("/members"),
|
||||||
action: () => router.push("/members"),
|
group: "NAVIGATION",
|
||||||
group: "NAVIGATION",
|
description: t`Go to members`,
|
||||||
description: t`Go to members`,
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
name: t`Settings`,
|
||||||
name: t`Settings`,
|
href: "/settings",
|
||||||
href: "/settings",
|
icon: isDarkMode ? settingsIconDark : settingsIconLight,
|
||||||
icon: isDarkMode ? settingsIconDark : settingsIconLight,
|
keyboardShortcut: {
|
||||||
keyboardShortcut: {
|
type: "SEQUENCE",
|
||||||
type: "SEQUENCE",
|
strokes: [{ key: "G" }, { key: "S" }],
|
||||||
strokes: [{ key: "G" }, { key: "S" }],
|
action: () => router.push("/settings"),
|
||||||
action: () => router.push("/settings"),
|
group: "NAVIGATION",
|
||||||
group: "NAVIGATION",
|
description: t`Go to settings`,
|
||||||
description: t`Go to settings`,
|
},
|
||||||
},
|
},
|
||||||
},
|
],
|
||||||
];
|
[isDarkMode],
|
||||||
|
);
|
||||||
|
|
||||||
const toggleCollapse = () => {
|
const toggleCollapse = () => {
|
||||||
setIsCollapsed(!isCollapsed);
|
setIsCollapsed(!isCollapsed);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { ReactNode } from "react";
|
import type { ReactNode } from "react";
|
||||||
import type { Root } from "react-dom/client";
|
import type { Root } from "react-dom/client";
|
||||||
import type { Placement } from "tippy.js";
|
import type { Placement, Instance as TippyInstance } from "tippy.js";
|
||||||
import { useEffect, useRef } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
import { createRoot } from "react-dom/client";
|
import { createRoot } from "react-dom/client";
|
||||||
import tippy from "tippy.js";
|
import tippy from "tippy.js";
|
||||||
@@ -20,16 +20,16 @@ export function Tooltip({
|
|||||||
}: TooltipProps) {
|
}: TooltipProps) {
|
||||||
const triggerRef = useRef<HTMLDivElement>(null);
|
const triggerRef = useRef<HTMLDivElement>(null);
|
||||||
const rootRef = useRef<Root | null>(null);
|
const rootRef = useRef<Root | null>(null);
|
||||||
|
const tippyRef = useRef<TippyInstance | null>(null);
|
||||||
|
const contentRef = useRef(content);
|
||||||
|
contentRef.current = content;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!triggerRef.current) return;
|
if (!triggerRef.current) return;
|
||||||
|
|
||||||
if (!content) return;
|
|
||||||
|
|
||||||
const container = document.createElement("div");
|
const container = document.createElement("div");
|
||||||
const root = createRoot(container);
|
const root = createRoot(container);
|
||||||
rootRef.current = root;
|
rootRef.current = root;
|
||||||
root.render(content);
|
|
||||||
|
|
||||||
const instance = tippy(triggerRef.current, {
|
const instance = tippy(triggerRef.current, {
|
||||||
content: container,
|
content: container,
|
||||||
@@ -39,12 +39,33 @@ export function Tooltip({
|
|||||||
theme: "tooltip",
|
theme: "tooltip",
|
||||||
touch: false,
|
touch: false,
|
||||||
});
|
});
|
||||||
|
tippyRef.current = instance;
|
||||||
|
|
||||||
|
if (contentRef.current) {
|
||||||
|
root.render(contentRef.current);
|
||||||
|
} else {
|
||||||
|
instance.disable();
|
||||||
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
instance.destroy();
|
instance.destroy();
|
||||||
rootRef.current?.unmount();
|
tippyRef.current = null;
|
||||||
|
root.unmount();
|
||||||
|
rootRef.current = null;
|
||||||
};
|
};
|
||||||
}, [content, placement, delay]);
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [placement, delay]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!content) {
|
||||||
|
tippyRef.current?.disable();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (tippyRef.current) {
|
||||||
|
tippyRef.current.enable();
|
||||||
|
rootRef.current?.render(content);
|
||||||
|
}
|
||||||
|
}, [content]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={triggerRef} className="inline-flex">
|
<div ref={triggerRef} className="inline-flex">
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { useRouter } from "next/navigation";
|
|||||||
import { Button, Menu, Transition } from "@headlessui/react";
|
import { Button, Menu, Transition } from "@headlessui/react";
|
||||||
import { t } from "@lingui/core/macro";
|
import { t } from "@lingui/core/macro";
|
||||||
import { env } from "next-runtime-env";
|
import { env } from "next-runtime-env";
|
||||||
import { Fragment, useState } from "react";
|
import { Fragment, useMemo, useState } from "react";
|
||||||
import { HiCheck, HiMagnifyingGlass } from "react-icons/hi2";
|
import { HiCheck, HiMagnifyingGlass } from "react-icons/hi2";
|
||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
@@ -26,17 +26,22 @@ export default function WorkspaceMenu({
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
const { tooltipContent: commandPaletteShortcutTooltipContent } =
|
const commandPaletteShortcut = useMemo(
|
||||||
useKeyboardShortcut({
|
() => ({
|
||||||
type: "PRESS",
|
type: "PRESS" as const,
|
||||||
stroke: {
|
stroke: {
|
||||||
key: "k",
|
key: "k",
|
||||||
modifiers: ["META"],
|
modifiers: ["META"] as ("META" | "CONTROL" | "ALT" | "SHIFT")[],
|
||||||
},
|
},
|
||||||
action: () => setIsOpen(true),
|
action: () => setIsOpen(true),
|
||||||
description: t`Open command menu`,
|
description: t`Open command menu`,
|
||||||
group: "GENERAL",
|
group: "GENERAL" as const,
|
||||||
});
|
}),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
const { tooltipContent: commandPaletteShortcutTooltipContent } =
|
||||||
|
useKeyboardShortcut(commandPaletteShortcut);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useEffect } from "react";
|
import { useCallback, useEffect, useRef } from "react";
|
||||||
|
|
||||||
import { useModal } from "~/providers/modal";
|
import { useModal } from "~/providers/modal";
|
||||||
|
|
||||||
interface UseModalFormStateOptions<T> {
|
interface UseModalFormStateOptions<T> {
|
||||||
@@ -12,25 +13,43 @@ export function useModalFormState<T extends Record<string, any>>({
|
|||||||
initialValues,
|
initialValues,
|
||||||
resetOnClose = false,
|
resetOnClose = false,
|
||||||
}: UseModalFormStateOptions<T>) {
|
}: UseModalFormStateOptions<T>) {
|
||||||
const { modalContentType, isOpen, getModalState, setModalState, clearModalState } = useModal();
|
const {
|
||||||
|
modalContentType,
|
||||||
|
isOpen,
|
||||||
|
getModalState,
|
||||||
|
setModalState,
|
||||||
|
clearModalState,
|
||||||
|
} = useModal();
|
||||||
|
|
||||||
const isCurrentModal = modalContentType === modalType;
|
const isCurrentModal = modalContentType === modalType;
|
||||||
const savedState = getModalState(modalType) as T | undefined;
|
const savedState = getModalState(modalType) as T | undefined;
|
||||||
|
|
||||||
// get current form state (using the saved values if available, otherwise the initial values)
|
// get current form state (using the saved values if available, otherwise the initial values)
|
||||||
const formState = savedState || initialValues;
|
const formState = savedState || initialValues;
|
||||||
|
|
||||||
const saveFormState = (state: Partial<T>) => {
|
// Keep refs so the callbacks below stay stable across re-renders.
|
||||||
if (!isCurrentModal) return;
|
const modalTypeRef = useRef(modalType);
|
||||||
|
const initialValuesRef = useRef(initialValues);
|
||||||
const currentState = getModalState(modalType) || initialValues;
|
const getModalStateRef = useRef(getModalState);
|
||||||
const newState = { ...currentState, ...state };
|
modalTypeRef.current = modalType;
|
||||||
setModalState(modalType, newState);
|
initialValuesRef.current = initialValues;
|
||||||
};
|
getModalStateRef.current = getModalState;
|
||||||
|
|
||||||
const clearFormState = () => {
|
const saveFormState = useCallback(
|
||||||
clearModalState(modalType);
|
(state: Partial<T>) => {
|
||||||
};
|
const type = modalTypeRef.current;
|
||||||
|
const currentState =
|
||||||
|
getModalStateRef.current(type) ?? initialValuesRef.current;
|
||||||
|
const newState = { ...currentState, ...state };
|
||||||
|
setModalState(type, newState);
|
||||||
|
},
|
||||||
|
// setModalState is stable (useCallback with [] deps in ModalProvider)
|
||||||
|
[setModalState],
|
||||||
|
);
|
||||||
|
|
||||||
|
const clearFormState = useCallback(() => {
|
||||||
|
clearModalState(modalTypeRef.current);
|
||||||
|
}, [clearModalState]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (resetOnClose && !isOpen && savedState) {
|
if (resetOnClose && !isOpen && savedState) {
|
||||||
@@ -45,4 +64,4 @@ export function useModalFormState<T extends Record<string, any>>({
|
|||||||
isCurrentModal,
|
isCurrentModal,
|
||||||
hasSavedState: !!savedState,
|
hasSavedState: !!savedState,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { createContext, useContext, useState } from "react";
|
import { createContext, useCallback, useContext, useState } from "react";
|
||||||
|
|
||||||
interface PopupContextType {
|
interface PopupContextType {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@@ -25,24 +25,27 @@ export const PopupProvider: React.FC<Props> = ({ children }) => {
|
|||||||
const [popupMessage, setPopupMessage] = useState("");
|
const [popupMessage, setPopupMessage] = useState("");
|
||||||
const [popupIcon, setPopupIcon] = useState("");
|
const [popupIcon, setPopupIcon] = useState("");
|
||||||
|
|
||||||
const showPopup = ({
|
const showPopup = useCallback(
|
||||||
header,
|
({
|
||||||
message,
|
header,
|
||||||
icon,
|
message,
|
||||||
}: {
|
icon,
|
||||||
header: string;
|
}: {
|
||||||
message: string;
|
header: string;
|
||||||
icon: string;
|
message: string;
|
||||||
}) => {
|
icon: string;
|
||||||
setIsOpen(true);
|
}) => {
|
||||||
setPopupHeader(header);
|
setIsOpen(true);
|
||||||
setPopupMessage(message);
|
setPopupHeader(header);
|
||||||
setPopupIcon(icon);
|
setPopupMessage(message);
|
||||||
};
|
setPopupIcon(icon);
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
const hidePopup = () => {
|
const hidePopup = useCallback(() => {
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
};
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PopupContext.Provider
|
<PopupContext.Provider
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { useRouter } from "next/router";
|
|||||||
import { t } from "@lingui/core/macro";
|
import { t } from "@lingui/core/macro";
|
||||||
import { keepPreviousData } from "@tanstack/react-query";
|
import { keepPreviousData } from "@tanstack/react-query";
|
||||||
import { env } from "next-runtime-env";
|
import { env } from "next-runtime-env";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import { DragDropContext, Draggable } from "react-beautiful-dnd";
|
import { DragDropContext, Draggable } from "react-beautiful-dnd";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import {
|
import {
|
||||||
@@ -46,10 +46,10 @@ import { CardContextMembersModal } from "./components/CardContextMembersModal";
|
|||||||
import { CardContextMenu } from "./components/CardContextMenu";
|
import { CardContextMenu } from "./components/CardContextMenu";
|
||||||
import { CardContextMoveListModal } from "./components/CardContextMoveListModal";
|
import { CardContextMoveListModal } from "./components/CardContextMoveListModal";
|
||||||
import { DeleteBoardConfirmation } from "./components/DeleteBoardConfirmation";
|
import { DeleteBoardConfirmation } from "./components/DeleteBoardConfirmation";
|
||||||
import { MoveBoardForm } from "./components/MoveBoardForm";
|
|
||||||
import { DeleteListConfirmation } from "./components/DeleteListConfirmation";
|
import { DeleteListConfirmation } from "./components/DeleteListConfirmation";
|
||||||
import Filters from "./components/Filters";
|
import Filters from "./components/Filters";
|
||||||
import List from "./components/List";
|
import List from "./components/List";
|
||||||
|
import { MoveBoardForm } from "./components/MoveBoardForm";
|
||||||
import { NewCardForm } from "./components/NewCardForm";
|
import { NewCardForm } from "./components/NewCardForm";
|
||||||
import { NewListForm } from "./components/NewListForm";
|
import { NewListForm } from "./components/NewListForm";
|
||||||
import { NewTemplateForm } from "./components/NewTemplateForm";
|
import { NewTemplateForm } from "./components/NewTemplateForm";
|
||||||
@@ -85,21 +85,26 @@ export default function BoardPage({ isTemplate }: { isTemplate?: boolean }) {
|
|||||||
const { canCreateList, canEditList, canEditCard, canEditBoard } =
|
const { canCreateList, canEditList, canEditCard, canEditBoard } =
|
||||||
usePermissions();
|
usePermissions();
|
||||||
|
|
||||||
const { tooltipContent: createListShortcutTooltipContent } =
|
|
||||||
useKeyboardShortcut({
|
|
||||||
type: "PRESS",
|
|
||||||
stroke: { key: "C" },
|
|
||||||
action: () => boardId && canCreateList && openNewListForm(boardId),
|
|
||||||
description: t`Create new list`,
|
|
||||||
group: "ACTIONS",
|
|
||||||
});
|
|
||||||
|
|
||||||
const boardId = params?.boardId
|
const boardId = params?.boardId
|
||||||
? Array.isArray(params.boardId)
|
? Array.isArray(params.boardId)
|
||||||
? params.boardId[0]
|
? params.boardId[0]
|
||||||
: params.boardId
|
: params.boardId
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
|
const createListShortcut = useMemo(
|
||||||
|
() => ({
|
||||||
|
type: "PRESS" as const,
|
||||||
|
stroke: { key: "C" },
|
||||||
|
action: () => boardId && canCreateList && openNewListForm(boardId),
|
||||||
|
description: t`Create new list`,
|
||||||
|
group: "ACTIONS" as const,
|
||||||
|
}),
|
||||||
|
[boardId, canCreateList],
|
||||||
|
);
|
||||||
|
|
||||||
|
const { tooltipContent: createListShortcutTooltipContent } =
|
||||||
|
useKeyboardShortcut(createListShortcut);
|
||||||
|
|
||||||
const updateBoard = api.board.update.useMutation();
|
const updateBoard = api.board.update.useMutation();
|
||||||
|
|
||||||
const { register, handleSubmit, setValue } = useForm<UpdateBoardInput>({
|
const { register, handleSubmit, setValue } = useForm<UpdateBoardInput>({
|
||||||
|
|||||||
@@ -5,8 +5,12 @@ import {
|
|||||||
ListboxOptions,
|
ListboxOptions,
|
||||||
} from "@headlessui/react";
|
} from "@headlessui/react";
|
||||||
import { t } from "@lingui/core/macro";
|
import { t } from "@lingui/core/macro";
|
||||||
import { HiArrowDownTray, HiChevronDown, HiOutlinePlusSmall } from "react-icons/hi2";
|
import { useMemo, useState } from "react";
|
||||||
import { useState } from "react";
|
import {
|
||||||
|
HiArrowDownTray,
|
||||||
|
HiChevronDown,
|
||||||
|
HiOutlinePlusSmall,
|
||||||
|
} from "react-icons/hi2";
|
||||||
|
|
||||||
import Button from "~/components/Button";
|
import Button from "~/components/Button";
|
||||||
import FeedbackModal from "~/components/FeedbackModal";
|
import FeedbackModal from "~/components/FeedbackModal";
|
||||||
@@ -33,14 +37,19 @@ export default function BoardsPage({ isTemplate }: { isTemplate?: boolean }) {
|
|||||||
const [activeTab, setActiveTab] = useState<"boards" | "archived">("boards");
|
const [activeTab, setActiveTab] = useState<"boards" | "archived">("boards");
|
||||||
const { canCreateBoard } = usePermissions();
|
const { canCreateBoard } = usePermissions();
|
||||||
|
|
||||||
const { tooltipContent: createModalShortcutTooltipContent } =
|
const createBoardShortcut = useMemo(
|
||||||
useKeyboardShortcut({
|
() => ({
|
||||||
type: "PRESS",
|
type: "PRESS" as const,
|
||||||
stroke: { key: "C" },
|
stroke: { key: "C" },
|
||||||
action: () => canCreateBoard && openModal("NEW_BOARD"),
|
action: () => canCreateBoard && openModal("NEW_BOARD"),
|
||||||
description: t`Create new ${isTemplate ? "template" : "board"}`,
|
description: t`Create new ${isTemplate ? "template" : "board"}`,
|
||||||
group: "ACTIONS",
|
group: "ACTIONS" as const,
|
||||||
});
|
}),
|
||||||
|
[canCreateBoard, isTemplate, openModal],
|
||||||
|
);
|
||||||
|
|
||||||
|
const { tooltipContent: createModalShortcutTooltipContent } =
|
||||||
|
useKeyboardShortcut(createBoardShortcut);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -137,7 +146,7 @@ export default function BoardsPage({ isTemplate }: { isTemplate?: boolean }) {
|
|||||||
onChange={(tab) => setActiveTab(tab)}
|
onChange={(tab) => setActiveTab(tab)}
|
||||||
>
|
>
|
||||||
<div className="relative mb-4">
|
<div className="relative mb-4">
|
||||||
<ListboxButton className="w-full appearance-none rounded-md border-0 bg-light-50 py-3 pl-3 pr-10 text-left text-sm font-semibold text-light-1000 shadow-sm ring-1 ring-inset ring-light-300 dark:bg-dark-50 dark:text-dark-1000 dark:ring-dark-300 dark:focus:ring-dark-500">
|
<ListboxButton className="w-full appearance-none rounded-md border-0 bg-light-50 py-3 pl-3 pr-10 text-left text-sm font-semibold text-light-1000 shadow-sm ring-1 ring-inset ring-light-300 dark:bg-dark-50 dark:text-dark-1000 dark:ring-dark-300 dark:focus:ring-dark-500">
|
||||||
{boardsTabs.find((tab) => tab.key === activeTab)?.label ??
|
{boardsTabs.find((tab) => tab.key === activeTab)?.label ??
|
||||||
"Select a tab"}
|
"Select a tab"}
|
||||||
<HiChevronDown
|
<HiChevronDown
|
||||||
@@ -151,9 +160,10 @@ export default function BoardsPage({ isTemplate }: { isTemplate?: boolean }) {
|
|||||||
key={tab.key}
|
key={tab.key}
|
||||||
value={tab.key}
|
value={tab.key}
|
||||||
className={({ selected }) =>
|
className={({ selected }) =>
|
||||||
`relative cursor-pointer select-none py-2 pl-3 pr-9 ${selected
|
`relative cursor-pointer select-none py-2 pl-3 pr-9 ${
|
||||||
? "font-bold text-light-1000 dark:text-dark-1000"
|
selected
|
||||||
: "font-normal text-light-1000 dark:text-dark-1000"
|
? "font-bold text-light-1000 dark:text-dark-1000"
|
||||||
|
: "font-normal text-light-1000 dark:text-dark-1000"
|
||||||
}`
|
}`
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
@@ -175,10 +185,11 @@ export default function BoardsPage({ isTemplate }: { isTemplate?: boolean }) {
|
|||||||
key={tab.key}
|
key={tab.key}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setActiveTab(tab.key)}
|
onClick={() => setActiveTab(tab.key)}
|
||||||
className={`whitespace-nowrap px-1 py-0 mt-2 mb-8 text-sm font-semibold transition-colors focus:outline-none ${activeTab === tab.key
|
className={`mb-8 mt-2 whitespace-nowrap px-1 py-0 text-sm font-semibold transition-colors focus:outline-none ${
|
||||||
? "border-light-1000 text-light-1000 dark:border-dark-1000 dark:text-dark-1000"
|
activeTab === tab.key
|
||||||
: "border-transparent text-light-900 hover:border-light-950 hover:text-light-950 dark:text-dark-900 dark:hover:border-white/20 dark:hover:text-dark-950"
|
? "border-light-1000 text-light-1000 dark:border-dark-1000 dark:text-dark-1000"
|
||||||
}`}
|
: "border-transparent text-light-900 hover:border-light-950 hover:text-light-950 dark:text-dark-900 dark:hover:border-white/20 dark:hover:text-dark-950"
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
{tab.label}
|
{tab.label}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user