update: show scroll arrows on narrow displays
This commit is contained in:
committed by
Nicolás Hatcher Andrés
parent
7bcd978998
commit
6c27ae1355
@@ -14,6 +14,8 @@ import {
|
|||||||
ArrowUpToLine,
|
ArrowUpToLine,
|
||||||
Bold,
|
Bold,
|
||||||
ChevronDown,
|
ChevronDown,
|
||||||
|
ChevronLeft,
|
||||||
|
ChevronRight,
|
||||||
DecimalsArrowLeft,
|
DecimalsArrowLeft,
|
||||||
DecimalsArrowRight,
|
DecimalsArrowRight,
|
||||||
Euro,
|
Euro,
|
||||||
@@ -36,7 +38,7 @@ import {
|
|||||||
Undo2,
|
Undo2,
|
||||||
WrapText,
|
WrapText,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useRef, useState } from "react";
|
import { useCallback, useEffect, useRef, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { ArrowMiddleFromLine } from "../../icons";
|
import { ArrowMiddleFromLine } from "../../icons";
|
||||||
import { theme } from "../../theme";
|
import { theme } from "../../theme";
|
||||||
@@ -94,17 +96,51 @@ function Toolbar(properties: ToolbarProperties) {
|
|||||||
const [fillColorPickerOpen, setFillColorPickerOpen] = useState(false);
|
const [fillColorPickerOpen, setFillColorPickerOpen] = useState(false);
|
||||||
const [borderPickerOpen, setBorderPickerOpen] = useState(false);
|
const [borderPickerOpen, setBorderPickerOpen] = useState(false);
|
||||||
const [nameManagerDialogOpen, setNameManagerDialogOpen] = useState(false);
|
const [nameManagerDialogOpen, setNameManagerDialogOpen] = useState(false);
|
||||||
|
const [showLeftArrow, setShowLeftArrow] = useState(false);
|
||||||
|
const [showRightArrow, setShowRightArrow] = useState(false);
|
||||||
|
|
||||||
const fontColorButton = useRef(null);
|
const fontColorButton = useRef(null);
|
||||||
const fillColorButton = useRef(null);
|
const fillColorButton = useRef(null);
|
||||||
const borderButton = useRef(null);
|
const borderButton = useRef(null);
|
||||||
|
const toolbarRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const { canEdit } = properties;
|
const { canEdit } = properties;
|
||||||
|
|
||||||
|
const scrollLeft = () =>
|
||||||
|
toolbarRef.current?.scrollBy({ left: -200, behavior: "smooth" });
|
||||||
|
const scrollRight = () =>
|
||||||
|
toolbarRef.current?.scrollBy({ left: 200, behavior: "smooth" });
|
||||||
|
|
||||||
|
const updateArrows = useCallback(() => {
|
||||||
|
if (!toolbarRef.current) return;
|
||||||
|
const { scrollLeft, scrollWidth, clientWidth } = toolbarRef.current;
|
||||||
|
setShowLeftArrow(scrollLeft > 0);
|
||||||
|
setShowRightArrow(scrollLeft < scrollWidth - clientWidth);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const toolbar = toolbarRef.current;
|
||||||
|
if (!toolbar) return;
|
||||||
|
|
||||||
|
updateArrows();
|
||||||
|
toolbar.addEventListener("scroll", updateArrows);
|
||||||
|
return () => toolbar.removeEventListener("scroll", updateArrows);
|
||||||
|
}, [updateArrows]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ToolbarContainer>
|
<ToolbarWrapper>
|
||||||
|
{showLeftArrow && (
|
||||||
|
<ScrollArrow
|
||||||
|
$direction="left"
|
||||||
|
onClick={scrollLeft}
|
||||||
|
title={t("toolbar.scroll_left")}
|
||||||
|
>
|
||||||
|
<ChevronLeft />
|
||||||
|
</ScrollArrow>
|
||||||
|
)}
|
||||||
|
<ToolbarContainer ref={toolbarRef}>
|
||||||
{/* History/Edit Group */}
|
{/* History/Edit Group */}
|
||||||
<ButtonGroup>
|
<ButtonGroup>
|
||||||
<StyledButton
|
<StyledButton
|
||||||
@@ -514,23 +550,40 @@ function Toolbar(properties: ToolbarProperties) {
|
|||||||
model={properties.nameManagerProperties}
|
model={properties.nameManagerProperties}
|
||||||
/>
|
/>
|
||||||
</ToolbarContainer>
|
</ToolbarContainer>
|
||||||
|
{showRightArrow && (
|
||||||
|
<ScrollArrow
|
||||||
|
$direction="right"
|
||||||
|
onClick={scrollRight}
|
||||||
|
title={t("toolbar.scroll_right")}
|
||||||
|
>
|
||||||
|
<ChevronRight />
|
||||||
|
</ScrollArrow>
|
||||||
|
)}
|
||||||
|
</ToolbarWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ToolbarContainer = styled("div")`
|
const ToolbarWrapper = styled("div")`
|
||||||
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-shrink: 0;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: ${({ theme }) => theme.palette.background.paper};
|
background: ${({ theme }) => theme.palette.background.paper};
|
||||||
height: ${TOOLBAR_HEIGHT}px;
|
height: ${TOOLBAR_HEIGHT}px;
|
||||||
line-height: ${TOOLBAR_HEIGHT}px;
|
|
||||||
border-bottom: 1px solid ${({ theme }) => theme.palette.grey["300"]};
|
border-bottom: 1px solid ${({ theme }) => theme.palette.grey["300"]};
|
||||||
font-family: Inter;
|
|
||||||
border-radius: 4px 4px 0px 0px;
|
border-radius: 4px 4px 0px 0px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ToolbarContainer = styled("div")`
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
align-items: center;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
padding: 0px 12px;
|
padding: 0px 12px;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
type TypeButtonProperties = { $pressed: boolean };
|
type TypeButtonProperties = { $pressed: boolean };
|
||||||
@@ -617,4 +670,33 @@ const ButtonGroup = styled("div")({
|
|||||||
gap: "4px",
|
gap: "4px",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
type ScrollArrowProps = { $direction: "left" | "right" };
|
||||||
|
const ScrollArrow = styled("button", {
|
||||||
|
shouldForwardProp: (prop) => prop !== "$direction",
|
||||||
|
})<ScrollArrowProps>(({ $direction }) => ({
|
||||||
|
position: "absolute",
|
||||||
|
top: "50%",
|
||||||
|
transform: "translateY(-50%)",
|
||||||
|
[$direction]: "0px",
|
||||||
|
zIndex: 10,
|
||||||
|
width: "24px",
|
||||||
|
height: "100%",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
backgroundColor: "white",
|
||||||
|
border:
|
||||||
|
$direction === "left"
|
||||||
|
? `none; border-right: 1px solid ${theme.palette.grey["300"]};`
|
||||||
|
: `none; border-left: 1px solid ${theme.palette.grey["300"]};`,
|
||||||
|
cursor: "pointer",
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: theme.palette.grey["100"],
|
||||||
|
},
|
||||||
|
svg: {
|
||||||
|
width: "16px",
|
||||||
|
height: "16px",
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
export default Toolbar;
|
export default Toolbar;
|
||||||
|
|||||||
@@ -27,6 +27,8 @@
|
|||||||
"vertical_align_top": "Align top",
|
"vertical_align_top": "Align top",
|
||||||
"selected_png": "Export Selected area as PNG",
|
"selected_png": "Export Selected area as PNG",
|
||||||
"wrap_text": "Wrap text",
|
"wrap_text": "Wrap text",
|
||||||
|
"scroll_left": "Scroll left",
|
||||||
|
"scroll_right": "Scroll right",
|
||||||
"format_menu": {
|
"format_menu": {
|
||||||
"auto": "Auto",
|
"auto": "Auto",
|
||||||
"number": "Number",
|
"number": "Number",
|
||||||
|
|||||||
Reference in New Issue
Block a user