(WOS.makeORef("tab", tabId));
const layoutTreeState = util.useAtomValueSafe(getLayoutStateAtomForTab(tabId, tabAtom));
- if (!isBlockMagnified(layoutTreeState, blockData.oid)) {
- return null;
- }
+ const isMagnified = isBlockMagnified(layoutTreeState, blockData.oid);
const magnifyDecl: HeaderIconButton = {
elemtype: "iconbutton",
- icon: "regular@magnifying-glass-minus",
- title: "Minimize",
+ icon: ,
+ title: isMagnified ? "Minimize" : "Magnify",
click: layoutModel?.onMagnifyToggle,
};
return ;
diff --git a/frontend/app/block/blockutil.tsx b/frontend/app/block/blockutil.tsx
index 613284534..b991c6317 100644
--- a/frontend/app/block/blockutil.tsx
+++ b/frontend/app/block/blockutil.tsx
@@ -163,7 +163,7 @@ export const IconButton = React.memo(({ decl, className }: { decl: HeaderIconBut
useLongClick(buttonRef, decl.click, decl.longClick);
return (
-
+ {typeof decl.icon === "string" ? : decl.icon}
);
});
diff --git a/frontend/app/element/magnify.less b/frontend/app/element/magnify.less
new file mode 100644
index 000000000..48a402f3b
--- /dev/null
+++ b/frontend/app/element/magnify.less
@@ -0,0 +1,36 @@
+.magnify-icon {
+ display: inline-block;
+ width: 15px;
+ height: 15px;
+ svg {
+ #arrow1 {
+ transform: rotate(180deg);
+ transform-origin: calc(29.167% + 4px) calc(70.833% + 4px); // account for path offset in the svg itself
+ }
+ #arrow2 {
+ transform: rotate(-180deg);
+ transform-origin: calc(70.833% + 4px) calc(29.167% + 4px);
+ }
+ #arrow1,
+ #arrow2 {
+ transition: transform 300ms ease-in;
+ }
+ }
+ &.enabled {
+ svg {
+ #arrow1,
+ #arrow2 {
+ transform: rotate(0deg);
+ }
+ }
+ }
+}
+
+@media (prefers-reduced-motion) {
+ .magnify-icon svg {
+ #arrow1,
+ #arrow2 {
+ transition: none;
+ }
+ }
+}
diff --git a/frontend/app/element/magnify.stories.tsx b/frontend/app/element/magnify.stories.tsx
new file mode 100644
index 000000000..5e52da4e6
--- /dev/null
+++ b/frontend/app/element/magnify.stories.tsx
@@ -0,0 +1,25 @@
+import type { Meta, StoryObj } from "@storybook/react";
+import { MagnifyIcon } from "./magnify";
+
+const meta = {
+ title: "Icons/Magnify",
+ component: MagnifyIcon,
+ args: {
+ enabled: true,
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Enabled: Story = {
+ args: {
+ enabled: true,
+ },
+};
+
+export const Disabled: Story = {
+ args: {
+ enabled: false,
+ },
+};
diff --git a/frontend/app/element/magnify.tsx b/frontend/app/element/magnify.tsx
new file mode 100644
index 000000000..f6ceadeb0
--- /dev/null
+++ b/frontend/app/element/magnify.tsx
@@ -0,0 +1,15 @@
+import clsx from "clsx";
+import MagnifySVG from "../asset/magnify.svg";
+import "./magnify.less";
+
+interface MagnifyIconProps {
+ enabled: boolean;
+}
+
+export function MagnifyIcon({ enabled }: MagnifyIconProps) {
+ return (
+
+
+
+ );
+}
diff --git a/frontend/app/theme.less b/frontend/app/theme.less
index 3ae59f0fe..7d2633ae8 100644
--- a/frontend/app/theme.less
+++ b/frontend/app/theme.less
@@ -32,6 +32,7 @@
--header-font: 700 11px / normal "Inter", sans-serif;
--header-icon-size: 14px;
--header-icon-width: 16px;
+ --header-height: 30px;
--tab-green: rgb(88, 193, 66);
diff --git a/frontend/layout/lib/tilelayout.less b/frontend/layout/lib/tilelayout.less
index 8ef09840e..08a29903c 100644
--- a/frontend/layout/lib/tilelayout.less
+++ b/frontend/layout/lib/tilelayout.less
@@ -117,3 +117,16 @@
border-radius: calc(var(--block-border-radius) + 2px);
}
}
+
+@media (prefers-reduced-motion) {
+ .tile-layout {
+ &.animate {
+ .tile-node,
+ .placeholder {
+ transition-duration: none;
+ transition-timing-function: none;
+ transition-property: none;
+ }
+ }
+ }
+}
diff --git a/frontend/types/custom.d.ts b/frontend/types/custom.d.ts
index ba8d797eb..508df4989 100644
--- a/frontend/types/custom.d.ts
+++ b/frontend/types/custom.d.ts
@@ -123,7 +123,7 @@ declare global {
type HeaderIconButton = {
elemtype: "iconbutton";
- icon: string;
+ icon: string | React.ReactNode;
className?: string;
title?: string;
click?: (e: React.MouseEvent) => void;