@@ -5,7 +5,9 @@ import styled from '@emotion/styled';
55import { Button } from '@sentry/scraps/button/button' ;
66import { ButtonBar } from '@sentry/scraps/button/buttonBar' ;
77import { Flex } from '@sentry/scraps/layout' ;
8+ import { Text } from '@sentry/scraps/text/text' ;
89
10+ import { Alert } from 'sentry/components/core/alert' ;
911import Panel from 'sentry/components/panels/panel' ;
1012import BaseSearchBar from 'sentry/components/searchBar' ;
1113import { IconChevron } from 'sentry/icons/iconChevron' ;
@@ -142,75 +144,86 @@ export function AttributeDistribution() {
142144
143145 return (
144146 < Panel >
145- < Flex direction = "column" gap = "2xl" padding = "xl" >
146- < Fragment >
147- < ControlsContainer >
148- < StyledBaseSearchBar
149- placeholder = { t ( 'Search keys' ) }
150- onChange = { q => {
151- setSearchQuery ( q ) ;
152- } }
153- query = { debouncedSearchQuery }
154- size = "sm"
155- />
156- < AttributeBreakdownsComponent . FeedbackButton />
157- </ ControlsContainer >
158- { isAttributeBreakdownsLoading || isCohortCountLoading ? (
159- < AttributeBreakdownsComponent . LoadingCharts />
160- ) : error ? (
161- < AttributeBreakdownsComponent . ErrorState error = { error } />
162- ) : filteredAttributeDistribution . length > 0 ? (
163- < Fragment >
164- < ChartsGrid >
165- { filteredAttributeDistribution
166- . slice ( page * CHARTS_PER_PAGE , ( page + 1 ) * CHARTS_PER_PAGE )
167- . map ( attribute => (
168- < Chart
169- key = { attribute . name }
170- attributeDistribution = { attribute }
171- cohortCount = { cohortCount }
172- theme = { theme }
173- />
174- ) ) }
175- </ ChartsGrid >
176- < PaginationContainer >
177- < ButtonBar merged gap = "0" >
178- < Button
179- icon = { < IconChevron direction = "left" /> }
180- aria-label = { t ( 'Previous' ) }
181- size = "sm"
182- disabled = { page === 0 }
183- onClick = { ( ) => {
184- setPage ( page - 1 ) ;
185- } }
147+ < Flex direction = "column" gap = "xl" padding = "xl" >
148+ < ChartSelectionAlert />
149+ < ControlsContainer >
150+ < StyledBaseSearchBar
151+ placeholder = { t ( 'Search keys' ) }
152+ onChange = { q => {
153+ setSearchQuery ( q ) ;
154+ } }
155+ query = { debouncedSearchQuery }
156+ size = "sm"
157+ />
158+ < AttributeBreakdownsComponent . FeedbackButton />
159+ </ ControlsContainer >
160+ { isAttributeBreakdownsLoading || isCohortCountLoading ? (
161+ < AttributeBreakdownsComponent . LoadingCharts />
162+ ) : error ? (
163+ < AttributeBreakdownsComponent . ErrorState error = { error } />
164+ ) : filteredAttributeDistribution . length > 0 ? (
165+ < Fragment >
166+ < ChartsGrid >
167+ { filteredAttributeDistribution
168+ . slice ( page * CHARTS_PER_PAGE , ( page + 1 ) * CHARTS_PER_PAGE )
169+ . map ( attribute => (
170+ < Chart
171+ key = { attribute . name }
172+ attributeDistribution = { attribute }
173+ cohortCount = { cohortCount }
174+ theme = { theme }
186175 />
187- < Button
188- icon = { < IconChevron direction = "right" /> }
189- aria-label = { t ( 'Next' ) }
190- size = "sm"
191- disabled = {
192- page ===
193- Math . ceil (
194- ( filteredAttributeDistribution ?. length ?? 0 ) / CHARTS_PER_PAGE
195- ) -
196- 1
197- }
198- onClick = { ( ) => {
199- setPage ( page + 1 ) ;
200- } }
201- />
202- </ ButtonBar >
203- </ PaginationContainer >
204- </ Fragment >
205- ) : (
206- < AttributeBreakdownsComponent . EmptySearchState />
207- ) }
208- </ Fragment >
176+ ) ) }
177+ </ ChartsGrid >
178+ < PaginationContainer >
179+ < ButtonBar merged gap = "0" >
180+ < Button
181+ icon = { < IconChevron direction = "left" /> }
182+ aria-label = { t ( 'Previous' ) }
183+ size = "sm"
184+ disabled = { page === 0 }
185+ onClick = { ( ) => {
186+ setPage ( page - 1 ) ;
187+ } }
188+ />
189+ < Button
190+ icon = { < IconChevron direction = "right" /> }
191+ aria-label = { t ( 'Next' ) }
192+ size = "sm"
193+ disabled = {
194+ page ===
195+ Math . ceil (
196+ ( filteredAttributeDistribution ?. length ?? 0 ) / CHARTS_PER_PAGE
197+ ) -
198+ 1
199+ }
200+ onClick = { ( ) => {
201+ setPage ( page + 1 ) ;
202+ } }
203+ />
204+ </ ButtonBar >
205+ </ PaginationContainer >
206+ </ Fragment >
207+ ) : (
208+ < AttributeBreakdownsComponent . EmptySearchState />
209+ ) }
209210 </ Flex >
210211 </ Panel >
211212 ) ;
212213}
213214
215+ function ChartSelectionAlert ( ) {
216+ return (
217+ < Alert type = "info" >
218+ < Text >
219+ { t (
220+ 'Drag to select a region in the chart above and see how its breakdowns differ from the baseline.'
221+ ) }
222+ </ Text >
223+ </ Alert >
224+ ) ;
225+ }
226+
214227const ControlsContainer = styled ( 'div' ) `
215228 display: flex;
216229 gap: ${ space ( 0.5 ) } ;
0 commit comments