diff --git a/packages/core/src/common/_variables-extended.scss b/packages/core/src/common/_variables-extended.scss index d7b5f7debd..cbc44bc310 100644 --- a/packages/core/src/common/_variables-extended.scss +++ b/packages/core/src/common/_variables-extended.scss @@ -22,3 +22,18 @@ $icon-classes: ( ".#{$ns}-icon-standard", ".#{$ns}-icon-large" ) !default; + +$elevation-shadows: ( + $pt-elevation-shadow-0 + $pt-elevation-shadow-1 + $pt-elevation-shadow-2 + $pt-elevation-shadow-3 + $pt-elevation-shadow-4 +); +$dark-elevation-shadows: ( + $pt-dark-elevation-shadow-0 + $pt-dark-elevation-shadow-1 + $pt-dark-elevation-shadow-2 + $pt-dark-elevation-shadow-3 + $pt-dark-elevation-shadow-4 +); diff --git a/packages/core/src/common/classes.ts b/packages/core/src/common/classes.ts index 9fc2f20f1b..dba6993746 100644 --- a/packages/core/src/common/classes.ts +++ b/packages/core/src/common/classes.ts @@ -113,6 +113,9 @@ export const CALLOUT_HAS_BODY_CONTENT = `${CALLOUT}-has-body-content`; export const CALLOUT_ICON = `${CALLOUT}-icon`; export const CARD = `${NS}-card`; +export const CONTROL_CARD = `${NS}-control-card`; +export const CONTROL_CARD_LABEL = `${CONTROL_CARD}-label`; +export const SWITCH_CONTROL_CARD = `${NS}-switch-control-card`; export const CARD_LIST = `${NS}-card-list`; export const CARD_LIST_BORDERED = `${CARD_LIST}-bordered`; diff --git a/packages/core/src/components/_index.scss b/packages/core/src/components/_index.scss index 43483c3ba9..24052e90a6 100644 --- a/packages/core/src/components/_index.scss +++ b/packages/core/src/components/_index.scss @@ -10,6 +10,7 @@ @import "card-list/card-list"; @import "collapse/collapse"; @import "context-menu/context-menu"; +@import "control-card/control-card"; @import "divider/divider"; @import "dialog/dialog"; @import "dialog/dialog-body"; diff --git a/packages/core/src/components/card-list/card-list.scss b/packages/core/src/components/card-list/card-list.scss index f368d5a723..bd09298813 100644 --- a/packages/core/src/components/card-list/card-list.scss +++ b/packages/core/src/components/card-list/card-list.scss @@ -1,14 +1,7 @@ -@import "../../common/variables"; +// Copyright 2023 Palantir Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. -$card-list-border-width: 1px !default; - -// N.B. min-height is calculated as height of a button + vertical padding. We need to add an extra pixel to account for -// the bottom border. -$card-list-item-default-min-height: ($pt-grid-size * 5) + $card-list-border-width !default; -$card-list-item-default-padding: $pt-grid-size (2 * $pt-grid-size) !default; - -$card-list-item-small-min-height: ($pt-grid-size * 4) + $card-list-border-width !default; -$card-list-item-small-padding: 7px 15px !default; +@import "../card/card-variables"; .#{$ns}-card-list { overflow: auto; @@ -20,8 +13,8 @@ $card-list-item-small-padding: 7px 15px !default; border-radius: 0; box-shadow: none; display: flex; - min-height: $card-list-item-default-min-height; - padding: $card-list-item-default-padding; + min-height: $card-list-item-min-height; + padding: $card-list-item-padding; &.#{$ns}-interactive:hover, &.#{$ns}-interactive:active { @@ -43,8 +36,8 @@ $card-list-item-small-padding: 7px 15px !default; } &.#{$ns}-compact > .#{$ns}-card { - min-height: $card-list-item-small-min-height; - padding: $card-list-item-small-padding; + min-height: $card-list-item-min-height-compact; + padding: $card-list-item-padding-compact; } .#{$ns}-dark & { diff --git a/packages/core/src/components/card-list/cardList.tsx b/packages/core/src/components/card-list/cardList.tsx index 2809e661ca..cba972bff1 100644 --- a/packages/core/src/components/card-list/cardList.tsx +++ b/packages/core/src/components/card-list/cardList.tsx @@ -56,6 +56,7 @@ export const CardList: React.FC = React.forwardRef((props, ref) = ); }); CardList.defaultProps = { + bordered: true, compact: false, }; CardList.displayName = `${DISPLAYNAME_PREFIX}.CardList`; diff --git a/packages/core/src/components/card/_card-variables.scss b/packages/core/src/components/card/_card-variables.scss new file mode 100644 index 0000000000..ed22b186b9 --- /dev/null +++ b/packages/core/src/components/card/_card-variables.scss @@ -0,0 +1,30 @@ +// Copyright 2023 Palantir Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. + +@import "../../common/variables-extended"; + +$card-padding: $pt-grid-size * 2 !default; +$card-padding-compact: $pt-grid-size * 1.5 !default; + +$card-background-color: $white !default; +$dark-card-background-color: $dark-gray3 !default; + +$card-list-border-width: 1px !default; + +// stylelint-disable max-line-length + +// CardList Card item min-height is calculated as height of a button + vertical padding. +// We need to add an extra pixel to account for the bottom border. +$card-list-item-padding-vertical: $pt-grid-size !default; +$card-list-item-min-height: $pt-button-height + ($card-list-item-padding-vertical * 2) + $card-list-border-width !default; +$card-list-item-padding: $card-list-item-padding-vertical $card-padding !default; + +$card-list-item-padding-vertical-compact: 7px !default; +$card-list-item-min-height-compact: $pt-button-height + ($card-list-item-padding-vertical-compact * 2) + $card-list-border-width !default; +$card-list-item-padding-compact: $card-list-item-padding-vertical-compact $card-padding-compact !default; + +// CardList ControlCard item min-height is calculated as height of a control indicator + vertical padding +$card-list-control-item-padding-vertical: $card-padding; +$card-list-control-item-min-height: $control-indicator-size + ($card-list-control-item-padding-vertical * 2) + $card-list-border-width !default; +$card-list-control-item-padding-vertical-compact: $card-padding-compact; +$card-list-control-item-min-height-compact: $control-indicator-size + ($card-list-control-item-padding-vertical-compact * 2) + $card-list-border-width !default; diff --git a/packages/core/src/components/card/_card.scss b/packages/core/src/components/card/_card.scss index e97162a7de..27192b7f2d 100644 --- a/packages/core/src/components/card/_card.scss +++ b/packages/core/src/components/card/_card.scss @@ -1,7 +1,7 @@ // Copyright 2015 Palantir Technologies, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0. -@import "../../common/variables"; +@import "./card-variables"; /* Cards @@ -21,26 +21,6 @@ Markup: Styleguide card */ -$card-padding: $pt-grid-size * 2 !default; - -$card-background-color: $white !default; -$dark-card-background-color: $dark-gray3 !default; - -$elevation-shadows: ( - $pt-elevation-shadow-0 - $pt-elevation-shadow-1 - $pt-elevation-shadow-2 - $pt-elevation-shadow-3 - $pt-elevation-shadow-4 -); -$dark-elevation-shadows: ( - $pt-dark-elevation-shadow-0 - $pt-dark-elevation-shadow-1 - $pt-dark-elevation-shadow-2 - $pt-dark-elevation-shadow-3 - $pt-dark-elevation-shadow-4 -); - .#{$ns}-card { background-color: $card-background-color; border-radius: $pt-border-radius; diff --git a/packages/core/src/components/card/card.md b/packages/core/src/components/card/card.md index 88647c2966..0484eac475 100644 --- a/packages/core/src/components/card/card.md +++ b/packages/core/src/components/card/card.md @@ -1,6 +1,6 @@ @# Card -A __Card__ is a bounded unit of UI content with a solid background color. +A **Card** is a bounded unit of UI content with a solid background color. @reactExample CardExample @@ -10,10 +10,12 @@ A __Card__ is a bounded unit of UI content with a solid background color. import { Button, Card, Elevation } from "@blueprintjs/core"; -
Card heading
+
+ Card heading +

Card content

-
+; ``` @## Elevation @@ -33,6 +35,7 @@ Note that the `Classes.ELEVATION_*` classes can be used on any element (not just
Deprecated API: use [``](#core/components/card) +
CSS APIs for Blueprint components are considered deprecated, as they are verbose, error-prone, and they diff --git a/packages/core/src/components/components.md b/packages/core/src/components/components.md index db1b0fed18..eb61d1d589 100644 --- a/packages/core/src/components/components.md +++ b/packages/core/src/components/components.md @@ -8,6 +8,7 @@ @page callout @page card @page card-list +@page control-card @page collapse @page divider @page editable-text diff --git a/packages/core/src/components/control-card/_control-card.scss b/packages/core/src/components/control-card/_control-card.scss new file mode 100644 index 0000000000..0eb2f7036f --- /dev/null +++ b/packages/core/src/components/control-card/_control-card.scss @@ -0,0 +1,42 @@ +// Copyright 2023 Palantir Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. + +@import "../card/card-variables"; + +// use an extra selector to increase specificity +.#{$ns}-card.#{$ns}-control-card { + &, + .#{$ns}-card-list > & { + // min-height & padding will be set on the label element so that it can take up the full size of the card and + // its entire visual element will be interactive This is partially to work around https://github.com/palantir/blueprint/issues/6251 + min-height: auto; + padding: 0; + } +} + +.#{$ns}-switch-control-card { + // need a lot of specificity here to override control styles + > .#{$ns}-switch.#{$ns}-control.#{$ns}-align-right { + align-items: center; + display: flex; + flex-direction: row-reverse; + justify-content: space-between; + margin: 0; + padding: $card-padding; + width: calc(100%); + + .#{$ns}-card-list & { + min-height: $card-list-control-item-min-height; + padding: $card-list-item-padding; + } + + .#{$ns}-card-list.#{$ns}-compact & { + min-height: $card-list-control-item-min-height-compact; + padding: $card-list-item-padding-compact; + } + + .#{$ns}-control-indicator { + margin: 0; + } + } +} diff --git a/packages/core/src/components/control-card/control-card.md b/packages/core/src/components/control-card/control-card.md new file mode 100644 index 0000000000..45453c0378 --- /dev/null +++ b/packages/core/src/components/control-card/control-card.md @@ -0,0 +1,34 @@ +--- +tag: new +--- + +@# Control card + +A control card is an interactive [**Card**](#core/components/card) with an embedded form control. +There are a few supported form controls: + +- [**SwitchCard**](#core/components/control-card.switch-card) +- CheckboxCard (_coming soon_) +- RadioCard (_coming soon_) + +The children of a control card will be used as the `labelElement` of the form control. Users may click anywhere +inside the card to toggle the control state. + +@## SwitchCard + +Card with an embedded [**Switch**](#core/components/switch) control. + +@reactExample SwitchCardExample + +@### Props interface + +Most of the properties in [**CardProps**](#core/components/card.props-interface) and +[**SwitchProps**](#core/components/switch.props-interface) are available on the root component. + +@interface SwitchCardProps + +@## Composing with CardList + +Control cards work just like regular cards inside a [**CardList**](#core/components/card-list). + +@reactExample ControlCardListExample diff --git a/packages/core/src/components/control-card/controlCard.tsx b/packages/core/src/components/control-card/controlCard.tsx new file mode 100644 index 0000000000..4ce1137cdf --- /dev/null +++ b/packages/core/src/components/control-card/controlCard.tsx @@ -0,0 +1,94 @@ +/* + * 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 { Classes } from "../../common"; +import { DISPLAYNAME_PREFIX, HTMLInputProps } from "../../common/props"; +import { Card, CardProps } from "../card/card"; +import { ControlProps, Switch } from "../forms/controls"; + +/** + * Subset of {@link Card} which can be used to adjust its behavior. + */ +type SupportedCardProps = Omit; + +/** + * Subset of {@link ControlProps} which can be used to adjust its behavior. + */ +type SupportedControlProps = Pick; + +export interface ControlCardProps extends SupportedCardProps, SupportedControlProps { + /** + * Which kind of form control to render inside the card. + */ + controlKind: "switch"; + + // N.B. this is split out of the root properties in the inerface because it would conflict with CardProps' HTMLDivProps + /** + * HTML input attributes to forward to the control `` element. + */ + inputProps?: HTMLInputProps; +} + +/** + * ControlCard component, used to render a {@link Card} with a form control. + * + * @internal + */ +export const ControlCard: React.FC = React.forwardRef((props, ref) => { + const { + checked, + children: labelContent, + className, + controlKind, + defaultChecked, + disabled, + inputProps, + inputRef, + onChange, + ...cardProps + } = props; + + const classes = classNames(Classes.CONTROL_CARD, className, { + [Classes.SWITCH_CONTROL_CARD]: controlKind === "switch", + }); + + // use a container element to achieve a good flex layout + const labelElement =
{labelContent}
; + const controlProps: ControlProps = { + checked, + defaultChecked, + disabled, + inputRef, + labelElement, + onChange, + ...inputProps, + }; + + return ( + + {controlKind === "switch" ? ( + + ) : ( + labelElement + )} + + ); +}); +ControlCard.defaultProps = {}; +ControlCard.displayName = `${DISPLAYNAME_PREFIX}.ControlCard`; diff --git a/packages/core/src/components/control-card/switchCard.tsx b/packages/core/src/components/control-card/switchCard.tsx new file mode 100644 index 0000000000..6ab161271c --- /dev/null +++ b/packages/core/src/components/control-card/switchCard.tsx @@ -0,0 +1,33 @@ +/* + * 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 { DISPLAYNAME_PREFIX } from "../../common/props"; +import { ControlCard, ControlCardProps } from "./controlCard"; + +export type SwitchCardProps = Omit; + +/** + * Switch Card component. + * + * @see https://blueprintjs.com/docs/#core/components/card#switch-card + */ +export const SwitchCard: React.FC = React.forwardRef((props, ref) => { + return ; +}); +SwitchCard.defaultProps = {}; +SwitchCard.displayName = `${DISPLAYNAME_PREFIX}.SwitchCard`; diff --git a/packages/core/src/components/forms/controls.tsx b/packages/core/src/components/forms/controls.tsx index b57cae0e5a..959114ab30 100644 --- a/packages/core/src/components/forms/controls.tsx +++ b/packages/core/src/components/forms/controls.tsx @@ -92,47 +92,50 @@ interface ControlInternalProps extends ControlProps { /** * Renders common control elements, with additional props to customize appearance. - * This function is not exported and is only used within this module for `Checkbox`, `Radio`, and `Switch` below. + * This component is not exported and is only used within this module for `Checkbox`, `Radio`, and `Switch` below. */ -function renderControl(props: ControlInternalProps, ref: React.Ref) { - const { - alignIndicator, - children, - className, - indicatorChildren, - inline, - inputRef, - label, - labelElement, - large, - style, - type, - typeClassName, - tagName = "label", - ...htmlProps - } = props; - const classes = classNames( - Classes.CONTROL, - typeClassName, - { - [Classes.DISABLED]: htmlProps.disabled, - [Classes.INLINE]: inline, - [Classes.LARGE]: large, - }, - Classes.alignmentClass(alignIndicator), - className, - ); +const ControlInternal: React.FC = React.forwardRef( + (props, ref) => { + const { + alignIndicator, + children, + className, + indicatorChildren, + inline, + inputRef, + label, + labelElement, + large, + style, + type, + typeClassName, + tagName = "label", + ...htmlProps + } = props; + const classes = classNames( + Classes.CONTROL, + typeClassName, + { + [Classes.DISABLED]: htmlProps.disabled, + [Classes.INLINE]: inline, + [Classes.LARGE]: large, + }, + Classes.alignmentClass(alignIndicator), + className, + ); - return React.createElement( - tagName, - { className: classes, style, ref }, - , - {indicatorChildren}, - label, - labelElement, - children, - ); -} + return React.createElement( + tagName, + { className: classes, style, ref }, + , + {indicatorChildren}, + label, + labelElement, + children, + ); + }, +); +ControlInternal.displayName = `${DISPLAYNAME_PREFIX}.Control`; // // Switch @@ -174,14 +177,14 @@ export const Switch: React.FC = React.forwardRef( , ] : null; - return renderControl( - { - ...controlProps, - indicatorChildren: switchLabels, - type: "checkbox", - typeClassName: Classes.SWITCH, - }, - ref, + return ( + ); }, ); @@ -198,16 +201,9 @@ export type RadioProps = ControlProps; * * @see https://blueprintjs.com/docs/#core/components/radio */ -export const Radio: React.FC = React.forwardRef((props, ref) => - renderControl( - { - ...props, - type: "radio", - typeClassName: Classes.RADIO, - }, - ref, - ), -); +export const Radio: React.FC = React.forwardRef((props, ref) => ( + +)); Radio.displayName = `${DISPLAYNAME_PREFIX}.Radio`; // @@ -267,15 +263,15 @@ export const Checkbox: React.FC = React.forwardRef((props, ref) = } }, [localInputRef, isIndeterminate]); - return renderControl( - { - ...controlProps, - inputRef, - onChange: handleChange, - type: "checkbox", - typeClassName: Classes.CHECKBOX, - }, - ref, + return ( + ); }); Checkbox.displayName = `${DISPLAYNAME_PREFIX}.Checkbox`; diff --git a/packages/core/src/components/index.ts b/packages/core/src/components/index.ts index bd1d3331b2..798790ef2d 100644 --- a/packages/core/src/components/index.ts +++ b/packages/core/src/components/index.ts @@ -102,6 +102,7 @@ export { Section, SectionElevation, SectionProps } from "./section/section"; export { SectionCard, SectionCardProps } from "./section/sectionCard"; export { Slider, SliderProps } from "./slider/slider"; export { Spinner, SpinnerProps, SpinnerSize } from "./spinner/spinner"; +export { SwitchCard, SwitchCardProps } from "./control-card/switchCard"; export { Tab, TabId, TabProps } from "./tabs/tab"; // eslint-disable-next-line deprecation/deprecation export { Tabs, TabsProps, TabsExpander, Expander } from "./tabs/tabs"; diff --git a/packages/core/test/control-card/controlCardTests.tsx b/packages/core/test/control-card/controlCardTests.tsx new file mode 100644 index 0000000000..e025bb5d75 --- /dev/null +++ b/packages/core/test/control-card/controlCardTests.tsx @@ -0,0 +1,51 @@ +/* + * 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 { assert } from "chai"; +import { mount } from "enzyme"; +import * as React from "react"; +import { SinonSpy, spy } from "sinon"; + +import { SwitchCard } from "../../src"; + +describe("ControlCard", () => { + let testsContainerElement: HTMLElement | undefined; + + beforeEach(() => { + testsContainerElement = document.createElement("div"); + document.body.appendChild(testsContainerElement); + }); + + afterEach(() => { + testsContainerElement?.remove(); + }); + + describe("SwitchCard", () => { + const handleControlChangeSpy = spy() as SinonSpy<[React.FormEvent], void>; + + beforeEach(() => { + handleControlChangeSpy.resetHistory(); + }); + + it("clicking on label element toggles switch state", () => { + const wrapper = mount(, { + attachTo: testsContainerElement, + }); + wrapper.find("input").simulate("change"); + assert.isTrue(handleControlChangeSpy.calledOnce, "expected onChange to be called"); + }); + }); +}); diff --git a/packages/core/test/index.ts b/packages/core/test/index.ts index bff53f46fa..c439e5ee17 100644 --- a/packages/core/test/index.ts +++ b/packages/core/test/index.ts @@ -33,6 +33,7 @@ import "./context-menu/contextMenuSingletonTests"; import "./context-menu/contextMenuTests"; import "./controls/controlsTests"; import "./controls/inputGroupTests"; +import "./control-card/controlCardTests"; import "./controls/numericInputTests"; import "./controls/radioGroupTests"; import "./dialog/dialogTests"; diff --git a/packages/docs-app/src/examples/core-examples/controlCardListExample.tsx b/packages/docs-app/src/examples/core-examples/controlCardListExample.tsx new file mode 100644 index 0000000000..55da3b6aac --- /dev/null +++ b/packages/docs-app/src/examples/core-examples/controlCardListExample.tsx @@ -0,0 +1,77 @@ +/* + * 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 { CardList, Classes, H5, Section, SectionCard, Switch, SwitchCard } from "@blueprintjs/core"; +import { Example, ExampleProps, handleBooleanChange } from "@blueprintjs/docs-theme"; +import { Cog, Moon, PageLayout } from "@blueprintjs/icons"; + +interface ControlCardListExampleState { + compact: boolean; + disabled: boolean; +} + +export class ControlCardListExample extends React.PureComponent { + public state: ControlCardListExampleState = { + compact: false, + disabled: false, + }; + + public render() { + const { compact, disabled } = this.state; + const sharedProps = { disabled }; + + return ( + +
+ + + + + Dark theme + + + + Show scrollbars + + + + Developer mode + + + +
+
+ ); + } + + private renderOptions() { + const { compact, disabled } = this.state; + return ( + <> +
Section & CardList Props
+ +
SwitchCard Props
+ + + ); + } + + private toggleDisabled = handleBooleanChange(disabled => this.setState({ disabled })); + + private toggleCompact = handleBooleanChange(compact => this.setState({ compact })); +} diff --git a/packages/docs-app/src/examples/core-examples/index.ts b/packages/docs-app/src/examples/core-examples/index.ts index 95a7e73e05..92f68e3cef 100644 --- a/packages/docs-app/src/examples/core-examples/index.ts +++ b/packages/docs-app/src/examples/core-examples/index.ts @@ -27,6 +27,7 @@ export * from "./cardExample"; export * from "./cardListExample"; export { ContextMenuExample } from "./contextMenuExample"; export { ContextMenuPopoverExample } from "./contextMenuPopoverExample"; +export { ControlCardListExample } from "./controlCardListExample"; export * from "./controlGroupExample"; export * from "./dialogExample"; export * from "./multistepDialogExample"; @@ -67,6 +68,7 @@ export * from "./radioExample"; export * from "./sectionExample"; export * from "./sliderExample"; export * from "./switchExample"; +export { SwitchCardExample } from "./switchCardExample"; export * from "./tagInputExample"; export * from "./textAreaExample"; export * from "./textExample"; diff --git a/packages/docs-app/src/examples/core-examples/switchCardExample.tsx b/packages/docs-app/src/examples/core-examples/switchCardExample.tsx new file mode 100644 index 0000000000..5668112d26 --- /dev/null +++ b/packages/docs-app/src/examples/core-examples/switchCardExample.tsx @@ -0,0 +1,61 @@ +/* + * 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 { H5, Switch, SwitchCard } from "@blueprintjs/core"; +import { Example, ExampleProps, handleBooleanChange } from "@blueprintjs/docs-theme"; + +interface SwitchCardExampleState { + // TODO: add compact option + // compact: boolean; + disabled: boolean; +} + +export class SwitchCardExample extends React.PureComponent { + public state: SwitchCardExampleState = { + // TODO: add compact option + // compact: false, + disabled: false, + }; + + public render() { + const { disabled } = this.state; + const sharedProps = { disabled }; + + return ( + +
+ Wifi + Bluetooth + NFC +
+
+ ); + } + + private renderOptions() { + const { disabled } = this.state; + return ( + <> +
Props
+ + + ); + } + + private toggleDisabled = handleBooleanChange(disabled => this.setState({ disabled })); +} diff --git a/packages/docs-app/src/styles/_examples.scss b/packages/docs-app/src/styles/_examples.scss index 384de022df..9a15ac7d34 100644 --- a/packages/docs-app/src/styles/_examples.scss +++ b/packages/docs-app/src/styles/_examples.scss @@ -90,6 +90,21 @@ } } +#{example("SwitchCard")} { + .docs-control-card-grid { + display: grid; + gap: $pt-grid-size * 2; + grid-template-columns: repeat(auto-fit, minmax($pt-grid-size * 10, 1fr)); + width: 100%; + } +} + +#{example("ControlCardList")} { + .#{$ns}-control-card-label .#{$ns}-icon { + margin-right: $pt-grid-size; + } +} + #{example("EditableText")} { .docs-example { display: block;