mirror of
https://github.com/apache/superset.git
synced 2024-09-18 11:39:49 -04:00
feat(control-utils): add infotooltipwithtrigger (#442)
* PR to merge packges for controls migration * fix: add bootstrap * fix: change tooltip to tsx * fix: types * fix: tsx error * appease linter, enhance a11y * addressing PR feedback * tweaking bootstrap types * fix test * test enter key * moar tests * code > key * ugh fine Co-authored-by: Phillip Kelley-Dotson <pkd@pkd.lan> Co-authored-by: David Aaron Suddjian <aasuddjian@gmail.com>
This commit is contained in:
parent
d40a7d140a
commit
307fb23bd6
@ -27,6 +27,15 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@superset-ui/translation": "^0.13",
|
||||
"@superset-ui/validator": "^0.13"
|
||||
"@superset-ui/validator": "^0.13",
|
||||
"react": "^16.13.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"enzyme": "^3.11.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/react-bootstrap": "0.32.21",
|
||||
"lodash": "^4.17.15",
|
||||
"react-bootstrap": "^0.33.1"
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { kebabCase } from 'lodash';
|
||||
import { Tooltip, OverlayTrigger } from 'react-bootstrap';
|
||||
|
||||
const tooltipStyle: React.CSSProperties = { wordWrap: 'break-word' };
|
||||
|
||||
interface Props {
|
||||
label?: string;
|
||||
tooltip?: string;
|
||||
icon?: string;
|
||||
onClick?: () => void;
|
||||
placement?: string;
|
||||
bsStyle?: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export default function InfoTooltipWithTrigger({
|
||||
label,
|
||||
tooltip,
|
||||
bsStyle,
|
||||
onClick,
|
||||
icon = 'info-circle',
|
||||
className = 'text-muted',
|
||||
placement = 'right',
|
||||
}: Props) {
|
||||
const iconClass = `fa fa-${icon} ${className} ${bsStyle ? `text-${bsStyle}` : ''}`;
|
||||
const iconEl = (
|
||||
<i
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
className={iconClass}
|
||||
style={{ cursor: onClick ? 'pointer' : undefined }}
|
||||
onClick={onClick}
|
||||
onKeyPress={
|
||||
onClick &&
|
||||
((event: React.KeyboardEvent) => {
|
||||
if (event.key === 'Enter' || event.key === ' ') {
|
||||
onClick();
|
||||
}
|
||||
})
|
||||
}
|
||||
/>
|
||||
);
|
||||
if (!tooltip) {
|
||||
return iconEl;
|
||||
}
|
||||
return (
|
||||
<OverlayTrigger
|
||||
placement={placement}
|
||||
overlay={
|
||||
<Tooltip id={`${kebabCase(label)}-tooltip`} style={tooltipStyle}>
|
||||
{tooltip}
|
||||
</Tooltip>
|
||||
}
|
||||
>
|
||||
{iconEl}
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
@ -3,3 +3,4 @@ import * as sectionModules from './sections';
|
||||
export const sections = sectionModules;
|
||||
export { D3_FORMAT_DOCS, D3_FORMAT_OPTIONS, D3_TIME_FORMAT_OPTIONS } from './D3Formatting';
|
||||
export { formatSelectOptions, formatSelectOptionsForRange } from './selectOptions';
|
||||
export { default as InfoTooltipWithTrigger } from './InfoTooltipWithTrigger';
|
||||
|
@ -0,0 +1,34 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { OverlayTrigger } from 'react-bootstrap';
|
||||
import InfoTooltipWithTrigger from '../src/InfoTooltipWithTrigger';
|
||||
|
||||
describe('InfoTooltipWithTrigger', () => {
|
||||
it('renders a tooltip', () => {
|
||||
const wrapper = shallow(<InfoTooltipWithTrigger label="test" tooltip="this is a test" />);
|
||||
expect(wrapper.find(OverlayTrigger)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('renders an info icon', () => {
|
||||
const wrapper = shallow(<InfoTooltipWithTrigger />);
|
||||
expect(wrapper.find('.fa-info-circle')).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('responds to keypresses', () => {
|
||||
const clickHandler = jest.fn();
|
||||
const wrapper = shallow(
|
||||
<InfoTooltipWithTrigger label="test" tooltip="this is a test" onClick={clickHandler} />,
|
||||
);
|
||||
wrapper.find('.fa-info-circle').simulate('keypress', { key: 'Tab' });
|
||||
expect(clickHandler).toHaveBeenCalledTimes(0);
|
||||
wrapper.find('.fa-info-circle').simulate('keypress', { key: 'Enter' });
|
||||
expect(clickHandler).toHaveBeenCalledTimes(1);
|
||||
wrapper.find('.fa-info-circle').simulate('keypress', { key: ' ' });
|
||||
expect(clickHandler).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('has a bsStyle', () => {
|
||||
const wrapper = shallow(<InfoTooltipWithTrigger bsStyle="something" />);
|
||||
expect(wrapper.find('.text-something')).toHaveLength(1);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user