Skip to content

Commit

Permalink
chore: Transitions for IDE (#35714)
Browse files Browse the repository at this point in the history
## Description

Uses `AnimatedGridLayout` component to introduce transitions for the
IDE. This is behind a feature flag

Fixes #34538
Fixes #30863 
Fixes #34544 

## Automation

/ok-to-test tags="@tag.All"

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!CAUTION]
> 🔴 🔴 🔴 Some tests have failed.
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/10737363879>
> Commit: a912f5c
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=10737363879&attempt=2&selectiontype=test&testsstatus=failed&specsstatus=fail"
target="_blank">Cypress dashboard</a>.
> Tags: @tag.All
> Spec: 
> The following are new failures, please fix them before merging the PR:
<ol>
>
<li>cypress/e2e/Regression/ServerSide/OnLoadTests/ExecuteAction_Spec.ts</ol>
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/identified-flaky-tests-65890b3c81d7400d08fa9ee3?branch=master"
target="_blank">List of identified flaky tests</a>.
> <hr>Fri, 06 Sep 2024 16:32:30 UTC
<!-- end of auto-generated comment: Cypress test results  -->


## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [ ] No


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Summary by CodeRabbit

- **New Features**
- Introduced two new layout components: `AnimatedLayout` and
`UnanimatedLayout` for improved editor interface structuring.
- Added TypeScript type definitions for the DOM View Transitions API to
enhance type safety and developer experience.
- Implemented custom hooks, `useGridLayoutTemplate` and
`useEditorStateLeftPaneWidth`, for dynamic grid management and left pane
width calculation in the IDE layout.

- **Improvements**
- Enhanced layout responsiveness with the addition of dynamic grid
management.
- Updated the `Editor` component to use a centralized constant for
height calculations, improving maintainability and consistency.
- Enhanced test accuracy by refining assertions in the Git Branch
Protection test suite.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Sagar Khalasi <[email protected]>
  • Loading branch information
hetunandu and sagar-qa007 committed Sep 9, 2024
1 parent 1b16be8 commit 60dbda4
Show file tree
Hide file tree
Showing 46 changed files with 517 additions and 243 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,7 @@ describe("Git Branch Protection", { tags: ["@tag.Git"] }, function () {
cy.wait("@gitProtectApi").then((res1) => {
_.agHelper.GetNClick(_.gitSync._closeGitSettingsModal);
expect(res1.response).to.have.property("statusCode", 200);
_.agHelper.AssertElementVisibility(
AppSidebar.locators.sidebar,
false,
);
_.agHelper.AssertElementAbsence(AppSidebar.locators.sidebar);
_.agHelper.AssertElementVisibility(
PageLeftPane.locators.selector,
false,
Expand Down
1 change: 1 addition & 0 deletions app/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@
"@types/codemirror": "^0.0.96",
"@types/deep-diff": "^1.0.0",
"@types/dom-mediacapture-record": "^1.0.11",
"@types/dom-view-transitions": "^1.0.5",
"@types/downloadjs": "^1.4.2",
"@types/jest": "^27.4.1",
"@types/js-beautify": "^1.13.2",
Expand Down
3 changes: 2 additions & 1 deletion app/client/src/IDE/Structure/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";
import { Divider, Flex } from "@appsmith/ads";
import { AppsmithLink } from "pages/Editor/AppsmithLink";
import { IDE_HEADER_HEIGHT } from "./constants";

interface ChildrenProps {
children: React.ReactNode | React.ReactNode[];
Expand Down Expand Up @@ -59,7 +60,7 @@ const Header = (props: ChildrenProps) => {
alignItems="center"
border="1px solid var(--ads-v2-color-border)"
className="t--editor-header"
height="40px"
height={IDE_HEADER_HEIGHT + "px"}
overflow="hidden"
width="100%"
>
Expand Down
1 change: 1 addition & 0 deletions app/client/src/IDE/Structure/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const IDE_HEADER_HEIGHT = 40;
1 change: 1 addition & 0 deletions app/client/src/IDE/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* These are composable components that you can use to spread the content of the header
* It is possible to use the IDE Header without using these subsections
*/
export { IDE_HEADER_HEIGHT } from "./Structure/constants";
export { default as IDEHeader } from "./Structure/Header";

/* ====================================================
Expand Down
2 changes: 2 additions & 0 deletions app/client/src/ce/entities/FeatureFlag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export const FEATURE_FLAG = {
"ab_learnability_discoverability_collapse_all_except_data_enabled",
release_layout_conversion_enabled: "release_layout_conversion_enabled",
release_anvil_toggle_enabled: "release_anvil_toggle_enabled",
release_ide_animations_enabled: "release_ide_animations_enabled",
} as const;

export type FeatureFlag = keyof typeof FEATURE_FLAG;
Expand Down Expand Up @@ -82,6 +83,7 @@ export const DEFAULT_FEATURE_FLAG_VALUE: FeatureFlags = {
ab_learnability_discoverability_collapse_all_except_data_enabled: true,
release_layout_conversion_enabled: false,
release_anvil_toggle_enabled: false,
release_ide_animations_enabled: false,
};

export const AB_TESTING_EVENT_KEYS = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function LayoutArea(props: LayoutAreaProps) {
>
<div
style={{
minWidth: dimensions?.width || "100%",
width: dimensions?.width || "100%",
height: "100%",
position: "absolute",
overflow: "auto",
Expand Down
6 changes: 4 additions & 2 deletions app/client/src/components/AnimatedGridLayout/constants.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { easings } from "@react-spring/web";
import type { AnimatedGridUnit } from "./types";

/** Default rows config. */
export const DEFAULT_ROWS: AnimatedGridUnit[] = ["1fr"];

export const SPRING_ANIMATION_CONFIG = {
easing: easings.easeInCirc,
duration: 375,
friction: 32,
mass: 1,
tension: 205,
};
3 changes: 2 additions & 1 deletion app/client/src/components/BottomBar/components.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import styled from "styled-components";
import { Layers } from "constants/Layers";
import { BOTTOM_BAR_HEIGHT } from "./constants";

export const Container = styled.div`
width: 100%;
height: ${(props) => props.theme.bottomBarHeight};
height: ${BOTTOM_BAR_HEIGHT}px;
display: flex;
position: fixed;
justify-content: space-between;
Expand Down
1 change: 1 addition & 0 deletions app/client/src/components/BottomBar/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const BOTTOM_BAR_HEIGHT = 37;
16 changes: 10 additions & 6 deletions app/client/src/components/BottomBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,18 @@ import { Button } from "@appsmith/ads";
import SwitchEnvironment from "ee/components/SwitchEnvironment";
import { Container, Wrapper } from "./components";
import { useSelector } from "react-redux";
import { getCurrentApplicationId } from "selectors/editorSelectors";
import {
getCurrentApplicationId,
previewModeSelector,
} from "selectors/editorSelectors";
import { useDispatch } from "react-redux";
import { softRefreshActions } from "actions/pluginActionActions";
import { START_SWITCH_ENVIRONMENT } from "ee/constants/messages";
import { getIsAnvilEnabledInCurrentApplication } from "layoutSystems/anvil/integrations/selectors";

export default function BottomBar({ viewMode }: { viewMode: boolean }) {
export default function BottomBar() {
const appId = useSelector(getCurrentApplicationId) || "";
const isPreviewMode = useSelector(previewModeSelector);
const dispatch = useDispatch();
// We check if the current application is an Anvil application.
// If it is an Anvil application, we remove the Git features from the bottomBar
Expand All @@ -28,17 +32,17 @@ export default function BottomBar({ viewMode }: { viewMode: boolean }) {
return (
<Container>
<Wrapper>
{!viewMode && (
{!isPreviewMode && (
<SwitchEnvironment
editorId={appId}
onChangeEnv={onChangeEnv}
startSwitchEnvMessage={START_SWITCH_ENVIRONMENT}
viewMode={viewMode}
viewMode={isPreviewMode}
/>
)}
{!viewMode && !isAnvilEnabled && <QuickGitActions />}
{!isPreviewMode && !isAnvilEnabled && <QuickGitActions />}
</Wrapper>
{!viewMode && (
{!isPreviewMode && (
<Wrapper>
<ManualUpgrades showTooltip>
<Button
Expand Down
92 changes: 19 additions & 73 deletions app/client/src/components/editorComponents/PropertyPaneSidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,51 +1,28 @@
import classNames from "classnames";
import React, {
memo,
useCallback,
useContext,
useEffect,
useMemo,
useRef,
} from "react";
import * as Sentry from "@sentry/react";
import { useSelector } from "react-redux";
import React, { memo, useContext, useEffect, useMemo, useRef } from "react";

import { getSelectedWidgets } from "selectors/ui";
import { tailwindLayers } from "constants/Layers";
import WidgetPropertyPane from "pages/Editor/PropertyPane";
import CanvasPropertyPane from "pages/Editor/CanvasPropertyPane";
import useHorizontalResize from "utils/hooks/useHorizontalResize";
import { getIsDraggingForSelection } from "selectors/canvasSelectors";
import MultiSelectPropertyPane from "pages/Editor/MultiSelectPropertyPane";
import { getIsDraggingOrResizing } from "selectors/widgetSelectors";
import { selectedWidgetsPresentInCanvas } from "selectors/propertyPaneSelectors";
import styled from "styled-components";
import WalkthroughContext from "components/featureWalkthrough/walkthroughContext";
import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants";

export const PROPERTY_PANE_ID = "t--property-pane-sidebar";

const StyledResizer = styled.div<{ resizing: boolean }>`
${(props) =>
props.resizing &&
`
& > div {
background-color: var(--ads-v2-color-outline);
}
`}
:hover {
& > div {
background-color: var(--ads-v2-color-bg-emphasis);
}
}
`;

interface Props {
width: number;
onDragEnd?: () => void;
onWidthChange: (width: number) => void;
}

export const PropertyPaneSidebar = memo((props: Props) => {
export const PropertyPaneSidebar = memo(() => {
const sidebarRef = useRef<HTMLDivElement>(null);
const prevSelectedWidgetId = useRef<string | undefined>();

const { onMouseDown, onMouseUp, onTouchStart, resizing } =
useHorizontalResize(sidebarRef, props.onWidthChange, props.onDragEnd, true);

const selectedWidgetIds = useSelector(getSelectedWidgets);
const isDraggingOrResizing = useSelector(getIsDraggingOrResizing);
const { isOpened: isWalkthroughOpened, popFeature } =
Expand All @@ -58,17 +35,10 @@ export const PropertyPaneSidebar = memo((props: Props) => {
selectedWidgetIds[0] !== prevSelectedWidgetId.current) ||
selectedWidgetIds[0] === MAIN_CONTAINER_WIDGET_ID;

// This is to keep the theming properties from changing,
// while dragging a widget when no other widgets were selected
const keepThemeWhileDragging =
prevSelectedWidgetId.current === undefined && shouldNotRenderPane;

const selectedWidgetsLength = useSelector(
(state) => selectedWidgetsPresentInCanvas(state).length,
);

const isDraggingForSelection = useSelector(getIsDraggingForSelection);

prevSelectedWidgetId.current =
selectedWidgetIds.length === 1 ? selectedWidgetIds[0] : undefined;

Expand All @@ -91,27 +61,24 @@ export const PropertyPaneSidebar = memo((props: Props) => {
default:
return <CanvasPropertyPane />;
}
}, [
selectedWidgetsLength,
isDraggingForSelection,
shouldNotRenderPane,
keepThemeWhileDragging,
]);
}, [selectedWidgetsLength, shouldNotRenderPane]);

const closeWalkthrough = () => {
const closeWalkthrough = useCallback(() => {
if (popFeature) {
popFeature("PROPERTY_PANE");
sidebarRef.current?.removeEventListener("click", closeWalkthrough);
}
};
}, [popFeature]);

useEffect(() => {
if (isWalkthroughOpened)
sidebarRef.current?.addEventListener("click", closeWalkthrough);
const currentSidebar = sidebarRef.current;
if (isWalkthroughOpened) {
currentSidebar?.addEventListener("click", closeWalkthrough);
}
return () => {
sidebarRef.current?.removeEventListener("click", closeWalkthrough);
currentSidebar?.removeEventListener("click", closeWalkthrough);
};
}, [isWalkthroughOpened]);
}, [closeWalkthrough, isWalkthroughOpened]);

return (
<div className="relative h-full">
Expand All @@ -122,28 +89,7 @@ export const PropertyPaneSidebar = memo((props: Props) => {
id={PROPERTY_PANE_ID}
ref={sidebarRef}
>
{/* RESIZER */}
<StyledResizer
className={`absolute top-0 left-0 w-2 h-full -ml-1 group cursor-ew-resize ${tailwindLayers.resizer}`}
onMouseDown={onMouseDown}
onTouchEnd={onMouseUp}
onTouchStart={onTouchStart}
resizing={resizing}
>
<div
className={classNames({
"w-1 h-full bg-transparent transform transition flex items-center":
true,
})}
/>
</StyledResizer>
<div
className={classNames({
"h-full p-0 overflow-y-auto min-w-72 max-w-104": true,
"transition-all duration-400": !resizing,
})}
style={{ width: props.width }}
>
<div className={"h-full p-0 overflow-y-auto min-w-72 max-w-104 w-full"}>
{propertyPane}
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import React, { useEffect, useState } from "react";
import type { ReactNode } from "react";
import styled from "styled-components";
import { Layers } from "constants/Layers";
import { theme } from "constants/DefaultTheme";
import { useDispatch, useSelector } from "react-redux";
import { getAppViewHeaderHeight } from "selectors/appViewSelectors";
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
import { useMaxModalWidth } from "widgets/ModalWidget/component/useModalWidth";
import { useAppViewerSidebarProperties } from "utils/hooks/useAppViewerSidebarProperties";

const Container = styled.div<{
width?: number;
height?: number;
Expand All @@ -22,7 +22,6 @@ const Container = styled.div<{
minSize?: number;
isEditMode?: boolean;
headerHeight?: number;
smallHeaderHeight?: string;
leftSidebarWidth?: string;
}>`
&&& {
Expand Down Expand Up @@ -152,7 +151,6 @@ export function ModalOverlayLayer(props: BaseWidgetProps) {
maxWidth={maxModalWidth}
minSize={props.minSize}
right={props.bottom}
smallHeaderHeight={theme.smallHeaderHeight}
top={props.top}
width={props.width}
zIndex={
Expand Down
3 changes: 2 additions & 1 deletion app/client/src/pages/AdminSettings/components.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import styled from "styled-components";
import { Classes } from "@blueprintjs/core";
import { Link, Text } from "@appsmith/ads";
import { IDE_HEADER_HEIGHT } from "IDE";

export const Wrapper = styled.div`
flex-basis: calc(100% - ${(props) => props.theme.homePage.leftPane.width}px);
Expand Down Expand Up @@ -37,7 +38,7 @@ export const BottomSpace = styled.div`
export const ContentWrapper = styled.div``;

export const LoaderContainer = styled.div`
height: ${(props) => `calc(100vh - ${props.theme.smallHeaderHeight})`};
height: calc(100vh - ${IDE_HEADER_HEIGHT}px);
display: flex;
justify-content: center;
width: 100%;
Expand Down
8 changes: 4 additions & 4 deletions app/client/src/pages/AppViewer/Navigation/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,12 @@ import {
StyledMenuContainer,
StyledSidebar,
} from "./Sidebar.styled";
import { getCurrentThemeDetails } from "selectors/themeSelectors";
import { getIsAppSettingsPaneWithNavigationTabOpen } from "selectors/appSettingsPaneSelectors";
import NavigationLogo from "ee/pages/AppViewer/NavigationLogo";
import MenuItemContainer from "./components/MenuItemContainer";
import BackToAppsButton from "./components/BackToAppsButton";
import { IDE_HEADER_HEIGHT } from "IDE";
import { BOTTOM_BAR_HEIGHT } from "components/BottomBar/constants";

interface SidebarProps {
currentApplicationDetails?: ApplicationPayload;
Expand Down Expand Up @@ -80,7 +81,6 @@ export function Sidebar(props: SidebarProps) {
const isPinned = useSelector(getAppSidebarPinned);
const [isOpen, setIsOpen] = useState(true);
const { x } = useMouse();
const theme = useSelector(getCurrentThemeDetails);
const isPreviewMode = useSelector(combinedPreviewModeSelector);
const isAppSettingsPaneWithNavigationTabOpen = useSelector(
getIsAppSettingsPaneWithNavigationTabOpen,
Expand Down Expand Up @@ -127,10 +127,10 @@ export function Sidebar(props: SidebarProps) {
const suffix = ")";

if (isPreviewMode) {
prefix += `${theme.smallHeaderHeight} - ${theme.bottomBarHeight}`;
prefix += `${IDE_HEADER_HEIGHT}px - ${BOTTOM_BAR_HEIGHT}px`;
} else if (isAppSettingsPaneWithNavigationTabOpen) {
// We deduct 64px as well since it is the margin coming from "m-8" class from tailwind
prefix += `${theme.smallHeaderHeight} - ${theme.bottomBarHeight} - 64px`;
prefix += `${IDE_HEADER_HEIGHT}px - ${BOTTOM_BAR_HEIGHT}px - 64px`;
} else {
prefix += "0px";
}
Expand Down
2 changes: 1 addition & 1 deletion app/client/src/pages/Editor/Canvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ const Canvas = (props: CanvasProps) => {
<Wrapper
$enableMainCanvasResizer={!!props.enableMainCanvasResizer}
background={isAnvilLayout ? "" : backgroundForCanvas}
className={`relative t--canvas-artboard ${paddingBottomClass} transition-all duration-400 ${marginHorizontalClass} ${getViewportClassName(
className={`relative t--canvas-artboard ${paddingBottomClass} ${marginHorizontalClass} ${getViewportClassName(
canvasWidth,
)}`}
data-testid={"t--canvas-artboard"}
Expand Down
Loading

0 comments on commit 60dbda4

Please sign in to comment.