Explorar o código

feat: redesign toolbar & tweaks (#4387)

David Luzar %!s(int64=3) %!d(string=hai) anos
pai
achega
7db63bd397

+ 11 - 4
src/components/Card.tsx

@@ -3,15 +3,22 @@ import OpenColor from "open-color";
 import "./Card.scss";
 import "./Card.scss";
 
 
 export const Card: React.FC<{
 export const Card: React.FC<{
-  color: keyof OpenColor;
+  color: keyof OpenColor | "primary";
 }> = ({ children, color }) => {
 }> = ({ children, color }) => {
   return (
   return (
     <div
     <div
       className="Card"
       className="Card"
       style={{
       style={{
-        ["--card-color" as any]: OpenColor[color][7],
-        ["--card-color-darker" as any]: OpenColor[color][8],
-        ["--card-color-darkest" as any]: OpenColor[color][9],
+        ["--card-color" as any]:
+          color === "primary" ? "var(--color-primary)" : OpenColor[color][7],
+        ["--card-color-darker" as any]:
+          color === "primary"
+            ? "var(--color-primary-darker)"
+            : OpenColor[color][8],
+        ["--card-color-darkest" as any]:
+          color === "primary"
+            ? "var(--color-primary-darkest)"
+            : OpenColor[color][9],
       }}
       }}
     >
     >
       {children}
       {children}

+ 1 - 1
src/components/IconPicker.scss

@@ -22,7 +22,7 @@
     align-items: center;
     align-items: center;
     justify-content: center;
     justify-content: center;
 
 
-    &:focus {
+    &:focus-visible {
       outline: transparent;
       outline: transparent;
       background-color: var(--button-gray-2);
       background-color: var(--button-gray-2);
       & svg {
       & svg {

+ 1 - 1
src/components/Island.scss

@@ -3,7 +3,7 @@
     --padding: 0;
     --padding: 0;
     background-color: var(--island-bg-color);
     background-color: var(--island-bg-color);
     box-shadow: var(--shadow-island);
     box-shadow: var(--shadow-island);
-    border-radius: 4px;
+    border-radius: var(--border-radius-lg);
     padding: calc(var(--padding) * var(--space-factor));
     padding: calc(var(--padding) * var(--space-factor));
     position: relative;
     position: relative;
     transition: box-shadow 0.5s ease-in-out;
     transition: box-shadow 0.5s ease-in-out;

+ 12 - 3
src/components/LayerUI.tsx

@@ -19,7 +19,6 @@ import { ExportCB, ImageExportDialog } from "./ImageExportDialog";
 import { FixedSideContainer } from "./FixedSideContainer";
 import { FixedSideContainer } from "./FixedSideContainer";
 import { HintViewer } from "./HintViewer";
 import { HintViewer } from "./HintViewer";
 import { Island } from "./Island";
 import { Island } from "./Island";
-import "./LayerUI.scss";
 import { LoadingMessage } from "./LoadingMessage";
 import { LoadingMessage } from "./LoadingMessage";
 import { LockButton } from "./LockButton";
 import { LockButton } from "./LockButton";
 import { MobileMenu } from "./MobileMenu";
 import { MobileMenu } from "./MobileMenu";
@@ -35,6 +34,9 @@ import { LibraryButton } from "./LibraryButton";
 import { isImageFileHandle } from "../data/blob";
 import { isImageFileHandle } from "../data/blob";
 import { LibraryMenu } from "./LibraryMenu";
 import { LibraryMenu } from "./LibraryMenu";
 
 
+import "./LayerUI.scss";
+import "./Toolbar.scss";
+
 interface LayerUIProps {
 interface LayerUIProps {
   actionManager: ActionManager;
   actionManager: ActionManager;
   appState: AppState;
   appState: AppState;
@@ -305,7 +307,12 @@ const LayerUI = ({
             <Section heading="shapes">
             <Section heading="shapes">
               {(heading) => (
               {(heading) => (
                 <Stack.Col gap={4} align="start">
                 <Stack.Col gap={4} align="start">
-                  <Stack.Row gap={1}>
+                  <Stack.Row
+                    gap={1}
+                    className={clsx("App-toolbar-container", {
+                      "zen-mode": zenModeEnabled,
+                    })}
+                  >
                     <LockButton
                     <LockButton
                       zenModeEnabled={zenModeEnabled}
                       zenModeEnabled={zenModeEnabled}
                       checked={appState.elementLocked}
                       checked={appState.elementLocked}
@@ -314,7 +321,9 @@ const LayerUI = ({
                     />
                     />
                     <Island
                     <Island
                       padding={1}
                       padding={1}
-                      className={clsx({ "zen-mode": zenModeEnabled })}
+                      className={clsx("App-toolbar", {
+                        "zen-mode": zenModeEnabled,
+                      })}
                     >
                     >
                       <HintViewer
                       <HintViewer
                         appState={appState}
                         appState={appState}

+ 4 - 4
src/components/LibraryButton.tsx

@@ -16,18 +16,18 @@ const LIBRARY_ICON = (
 export const LibraryButton: React.FC<{
 export const LibraryButton: React.FC<{
   appState: AppState;
   appState: AppState;
   setAppState: React.Component<any, AppState>["setState"];
   setAppState: React.Component<any, AppState>["setState"];
-}> = ({ appState, setAppState }) => {
+  isMobile?: boolean;
+}> = ({ appState, setAppState, isMobile }) => {
   return (
   return (
     <label
     <label
       className={clsx(
       className={clsx(
-        "ToolIcon ToolIcon_type_floating ToolIcon__library zen-mode-visibility",
+        "ToolIcon ToolIcon_type_floating ToolIcon__library",
         `ToolIcon_size_medium`,
         `ToolIcon_size_medium`,
         {
         {
-          "zen-mode-visibility--hidden": appState.zenModeEnabled,
+          "is-mobile": isMobile,
         },
         },
       )}
       )}
       title={`${capitalizeString(t("toolBar.library"))} — 0`}
       title={`${capitalizeString(t("toolBar.library"))} — 0`}
-      style={{ marginInlineStart: "var(--space-factor)" }}
     >
     >
       <input
       <input
         className="ToolIcon_type_checkbox"
         className="ToolIcon_type_checkbox"

+ 3 - 2
src/components/LockButton.tsx

@@ -10,6 +10,7 @@ type LockIconProps = {
   checked: boolean;
   checked: boolean;
   onChange?(): void;
   onChange?(): void;
   zenModeEnabled?: boolean;
   zenModeEnabled?: boolean;
+  isMobile?: boolean;
 };
 };
 
 
 const DEFAULT_SIZE: ToolButtonSize = "medium";
 const DEFAULT_SIZE: ToolButtonSize = "medium";
@@ -42,10 +43,10 @@ export const LockButton = (props: LockIconProps) => {
   return (
   return (
     <label
     <label
       className={clsx(
       className={clsx(
-        "ToolIcon ToolIcon__lock ToolIcon_type_floating zen-mode-visibility",
+        "ToolIcon ToolIcon__lock ToolIcon_type_floating",
         `ToolIcon_size_${DEFAULT_SIZE}`,
         `ToolIcon_size_${DEFAULT_SIZE}`,
         {
         {
-          "zen-mode-visibility--hidden": props.zenModeEnabled,
+          "is-mobile": props.isMobile,
         },
         },
       )}
       )}
       title={`${props.title} — Q`}
       title={`${props.title} — Q`}

+ 8 - 3
src/components/MobileMenu.tsx

@@ -64,8 +64,8 @@ export const MobileMenu = ({
         <Section heading="shapes">
         <Section heading="shapes">
           {(heading) => (
           {(heading) => (
             <Stack.Col gap={4} align="center">
             <Stack.Col gap={4} align="center">
-              <Stack.Row gap={1}>
-                <Island padding={1}>
+              <Stack.Row gap={1} className="App-toolbar-container">
+                <Island padding={1} className="App-toolbar">
                   {heading}
                   {heading}
                   <Stack.Row gap={1}>
                   <Stack.Row gap={1}>
                     <ShapesSwitcher
                     <ShapesSwitcher
@@ -85,8 +85,13 @@ export const MobileMenu = ({
                   checked={appState.elementLocked}
                   checked={appState.elementLocked}
                   onChange={onLockToggle}
                   onChange={onLockToggle}
                   title={t("toolBar.lock")}
                   title={t("toolBar.lock")}
+                  isMobile
+                />
+                <LibraryButton
+                  appState={appState}
+                  setAppState={setAppState}
+                  isMobile
                 />
                 />
-                <LibraryButton appState={appState} setAppState={setAppState} />
               </Stack.Row>
               </Stack.Row>
               {libraryMenu}
               {libraryMenu}
             </Stack.Col>
             </Stack.Col>

+ 21 - 28
src/components/ToolIcon.scss

@@ -8,17 +8,7 @@
     position: relative;
     position: relative;
     cursor: pointer;
     cursor: pointer;
     -webkit-tap-highlight-color: transparent;
     -webkit-tap-highlight-color: transparent;
-    border-radius: var(--space-factor);
     user-select: none;
     user-select: none;
-
-    background-color: var(--button-gray-1);
-
-    &:hover {
-      background-color: var(--button-gray-2);
-    }
-    &:active {
-      background-color: var(--button-gray-3);
-    }
   }
   }
 
 
   .ToolIcon--plain {
   .ToolIcon--plain {
@@ -29,6 +19,20 @@
     }
     }
   }
   }
 
 
+  .ToolIcon_type_radio,
+  .ToolIcon_type_checkbox {
+    & + .ToolIcon__icon {
+      background-color: var(--button-gray-1);
+
+      &:hover {
+        background-color: var(--button-gray-2);
+      }
+      &:active {
+        background-color: var(--button-gray-3);
+      }
+    }
+  }
+
   .ToolIcon__icon {
   .ToolIcon__icon {
     width: 2.5rem;
     width: 2.5rem;
     height: 2.5rem;
     height: 2.5rem;
@@ -38,7 +42,11 @@
     justify-content: center;
     justify-content: center;
     align-items: center;
     align-items: center;
 
 
-    border-radius: var(--space-factor);
+    border-radius: var(--border-radius-lg);
+
+    & + .ToolIcon__label {
+      margin-inline-start: 0;
+    }
 
 
     svg {
     svg {
       position: relative;
       position: relative;
@@ -46,10 +54,6 @@
       fill: var(--icon-fill-color);
       fill: var(--icon-fill-color);
       color: var(--icon-fill-color);
       color: var(--icon-fill-color);
     }
     }
-
-    & + .ToolIcon__label {
-      margin-inline-start: 0;
-    }
   }
   }
 
 
   .ToolIcon__label {
   .ToolIcon__label {
@@ -79,7 +83,7 @@
     margin: 0;
     margin: 0;
     font-size: inherit;
     font-size: inherit;
 
 
-    &:focus {
+    &:focus-visible {
       box-shadow: 0 0 0 2px var(--focus-highlight-color);
       box-shadow: 0 0 0 2px var(--focus-highlight-color);
     }
     }
 
 
@@ -121,7 +125,7 @@
       }
       }
     }
     }
 
 
-    &:focus + .ToolIcon__icon {
+    &:focus-visible + .ToolIcon__icon {
       box-shadow: 0 0 0 2px var(--focus-highlight-color);
       box-shadow: 0 0 0 2px var(--focus-highlight-color);
     }
     }
 
 
@@ -141,10 +145,6 @@
       background-color: transparent;
       background-color: transparent;
     }
     }
 
 
-    &:focus {
-      box-shadow: none;
-    }
-
     .ToolIcon__icon {
     .ToolIcon__icon {
       background-color: var(--button-gray-1);
       background-color: var(--button-gray-1);
       &:hover {
       &:hover {
@@ -159,13 +159,6 @@
     }
     }
   }
   }
 
 
-  .ToolIcon.ToolIcon__lock {
-    margin-inline-end: var(--space-factor);
-    &.ToolIcon_type_floating {
-      margin-left: 0.1rem;
-    }
-  }
-
   .ToolIcon__keybinding {
   .ToolIcon__keybinding {
     position: absolute;
     position: absolute;
     bottom: 2px;
     bottom: 2px;

+ 112 - 0
src/components/Toolbar.scss

@@ -0,0 +1,112 @@
+@import "open-color/open-color.scss";
+
+@mixin toolbarButtonColorStates {
+  .ToolIcon_type_radio,
+  .ToolIcon_type_checkbox {
+    & + .ToolIcon__icon:active {
+      background: var(--color-primary-light);
+    }
+    &:checked + .ToolIcon__icon {
+      background: var(--color-primary);
+      --icon-fill-color: #{$oc-white};
+      --keybinding-color: #{$oc-white};
+    }
+    &:checked + .ToolIcon__icon:active {
+      background: var(--color-primary-darker);
+    }
+  }
+
+  .ToolIcon__keybinding {
+    bottom: 4px;
+    right: 4px;
+  }
+}
+
+.excalidraw {
+  .App-toolbar-container {
+    .ToolIcon_type_floating {
+      @include toolbarButtonColorStates;
+
+      &:not(.is-mobile) {
+        .ToolIcon__icon {
+          padding: 1px;
+          background-color: var(--island-bg-color);
+          box-shadow: 1px 3px 4px 0px rgb(0 0 0 / 15%);
+          border-radius: 50%;
+          transition: box-shadow 0.5s ease, transform 0.5s ease;
+        }
+      }
+
+      .ToolIcon_type_radio,
+      .ToolIcon_type_checkbox {
+        &:focus-within + .ToolIcon__icon {
+          // override for custom floating button shadow
+          box-shadow: 0 0 0 2px var(--focus-highlight-color);
+        }
+      }
+    }
+
+    .ToolIcon.ToolIcon__lock {
+      margin-inline-end: var(--space-factor);
+      &.ToolIcon_type_floating {
+        margin-left: 0.1rem;
+      }
+    }
+
+    .ToolIcon__library {
+      margin-inline-start: var(--space-factor);
+    }
+
+    &.zen-mode {
+      .ToolIcon_type_floating {
+        .ToolIcon__icon {
+          box-shadow: none;
+          transform: scale(0.9);
+        }
+        .ToolIcon_type_checkbox:not(:checked):not(:hover):not(:active) {
+          & + .ToolIcon__icon {
+            svg {
+              fill: $oc-gray-5;
+              color: $oc-gray-5;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  .App-toolbar {
+    border-radius: var(--border-radius-lg);
+    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.01), 1px 1px 5px rgb(0 0 0 / 15%);
+
+    .ToolIcon {
+      &:hover {
+        --icon-fill-color: var(--color-primary-chubb);
+        --keybinding-color: var(--color-primary-chubb);
+      }
+      &:active {
+        --icon-fill-color: #{$oc-gray-9};
+        --keybinding-color: #{$oc-gray-9};
+      }
+
+      .ToolIcon__icon {
+        background: transparent;
+        border-radius: var(--border-radius-lg);
+      }
+
+      @include toolbarButtonColorStates;
+    }
+
+    &.zen-mode {
+      .ToolIcon__keybinding,
+      .HintViewer {
+        display: none;
+      }
+    }
+  }
+
+  &.theme--dark .App-toolbar .ToolIcon:active {
+    --icon-fill-color: #{$oc-gray-3};
+    --keybinding-color: #{$oc-gray-3};
+  }
+}

+ 3 - 2
src/components/icons.tsx

@@ -15,8 +15,9 @@ import { THEME } from "../constants";
 
 
 const activeElementColor = (theme: Theme) =>
 const activeElementColor = (theme: Theme) =>
   theme === THEME.LIGHT ? oc.orange[4] : oc.orange[9];
   theme === THEME.LIGHT ? oc.orange[4] : oc.orange[9];
-const iconFillColor = (theme: Theme) =>
-  theme === THEME.LIGHT ? oc.black : oc.gray[4];
+
+const iconFillColor = (theme: Theme) => "var(--icon-fill-color)";
+
 const handlerColor = (theme: Theme) =>
 const handlerColor = (theme: Theme) =>
   theme === THEME.LIGHT ? oc.white : "#1e1e1e";
   theme === THEME.LIGHT ? oc.white : "#1e1e1e";
 
 

+ 9 - 7
src/css/styles.scss

@@ -180,7 +180,7 @@
   }
   }
 
 
   .buttonList label:focus-within,
   .buttonList label:focus-within,
-  input:focus {
+  input:focus-visible {
     outline: transparent;
     outline: transparent;
     box-shadow: 0 0 0 2px var(--focus-highlight-color);
     box-shadow: 0 0 0 2px var(--focus-highlight-color);
   }
   }
@@ -190,14 +190,14 @@
     user-select: none;
     user-select: none;
     background-color: var(--button-gray-1);
     background-color: var(--button-gray-1);
     border: 0;
     border: 0;
-    border-radius: 4px;
+    border-radius: var(--border-radius-md);
     margin: 0.125rem 0;
     margin: 0.125rem 0;
     padding: 0.25rem;
     padding: 0.25rem;
     white-space: nowrap;
     white-space: nowrap;
 
 
     cursor: pointer;
     cursor: pointer;
 
 
-    &:focus {
+    &:focus-visible {
       outline: transparent;
       outline: transparent;
       box-shadow: 0 0 0 2px var(--focus-highlight-color);
       box-shadow: 0 0 0 2px var(--focus-highlight-color);
     }
     }
@@ -217,14 +217,16 @@
 
 
   .active,
   .active,
   .buttonList label.active {
   .buttonList label.active {
-    background-color: var(--button-gray-2);
+    background-color: var(--color-primary);
+
+    --icon-fill-color: #{$oc-white};
 
 
     &:hover {
     &:hover {
-      background-color: var(--button-gray-2);
+      background-color: var(--color-primary-darker);
     }
     }
 
 
     &:active {
     &:active {
-      background-color: var(--button-gray-3);
+      background-color: var(--color-primary-darkest);
     }
     }
   }
   }
 
 
@@ -234,7 +236,7 @@
       justify-content: center;
       justify-content: center;
       align-items: center;
       align-items: center;
       svg {
       svg {
-        width: 36px;
+        width: 35px;
         height: 14px;
         height: 14px;
         padding: 2px;
         padding: 2px;
         opacity: 0.6;
         opacity: 0.6;

+ 19 - 3
src/css/theme.scss

@@ -12,7 +12,7 @@
   --dialog-border-color: #{$oc-gray-6};
   --dialog-border-color: #{$oc-gray-6};
   --dropdown-icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="292.4" height="292.4" viewBox="0 0 292 292"><path d="M287 197L159 69c-4-3-8-5-13-5s-9 2-13 5L5 197c-3 4-5 8-5 13s2 9 5 13c4 4 8 5 13 5h256c5 0 9-1 13-5s5-8 5-13-1-9-5-13z"/></svg>');
   --dropdown-icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="292.4" height="292.4" viewBox="0 0 292 292"><path d="M287 197L159 69c-4-3-8-5-13-5s-9 2-13 5L5 197c-3 4-5 8-5 13s2 9 5 13c4 4 8 5 13 5h256c5 0 9-1 13-5s5-8 5-13-1-9-5-13z"/></svg>');
   --focus-highlight-color: #{$oc-blue-2};
   --focus-highlight-color: #{$oc-blue-2};
-  --icon-fill-color: #{$oc-black};
+  --icon-fill-color: #{$oc-gray-9};
   --icon-green-fill-color: #{$oc-green-9};
   --icon-green-fill-color: #{$oc-green-9};
   --default-bg-color: #{$oc-white};
   --default-bg-color: #{$oc-white};
   --input-bg-color: #{$oc-white};
   --input-bg-color: #{$oc-white};
@@ -32,10 +32,20 @@
   --sar: env(safe-area-inset-right);
   --sar: env(safe-area-inset-right);
   --sat: env(safe-area-inset-top);
   --sat: env(safe-area-inset-top);
   --select-highlight-color: #{$oc-blue-5};
   --select-highlight-color: #{$oc-blue-5};
-  --shadow-island: 0 1px 5px #{transparentize($oc-black, 0.85)};
+  --shadow-island: 0 0 0 1px rgba(0, 0, 0, 0.01), 1px 1px 5px rgb(0 0 0 / 12%);
+
   --space-factor: 0.25rem;
   --space-factor: 0.25rem;
   --text-primary-color: #{$oc-gray-8};
   --text-primary-color: #{$oc-gray-8};
 
 
+  --color-primary: #6965db;
+  --color-primary-chubb: #625ee0; // to offset Chubb illusion
+  --color-primary-darker: #5b57d1;
+  --color-primary-darkest: #4a47b1;
+  --color-primary-light: #e2e1fc;
+
+  --border-radius-md: 0.375rem;
+  --border-radius-lg: 0.5rem;
+
   &.theme--dark {
   &.theme--dark {
     background: $oc-black;
     background: $oc-black;
 
 
@@ -71,7 +81,13 @@
     --popup-text-color: #{$oc-gray-4};
     --popup-text-color: #{$oc-gray-4};
     --popup-text-inverted-color: #2c2c2c;
     --popup-text-inverted-color: #2c2c2c;
     --select-highlight-color: #{$oc-blue-4};
     --select-highlight-color: #{$oc-blue-4};
-    --shadow-island: 0 1px 5px #{transparentize($oc-black, 0.7)};
+    --shadow-island: 1px 1px 5px #{transparentize($oc-black, 0.7)};
     --text-primary-color: #{$oc-gray-4};
     --text-primary-color: #{$oc-gray-4};
+
+    --color-primary: #5650f0;
+    --color-primary-chubb: #726dff; // to offset Chubb illusion
+    --color-primary-darker: #4b46d8;
+    --color-primary-darkest: #3e39be;
+    --color-primary-light: #3f3d64;
   }
   }
 }
 }

+ 1 - 1
src/excalidraw-app/components/ExportToExcalidrawPlus.tsx

@@ -78,7 +78,7 @@ export const ExportToExcalidrawPlus: React.FC<{
   onError: (error: Error) => void;
   onError: (error: Error) => void;
 }> = ({ elements, appState, files, onError }) => {
 }> = ({ elements, appState, files, onError }) => {
   return (
   return (
-    <Card color="indigo">
+    <Card color="primary">
       <div className="Card-icon">{excalidrawPlusIcon}</div>
       <div className="Card-icon">{excalidrawPlusIcon}</div>
       <h2>Excalidraw+</h2>
       <h2>Excalidraw+</h2>
       <div className="Card-details">
       <div className="Card-details">

+ 1 - 1
src/excalidraw-app/index.scss

@@ -9,7 +9,7 @@
 
 
   .encrypted-icon {
   .encrypted-icon {
     border-radius: var(--space-factor);
     border-radius: var(--space-factor);
-    color: var(--icon-green-fill-color);
+    color: var(--color-primary);
     margin-top: auto;
     margin-top: auto;
     margin-bottom: auto;
     margin-bottom: auto;
     margin-inline-start: auto;
     margin-inline-start: auto;

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

@@ -19,6 +19,8 @@ Please add the latest change on the top under the correct section.
 
 
 ### Features
 ### Features
 
 
+- Introduced primary colors to the app. The colors can be overriden. Check [readme](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#customizing-styles) on how to do so.
+
 - #### BREAKING CHANGE
 - #### BREAKING CHANGE
 
 
   Removed `getElementMap` util method.
   Removed `getElementMap` util method.

+ 25 - 0
src/packages/excalidraw/README_NEXT.md

@@ -353,6 +353,31 @@ To view the full example visit :point_down:
 
 
 </details>
 </details>
 
 
+### Customizing styles
+
+Excalidraw is using CSS variables to style certain components. To override them, you should set your own on the `.excalidraw` and `.excalidraw.theme--dark` (for dark mode variables) selectors.
+
+Make sure the selector has higher specificity, e.g. by prefixing it with your app's selector:
+
+```css
+.your-app .excalidraw {
+  --color-primary: red;
+}
+.your-app .excalidraw.theme--dark {
+  --color-primary: pink;
+}
+```
+
+Most notably, you can customize the primary colors, by overriding these variables:
+
+- `--color-primary`
+- `--color-primary-darker`
+- `--color-primary-darkest`
+- `--color-primary-light`
+- `--color-primary-chubb` — a slightly darker (in light mode), or lighter (in dark mode) `--color-primary` color to account for [Chubb illusion](https://en.wikipedia.org/wiki/Chubb_illusion).
+
+For a complete list of variables, check [theme.scss](https://github.com/excalidraw/excalidraw/blob/master/src/css/theme.scss), though most of them will not make sense to override.
+
 ### Props
 ### Props
 
 
 | Name | Type | Default | Description |
 | Name | Type | Default | Description |