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

[Tags] Add pt-interactive support #2251

Merged
merged 7 commits into from
Mar 19, 2018
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
49 changes: 47 additions & 2 deletions packages/core/src/components/tag/_common.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Copyright 2015 Palantir Technologies, Inc. All rights reserved.
// Licensed under the terms of the LICENSE file distributed with this project.

$tag-default-color: $gray1 !default;
$dark-tag-default-color: $gray5 !default;

$tag-icon-spacing: 3px !default;
$tag-height: $pt-grid-size * 2 !default;
$tag-padding: ($tag-height - $pt-icon-size-standard) / 2 !default;
Expand All @@ -10,12 +13,14 @@ $tag-height-large: $pt-grid-size * 3 !default;
$tag-padding-large: ($tag-height-large - $pt-icon-size-large) / 2 !default;

@mixin pt-tag() {
@include pt-tag-interactive($tag-default-color, 1);

display: inline-block;
position: relative;
border: none;
border-radius: $pt-border-radius;
box-shadow: none;
background-color: $gray1;
background-color: $tag-default-color;
min-width: $tag-height;
padding: $tag-padding ($tag-padding * 3);
line-height: $pt-icon-size-standard;
Expand All @@ -27,7 +32,9 @@ $tag-padding-large: ($tag-height-large - $pt-icon-size-large) / 2 !default;
}

.pt-dark & {
background-color: $gray5;
@include pt-tag-interactive($dark-tag-default-color, 1);

background-color: $dark-tag-default-color;
color: $pt-text-color;
}

Expand Down Expand Up @@ -56,31 +63,69 @@ $tag-padding-large: ($tag-height-large - $pt-icon-size-large) / 2 !default;
}

@mixin pt-tag-intent($background-color, $text-color: $white) {
@include pt-tag-interactive($background-color, 1);

background: $background-color;
color: $text-color;
}

@mixin pt-tag-minimal() {
&:not([class*="pt-intent-"]) {
@include pt-tag-minimal-interactive($tag-default-color, 0.2);

background-color: rgba($gray3, 0.2);
color: $pt-text-color;

.pt-dark & {
@include pt-tag-minimal-interactive($dark-tag-default-color, 0.2);

color: $pt-dark-text-color;
}
}
}

@mixin pt-tag-minimal-intent($background-color, $text-color, $dark-text-color) {
@include pt-tag-minimal-interactive($background-color, 0.15);

background-color: rgba($background-color, 0.15);
color: $text-color;

.pt-dark & {
@include pt-tag-minimal-interactive($background-color, 0.25);

background-color: rgba($background-color, 0.25);
color: $dark-text-color;
}
}

@mixin pt-tag-interactive($background-color, $opacity) {
&.pt-interactive {
cursor: pointer;

&:hover {
background-color: rgba($background-color, $opacity - 0.15);
}

&:active {
background-color: rgba($background-color, $opacity - 0.3);
}
}
}

@mixin pt-tag-minimal-interactive($background-color, $opacity) {
&.pt-interactive {
cursor: pointer;

&:hover {
background-color: rgba($background-color, $opacity + 0.1);
}

&:active {
background-color: rgba($background-color, $opacity + 0.2);
}
}
}

@mixin pt-tag-remove() {
position: absolute;
top: 0;
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/components/tag/_tag.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Markup:

.pt-large - Large
.pt-round - Rounded corners, ideal for badges
.pt-interactive - Hover and active effects
.pt-intent-primary - Primary intent
.pt-intent-success - Success intent
.pt-intent-warning - Warning intent
Expand Down Expand Up @@ -63,6 +64,7 @@ Styleguide pt-tag

.pt-large - Large
.pt-round - Rounded corners, ideal for badges
.pt-interactive - Hover and active effects
Copy link
Contributor

Choose a reason for hiding this comment

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

@llorca i added CSS example for minimal tags

.pt-intent-primary - Primary intent
.pt-intent-success - Success intent
.pt-intent-warning - Warning intent
Expand Down
19 changes: 18 additions & 1 deletion packages/core/src/components/tag/tag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,22 @@ export interface ITagProps extends IProps, IIntentProps, React.HTMLAttributes<HT
*/
active?: boolean;

/**
* Whether the tag should visually respond to user interactions. If set
* to `true`, hovering over the tag will change its color and mouse cursor.
*
* Recommended when `onClick` is also defined.
*
* @default false
*/
interactive?: boolean;

/**
* Callback invoked when the tag is clicked.
* Recommended when `interactive` is `true`.
*/
onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;

/**
* Click handler for remove button.
* Button will only be rendered if this prop is defined.
Expand All @@ -29,14 +45,15 @@ export class Tag extends React.PureComponent<ITagProps, {}> {
public static displayName = "Blueprint2.Tag";

public render() {
const { active, children, className, intent, onRemove, ...htmlProps } = this.props;
const { active, children, className, intent, interactive, onRemove, ...htmlProps } = this.props;
const isRemovable = Utils.isFunction(onRemove);
const tagClasses = classNames(
Classes.TAG,
Classes.intentClass(intent),
{
[Classes.TAG_REMOVABLE]: isRemovable,
[Classes.ACTIVE]: active,
[Classes.INTERACTIVE]: interactive,
},
className,
);
Expand Down
21 changes: 18 additions & 3 deletions packages/docs-app/src/examples/core-examples/tagExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { IntentSelect } from "./common/intentSelect";

export interface ITagExampleState {
intent: Intent;
interactive: boolean;
large: boolean;
minimal: boolean;
removable: boolean;
Expand All @@ -22,6 +23,7 @@ export interface ITagExampleState {
export class TagExample extends BaseExample<ITagExampleState> {
public state: ITagExampleState = {
intent: Intent.NONE,
interactive: false,
large: false,
minimal: false,
removable: false,
Expand All @@ -34,14 +36,21 @@ export class TagExample extends BaseExample<ITagExampleState> {
private handleLargeChange = handleBooleanChange(large => this.setState({ large }));
private handleMinimalChange = handleBooleanChange(minimal => this.setState({ minimal }));
private handleRemovableChange = handleBooleanChange(removable => this.setState({ removable }));
private handleInteractiveChange = handleBooleanChange(interactive => this.setState({ interactive }));

protected renderExample() {
const { intent, large, minimal, removable } = this.state;
const { intent, interactive, 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 key={tag} className={tagClasses} intent={intent} onRemove={removable && onRemove}>
<Tag
key={tag}
className={tagClasses}
intent={intent}
interactive={interactive}
onRemove={removable && onRemove}
>
{tag}
</Tag>
);
Expand All @@ -50,12 +59,18 @@ export class TagExample extends BaseExample<ITagExampleState> {
}

protected renderOptions() {
const { intent, large, minimal, removable } = this.state;
const { intent, interactive, 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} />,
<Switch
key="interactive"
label="Interactive"
checked={interactive}
onChange={this.handleInteractiveChange}
/>,
],
[<IntentSelect key="intent" intent={intent} onChange={this.handleIntentChange} />],
[<Button key="reset" text="Reset tags" onClick={this.resetTags} />],
Expand Down