diff --git a/static/app/components/core/compactSelect/composite.mdx b/static/app/components/core/compactSelect/composite.mdx index 55f9b2a1126477..94c4a9045cdb45 100644 --- a/static/app/components/core/compactSelect/composite.mdx +++ b/static/app/components/core/compactSelect/composite.mdx @@ -53,6 +53,7 @@ Use `` when you need a dropdown with multiple independent selec - **``**: The wrapper component that manages the dropdown - **``**: Individual selection sections within the dropdown +- **``**: A "Clear" button for use in `menuHeaderTrailingItems` that calls your `onClick` to reset all regions. Re-exported from ``'s internal clear button for visual consistency Each region acts like an independent ``, requiring its own `value`, `onChange`, and `options`. @@ -124,6 +125,102 @@ const [day, setDay] = useState('1'); ; ``` +## Clear Button + +Use `` in `menuHeaderTrailingItems` to add a "Clear" button to the menu header. When clicked, it calls your `onClick` handler where you reset each region's value. The menu stays open, matching the behavior of the built-in clear button in ``. The component is the same styled button used internally by ``, ensuring visual consistency. + +Only render the button when there is an active selection to clear. + +export function ClearButtonDemo() { + const monthOptions = [ + {value: 'jan', label: 'January'}, + {value: 'feb', label: 'February'}, + {value: 'mar', label: 'March'}, + ]; + const tagOptions = [ + {value: 'cool', label: 'cool'}, + {value: 'funny', label: 'funny'}, + {value: 'awesome', label: 'awesome'}, + ]; + const [month, setMonth] = useState(''); + const [tags, setTags] = useState(tagOptions.slice(0, 0).map(o => o.value)); + const hasSelection = month !== '' || tags.length > 0; + return ( + { + setMonth(''); + setTags([]); + }} + /> + ) : null + } + trigger={props => ( + } {...props}> + Filters + + )} + > + setMonth(selection.value)} + options={monthOptions} + /> + setTags(selection.map(s => s.value))} + options={tagOptions} + /> + + ); +} + + + + + +```jsx +const [month, setMonth] = useState(null); +const [tags, setTags] = useState([]); +const hasSelection = month !== null || tags.length > 0; + + { + setMonth(null); + setTags([]); + }} + /> + ) : null + } + trigger={props => Filters} +> + setMonth(selection.value)} + options={monthOptions} + /> + setTags(selection.map(s => s.value))} + options={tagOptions} + /> +; +``` + ## Multi-Select Regions Individual regions can enable multi-select by setting the `multiple` prop. This allows mixing single and multi-select behavior within the same dropdown. diff --git a/static/app/components/core/compactSelect/composite.tsx b/static/app/components/core/compactSelect/composite.tsx index 7d67012bf994f7..34ea6b5ce98abf 100644 --- a/static/app/components/core/compactSelect/composite.tsx +++ b/static/app/components/core/compactSelect/composite.tsx @@ -4,10 +4,12 @@ import {FocusScope} from '@react-aria/focus'; import {Item} from '@react-stately/collections'; import type {DistributedOmit} from 'type-fest'; +import {type ButtonProps} from '@sentry/scraps/button'; + import {t} from 'sentry/locale'; +import {ClearButton, Control} from './control'; import type {ControlProps} from './control'; -import {Control} from './control'; import type {MultipleListProps, SingleListProps} from './list'; import {List} from './list'; import {EmptyMessage} from './styles'; @@ -118,6 +120,16 @@ CompositeSelect.Region = function ( return null; }; +CompositeSelect.ClearButton = function CompositeSelectClearButton( + props: DistributedOmit +) { + return ( + + {t('Clear')} + + ); +}; + export {CompositeSelect}; type RegionProps = CompositeSelectRegion & { diff --git a/static/app/components/core/compactSelect/control.tsx b/static/app/components/core/compactSelect/control.tsx index 493efbef4a61c2..bc99eecc9b20f2 100644 --- a/static/app/components/core/compactSelect/control.tsx +++ b/static/app/components/core/compactSelect/control.tsx @@ -643,7 +643,7 @@ const StyledLoadingIndicator = styled(LoadingIndicator)` } `; -const ClearButton = styled(Button)` +export const ClearButton = styled(Button)` font-size: inherit; /* Inherit font size from MenuHeader */ font-weight: ${p => p.theme.font.weight.sans.regular}; color: ${p => p.theme.tokens.content.secondary}; diff --git a/static/app/views/explore/metrics/metricToolbar/aggregateDropdown.tsx b/static/app/views/explore/metrics/metricToolbar/aggregateDropdown.tsx index d308eea86c3bef..ab1dc14f95dd1a 100644 --- a/static/app/views/explore/metrics/metricToolbar/aggregateDropdown.tsx +++ b/static/app/views/explore/metrics/metricToolbar/aggregateDropdown.tsx @@ -48,10 +48,18 @@ export function AggregateDropdown({traceMetric}: {traceMetric: TraceMetric}) { } const selectedList = [...selectedNames].filter(Boolean); + const defaultValue = DEFAULT_YAXIS_BY_TYPE[traceMetric.type]; + const isDefaultSelection = + selectedList.length === 1 && selectedList[0] === defaultValue; return ( handleChange([])} /> + } style={{width: '100%'}} trigger={triggerProps => ( >) => handleChange(opts)} + onChange={handleChange} /> ); } @@ -100,10 +108,10 @@ export function AggregateDropdown({traceMetric}: {traceMetric: TraceMetric}) { return ( ) => handleChange([opt])} + value={activeValues[0]} + onChange={opt => handleChange([opt])} /> ); })}