arrayLinks.tsx 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  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. const firstItem = items[0];
  17. return (
  18. <ArrayContainer expanded={expanded}>
  19. {firstItem && <LinkedItem item={firstItem} />}
  20. {items.length > 1 &&
  21. expanded &&
  22. items
  23. .slice(1, items.length)
  24. .map(item => <LinkedItem key={item.value} item={item} />)}
  25. {items.length > 1 ? (
  26. <ButtonContainer>
  27. <button onClick={() => setExpanded(!expanded)}>
  28. {expanded ? t('[collapse]') : t('[+%s more]', items.length - 1)}
  29. </button>
  30. </ButtonContainer>
  31. ) : null}
  32. </ArrayContainer>
  33. );
  34. }
  35. function LinkedItem({item}: {item: Item}) {
  36. return (
  37. <ArrayItem>
  38. <Link to={item.target}>{item.value}</Link>
  39. </ArrayItem>
  40. );
  41. }
  42. const ArrayContainer = styled('div')<{expanded: boolean}>`
  43. display: flex;
  44. flex-direction: ${p => (p.expanded ? 'column' : 'row')};
  45. `;
  46. const ArrayItem = styled('span')`
  47. flex-shrink: 1;
  48. display: block;
  49. ${p => p.theme.overflowEllipsis};
  50. width: unset;
  51. `;
  52. const ButtonContainer = styled('div')`
  53. white-space: nowrap;
  54. & button {
  55. background: none;
  56. border: 0;
  57. outline: none;
  58. padding: 0;
  59. cursor: pointer;
  60. color: ${p => p.theme.blue300};
  61. margin-left: ${space(0.5)};
  62. }
  63. `;
  64. export {ArrayLinks};