From dc539effb77075224093668d3488d6efaa212bed Mon Sep 17 00:00:00 2001 From: dustinengle Date: Tue, 21 Aug 2018 14:10:56 -0700 Subject: [PATCH 1/4] #23 tooltip added --- react/IconButton.jsx | 2 +- react/Tooltip.jsx | 32 +++++-------- sass/inc/_tooltip.scss | 90 ++++++++++++++++++++++++++++++++++-- test/Tooltip.test.js | 39 ++++++++++++++++ todo/Section/TooltipDemo.jsx | 10 ++-- 5 files changed, 143 insertions(+), 30 deletions(-) create mode 100644 test/Tooltip.test.js diff --git a/react/IconButton.jsx b/react/IconButton.jsx index 9cdc2d8..7520bd8 100644 --- a/react/IconButton.jsx +++ b/react/IconButton.jsx @@ -9,7 +9,7 @@ export default class IconButton extends React.Component { const [ mods, {children, as, k, ...rest} ] = pickRest(this.props, ['primary', 'secondary', 'disabled']) const As = as return ( - + ) diff --git a/react/Tooltip.jsx b/react/Tooltip.jsx index f0a7e34..52a7c02 100644 --- a/react/Tooltip.jsx +++ b/react/Tooltip.jsx @@ -1,36 +1,26 @@ import PropTypes from 'prop-types' import React from 'react' +import {pickRest} from '../lib/utils' -const Tooltip = ({bgcolor, children, content, fgcolor, position, ...props}) => { +const Tooltip = (props) => { + const [ mods, {children, content, ...rest} ] = pickRest(props, ['bottom', 'left', 'primary', 'right', 'top', 'urgent']) return ( -
-
- {content} -
+
+ {content} {children}
) } -Tooltip.defaultProps = { - bgcolor: 'black', - fgcolor: 'white', - position: 'top' -} - Tooltip.propTypes = { - bgcolor: PropTypes.string.isRequired, + bottom: PropTypes.bool, children: PropTypes.any.isRequired, content: PropTypes.any.isRequired, - fgcolor: PropTypes.string.isRequired, - position: PropTypes.oneOf([ - 'top', - 'right', - 'bottom', - 'left' - ]).isRequired + left: PropTypes.bool, + primary: PropTypes.bool, + right: PropTypes.bool, + top: PropTypes.bool, + urgent: PropTypes.bool } export default Tooltip diff --git a/sass/inc/_tooltip.scss b/sass/inc/_tooltip.scss index b9ba31a..0b87aee 100644 --- a/sass/inc/_tooltip.scss +++ b/sass/inc/_tooltip.scss @@ -4,22 +4,104 @@ position: relative; &__content { - background-color: $black; + background-color: $secondary; border-radius: $border-radius; color: $white; - padding: $grid-gutter 0; + display: inline-block; + font-size: 9px; + line-height: 11px; + padding: $grid-gutter/2 $grid-gutter; position: absolute; text-align: center; visibility: hidden; + width: max-content; z-index: 1; + $self: &; + + &::after { + border-style: solid; + border-width: 5px; + content: " "; + position: absolute; + } + + &--primary { + background-color: $primary; + + &#{$self}--bottom::after { border-color: transparent transparent $primary transparent; } + &#{$self}--left::after { border-color: transparent transparent transparent $primary; } + &#{$self}--right::after { border-color: transparent $primary transparent transparent; } + &#{$self}--top::after { border-color: $primary transparent transparent transparent; } + } + + &--urgent { + background-color: $red; + + &#{$self}--bottom::after { border-color: transparent transparent $red transparent; } + &#{$self}--left::after { border-color: transparent transparent transparent $red; } + &#{$self}--right::after { border-color: transparent $red transparent transparent; } + &#{$self}--top::after { border-color: $red transparent transparent transparent; } + } + + &--bottom { + left: 50%; + top: 105%; + transform: translateX(-50%); + + &::after { + border-color: transparent transparent $secondary transparent; + bottom: 100%; + left: 50%; + transform: translateX(-50%); + } + } + + &--left { + top: 50%; + right: 105%; + transform: translateY(-50%); + + &::after { + border-color: transparent transparent transparent $secondary; + left: 100%; + top: 50%; + transform: translateY(-50%); + } + } + + &--right { + left: 105%; + top: 50%; + transform: translateY(-50%); + + &::after { + border-color: transparent $secondary transparent transparent; + right: 100%; + top: 50%; + transform: translateY(-50%); + } + } + &--top { - bottom: 40px; - left: 0; + bottom: 105%; + left: 50%; + transform: translateX(-50%); + + &::after { + border-color: $secondary transparent transparent transparent; + left: 50%; + top: 100%; + transform: translateX(-50%); + } } } &:hover &__content { visibility: visible; } + + .button { + margin: 5px; + } } diff --git a/test/Tooltip.test.js b/test/Tooltip.test.js new file mode 100644 index 0000000..bf2a464 --- /dev/null +++ b/test/Tooltip.test.js @@ -0,0 +1,39 @@ +/* global describe, it */ +import React from 'react' +import expect from 'must' +import { shallow } from 'enzyme' +import Tooltip from '../react/Tooltip' + +describe('', () => { + it('renders as a tooltip', () => { + const wrapper = shallow(testtip) + expect(wrapper.children()).to.have.length(2) + expect(wrapper.children().at(0).html()).to.equal('testtip') + expect(wrapper.children().at(1).text()).to.equal('testtip') + }) + + it('renders as a tooltip__content', () => { + const wrapper = shallow(testtip) + expect(wrapper.children()).to.have.length(2) + expect(wrapper.children().at(0).html()).to.equal('testtip') + expect(wrapper.children().at(1).text()).to.equal('testtip') + }) + + it('renders classes', () => { + const wrapper = shallow(foo bar) + const content = wrapper.children('.tooltip__content') + expect(wrapper.hasClass('tooltip')).to.be.true() + expect(content.hasClass('tooltip__content--bottom')).to.be.true() + expect(content.hasClass('tooltip__content--left')).to.be.true() + expect(content.hasClass('tooltip__content--right')).to.be.true() + expect(content.hasClass('tooltip__content--top')).to.be.true() + expect(content.hasClass('tooltip__content--primary')).to.be.true() + expect(content.hasClass('tooltip__content--urgent')).to.be.true() + }) + + it('renders its text', () => { + const wrapper = shallow(lorem ipsum) + expect(wrapper.children('.tooltip__content').text()).to.equal('muspi') + expect(wrapper.text()).to.equal('muspilorem ipsum') + }) +}) diff --git a/todo/Section/TooltipDemo.jsx b/todo/Section/TooltipDemo.jsx index 1423bbe..7b2da99 100644 --- a/todo/Section/TooltipDemo.jsx +++ b/todo/Section/TooltipDemo.jsx @@ -1,14 +1,16 @@ import React from 'react' +import Button from '../../react/Button' +import Icon from '../../react/Icon' import Tooltip from '../../react/Tooltip' const TooltipDemo = () => (

Tooltips

- Default Top - Default Top - Default Top - Default Top + + + +
) From a7490627026938099a583a335f99e280aa3053a7 Mon Sep 17 00:00:00 2001 From: dustinengle Date: Tue, 21 Aug 2018 14:12:14 -0700 Subject: [PATCH 2/4] icon button fix --- react/IconButton.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/react/IconButton.jsx b/react/IconButton.jsx index 7520bd8..9cdc2d8 100644 --- a/react/IconButton.jsx +++ b/react/IconButton.jsx @@ -9,7 +9,7 @@ export default class IconButton extends React.Component { const [ mods, {children, as, k, ...rest} ] = pickRest(this.props, ['primary', 'secondary', 'disabled']) const As = as return ( - + ) From 1420139dcaacf2739fa192342bc4b372801c2081 Mon Sep 17 00:00:00 2001 From: dustinengle Date: Tue, 21 Aug 2018 14:18:21 -0700 Subject: [PATCH 3/4] tooltip test fix #23 --- test/Tooltip.test.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/Tooltip.test.js b/test/Tooltip.test.js index bf2a464..58a4dbd 100644 --- a/test/Tooltip.test.js +++ b/test/Tooltip.test.js @@ -7,9 +7,7 @@ import Tooltip from '../react/Tooltip' describe('', () => { it('renders as a tooltip', () => { const wrapper = shallow(testtip) - expect(wrapper.children()).to.have.length(2) - expect(wrapper.children().at(0).html()).to.equal('testtip') - expect(wrapper.children().at(1).text()).to.equal('testtip') + expect(wrapper.hasClass('tooltip')).to.be.true() }) it('renders as a tooltip__content', () => { From a7c0c3357988f70bd9422a5f599b5f9760919621 Mon Sep 17 00:00:00 2001 From: dustinengle Date: Tue, 21 Aug 2018 14:20:08 -0700 Subject: [PATCH 4/4] added more test for tooltip #23 --- test/Tooltip.test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/Tooltip.test.js b/test/Tooltip.test.js index 58a4dbd..8d22400 100644 --- a/test/Tooltip.test.js +++ b/test/Tooltip.test.js @@ -7,12 +7,14 @@ import Tooltip from '../react/Tooltip' describe('', () => { it('renders as a tooltip', () => { const wrapper = shallow(testtip) + expect(wrapper.is('div')).to.be.true() expect(wrapper.hasClass('tooltip')).to.be.true() }) it('renders as a tooltip__content', () => { const wrapper = shallow(testtip) expect(wrapper.children()).to.have.length(2) + expect(wrapper.children().at(0).is('span')).to.be.true() expect(wrapper.children().at(0).html()).to.equal('testtip') expect(wrapper.children().at(1).text()).to.equal('testtip') })