Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[core] feat: new SegmentedControl component #6454

Merged
merged 11 commits into from
Nov 10, 2023
2 changes: 2 additions & 0 deletions packages/core/src/common/classes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,8 @@ export const SPINNER_HEAD = `${SPINNER}-head`;
export const SPINNER_NO_SPIN = `${NS}-no-spin`;
export const SPINNER_TRACK = `${SPINNER}-track`;

export const SEGMENTED_CONTROL = `${NS}-segmented-control`;

export const TAB = `${NS}-tab`;
export const TAB_ICON = `${TAB}-icon`;
export const TAB_TAG = `${TAB}-tag`;
Expand Down
5 changes: 1 addition & 4 deletions packages/core/src/common/interactionMode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,7 @@
export class InteractionModeEngine {
private isRunning = false;

constructor(
private container: HTMLElement,
private className: string,
) {}
constructor(private container: HTMLElement, private className: string) {}

/** Returns whether the engine is currently running. */
public isActive() {
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/components/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
@import "portal/portal";
@import "progress-bar/progress-bar";
@import "section/section";
@import "segmented-control/segmented-control";
@import "skeleton/skeleton";
@import "slider/slider";
@import "spinner/spinner";
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/components/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
@page progress-bar
@page resize-sensor
@page section
@page segmented-control
@page skeleton
@page spinner
@page tabs
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export { MultiSlider, MultiSliderProps, SliderBaseProps } from "./slider/multiSl
export { NumberRange, RangeSlider, RangeSliderProps } from "./slider/rangeSlider";
export { Section, SectionElevation, SectionProps } from "./section/section";
export { SectionCard, SectionCardProps } from "./section/sectionCard";
export { SegmentedControl } from "./segmented-control/segmentedControl";
export { Slider, SliderProps } from "./slider/slider";
export { Spinner, SpinnerProps, SpinnerSize } from "./spinner/spinner";
export { SwitchCard, SwitchCardProps } from "./control-card/switchCard";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
@use "sass:math";
@import "../../common/variables";

.#{$ns}-segmented-control {
padding: $pt-grid-size * 0.5;
background-color: $light-gray5;

> .#{$ns}-button-group {
gap: $pt-grid-size * 0.5;
}

.#{$ns}-dark & {
background-color: $dark-gray4;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
tag: new
---

@# SegmentedControl

@reactExample SegmentedControlExample

@## Props interface

@interface SegmentedControlProps
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Copyright 2023 Palantir Technologies, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import classNames from "classnames";
import * as React from "react";
import { ButtonGroup } from "../button/buttonGroup";
import { Button } from "../button/buttons";

import { Classes, Intent } from "../../common";
import { DISPLAYNAME_PREFIX, HTMLDivProps, Props } from "../../common/props";

export interface SegmentedControlProps extends Props, HTMLDivProps, React.RefAttributes<HTMLDivElement> {
options: {
id: string;
label: string;
}[];
defaultActiveOptionIds?: string[];
onActiveOptionsChange?: (activeOptionIds: string[]) => void;
intent?: typeof Intent.NONE | typeof Intent.PRIMARY;
}

/**
* Segmented control component.
*
* @see https://blueprintjs.com/docs/#core/components/segmented-control
*/
export const SegmentedControl: React.FC<SegmentedControlProps> = React.forwardRef((props, ref) => {
const { className, options, defaultActiveOptionIds, intent, onActiveOptionsChange, ...htmlProps } = props;
const classes = classNames(Classes.SEGMENTED_CONTROL, className);

const [activeOptionIds, setActiveOptionIds] = React.useState<string[]>(defaultActiveOptionIds ?? []);

const handleButtonClick = React.useCallback(
(optionId: string) => () => {
const optionIndex = activeOptionIds.indexOf(optionId);

if (optionIndex === -1) {
setActiveOptionIds([...activeOptionIds, optionId]);
} else {
setActiveOptionIds(activeOptionIds.splice(optionIndex, 1));
}

if (onActiveOptionsChange != null) {
onActiveOptionsChange(activeOptionIds);
}
},
[activeOptionIds, onActiveOptionsChange],
);

return (
<div className={classes} ref={ref} {...htmlProps}>
<ButtonGroup>
{options.map(({ id, label }) => {
const active = activeOptionIds?.includes(id);

return (
<Button
onClick={handleButtonClick(id)}
intent={active ? intent : Intent.NONE}
minimal={!active}
key={id}
>
{label}
</Button>
);
})}
</ButtonGroup>
</div>
);
});
SegmentedControl.defaultProps = {
defaultActiveOptionIds: undefined,
intent: Intent.NONE,
};
SegmentedControl.displayName = `${DISPLAYNAME_PREFIX}.SegmentedControl`;
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@
export class Oscillator {
public oscillator: OscillatorNode;

public constructor(
private context: AudioContext,
freq: number,
) {
public constructor(private context: AudioContext, freq: number) {
adidahiya marked this conversation as resolved.
Show resolved Hide resolved
this.oscillator = this.context.createOscillator();
this.oscillator.type = "sine";
this.oscillator.frequency.value = freq;
Expand Down
1 change: 1 addition & 0 deletions packages/docs-app/src/examples/core-examples/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export * from "./popoverSizingExample";
export * from "./progressExample";
export * from "./rangeSliderExample";
export * from "./radioExample";
export * from "./segmentedControlExample";
export * from "./sectionExample";
export * from "./sliderExample";
export * from "./switchExample";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2023 Palantir Technologies, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import * as React from "react";

import { SegmentedControl } from "@blueprintjs/core";
import { Example, ExampleProps } from "@blueprintjs/docs-theme";

export interface SegmentedControlState {}

export class SegmentedControlExample extends React.PureComponent<ExampleProps, SegmentedControlState> {
public state: SegmentedControlState = {};

public render() {
const {} = this.state;

const options = <></>;

return (
<Example options={options} {...this.props}>
<SegmentedControl
options={[
{
id: "test",
label: "Test",
},
]}
/>
</Example>
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,7 @@ export interface SortableColumn {
}

abstract class AbstractSortableColumn implements SortableColumn {
constructor(
protected name: string,
protected index: number,
) {}
constructor(protected name: string, protected index: number) {}

public getColumn(getCellData: CellLookup, sortColumn: SortCallback) {
const cellRenderer = (rowIndex: number, columnIndex: number) => (
Expand Down
2 changes: 1 addition & 1 deletion packages/docs-theme/src/common/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export interface DocumentationContextApi {
}

export const DocumentationContext = React.createContext<DocumentationContextApi>({
getDocsData: () => ({}) as DocsData,
getDocsData: () => ({} as DocsData),
renderBlock: (_block: IBlock) => undefined,
renderType: (type: string) => type,
renderViewSourceLinkText: (entry: ITsDocBase) => entry.sourceUrl,
Expand Down
28 changes: 5 additions & 23 deletions packages/landing-app/src/logo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,7 @@ export class Quaternion {

private static POOL = new Quaternion();

public constructor(
public x = 0,
public y = 0,
public z = 0,
public w = 0,
) {}
public constructor(public x = 0, public y = 0, public z = 0, public w = 0) {}

public copy() {
return new Quaternion(this.x, this.y, this.z, this.w);
Expand Down Expand Up @@ -210,11 +205,7 @@ export class Quaternion {
export class Point extends Transformable<Point> {
private static POOL = new Point();

public constructor(
public x = 0,
public y = 0,
public z = 0,
) {
public constructor(public x = 0, public y = 0, public z = 0) {
super();
}

Expand Down Expand Up @@ -458,10 +449,7 @@ export class Corner extends Transformable<Corner> {

public projectedCenter: Point;

public constructor(
public segments: Segment[],
public center: Point,
) {
public constructor(public segments: Segment[], public center: Point) {
super();
}

Expand Down Expand Up @@ -594,10 +582,7 @@ export class Accumulator implements Tickable {

public value: number;

public constructor(
public target: number,
public callback?: AnimatedCallback,
) {
public constructor(public target: number, public callback?: AnimatedCallback) {
this.value = this.target;
}

Expand Down Expand Up @@ -883,10 +868,7 @@ class BackgroundRenderer extends CanvasRenderer {
}

export class SceneRenderer extends CanvasRenderer {
public constructor(
ctx: CanvasRenderingContext2D,
private scene: SceneModel,
) {
public constructor(ctx: CanvasRenderingContext2D, private scene: SceneModel) {
super(ctx);
}

Expand Down
5 changes: 1 addition & 4 deletions packages/table-dev-app/src/localStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,7 @@ import defaults from "lodash/defaults";
export class LocalStore<T extends {}> {
private storage: Storage;

constructor(
private key: string,
session = false,
) {
constructor(private key: string, session = false) {
this.storage = session ? sessionStorage : localStorage;
}

Expand Down
6 changes: 1 addition & 5 deletions packages/table-dev-app/src/sparseGridMutableStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,7 @@ class GridEntry<T> {
return `${i}_${j}`;
}

public constructor(
public i: number,
public j: number,
public value: T,
) {}
public constructor(public i: number, public j: number, public value: T) {}

// there are two things here called `key` but they're certainly not overloaded (one being static)
// TSLint bug report: https://github.com/palantir/tslint/issues/2139
Expand Down
7 changes: 1 addition & 6 deletions packages/table/src/common/rect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,7 @@ export class Rect {
}
}

public constructor(
public left: number,
public top: number,
public width: number,
public height: number,
) {}
public constructor(public left: number, public top: number, public width: number, public height: number) {}

public subtractOrigin(anyRect: AnyRect) {
return Rect.subtractOrigin(this, anyRect);
Expand Down
6 changes: 1 addition & 5 deletions packages/table/src/tableHotkeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,7 @@ export interface TableHandlers {
export class TableHotkeys {
private grid?: Grid;

public constructor(
private props: TableProps,
private state: TableState,
private tableHandlers: TableHandlers,
) {
public constructor(private props: TableProps, private state: TableState, private tableHandlers: TableHandlers) {
// no-op
}

Expand Down