arrayLinks.tsx 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import {useState} from 'react';
  2. import {Link} from 'react-router';
  3. import styled from '@emotion/styled';
  4. import {LocationDescriptor} from 'history';
  5. import {t} from 'sentry/locale';
  6. import space from 'sentry/styles/space';
  7. type Item = {
  8. target: LocationDescriptor;
  9. value: string;
  10. };
  11. interface ArrayLinksProps {
  12. items: Item[];
  13. }
  14. function ArrayLinks({items}: ArrayLinksProps) {
  15. const [expanded, setExpanded] = useState(false);
  16. return (
  17. <ArrayContainer expanded={expanded}>
  18. {items.length > 0 && <LinkedItem item={items[0]} />}
  19. {items.length > 1 &&
  20. expanded &&
  21. items
  22. .slice(1, items.length)
  23. .map(item => <LinkedItem key={item.value} item={item} />)}
  24. {items.length > 1 ? (
  25. <ButtonContainer>
  26. <button onClick={() => setExpanded(!expanded)}>
  27. {expanded ? t('[collapse]') : t('[+%s more]', items.length - 1)}
  28. </button>
  29. </ButtonContainer>
  30. ) : null}
  31. </ArrayContainer>
  32. );
  33. }
  34. function LinkedItem({item}: {item: Item}) {
  35. return (
  36. <ArrayItem>
  37. <Link to={item.target}>{item.value}</Link>
  38. </ArrayItem>
  39. );
  40. }
  41. const ArrayContainer = styled('div')<{expanded: boolean}>`
  42. display: flex;
  43. flex-direction: ${p => (p.expanded ? 'column' : 'row')};
  44. `;
  45. const ArrayItem = styled('span')`
  46. flex-shrink: 1;
  47. display: block;
  48. ${p => p.theme.overflowEllipsis};
  49. width: unset;
  50. `;
  51. const ButtonContainer = styled('div')`
  52. white-space: nowrap;
  53. & button {
  54. background: none;
  55. border: 0;
  56. outline: none;
  57. padding: 0;
  58. cursor: pointer;
  59. color: ${p => p.theme.blue300};
  60. margin-left: ${space(0.5)};
  61. }
  62. `;
  63. export {ArrayLinks};