Browse Source

feat(insights): allow insight charts to be expanded (#74467)

Adds a full-screen button to insight charts to allow users to view in
full-screen.

<img width="1502" alt="image"
src="https://github.com/user-attachments/assets/0e0c7a07-ab2f-42c1-9d4c-6e94cbf00a13">
<img width="1507" alt="image"
src="https://github.com/user-attachments/assets/2071809b-26c1-4b7c-be1d-8aea756ccd9f">

---------

Co-authored-by: Dominik Buszowiecki <44422760+DominikB2014@users.noreply.github.com>
Kevin Liu 7 months ago
parent
commit
bd55f6a7dc

+ 8 - 0
static/app/actionCreators/modal.tsx

@@ -4,6 +4,7 @@ import type {ModalTypes} from 'sentry/components/globalModal';
 import type {CreateNewIntegrationModalOptions} from 'sentry/components/modals/createNewIntegrationModal';
 import type {CreateReleaseIntegrationModalOptions} from 'sentry/components/modals/createReleaseIntegrationModal';
 import type {DashboardWidgetQuerySelectorModalOptions} from 'sentry/components/modals/dashboardWidgetQuerySelectorModal';
+import type {InsightChartModalOptions} from 'sentry/components/modals/insightChartModal';
 import type {InviteRow} from 'sentry/components/modals/inviteMembersModal/types';
 import type {ReprocessEventModalOptions} from 'sentry/components/modals/reprocessEventModal';
 import type {OverwriteWidgetModalProps} from 'sentry/components/modals/widgetBuilder/overwriteWidgetModal';
@@ -394,3 +395,10 @@ export async function openBulkEditMonitorsModal({onClose, ...options}: ModalOpti
 
   openModal(deps => <Modal {...deps} {...options} />, {modalCss, onClose});
 }
+
+export async function openInsightChartModal(options: InsightChartModalOptions) {
+  const mod = await import('sentry/components/modals/insightChartModal');
+  const {default: Modal, modalCss} = mod;
+
+  openModal(deps => <Modal {...deps} {...options} />, {modalCss});
+}

+ 39 - 0
static/app/components/modals/insightChartModal.tsx

@@ -0,0 +1,39 @@
+import type React from 'react';
+import {Fragment} from 'react';
+import {css} from '@emotion/react';
+import styled from '@emotion/styled';
+
+import type {ModalRenderProps} from 'sentry/actionCreators/modal';
+import {space} from 'sentry/styles/space';
+import {ChartHeightContext} from 'sentry/views/insights/common/components/chart';
+
+export type InsightChartModalOptions = {
+  children: React.ReactNode;
+  title: React.ReactNode;
+};
+type Props = ModalRenderProps & InsightChartModalOptions;
+
+export default function InsightChartModal({Header, title, children}: Props) {
+  return (
+    <Fragment>
+      <Container>
+        <Header closeButton>
+          <h3>{title}</h3>
+        </Header>
+
+        <ChartHeightContext.Provider value={300}>{children}</ChartHeightContext.Provider>
+      </Container>
+    </Fragment>
+  );
+}
+
+const Container = styled('div')<{height?: number | null}>`
+  height: ${p => (p.height ? `${p.height}px` : 'auto')};
+  position: relative;
+  padding-bottom: ${space(3)};
+`;
+
+export const modalCss = css`
+  width: 100%;
+  max-width: 1200px;
+`;

+ 6 - 2
static/app/views/insights/common/components/chart.tsx

@@ -1,5 +1,5 @@
 import type {RefObject} from 'react';
-import {useEffect, useMemo, useRef, useState} from 'react';
+import {createContext, useContext, useEffect, useMemo, useRef, useState} from 'react';
 import {useTheme} from '@emotion/react';
 import styled from '@emotion/styled';
 import type {LineSeriesOption} from 'echarts';
@@ -63,6 +63,8 @@ export enum ChartType {
   AREA = 2,
 }
 
+export const ChartHeightContext = createContext<number | undefined>(undefined);
+
 type Props = {
   data: Series[];
   loading: boolean;
@@ -107,7 +109,7 @@ function Chart({
   dataMax,
   previousData,
   loading,
-  height,
+  height: chartHeight,
   grid,
   disableXAxis,
   definedAxisTicks,
@@ -143,6 +145,8 @@ function Chart({
   const pageFilters = usePageFilters();
   const {start, end, period, utc} = pageFilters.selection.datetime;
 
+  const height = useContext(ChartHeightContext) ?? chartHeight;
+
   const defaultRef = useRef<ReactEchartsRef>(null);
   const chartRef = forwardedRef || defaultRef;
 

+ 13 - 1
static/app/views/insights/common/components/chartPanel.tsx

@@ -1,6 +1,10 @@
 import styled from '@emotion/styled';
 
+import {openInsightChartModal} from 'sentry/actionCreators/modal';
+import {Button} from 'sentry/components/button';
 import Panel from 'sentry/components/panels/panel';
+import {IconExpand} from 'sentry/icons';
+import {t} from 'sentry/locale';
 import {space} from 'sentry/styles/space';
 import {Subtitle} from 'sentry/views/performance/landing/widgets/widgets/singleFieldAreaWidget';
 
@@ -27,6 +31,15 @@ export default function ChartPanel({title, children, button, subtitle}: Props) {
               </ChartLabel>
             )}
             {button}
+            <Button
+              aria-label={t('Expand Insight Chart')}
+              borderless
+              size="xs"
+              icon={<IconExpand />}
+              onClick={() => {
+                openInsightChartModal({title, children});
+              }}
+            />
           </Header>
         )}
         {subtitle && (
@@ -61,7 +74,6 @@ const PanelBody = styled('div')`
 `;
 
 const Header = styled('div')`
-  padding: 0 ${space(1)} 0 0;
   width: 100%;
   display: flex;
   align-items: center;