mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-11-12 00:34:21 +01:00
feat: compact layout for tablets (#9910)
* feat: allow the hiding of top picks * feat: allow the hiding of default fonts * refactor: rename to compactMode * feat: introduce layout (incomplete) * tweak icons * do not show border * lint * add isTouchMobile to device * add isTouchMobile to device * refactor to use showCompactSidebar instead * hide library label in compact * fix icon color in dark theme * fix library and share btns getting hidden in smaller tablet widths * update tests * use a smaller gap between shapes * proper fix of range * quicker switching between different popovers * to not show properties panel at all when editing text * fix switching between different popovers for texts * fix popover not closable and font search auto focus * change properties for a new or editing text * change icon for more style settings * use bolt icon for extra actions * fix breakpoints * use rem for icon sizes * fix tests * improve switching between triggers (incomplete) * improve trigger switching (complete) * clean up code * put compact into app state * fix button size * remove redundant PanelComponentProps["compactMode"] * move fontSize UI on top * mobile detection (breakpoints incomplete) * tweak compact mode detection * rename appState prop & values * update snapshots --------- Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
This commit is contained in:
@@ -41,9 +41,6 @@ import {
|
||||
LINE_CONFIRM_THRESHOLD,
|
||||
MAX_ALLOWED_FILE_BYTES,
|
||||
MIME_TYPES,
|
||||
MQ_MAX_HEIGHT_LANDSCAPE,
|
||||
MQ_MAX_WIDTH_LANDSCAPE,
|
||||
MQ_MAX_WIDTH_PORTRAIT,
|
||||
MQ_RIGHT_SIDEBAR_MIN_WIDTH,
|
||||
POINTER_BUTTON,
|
||||
ROUNDNESS,
|
||||
@@ -100,9 +97,14 @@ import {
|
||||
randomInteger,
|
||||
CLASSES,
|
||||
Emitter,
|
||||
isMobile,
|
||||
MINIMUM_ARROW_SIZE,
|
||||
DOUBLE_TAP_POSITION_THRESHOLD,
|
||||
isMobileOrTablet,
|
||||
MQ_MAX_WIDTH_MOBILE,
|
||||
MQ_MAX_HEIGHT_LANDSCAPE,
|
||||
MQ_MAX_WIDTH_LANDSCAPE,
|
||||
MQ_MIN_TABLET,
|
||||
MQ_MAX_TABLET,
|
||||
} from "@excalidraw/common";
|
||||
|
||||
import {
|
||||
@@ -667,7 +669,7 @@ class App extends React.Component<AppProps, AppState> {
|
||||
constructor(props: AppProps) {
|
||||
super(props);
|
||||
const defaultAppState = getDefaultAppState();
|
||||
this.defaultSelectionTool = this.isMobileOrTablet()
|
||||
this.defaultSelectionTool = isMobileOrTablet()
|
||||
? ("lasso" as const)
|
||||
: ("selection" as const);
|
||||
const {
|
||||
@@ -2420,23 +2422,20 @@ class App extends React.Component<AppProps, AppState> {
|
||||
}
|
||||
};
|
||||
|
||||
private isMobileOrTablet = (): boolean => {
|
||||
const hasTouch = "ontouchstart" in window || navigator.maxTouchPoints > 0;
|
||||
const hasCoarsePointer =
|
||||
"matchMedia" in window &&
|
||||
window?.matchMedia("(pointer: coarse)")?.matches;
|
||||
const isTouchMobile = hasTouch && hasCoarsePointer;
|
||||
|
||||
return isMobile || isTouchMobile;
|
||||
};
|
||||
|
||||
private isMobileBreakpoint = (width: number, height: number) => {
|
||||
return (
|
||||
width < MQ_MAX_WIDTH_PORTRAIT ||
|
||||
width <= MQ_MAX_WIDTH_MOBILE ||
|
||||
(height < MQ_MAX_HEIGHT_LANDSCAPE && width < MQ_MAX_WIDTH_LANDSCAPE)
|
||||
);
|
||||
};
|
||||
|
||||
private isTabletBreakpoint = (editorWidth: number, editorHeight: number) => {
|
||||
const minSide = Math.min(editorWidth, editorHeight);
|
||||
const maxSide = Math.max(editorWidth, editorHeight);
|
||||
|
||||
return minSide >= MQ_MIN_TABLET && maxSide <= MQ_MAX_TABLET;
|
||||
};
|
||||
|
||||
private refreshViewportBreakpoints = () => {
|
||||
const container = this.excalidrawContainerRef.current;
|
||||
if (!container) {
|
||||
@@ -2481,6 +2480,17 @@ class App extends React.Component<AppProps, AppState> {
|
||||
canFitSidebar: editorWidth > sidebarBreakpoint,
|
||||
});
|
||||
|
||||
// also check if we need to update the app state
|
||||
this.setState({
|
||||
stylesPanelMode:
|
||||
// NOTE: we could also remove the isMobileOrTablet check here and
|
||||
// always switch to compact mode when the editor is narrow (e.g. < MQ_MIN_WIDTH_DESKTOP)
|
||||
// but not too narrow (> MQ_MAX_WIDTH_MOBILE)
|
||||
this.isTabletBreakpoint(editorWidth, editorHeight) && isMobileOrTablet()
|
||||
? "compact"
|
||||
: "full",
|
||||
});
|
||||
|
||||
if (prevEditorState !== nextEditorState) {
|
||||
this.device = { ...this.device, editor: nextEditorState };
|
||||
return true;
|
||||
@@ -3147,7 +3157,7 @@ class App extends React.Component<AppProps, AppState> {
|
||||
this.addElementsFromPasteOrLibrary({
|
||||
elements,
|
||||
files: data.files || null,
|
||||
position: this.isMobileOrTablet() ? "center" : "cursor",
|
||||
position: isMobileOrTablet() ? "center" : "cursor",
|
||||
retainSeed: isPlainPaste,
|
||||
});
|
||||
return;
|
||||
@@ -3172,7 +3182,7 @@ class App extends React.Component<AppProps, AppState> {
|
||||
this.addElementsFromPasteOrLibrary({
|
||||
elements,
|
||||
files,
|
||||
position: this.isMobileOrTablet() ? "center" : "cursor",
|
||||
position: isMobileOrTablet() ? "center" : "cursor",
|
||||
});
|
||||
|
||||
return;
|
||||
@@ -6668,8 +6678,6 @@ class App extends React.Component<AppProps, AppState> {
|
||||
pointerDownState.hit.element &&
|
||||
this.isASelectedElement(pointerDownState.hit.element);
|
||||
|
||||
const isMobileOrTablet = this.isMobileOrTablet();
|
||||
|
||||
if (
|
||||
!pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements &&
|
||||
!pointerDownState.resize.handleType &&
|
||||
@@ -6683,12 +6691,12 @@ class App extends React.Component<AppProps, AppState> {
|
||||
|
||||
// block dragging after lasso selection on PCs until the next pointer down
|
||||
// (on mobile or tablet, we want to allow user to drag immediately)
|
||||
pointerDownState.drag.blockDragging = !isMobileOrTablet;
|
||||
pointerDownState.drag.blockDragging = !isMobileOrTablet();
|
||||
}
|
||||
|
||||
// only for mobile or tablet, if we hit an element, select it immediately like normal selection
|
||||
if (
|
||||
isMobileOrTablet &&
|
||||
isMobileOrTablet() &&
|
||||
pointerDownState.hit.element &&
|
||||
!hitSelectedElement
|
||||
) {
|
||||
@@ -8489,7 +8497,7 @@ class App extends React.Component<AppProps, AppState> {
|
||||
if (
|
||||
this.state.activeTool.type === "lasso" &&
|
||||
this.lassoTrail.hasCurrentTrail &&
|
||||
!(this.isMobileOrTablet() && pointerDownState.hit.element) &&
|
||||
!(isMobileOrTablet() && pointerDownState.hit.element) &&
|
||||
!this.state.activeTool.fromSelection
|
||||
) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user