DynamicTableWithGuidelines.tsx 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import { css, cx } from '@emotion/css';
  2. import React from 'react';
  3. import { GrafanaTheme2 } from '@grafana/data';
  4. import { useStyles2 } from '@grafana/ui';
  5. import { DynamicTable, DynamicTableProps } from './DynamicTable';
  6. export type DynamicTableWithGuidelinesProps<T> = Omit<DynamicTableProps<T>, 'renderPrefixHeader, renderPrefixCell'>;
  7. // DynamicTable, but renders visual guidelines on the left, for larger screen widths
  8. export const DynamicTableWithGuidelines = <T extends object>({
  9. renderExpandedContent,
  10. ...props
  11. }: DynamicTableWithGuidelinesProps<T>) => {
  12. const styles = useStyles2(getStyles);
  13. return (
  14. <DynamicTable
  15. renderExpandedContent={
  16. renderExpandedContent
  17. ? (item, index, items) => (
  18. <>
  19. {!(index === items.length - 1) && <div className={cx(styles.contentGuideline, styles.guideline)} />}
  20. {renderExpandedContent(item, index, items)}
  21. </>
  22. )
  23. : undefined
  24. }
  25. renderPrefixHeader={() => (
  26. <div className={styles.relative}>
  27. <div className={cx(styles.headerGuideline, styles.guideline)} />
  28. </div>
  29. )}
  30. renderPrefixCell={(_, index, items) => (
  31. <div className={styles.relative}>
  32. <div className={cx(styles.topGuideline, styles.guideline)} />
  33. {!(index === items.length - 1) && <div className={cx(styles.bottomGuideline, styles.guideline)} />}
  34. </div>
  35. )}
  36. {...props}
  37. />
  38. );
  39. };
  40. export const getStyles = (theme: GrafanaTheme2) => ({
  41. relative: css`
  42. position: relative;
  43. height: 100%;
  44. `,
  45. guideline: css`
  46. left: -19px;
  47. border-left: 1px solid ${theme.colors.border.medium};
  48. position: absolute;
  49. ${theme.breakpoints.down('md')} {
  50. display: none;
  51. }
  52. `,
  53. topGuideline: css`
  54. width: 18px;
  55. border-bottom: 1px solid ${theme.colors.border.medium};
  56. top: 0;
  57. bottom: 50%;
  58. `,
  59. bottomGuideline: css`
  60. top: 50%;
  61. bottom: 0;
  62. `,
  63. contentGuideline: css`
  64. top: 0;
  65. bottom: 0;
  66. left: -49px !important;
  67. `,
  68. headerGuideline: css`
  69. top: -25px;
  70. bottom: 0;
  71. `,
  72. });