mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
- Move to using Material-UI's <Icon /> and <SvgIcon /> - Move to using Material-UI's <Tooltip /> - Move to using Material-UI's <IconButton /> - Switch *.svg webpack importer so we can import then as React components - Export the above to the extension API - Move to using the Material-UI's component names for menuItem.icon's. This means that they are now in PascalCase instead of snake_case - Remove the Material-UI font Signed-off-by: Sebastian Malton <sebastian@malton.name>
125 lines
3.5 KiB
TypeScript
125 lines
3.5 KiB
TypeScript
import "./icon.scss";
|
|
|
|
import React, { ReactNode } from "react";
|
|
import { findDOMNode } from "react-dom";
|
|
import { NavLink } from "react-router-dom";
|
|
import { LocationDescriptor } from "history";
|
|
import { autobind, cssNames } from "../../utils";
|
|
import { TooltipDecoratorProps, withTooltip } from "../tooltip";
|
|
import isNumber from "lodash/isNumber";
|
|
|
|
export interface IconProps extends React.HTMLAttributes<any>, TooltipDecoratorProps {
|
|
material?: string; // material-icon, see available names at https://material.io/icons/
|
|
link?: LocationDescriptor; // render icon as NavLink from react-router-dom
|
|
href?: string; // render icon as hyperlink
|
|
size?: string | number; // icon-size
|
|
small?: boolean; // pre-defined icon-size
|
|
smallest?: boolean; // pre-defined icon-size
|
|
big?: boolean; // pre-defined icon-size
|
|
active?: boolean; // apply active-state styles
|
|
interactive?: boolean; // indicates that icon is interactive and highlight it on focus/hover
|
|
focusable?: boolean; // allow focus to the icon + show .active styles (default: "true", when icon is interactive)
|
|
sticker?: boolean;
|
|
disabled?: boolean;
|
|
}
|
|
|
|
@withTooltip
|
|
export class Icon extends React.PureComponent<IconProps> {
|
|
static defaultProps: IconProps = {
|
|
focusable: true,
|
|
};
|
|
|
|
get isInteractive() {
|
|
const { interactive, onClick, href, link } = this.props;
|
|
|
|
return interactive ?? !!(onClick || href || link);
|
|
}
|
|
|
|
@autobind()
|
|
onClick(evt: React.MouseEvent) {
|
|
if (this.props.disabled) {
|
|
return;
|
|
}
|
|
|
|
if (this.props.onClick) {
|
|
this.props.onClick(evt);
|
|
}
|
|
}
|
|
|
|
@autobind()
|
|
onKeyDown(evt: React.KeyboardEvent<any>) {
|
|
switch (evt.nativeEvent.code) {
|
|
case "Space":
|
|
|
|
case "Enter": {
|
|
// eslint-disable-next-line react/no-find-dom-node
|
|
const icon = findDOMNode(this) as HTMLElement;
|
|
|
|
setTimeout(() => icon.click());
|
|
evt.preventDefault();
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (this.props.onKeyDown) {
|
|
this.props.onKeyDown(evt);
|
|
}
|
|
}
|
|
|
|
render() {
|
|
const { isInteractive } = this;
|
|
const {
|
|
// skip passing props to icon's html element
|
|
className, href, link, material, size, smallest, small, big,
|
|
disabled, sticker, active, focusable, children,
|
|
interactive: _interactive,
|
|
onClick: _onClick,
|
|
onKeyDown: _onKeyDown,
|
|
...elemProps
|
|
} = this.props;
|
|
|
|
let iconContent: ReactNode;
|
|
const iconProps: Partial<IconProps> = {
|
|
className: cssNames("Icon", className,
|
|
{ material, interactive: isInteractive, disabled, sticker, active, focusable },
|
|
!size ? { smallest, small, big } : {}
|
|
),
|
|
onClick: isInteractive ? this.onClick : undefined,
|
|
onKeyDown: isInteractive ? this.onKeyDown : undefined,
|
|
tabIndex: isInteractive && focusable && !disabled ? 0 : undefined,
|
|
style: size ? { "--size": size + (isNumber(size) ? "px" : "") } as React.CSSProperties : undefined,
|
|
...elemProps
|
|
};
|
|
|
|
// render as material-icon
|
|
if (material) {
|
|
iconContent = <span className="icon">{material}</span>;
|
|
}
|
|
|
|
// wrap icon's content passed from decorator
|
|
iconProps.children = (
|
|
<>
|
|
{iconContent}
|
|
{children}
|
|
</>
|
|
);
|
|
|
|
// render icon type
|
|
if (link) {
|
|
const { className, children } = iconProps;
|
|
|
|
return (
|
|
<NavLink className={className} to={link}>
|
|
{children}
|
|
</NavLink>
|
|
);
|
|
}
|
|
|
|
if (href) {
|
|
return <a {...iconProps} href={href}/>;
|
|
}
|
|
|
|
return <i {...iconProps} />;
|
|
}
|
|
}
|