From ba5dcd472283ff5037c24b66acf52bfdb9b47e83 Mon Sep 17 00:00:00 2001 From: Blake Vandercar Date: Mon, 23 Sep 2024 18:11:36 -0600 Subject: [PATCH 1/5] feat(SegmentedControl): compact prop, custom button styling prop --- .../segmented-control/_segmented-control.scss | 7 ++- .../segmented-control/segmentedControl.tsx | 54 +++++++++++++++---- .../core-examples/segmentedControlExample.tsx | 5 +- 3 files changed, 53 insertions(+), 13 deletions(-) diff --git a/packages/core/src/components/segmented-control/_segmented-control.scss b/packages/core/src/components/segmented-control/_segmented-control.scss index e6b083f931..da52f674a1 100644 --- a/packages/core/src/components/segmented-control/_segmented-control.scss +++ b/packages/core/src/components/segmented-control/_segmented-control.scss @@ -8,6 +8,11 @@ gap: 3px; padding: 3px; + &.#{$ns}-compact { + gap: 0px; + padding: 0px; + } + &.#{$ns}-inline { display: inline-flex; } @@ -20,7 +25,7 @@ } } - > .#{$ns}-button:not(.#{$ns}-minimal) { + > .#{$ns}-button.#{$ns}-selected { &:not(.#{$ns}-intent-primary) { background-color: $white; diff --git a/packages/core/src/components/segmented-control/segmentedControl.tsx b/packages/core/src/components/segmented-control/segmentedControl.tsx index ee48c4d4bb..add16a5f73 100644 --- a/packages/core/src/components/segmented-control/segmentedControl.tsx +++ b/packages/core/src/components/segmented-control/segmentedControl.tsx @@ -30,6 +30,8 @@ import { Button } from "../button/buttons"; export type SegmentedControlIntent = typeof Intent.NONE | typeof Intent.PRIMARY; +type SegmentedControlButtonProps = Pick; + /** * SegmentedControl component props. */ @@ -37,6 +39,13 @@ export interface SegmentedControlProps extends Props, ControlledValueProps, React.RefAttributes { + /** + * Whether the control should use compact styles. + * + * @default false + */ + compact?: boolean; + /** * Whether the control should take up the full width of its container. * @@ -66,6 +75,27 @@ export interface SegmentedControlProps */ options: Array>; + /** + * Style props for the button elements. + */ + buttonProps?: { + /** + * Props applied to selected button + * @default { className: 'bp5-selected' } + */ + selected?: SegmentedControlButtonProps; + /** + * Props applied to non-selected buttons + * @default { className: 'bp5-minimal' } + */ + nonSelected?: SegmentedControlButtonProps; + /** + * Props applied to all buttons (selected and non-selected) + * @default undefined + */ + all?: SegmentedControlButtonProps; + }; + /** * Aria role for the overall component. Child buttons get appropriate roles. * @@ -90,7 +120,9 @@ export interface SegmentedControlProps */ export const SegmentedControl: React.FC = React.forwardRef((props, ref) => { const { + buttonProps, className, + compact, defaultValue, fill, inline, @@ -122,7 +154,7 @@ export const SegmentedControl: React.FC = React.forwardRe if (role === "radiogroup") { // in a `radiogroup`, arrow keys select next item, not tab key. const direction = Utils.getArrowKeyDirection(e, ["ArrowLeft", "ArrowUp"], ["ArrowRight", "ArrowDown"]); - const { current: outerElement } = outerRef; + const outerElement = outerRef.current; if (direction === undefined || !outerElement) return; const focusedElement = Utils.getActiveElement(outerElement)?.closest("button"); @@ -148,6 +180,8 @@ export const SegmentedControl: React.FC = React.forwardRe ); const classes = classNames(Classes.SEGMENTED_CONTROL, className, { + [Classes.COMPACT]: compact, + [Classes.BUTTON_GROUP]: compact, [Classes.FILL]: fill, [Classes.INLINE]: inline, }); @@ -166,9 +200,12 @@ export const SegmentedControl: React.FC = React.forwardRe const isSelected = selectedValue === option.value; return ( , - Pick, - Pick, - React.AriaAttributes { - isSelected: boolean; +interface SegmentedControlOptionProps extends OptionProps, Omit { onClick: (value: string, targetElement: HTMLElement) => void; } -function SegmentedControlOption({ isSelected, label, onClick, value, ...buttonProps }: SegmentedControlOptionProps) { +function SegmentedControlOption({ label, onClick, value, ...buttonProps }: SegmentedControlOptionProps) { const handleClick = React.useCallback( (event: React.MouseEvent) => onClick?.(value, event.currentTarget), [onClick, value], ); - return