Skip to content

Commit

Permalink
UI improvements hover tooltip (#2150)
Browse files Browse the repository at this point in the history
* move style to style file

* move style to style file

* fix icon stack

* add 99+ notifications messaging

* replace span and div in components

* fixes based on review

* some changes

* some fix

* post build
  • Loading branch information
cphelefu authored May 21, 2024
1 parent eb50540 commit da7d45b
Show file tree
Hide file tree
Showing 22 changed files with 151 additions and 210 deletions.
2 changes: 1 addition & 1 deletion packages/geoview-basemap-panel/src/basemap-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ export function BasemapPanel(props: BaseMapPanelProps): JSX.Element {
// eslint-disable-next-line react/no-array-index-key
return <img key={index} src={thumbnail} alt={basemap.altText} className="basemapCardThumbnail" />;
})}
<div className={basemap.basemapId !== activeBasemapId ? 'basemapCardThumbnailOverlay' : ''} />
<Box className={basemap.basemapId !== activeBasemapId ? 'basemapCardThumbnailOverlay' : ''} />
</>
}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export default function Version(): JSX.Element {

return (
<ClickAwayListener mouseEvent="onMouseDown" touchEvent="onTouchStart" onClickAway={handleClickAway}>
<div>
<Box>
<IconButton
id="version-button"
tooltip="appbar.version"
Expand Down Expand Up @@ -111,7 +111,7 @@ export default function Version(): JSX.Element {
</Box>
</Paper>
</Popper>
</div>
</Box>
</ClickAwayListener>
);
}
74 changes: 72 additions & 2 deletions packages/geoview-core/src/core/components/common/layer-icon.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,78 @@
import { Box, CircularProgressBase, ErrorIcon, GroupWorkOutlinedIcon } from '@/ui';
import { useTheme } from '@mui/material/styles';
import { Box, CircularProgressBase, ErrorIcon, GroupWorkOutlinedIcon, IconButton, BrowserNotSupportedIcon } from '@/ui';
import { TypeLegendLayer } from '@/core/components/layers/types';
import { IconStack } from '@/core/components/icon-stack/icon-stack';
import { getSxClasses } from './layer-icon-style';
import { useIconLayerSet } from '@/core/stores/store-interface-and-intial-values/layer-state';
import { LayerListEntry } from '.';

export interface TypeIconStackProps {
layerPath: string;
onIconClick?: () => void;
onStackIconClick?: (e: React.KeyboardEvent<HTMLElement>) => void;
}

/**
* Icon Stack to represent layer icons
*
* @param {string} layerPath
* @returns {JSX.Element} the icon stack item
*/
function IconStack({ layerPath, onIconClick, onStackIconClick }: TypeIconStackProps): JSX.Element | null {
const theme = useTheme();
const sxClasses = getSxClasses(theme);

const iconData = useIconLayerSet(layerPath);

const iconImage: string = iconData?.length > 0 ? iconData[0] : '';
const iconImageStacked: string = iconData?.length > 1 ? iconData[1] : '';
const numOfIcons: number | undefined = iconData?.length;

const iconStackContent = (): JSX.Element | null => {
// TODO: refactor - try to remove the nested ternary to simplify reading
// eslint-disable-next-line no-nested-ternary
return numOfIcons === 1 ? (
<IconButton
tabIndex={-1}
sx={sxClasses.iconPreview}
color="primary"
size="small"
onClick={iconImage === 'no data' ? undefined : onIconClick}
aria-hidden="true"
>
{iconImage === 'no data' ? (
<BrowserNotSupportedIcon />
) : (
<Box sx={sxClasses.legendIcon}>
<img alt="icon" src={iconImage} style={sxClasses.maxIconImg} />
</Box>
)}
</IconButton>
) : // eslint-disable-next-line no-nested-ternary
numOfIcons && numOfIcons > 0 ? (
<Box tabIndex={-1} onClick={onIconClick} sx={sxClasses.stackIconsBox} onKeyPress={(e) => onStackIconClick?.(e)} aria-hidden="true">
<IconButton sx={sxClasses.iconPreviewStacked} color="primary" size="small" tabIndex={-1} aria-hidden="true">
<Box sx={sxClasses.legendIconTransparent}>
{iconImageStacked && <img alt="icon" src={iconImageStacked} style={sxClasses.maxIconImg} />}
</Box>
</IconButton>
<IconButton sx={sxClasses.iconPreviewHoverable} color="primary" size="small" tabIndex={-1} aria-hidden="true">
<Box sx={sxClasses.legendIcon}>{iconImage && <img alt="icon" src={iconImage} style={sxClasses.maxIconImg} />}</Box>
</IconButton>
</Box>
) : layerPath !== '' && iconData.length === 0 && layerPath.charAt(0) !== '!' ? (
<Box tabIndex={-1} onClick={onIconClick} sx={sxClasses.stackIconsBox} onKeyPress={(e) => onStackIconClick?.(e)} aria-hidden="true">
<IconButton sx={sxClasses.iconPreviewStacked} color="primary" size="small" tabIndex={-1} aria-hidden="true">
<Box sx={sxClasses.legendIconTransparent}>
<BrowserNotSupportedIcon />
</Box>
</IconButton>
</Box>
) : null;
};

return iconStackContent();
}

interface LayerIconProps {
layer: TypeLegendLayer | LayerListEntry;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ const ResponsiveGridLayout = forwardRef(
[theme.breakpoints.down('md')]: { justifyContent: 'space-between' },
}}
>
{rightTop ?? <div />}
{rightTop ?? <Box />}

<Box sx={{ display: 'flex', flexDirection: 'row', gap: '0.6rem' }}>
{!fullWidth && !hideEnlargeBtn && renderEnlargeButton()}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,7 @@ export default function DataTableModal(): JSX.Element {
* @returns {JSX.Element}
*/
const getCellValue = (cellValue: string): JSX.Element => {
return (
<Box component="div" sx={sxClasses.tableCell}>
{cellValue}
</Box>
);
return <Box sx={sxClasses.tableCell}>{cellValue}</Box>;
};

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Theme } from '@mui/material/styles';

// ? I doubt we want to define an explicit type for style properties?
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const getSxClasses = (theme: Theme): any => ({
tooltipItem: {
color: theme.palette.geoViewColor.bgColor.light[900],
background: theme.palette.geoViewColor.bgColor.dark[900],
opacity: 0.9,
fontSize: theme.palette.geoViewFontSize.default,
padding: '3px 8px',
borderRadius: '5px',
textAlign: 'center',
maxWidth: '350px',
maxHeight: '60px',
position: 'absolute',
display: 'flex',
top: '-5px',
left: '3px',
},
tooltipText: {
fontSize: theme.palette.geoViewFontSize.default,
color: theme.palette.geoViewColor.bgColor.light[900],
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
overflow: 'hidden',
padding: '5px',
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import { useTheme, Theme } from '@mui/material/styles';
import { Box } from '@/ui';
import { logger } from '@/core/utils/logger';
import { useMapHoverFeatureInfo, useMapPointerPosition } from '@/core/stores/store-interface-and-intial-values/map-state';
import { getSxClasses } from './hover-tooltip-styles';

/**
* Hover tooltip component to show name field information on hover
*
* @returns {JSX.Element} the hover tooltip component
*/
export function HoverTooltip(): JSX.Element {
export function HoverTooltip(): JSX.Element | null {
// Log, commented too annoying
// logger.logTraceRender('components/hover-tooltip/hover-tooltip');

Expand All @@ -21,38 +22,14 @@ export function HoverTooltip(): JSX.Element {
iconImage: React.CSSProperties;
} = useTheme();

const sxClasses = {
tooltipItem: {
color: theme.palette.geoViewColor.bgColor.light[900],
background: theme.palette.geoViewColor.bgColor.dark[900],
opacity: 0.9,
fontSize: theme.palette.geoViewFontSize.default,
padding: '3px 8px',
borderRadius: '5px',
textAlign: 'center',
maxWidth: '350px',
maxHeight: '60px',
position: 'absolute',
display: 'flex',
top: '-5px',
left: '3px',
},
tooltipText: {
fontSize: theme.palette.geoViewFontSize.default,
color: theme.palette.geoViewColor.bgColor.light[900],
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
overflow: 'hidden',
padding: '5px',
},
};

// internal component state
const [pixel, setPixel] = useState<[number, number]>([0, 0]);
const [tooltipValue, setTooltipValue] = useState<string>('');
const [tooltipIcon, setTooltipIcon] = useState<string>('');
const [showTooltip, setShowTooltip] = useState<boolean>(false);

const sxClasses = getSxClasses(theme);

// store state
const hoverFeatureInfo = useMapHoverFeatureInfo();
const pointerPosition = useMapPointerPosition();
Expand Down Expand Up @@ -81,6 +58,10 @@ export function HoverTooltip(): JSX.Element {
if (pointerPosition !== undefined) setPixel(pointerPosition.pixel as [number, number]);
}, [pointerPosition]);

if (showTooltip && !tooltipValue) {
return null;
}

return (
<Box
sx={sxClasses.tooltipItem}
Expand Down
Loading

0 comments on commit da7d45b

Please sign in to comment.