Skip to content

Commit

Permalink
[tag] use Icon in remove button (#2231)
Browse files Browse the repository at this point in the history
  • Loading branch information
giladgray authored and adidahiya committed Mar 14, 2018
1 parent c86208e commit 74e7c1a
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 56 deletions.
10 changes: 7 additions & 3 deletions packages/core/src/components/tag/_common.scss
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ $tag-padding-large: ($tag-height-large - $pt-icon-size-large) / 2 !default;
}

@mixin pt-tag-remove() {
@include pt-icon();
position: absolute;
top: 0;
right: 0;
Expand All @@ -103,12 +102,17 @@ $tag-padding-large: ($tag-height-large - $pt-icon-size-large) / 2 !default;
opacity: 1;
}

&::before {
// CSS API support
&:empty::before {
@include pt-icon();
content: $pt-icon-small-cross;
}

.pt-large & {
@include pt-icon-sized($pt-icon-size-large);
padding: $tag-padding-large;

&:empty::before {
@include pt-icon-sized($pt-icon-size-large);
}
}
}
3 changes: 2 additions & 1 deletion packages/core/src/components/tag/tag.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

Tags are great for lists of strings.

@reactExample TagExample

@## CSS API

An optional "remove" button can be added inside a tag as a `button.pt-tag-remove`. Also add the
Expand Down Expand Up @@ -41,4 +43,3 @@ Blueprint class name.

@interface ITagProps

@reactExample TagExample
28 changes: 14 additions & 14 deletions packages/core/src/components/tag/tag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@
import classNames from "classnames";
import * as React from "react";

import { Utils } from "../../common";
import { IIntentProps, IProps, removeNonHTMLProps } from "../../common/props";

import * as Classes from "../../common/classes";
import { Classes, IIntentProps, IProps, Utils } from "../../common";
import { Icon } from "../icon/icon";

export interface ITagProps extends IProps, IIntentProps, React.HTMLAttributes<HTMLSpanElement> {
/**
Expand All @@ -31,26 +29,28 @@ export class Tag extends React.PureComponent<ITagProps, {}> {
public static displayName = "Blueprint2.Tag";

public render() {
const { active, className, intent, onRemove } = this.props;
const { active, children, className, intent, onRemove, ...htmlProps } = this.props;
const isRemovable = Utils.isFunction(onRemove);
const tagClasses = classNames(
Classes.TAG,
Classes.intentClass(intent),
{
[Classes.TAG_REMOVABLE]: onRemove != null,
[Classes.TAG_REMOVABLE]: isRemovable,
[Classes.ACTIVE]: active,
},
className,
);
const button = Utils.isFunction(onRemove) ? (
<button type="button" className={Classes.TAG_REMOVE} onClick={this.onRemoveClick} />
) : (
undefined
);
const isLarge = tagClasses.indexOf(Classes.LARGE) >= 0;
const removeButton = isRemovable ? (
<button type="button" className={Classes.TAG_REMOVE} onClick={this.onRemoveClick}>
<Icon icon="small-cross" iconSize={isLarge ? Icon.SIZE_LARGE : Icon.SIZE_STANDARD} />
</button>
) : null;

return (
<span {...removeNonHTMLProps(this.props)} className={tagClasses}>
{this.props.children}
{button}
<span {...htmlProps} className={tagClasses}>
{children}
{removeButton}
</span>
);
}
Expand Down
86 changes: 48 additions & 38 deletions packages/docs-app/src/examples/core-examples/tagExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,53 +6,63 @@

import * as React from "react";

import { Classes, Intent, Tag } from "@blueprintjs/core";
import { BaseExample } from "@blueprintjs/docs-theme";
import { Button, Classes, Intent, Switch, Tag } from "@blueprintjs/core";
import { BaseExample, handleBooleanChange, handleStringChange } from "@blueprintjs/docs-theme";
import classNames from "classnames";
import { IntentSelect } from "./common/intentSelect";

export class TagExample extends BaseExample<{ showTag?: boolean }> {
public state = {
showTag: true,
export interface ITagExampleState {
intent: Intent;
large: boolean;
minimal: boolean;
removable: boolean;
tags: string[];
}

export class TagExample extends BaseExample<ITagExampleState> {
public state: ITagExampleState = {
intent: Intent.NONE,
large: false,
minimal: false,
removable: false,
tags: INITIAL_TAGS,
};

protected className = "docs-tag-example";

protected renderExample() {
return (
<div>
<Tag className={Classes.MINIMAL} intent={Intent.PRIMARY}>
@jkillian
</Tag>
<Tag className={Classes.MINIMAL} intent={Intent.PRIMARY}>
@adahiya
</Tag>
<Tag className={Classes.MINIMAL} intent={Intent.PRIMARY}>
@ggray
</Tag>
<Tag className={Classes.MINIMAL} intent={Intent.PRIMARY}>
@allorca
</Tag>
<Tag className={Classes.MINIMAL} intent={Intent.PRIMARY}>
@bdwyer
</Tag>
<Tag className={Classes.MINIMAL} intent={Intent.PRIMARY}>
@piotrk
</Tag>
{this.maybeRenderTag()}
</div>
);
}
private handleIntentChange = handleStringChange((intent: Intent) => this.setState({ intent }));
private handleLargeChange = handleBooleanChange(large => this.setState({ large }));
private handleMinimalChange = handleBooleanChange(minimal => this.setState({ minimal }));
private handleRemovableChange = handleBooleanChange(removable => this.setState({ removable }));

private maybeRenderTag() {
if (this.state.showTag) {
protected renderExample() {
const { intent, large, minimal, removable } = this.state;
const tagClasses = classNames({ [Classes.LARGE]: large, [Classes.MINIMAL]: minimal });
const tags = this.state.tags.map(tag => {
const onRemove = () => this.setState({ tags: this.state.tags.filter(t => t !== tag) });
return (
<Tag className={Classes.MINIMAL} intent={Intent.PRIMARY} onRemove={this.deleteTag}>
@dlipowicz
<Tag key={tag} className={tagClasses} intent={intent} onRemove={removable && onRemove}>
{tag}
</Tag>
);
} else {
return undefined;
}
});
return <div>{tags}</div>;
}

private deleteTag = () => this.setState({ showTag: false });
protected renderOptions() {
const { intent, large, minimal, removable } = this.state;
return [
[
<Switch key="large" label="Large" checked={large} onChange={this.handleLargeChange} />,
<Switch key="minimal" label="Minimal" checked={minimal} onChange={this.handleMinimalChange} />,
<Switch key="removable" label="Removable" checked={removable} onChange={this.handleRemovableChange} />,
],
[<IntentSelect key="intent" intent={intent} onChange={this.handleIntentChange} />],
[<Button key="reset" text="Reset tags" onClick={this.resetTags} />],
];
}

private resetTags = () => this.setState({ tags: INITIAL_TAGS });
}

const INITIAL_TAGS = ["@jkillian", "@adahiya", "@ggray", "@allorca", "@bdwyer", "@piotrk"];

1 comment on commit 74e7c1a

@blueprint-bot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[tag] use Icon in remove button (#2231)

Preview: documentation | landing | table

Please sign in to comment.