Bläddra i källkod

feat: support menu / dropdown items to have `selected` state (#7078)

David Luzar 1 år sedan
förälder
incheckning
12420592ef

+ 2 - 0
dev-docs/docs/@excalidraw/excalidraw/api/children-components/main-menu.mdx

@@ -38,6 +38,7 @@ To render an item, its recommended to use `MainMenu.Item`.
 | Prop | Type | Required | Default | Description |
 | --- | --- | :-: | :-: | --- |
 | `onSelect` | `function` | Yes | - | Triggered when selected (via mouse). Calling `event.preventDefault()` will stop menu from closing. |
+| `selected` | `boolean` | No | `false` | Whether item is active |
 | `children` | `React.ReactNode` | Yes | - | The content of the menu item |
 | `icon` | `JSX.Element` | No | - | The icon used in the menu item |
 | `shortcut` | `string` | No | - | The shortcut to be shown for the menu item |
@@ -70,6 +71,7 @@ function App() {
 | Prop | Type | Required | Default | Description |
 | --- | --- | :-: | :-: | --- |
 | `onSelect` | `function` | No | - | Triggered when selected (via mouse). Calling `event.preventDefault()` will stop menu from closing. |
+| `selected` | `boolean` | No | `false` | Whether item is active |
 | `href` | `string` | Yes | - | The `href` attribute to be added to the `anchor` element. |
 | `children` | `React.ReactNode` | Yes | - | The content of the menu item |
 | `icon` | `JSX.Element` | No | - | The icon used in the menu item |

+ 4 - 0
src/components/Actions.tsx

@@ -318,6 +318,7 @@ export const ShapesSwitcher = ({
                 activeEmbeddable: null,
               });
             }}
+            selected={activeTool.type === "frame"}
           />
           <ToolButton
             className={clsx("Shape", { fillable: false })}
@@ -348,6 +349,7 @@ export const ShapesSwitcher = ({
                 activeEmbeddable: null,
               });
             }}
+            selected={activeTool.type === "embeddable"}
           />
         </>
       ) : (
@@ -378,6 +380,7 @@ export const ShapesSwitcher = ({
               icon={frameToolIcon}
               shortcut={KEYS.F.toLocaleUpperCase()}
               data-testid="toolbar-frame"
+              selected={activeTool.type === "frame"}
             >
               {t("toolBar.frame")}
             </DropdownMenu.Item>
@@ -394,6 +397,7 @@ export const ShapesSwitcher = ({
               }}
               icon={EmbedIcon}
               data-testid="toolbar-embeddable"
+              selected={activeTool.type === "embeddable"}
             >
               {t("toolBar.embeddable")}
             </DropdownMenu.Item>

+ 5 - 0
src/components/dropdownMenu/DropdownMenu.scss

@@ -59,6 +59,11 @@
         height: 2.25rem;
       }
 
+      &--selected {
+        background: var(--color-primary-light);
+        --icon-fill-color: var(--color-primary-darker);
+      }
+
       &__text {
         text-overflow: ellipsis;
         overflow: hidden;

+ 3 - 1
src/components/dropdownMenu/DropdownMenuItem.tsx

@@ -11,12 +11,14 @@ const DropdownMenuItem = ({
   children,
   shortcut,
   className,
+  selected,
   ...rest
 }: {
   icon?: JSX.Element;
   onSelect: (event: Event) => void;
   children: React.ReactNode;
   shortcut?: string;
+  selected?: boolean;
   className?: string;
 } & Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "onSelect">) => {
   const handleClick = useHandleDropdownMenuItemClick(rest.onClick, onSelect);
@@ -26,7 +28,7 @@ const DropdownMenuItem = ({
       {...rest}
       onClick={handleClick}
       type="button"
-      className={getDropdownMenuItemClassName(className)}
+      className={getDropdownMenuItemClassName(className, selected)}
       title={rest.title ?? rest["aria-label"]}
     >
       <MenuItemContent icon={icon} shortcut={shortcut}>

+ 5 - 1
src/components/dropdownMenu/DropdownMenuItemCustom.tsx

@@ -3,15 +3,19 @@ import React from "react";
 const DropdownMenuItemCustom = ({
   children,
   className = "",
+  selected,
   ...rest
 }: {
   children: React.ReactNode;
   className?: string;
+  selected?: boolean;
 } & React.HTMLAttributes<HTMLDivElement>) => {
   return (
     <div
       {...rest}
-      className={`dropdown-menu-item-base dropdown-menu-item-custom ${className}`.trim()}
+      className={`dropdown-menu-item-base dropdown-menu-item-custom ${className} ${
+        selected ? `dropdown-menu-item--selected` : ``
+      }`.trim()}
     >
       {children}
     </div>

+ 3 - 1
src/components/dropdownMenu/DropdownMenuItemLink.tsx

@@ -12,6 +12,7 @@ const DropdownMenuItemLink = ({
   children,
   onSelect,
   className = "",
+  selected,
   ...rest
 }: {
   href: string;
@@ -19,6 +20,7 @@ const DropdownMenuItemLink = ({
   children: React.ReactNode;
   shortcut?: string;
   className?: string;
+  selected?: boolean;
   onSelect?: (event: Event) => void;
 } & React.AnchorHTMLAttributes<HTMLAnchorElement>) => {
   const handleClick = useHandleDropdownMenuItemClick(rest.onClick, onSelect);
@@ -29,7 +31,7 @@ const DropdownMenuItemLink = ({
       href={href}
       target="_blank"
       rel="noreferrer"
-      className={getDropdownMenuItemClassName(className)}
+      className={getDropdownMenuItemClassName(className, selected)}
       title={rest.title ?? rest["aria-label"]}
       onClick={handleClick}
     >

+ 7 - 2
src/components/dropdownMenu/common.ts

@@ -6,8 +6,13 @@ export const DropdownMenuContentPropsContext = React.createContext<{
   onSelect?: (event: Event) => void;
 }>({});
 
-export const getDropdownMenuItemClassName = (className = "") => {
-  return `dropdown-menu-item dropdown-menu-item-base ${className}`.trim();
+export const getDropdownMenuItemClassName = (
+  className = "",
+  selected = false,
+) => {
+  return `dropdown-menu-item dropdown-menu-item-base ${className} ${
+    selected ? "dropdown-menu-item--selected" : ""
+  }`.trim();
 };
 
 export const useHandleDropdownMenuItemClick = (

+ 6 - 0
src/packages/excalidraw/CHANGELOG.md

@@ -11,6 +11,12 @@ The change should be grouped under one of the below section and must contain PR
 Please add the latest change on the top under the correct section.
 -->
 
+## Unreleased
+
+### Features
+
+- Add `selected` prop for `MainMenu.Item` and `MainMenu.ItemCustom` components to indicate active state. [7078](https://github.com/excalidraw/excalidraw/pull/7078)
+
 ## 0.16.1 (2023-09-21)
 
 ## Excalidraw Library