Files
2024-02-15 17:01:50 +00:00

92 lines
2.3 KiB
TypeScript

import {browserHistory} from 'react-router';
import styled from '@emotion/styled';
import type {LocationDescriptorObject} from 'history';
import Link from 'sentry/components/links/link';
import {IconArrow} from 'sentry/icons';
export type Alignments = 'left' | 'right' | undefined;
export type Directions = 'desc' | 'asc' | undefined;
type Props = {
align: Alignments;
canSort: boolean;
direction: Directions;
generateSortLink: () => LocationDescriptorObject | undefined;
title: React.ReactNode;
onClick?: (e: React.MouseEvent<HTMLAnchorElement>) => void;
replace?: boolean;
};
function SortLink({
align,
title,
canSort,
generateSortLink,
onClick,
direction,
replace,
}: Props) {
const target = generateSortLink();
if (!target || !canSort) {
return <StyledNonLink align={align}>{title}</StyledNonLink>;
}
const arrow = !direction ? null : (
<StyledIconArrow size="xs" direction={direction === 'desc' ? 'down' : 'up'} />
);
const handleOnClick: React.MouseEventHandler<HTMLAnchorElement> = e => {
if (replace) {
e.preventDefault();
browserHistory.replace(target);
}
onClick?.(e);
};
return (
<StyledLink align={align} to={target} onClick={handleOnClick}>
{title} {arrow}
</StyledLink>
);
}
type LinkProps = React.ComponentPropsWithoutRef<typeof Link>;
type StyledLinkProps = LinkProps & {align: Alignments};
const StyledLink = styled((props: StyledLinkProps) => {
// @ts-expect-error It doesn't look like the `css` property is a part of the props,
// but prior to this style of destructure-omitting it, it was being omitted
// with lodash.omit. I mean keeping it omitted here just in case.
const {align: _align, css: _css, ...forwardProps} = props;
return <Link {...forwardProps} />;
})`
display: block;
width: 100%;
white-space: nowrap;
color: inherit;
&:hover,
&:active,
&:focus,
&:visited {
color: inherit;
}
${(p: StyledLinkProps) => (p.align ? `text-align: ${p.align};` : '')}
`;
const StyledNonLink = styled('div')<{align: Alignments}>`
display: block;
width: 100%;
white-space: nowrap;
${(p: {align: Alignments}) => (p.align ? `text-align: ${p.align};` : '')}
`;
const StyledIconArrow = styled(IconArrow)`
vertical-align: top;
`;
export default SortLink;