Legend.story.tsx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import React from 'react';
  2. import { storiesOf } from '@storybook/react';
  3. import { LegendList, LegendPlacement, LegendItem, LegendTable } from './Legend';
  4. import tinycolor from 'tinycolor2';
  5. import { DisplayValue } from '@grafana/data';
  6. import { number, select, text } from '@storybook/addon-knobs';
  7. import { action } from '@storybook/addon-actions';
  8. import { GraphLegendListItem, GraphLegendTableRow, GraphLegendItemProps } from '../Graph/GraphLegendItem';
  9. export const generateLegendItems = (numberOfSeries: number, statsToDisplay?: DisplayValue[]): LegendItem[] => {
  10. const alphabet = 'abcdefghijklmnopqrstuvwxyz'.split('');
  11. return [...new Array(numberOfSeries)].map((item, i) => {
  12. return {
  13. label: `${alphabet[i].toUpperCase()}-series`,
  14. color: tinycolor.fromRatio({ h: i / alphabet.length, s: 1, v: 1 }).toHexString(),
  15. isVisible: true,
  16. yAxis: 1,
  17. displayValues: statsToDisplay || [],
  18. };
  19. });
  20. };
  21. const getStoriesKnobs = (table = false) => {
  22. const numberOfSeries = number('Number of series', 3);
  23. const containerWidth = select(
  24. 'Container width',
  25. {
  26. Small: '200px',
  27. Medium: '500px',
  28. 'Full width': '100%',
  29. },
  30. '100%'
  31. );
  32. const rawRenderer = (item: LegendItem) => (
  33. <>
  34. Label: <strong>{item.label}</strong>, Color: <strong>{item.color}</strong>, isVisible:{' '}
  35. <strong>{item.isVisible ? 'yes' : 'no'}</strong>
  36. </>
  37. );
  38. const customRenderer = (component: React.ComponentType<GraphLegendItemProps>) => (item: LegendItem) =>
  39. React.createElement(component, {
  40. item,
  41. onLabelClick: action('GraphLegendItem label clicked'),
  42. onSeriesColorChange: action('Series color changed'),
  43. onToggleAxis: action('Y-axis toggle'),
  44. });
  45. const typeSpecificRenderer = table
  46. ? {
  47. 'Custom renderer(GraphLegendTablerow)': 'custom-tabe',
  48. }
  49. : {
  50. 'Custom renderer(GraphLegendListItem)': 'custom-list',
  51. };
  52. const legendItemRenderer = select(
  53. 'Item rendered',
  54. {
  55. 'Raw renderer': 'raw',
  56. ...typeSpecificRenderer,
  57. },
  58. 'raw'
  59. );
  60. const rightAxisSeries = text('Right y-axis series, i.e. A,C', '');
  61. const legendPlacement = select<LegendPlacement>(
  62. 'Legend placement',
  63. {
  64. under: 'under',
  65. right: 'right',
  66. },
  67. 'under'
  68. );
  69. return {
  70. numberOfSeries,
  71. containerWidth,
  72. itemRenderer:
  73. legendItemRenderer === 'raw'
  74. ? rawRenderer
  75. : customRenderer(legendItemRenderer === 'custom-list' ? GraphLegendListItem : GraphLegendTableRow),
  76. rightAxisSeries,
  77. legendPlacement,
  78. };
  79. };
  80. const LegendStories = storiesOf('UI/Legend/Legend', module);
  81. LegendStories.add('list', () => {
  82. const { numberOfSeries, itemRenderer, containerWidth, rightAxisSeries, legendPlacement } = getStoriesKnobs();
  83. let items = generateLegendItems(numberOfSeries);
  84. items = items.map(i => {
  85. if (
  86. rightAxisSeries
  87. .split(',')
  88. .map(s => s.trim())
  89. .indexOf(i.label.split('-')[0]) > -1
  90. ) {
  91. i.yAxis = 2;
  92. }
  93. return i;
  94. });
  95. return (
  96. <div style={{ width: containerWidth }}>
  97. <LegendList itemRenderer={itemRenderer} items={items} placement={legendPlacement} />
  98. </div>
  99. );
  100. });
  101. LegendStories.add('table', () => {
  102. const { numberOfSeries, itemRenderer, containerWidth, rightAxisSeries, legendPlacement } = getStoriesKnobs(true);
  103. let items = generateLegendItems(numberOfSeries);
  104. items = items.map(i => {
  105. if (
  106. rightAxisSeries
  107. .split(',')
  108. .map(s => s.trim())
  109. .indexOf(i.label.split('-')[0]) > -1
  110. ) {
  111. i.yAxis = 2;
  112. }
  113. return {
  114. ...i,
  115. info: [
  116. { title: 'min', text: '14.42', numeric: 14.427101844163694 },
  117. { title: 'max', text: '18.42', numeric: 18.427101844163694 },
  118. ],
  119. };
  120. });
  121. return (
  122. <div style={{ width: containerWidth }}>
  123. <LegendTable itemRenderer={itemRenderer} items={items} columns={['', 'min', 'max']} placement={legendPlacement} />
  124. </div>
  125. );
  126. });