Fix widget header shrink and make widget placeholder to change state on click (#14999)
closes closes https://github.com/twentyhq/core-team-issues/issues/1609
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
import { useNavigatePageLayoutCommandMenu } from '@/command-menu/pages/page-layout/hooks/useNavigatePageLayoutCommandMenu';
|
||||
import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
|
||||
import { PageLayoutGridLayoutDragSelector } from '@/page-layout/components/PageLayoutGridLayoutDragSelector';
|
||||
import { PageLayoutGridOverlay } from '@/page-layout/components/PageLayoutGridOverlay';
|
||||
import { EMPTY_LAYOUT } from '@/page-layout/constants/EmptyLayout';
|
||||
@@ -75,8 +73,6 @@ export const PageLayoutGridLayout = () => {
|
||||
|
||||
const activeTabId = useRecoilComponentValue(activeTabIdComponentState);
|
||||
|
||||
const { navigatePageLayoutCommandMenu } = useNavigatePageLayoutCommandMenu();
|
||||
|
||||
const { currentPageLayout } = useCurrentPageLayout();
|
||||
|
||||
if (!isDefined(activeTabId) || !isDefined(currentPageLayout)) {
|
||||
@@ -128,14 +124,7 @@ export const PageLayoutGridLayout = () => {
|
||||
>
|
||||
{isLayoutEmpty ? (
|
||||
<div key="empty-placeholder" data-select-disable="true">
|
||||
<WidgetPlaceholder
|
||||
onClick={() => {
|
||||
navigatePageLayoutCommandMenu({
|
||||
commandMenuPage:
|
||||
CommandMenuPages.PageLayoutWidgetTypeSelect,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<WidgetPlaceholder />
|
||||
</div>
|
||||
) : (
|
||||
activeTabWidgets?.map((widget) => (
|
||||
|
||||
@@ -6,6 +6,8 @@ const StyledHeader = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
height: ${({ theme }) => theme.spacing(6)};
|
||||
flex-shrink: 0;
|
||||
`;
|
||||
|
||||
const StyledDragHandleButton = styled(IconButton)`
|
||||
|
||||
+39
-8
@@ -1,5 +1,14 @@
|
||||
import { useNavigatePageLayoutCommandMenu } from '@/command-menu/pages/page-layout/hooks/useNavigatePageLayoutCommandMenu';
|
||||
import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
|
||||
import { useSetIsDashboardInEditMode } from '@/dashboards/hooks/useSetDashboardInEditMode';
|
||||
import { PageLayoutComponentInstanceContext } from '@/page-layout/states/contexts/PageLayoutComponentInstanceContext';
|
||||
import { isPageLayoutInEditModeComponentState } from '@/page-layout/states/isPageLayoutInEditModeComponentState';
|
||||
import { WidgetContainer } from '@/page-layout/widgets/components/WidgetContainer';
|
||||
import { WidgetHeader } from '@/page-layout/widgets/components/WidgetHeader';
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import {
|
||||
AnimatedPlaceholder,
|
||||
AnimatedPlaceholderEmptyContainer,
|
||||
@@ -9,14 +18,36 @@ import {
|
||||
EMPTY_PLACEHOLDER_TRANSITION_PROPS,
|
||||
} from 'twenty-ui/layout';
|
||||
|
||||
type WidgetPlaceholderProps = {
|
||||
onClick: () => void;
|
||||
};
|
||||
export const WidgetPlaceholder = () => {
|
||||
const pageLayoutId = useAvailableComponentInstanceIdOrThrow(
|
||||
PageLayoutComponentInstanceContext,
|
||||
);
|
||||
|
||||
const isPageLayoutInEditMode = useRecoilComponentValue(
|
||||
isPageLayoutInEditModeComponentState,
|
||||
);
|
||||
|
||||
const { setIsDashboardInEditMode } =
|
||||
useSetIsDashboardInEditMode(pageLayoutId);
|
||||
|
||||
const { navigatePageLayoutCommandMenu } = useNavigatePageLayoutCommandMenu();
|
||||
|
||||
const handleClick = () => {
|
||||
if (!isPageLayoutInEditMode) {
|
||||
setIsDashboardInEditMode(true);
|
||||
}
|
||||
navigatePageLayoutCommandMenu({
|
||||
commandMenuPage: CommandMenuPages.PageLayoutWidgetTypeSelect,
|
||||
});
|
||||
};
|
||||
|
||||
export const WidgetPlaceholder = ({ onClick }: WidgetPlaceholderProps) => {
|
||||
return (
|
||||
<WidgetContainer onClick={onClick}>
|
||||
<WidgetHeader isInEditMode={true} title="Add Widget" isEmpty />
|
||||
<WidgetContainer onClick={handleClick}>
|
||||
<WidgetHeader
|
||||
isInEditMode={isPageLayoutInEditMode}
|
||||
title={t`Add Widget`}
|
||||
isEmpty
|
||||
/>
|
||||
<AnimatedPlaceholderEmptyContainer
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
{...EMPTY_PLACEHOLDER_TRANSITION_PROPS}
|
||||
@@ -24,10 +55,10 @@ export const WidgetPlaceholder = ({ onClick }: WidgetPlaceholderProps) => {
|
||||
<AnimatedPlaceholder type="noWidgets" />
|
||||
<AnimatedPlaceholderEmptyTextContainer>
|
||||
<AnimatedPlaceholderEmptyTitle>
|
||||
No widgets yet
|
||||
<Trans>No widgets yet</Trans>
|
||||
</AnimatedPlaceholderEmptyTitle>
|
||||
<AnimatedPlaceholderEmptySubTitle>
|
||||
Click to add your first widget
|
||||
<Trans>Click to add your first widget</Trans>
|
||||
</AnimatedPlaceholderEmptySubTitle>
|
||||
</AnimatedPlaceholderEmptyTextContainer>
|
||||
</AnimatedPlaceholderEmptyContainer>
|
||||
|
||||
+24
-17
@@ -1,48 +1,55 @@
|
||||
import { isAppWaitingForFreshObjectMetadataState } from '@/object-metadata/states/isAppWaitingForFreshObjectMetadataState';
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { PageLayoutTestWrapper } from '@/page-layout/hooks/__tests__/PageLayoutTestWrapper';
|
||||
import { WidgetPlaceholder } from '@/page-layout/widgets/components/WidgetPlaceholder';
|
||||
import { type Meta, type StoryObj } from '@storybook/react';
|
||||
import { type MutableSnapshot } from 'recoil';
|
||||
import { ComponentDecorator } from 'twenty-ui/testing';
|
||||
import { I18nFrontDecorator } from '~/testing/decorators/I18nFrontDecorator';
|
||||
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
|
||||
|
||||
const meta: Meta<typeof WidgetPlaceholder> = {
|
||||
title: 'Modules/PageLayout/Widgets/WidgetPlaceholder',
|
||||
component: WidgetPlaceholder,
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<PageLayoutTestWrapper>
|
||||
<Story />
|
||||
</PageLayoutTestWrapper>
|
||||
),
|
||||
(Story) => {
|
||||
const initializeState = (snapshot: MutableSnapshot) => {
|
||||
snapshot.set(
|
||||
objectMetadataItemsState,
|
||||
generatedMockObjectMetadataItems,
|
||||
);
|
||||
snapshot.set(isAppWaitingForFreshObjectMetadataState, false);
|
||||
};
|
||||
|
||||
return (
|
||||
<PageLayoutTestWrapper initializeState={initializeState}>
|
||||
<Story />
|
||||
</PageLayoutTestWrapper>
|
||||
);
|
||||
},
|
||||
ComponentDecorator,
|
||||
I18nFrontDecorator,
|
||||
],
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
'A placeholder widget that appears when no widgets are present. Shows an empty state with a call-to-action to add the first widget.',
|
||||
'A self-contained placeholder widget that appears when no widgets are present. Automatically enables edit mode when clicked and opens the widget type selection command menu.',
|
||||
},
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
onClick: {
|
||||
action: 'onClick',
|
||||
description:
|
||||
'Callback function triggered when the placeholder is clicked',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof WidgetPlaceholder>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
onClick: () => {},
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story: 'Default widget placeholder state.',
|
||||
story:
|
||||
'Default widget placeholder state. Click to trigger the add widget flow.',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user