Skip to content

Commit

Permalink
[Lens] Consistent Drag and Drop styles (#78674)
Browse files Browse the repository at this point in the history
* Remove wrapping div of DragDrop and pass props to child
* Using EuiHighlight
* Basic styles in for all DnD states
* Fixing dimension button styles
* Fix FieldButton to accept `…rest` props
* A few other minor fixes
* Fixed horizontal scroll of error message
* Quick fix for invalid link
  • Loading branch information
cchaos committed Oct 1, 2020
1 parent d70eaf1 commit f1c50b7
Show file tree
Hide file tree
Showing 21 changed files with 431 additions and 293 deletions.
37 changes: 27 additions & 10 deletions src/plugins/kibana_react/public/field_button/field_button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@

import './field_button.scss';
import classNames from 'classnames';
import React, { ReactNode, HTMLAttributes } from 'react';
import React, { ReactNode, HTMLAttributes, ButtonHTMLAttributes } from 'react';
import { CommonProps } from '@elastic/eui';

export interface FieldButtonProps extends HTMLAttributes<HTMLDivElement> {
/**
Expand Down Expand Up @@ -56,7 +57,14 @@ export interface FieldButtonProps extends HTMLAttributes<HTMLDivElement> {
* The component will render a `<button>` when provided an `onClick`
*/
onClick?: () => void;
/**
* Applies to the inner `<button>` or `<div>`
*/
dataTestSubj?: string;
/**
* Pass more button props to the `<button>` element
*/
buttonProps?: ButtonHTMLAttributes<HTMLButtonElement> & CommonProps;
}

const sizeToClassNameMap = {
Expand All @@ -79,6 +87,8 @@ export function FieldButton({
isDraggable = false,
onClick,
dataTestSubj,
buttonProps,
...rest
}: FieldButtonProps) {
const classes = classNames(
'kbnFieldButton',
Expand All @@ -88,8 +98,18 @@ export function FieldButton({
className
);

const contentClasses = classNames('kbn-resetFocusState', 'kbnFieldButton__button');

const innerContent = (
<>
{fieldIcon && <span className="kbnFieldButton__fieldIcon">{fieldIcon}</span>}
{fieldName && <span className="kbnFieldButton__name">{fieldName}</span>}
{fieldInfoIcon && <div className="kbnFieldButton__infoIcon">{fieldInfoIcon}</div>}
</>
);

return (
<div className={classes}>
<div className={classes} {...rest}>
{onClick ? (
<button
onClick={(e) => {
Expand All @@ -99,17 +119,14 @@ export function FieldButton({
onClick();
}}
data-test-subj={dataTestSubj}
className={'kbn-resetFocusState kbnFieldButton__button'}
className={contentClasses}
{...buttonProps}
>
{fieldIcon && <span className="kbnFieldButton__fieldIcon">{fieldIcon}</span>}
{fieldName && <span className="kbnFieldButton__name">{fieldName}</span>}
{fieldInfoIcon && <div className="kbnFieldButton__infoIcon">{fieldInfoIcon}</div>}
{innerContent}
</button>
) : (
<div className={'kbn-resetFocusState kbnFieldButton__button'} data-test-subj={dataTestSubj}>
{fieldIcon && <span className="kbnFieldButton__fieldIcon">{fieldIcon}</span>}
{fieldName && <span className="kbnFieldButton__name">{fieldName}</span>}
{fieldInfoIcon && <div className="kbnFieldButton__infoIcon">{fieldInfoIcon}</div>}
<div className={contentClasses} data-test-subj={dataTestSubj}>
{innerContent}
</div>
)}

Expand Down
36 changes: 36 additions & 0 deletions x-pack/plugins/lens/public/_mixins.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,39 @@
transparentize(red, .9) 100%
);
}

// Static styles for a draggable item
@mixin lnsDraggable {
@include euiSlightShadow;
background: lightOrDarkTheme($euiColorEmptyShade, $euiColorLightestShade);
border: $euiBorderWidthThin dashed transparent;
cursor: grab;
}

// Static styles for a drop area
@mixin lnsDroppable {
border: $euiBorderWidthThin dashed $euiBorderColor;
}

// Hovering state for drag item and drop area
@mixin lnsDragDropHover {
&:hover {
border: $euiBorderWidthThin dashed $euiColorMediumShade;
}
}

// Style for drop area when there's an item being dragged
@mixin lnsDroppableActive {
background-color: transparentize($euiColorVis0, .9);
}

// Style for drop area while hovering with item
@mixin lnsDroppableActiveHover {
background-color: transparentize($euiColorVis0, .75);
border: $euiBorderWidthThin dashed $euiColorVis0;
}

// Style for drop area that is not allowed for current item
@mixin lnsDroppableNotAllowed {
opacity: .5;
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

55 changes: 48 additions & 7 deletions x-pack/plugins/lens/public/drag_drop/drag_drop.scss
Original file line number Diff line number Diff line change
@@ -1,13 +1,54 @@
.lnsDragDrop-isNotDroppable {
opacity: .5;
@import '../variables';
@import '../mixins';

.lnsDragDrop {
transition: background-color $euiAnimSpeedFast ease-in-out, border-color $euiAnimSpeedFast ease-in-out;
}

// Draggable item
.lnsDragDrop-isDraggable {
@include lnsDraggable;
@include lnsDragDropHover;

// Include a possible nested button like when using FieldButton
> .kbnFieldButton__button {
cursor: grab;
}

&:focus {
@include euiFocusRing;
}
}

// Draggable item when it is moving
.lnsDragDrop-isHidden {
opacity: 0;
}

// Drop area
.lnsDragDrop-isDroppable {
@include lnsDroppable;
}

// Fix specificity by chaining classes
// Drop area when there's an item being dragged
.lnsDragDrop-isDropTarget {
@include lnsDroppableActive;
}

.lnsDragDrop.lnsDragDrop-isDropTarget {
background-color: transparentize($euiColorSecondary, .9);
// Drop area while hovering with item
.lnsDragDrop-isActiveDropTarget {
@include lnsDroppableActiveHover;
}

// Drop area that is not allowed for current item
.lnsDragDrop-isNotDroppable {
@include lnsDroppableNotAllowed;
}

.lnsDragDrop.lnsDragDrop-isActiveDropTarget {
background-color: transparentize($euiColorSecondary, .75);
// Drop area will be replacing existing content
.lnsDragDrop-isReplacing {
&,
.lnsLayerPanel__triggerLink {
text-decoration: line-through;
}
}
30 changes: 19 additions & 11 deletions x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('DragDrop', () => {
test('renders if nothing is being dragged', () => {
const component = render(
<DragDrop value="hello" draggable label="dragging">
Hello!
<button>Hello!</button>
</DragDrop>
);

Expand All @@ -24,7 +24,11 @@ describe('DragDrop', () => {

test('dragover calls preventDefault if droppable is true', () => {
const preventDefault = jest.fn();
const component = mount(<DragDrop droppable>Hello!</DragDrop>);
const component = mount(
<DragDrop droppable>
<button>Hello!</button>
</DragDrop>
);

component.find('[data-test-subj="lnsDragDrop"]').simulate('dragover', { preventDefault });

Expand All @@ -33,7 +37,11 @@ describe('DragDrop', () => {

test('dragover does not call preventDefault if droppable is false', () => {
const preventDefault = jest.fn();
const component = mount(<DragDrop>Hello!</DragDrop>);
const component = mount(
<DragDrop>
<button>Hello!</button>
</DragDrop>
);

component.find('[data-test-subj="lnsDragDrop"]').simulate('dragover', { preventDefault });

Expand All @@ -51,7 +59,7 @@ describe('DragDrop', () => {
const component = mount(
<ChildDragDropProvider dragging={value} setDragging={setDragging}>
<DragDrop value={value} draggable={true} label="drag label">
Hello!
<button>Hello!</button>
</DragDrop>
</ChildDragDropProvider>
);
Expand All @@ -74,7 +82,7 @@ describe('DragDrop', () => {
const component = mount(
<ChildDragDropProvider dragging="hola" setDragging={setDragging}>
<DragDrop onDrop={onDrop} droppable={true} value={value}>
Hello!
<button>Hello!</button>
</DragDrop>
</ChildDragDropProvider>
);
Expand All @@ -98,7 +106,7 @@ describe('DragDrop', () => {
const component = mount(
<ChildDragDropProvider dragging="hola" setDragging={setDragging}>
<DragDrop onDrop={onDrop} droppable={false} value={{}}>
Hello!
<button>Hello!</button>
</DragDrop>
</ChildDragDropProvider>
);
Expand All @@ -121,7 +129,7 @@ describe('DragDrop', () => {
}}
droppable
>
Hello!
<button>Hello!</button>
</DragDrop>
);

Expand All @@ -132,10 +140,10 @@ describe('DragDrop', () => {
const component = mount(
<ChildDragDropProvider dragging={'ignored'} setDragging={() => {}}>
<DragDrop value="ignored" draggable={true} label="a">
Ignored
<button>Hello!</button>
</DragDrop>
<DragDrop onDrop={(x: unknown) => {}} droppable={false}>
Hello!
<button>Hello!</button>
</DragDrop>
</ChildDragDropProvider>
);
Expand All @@ -154,14 +162,14 @@ describe('DragDrop', () => {
}}
>
<DragDrop value="ignored" draggable={true} label="a">
Ignored
<button>Hello!</button>
</DragDrop>
<DragDrop
onDrop={(x: unknown) => {}}
droppable
getAdditionalClassesOnEnter={getAdditionalClasses}
>
Hello!
<button>Hello!</button>
</DragDrop>
</ChildDragDropProvider>
);
Expand Down
Loading

0 comments on commit f1c50b7

Please sign in to comment.