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] fix(Callout): use visual margin when content is simple text #6276

Merged
merged 3 commits into from
Jul 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/core/src/common/classes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export const BUTTON_TEXT = `${BUTTON}-text`;

export const CALLOUT = `${NS}-callout`;
export const CALLOUT_ICON = `${CALLOUT}-icon`;
export const CALLOUT_BODY = `${CALLOUT}-body`;

export const CARD = `${NS}-card`;

Expand Down
8 changes: 4 additions & 4 deletions packages/core/src/components/callout/_callout.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2015 Palantir Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0.

@import "../../common/variables";
@import "../../common/variables-extended";

/*
Callout
Expand Down Expand Up @@ -63,11 +63,11 @@ $callout-header-margin-top: $pt-grid-size * 0.2;

.#{$ns}-heading {
line-height: $pt-icon-size-standard;
margin-bottom: $pt-grid-size * 0.5;
margin-bottom: 0;
margin-top: $callout-header-margin-top;

&:last-child {
margin-bottom: 0;
+ .#{$ns}-callout-body {
margin-top: $half-grid-size;
}
}

Expand Down
24 changes: 16 additions & 8 deletions packages/core/src/components/callout/callout.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
@# Callout

Callouts visually highlight important content for the user. They can contain
__Callouts__ visually highlight important content for the user. They may contain
a title, an icon and content. Each intent has a default icon associated with it.

@reactExample CalloutExample

@## Props interface

The `<Callout>` component is a simple wrapper around the CSS API that provides props for
modifiers and an optional title element. Any additional HTML props will be spread to the
rendered `<div>` element.

@interface CalloutProps

@## CSS
@## CSS API

<div class="@ns-callout @ns-intent-warning @ns-icon-warning-sign">
<h5 class="@ns-heading">

Deprecated API: use [`<Callout>`](#core/components/callout)

</h5>

CSS APIs for Blueprint components are considered deprecated, as they are verbose, error-prone, and they
often fall out of sync as the design system is updated. You should use the React component APIs instead.

</div>

Callouts use the same visual intent modifier classes as buttons. If you need a
heading, use the `<h5>` element with a `.@ns-heading` class.
Callouts use the same visual intent modifier classes as buttons. If you need a heading, use the `<h5>`
element with a `.@ns-heading` class.

@css callout
7 changes: 6 additions & 1 deletion packages/core/src/components/callout/callout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export class Callout extends AbstractPureComponent<CalloutProps> {
<div className={classes} {...htmlProps}>
{iconElement}
{title && <H5>{title}</H5>}
{children}
{this.hasEmptyContent() ? undefined : <div className={Classes.CALLOUT_BODY}>{children}</div>}
</div>
);
}
Expand Down Expand Up @@ -117,4 +117,9 @@ export class Callout extends AbstractPureComponent<CalloutProps> {
return undefined;
}
}

private hasEmptyContent() {
const { children } = this.props;
return children == null || (typeof children === "string" && children.trim().length === 0);
}
}
54 changes: 41 additions & 13 deletions packages/docs-app/src/examples/core-examples/calloutExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,47 +16,75 @@

import * as React from "react";

import { Callout, Code, H5, Intent, Switch } from "@blueprintjs/core";
import { DocsExampleProps, Example, handleBooleanChange } from "@blueprintjs/docs-theme";
import { Button, Callout, Code, H5, HTMLSelect, Intent, Label, Switch } from "@blueprintjs/core";
import { DocsExampleProps, Example, handleBooleanChange, handleNumberChange } from "@blueprintjs/docs-theme";
import { IconName } from "@blueprintjs/icons";

import { IconSelect } from "./common/iconSelect";
import { IntentSelect } from "./common/intentSelect";

interface CalloutExampleState {
contentIndex?: number;
icon?: IconName;
intent?: Intent;
showHeader: boolean;
showTitle: boolean;
}

export class CalloutExample extends React.PureComponent<DocsExampleProps, CalloutExampleState> {
public state: CalloutExampleState = { showHeader: true };
public state: CalloutExampleState = {
contentIndex: 0,
showTitle: true,
};

private handleHeaderChange = handleBooleanChange((showHeader: boolean) => this.setState({ showHeader }));
private handleContentIndexChange = handleNumberChange(contentIndex => this.setState({ contentIndex }));

private handleIconNameChange = (icon: IconName) => this.setState({ icon });

private handleIntentChange = (intent: Intent) => this.setState({ intent });

private handleShowTitleChange = handleBooleanChange((showTitle: boolean) => this.setState({ showTitle }));

public render() {
const { showHeader, ...calloutProps } = this.state;
const { contentIndex, showTitle, ...calloutProps } = this.state;
const options = (
<>
<H5>Props</H5>
<IntentSelect intent={calloutProps.intent} onChange={this.handleIntentChange} />
<Switch checked={showTitle} label="Title" onChange={this.handleShowTitleChange} />
<IntentSelect intent={calloutProps.intent} onChange={this.handleIntentChange} showClearButton={true} />
<IconSelect iconName={calloutProps.icon} onChange={this.handleIconNameChange} />
<H5>Example</H5>
<Switch checked={showHeader} label="Show header" onChange={this.handleHeaderChange} />
<H5>Children</H5>
<Label>
Example content
<HTMLSelect value={contentIndex} onChange={this.handleContentIndexChange}>
<option value="0">Text with formatting</option>
<option value="1">Simple text string</option>
<option value="2">Button</option>
<option value="3">Empty</option>
</HTMLSelect>
</Label>
</>
);

return (
<Example options={options} {...this.props}>
<Callout {...calloutProps} title={showHeader ? "Visually important content" : undefined}>
Long-form information about the important content. This text is styled as{" "}
<a href="#core/typography.running-text">"Running text"</a>, so it may contain things like headers,
links, lists, <Code>code</Code> etc.
<Callout {...calloutProps} title={showTitle ? "Visually important content" : undefined}>
{this.renderChildren(contentIndex)}
</Callout>
</Example>
);
}

/* eslint-disable react/jsx-key */
private renderChildren(contentIndex: number) {
return [
<React.Fragment>
Long-form information about the important content. This text is styled as{" "}
<a href="#core/typography.running-text">"Running text"</a>, so it may contain things like headers,
links, lists, <Code>code</Code> etc.
</React.Fragment>,
"Long-form information about the important content",
<Button text="Example button" intent="primary" />,
undefined,
][contentIndex];
}
}