widgetFrame.stories.tsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import JSXNode from 'sentry/components/stories/jsxNode';
  4. import SideBySide from 'sentry/components/stories/sideBySide';
  5. import {t} from 'sentry/locale';
  6. import storyBook from 'sentry/stories/storyBook';
  7. import {WidgetFrame} from 'sentry/views/dashboards/widgets/common/widgetFrame';
  8. export default storyBook(WidgetFrame, story => {
  9. story('Getting Started', () => {
  10. return (
  11. <Fragment>
  12. <p>
  13. <JSXNode name="WidgetFrame" /> is a container element used for all widgets in
  14. the Dashboards Widget Platform. It's mostly an under-the-hood component, but it
  15. can be useful to emulate widget-like states, like widget cards with actions.
  16. </p>
  17. </Fragment>
  18. );
  19. });
  20. story('Layout', () => {
  21. return (
  22. <Fragment>
  23. <p>
  24. <JSXNode name="WidgetFrame" /> supports a few basic props that control its
  25. content. This includes a title, a description, and the <code>children</code>.
  26. The title is automatically wrapped in a tooltip if it does not fit.
  27. </p>
  28. <SideBySide>
  29. <NormalWidget>
  30. <WidgetFrame
  31. title="Count"
  32. description="This counts up the amount of something that happens."
  33. />
  34. </NormalWidget>
  35. <NormalWidget>
  36. <WidgetFrame
  37. title="p95(measurements.lcp) / p95(measurements.inp)"
  38. description="This is a tough formula to reason about"
  39. />
  40. </NormalWidget>
  41. </SideBySide>
  42. </Fragment>
  43. );
  44. });
  45. story('Warnings', () => {
  46. return (
  47. <Fragment>
  48. <p>
  49. <JSXNode name="WidgetFrame" /> supports a <code>warnings</code> prop. If
  50. supplied, it shows a small warning icon next to the title. Hovering over the
  51. icon shows the warnings.
  52. </p>
  53. <SideBySide>
  54. <NormalWidget>
  55. <WidgetFrame
  56. title="count()"
  57. warnings={[
  58. 'We have automatically converted this widget to use sampled data.',
  59. 'Data for this metrics has not been extracted yet',
  60. ]}
  61. />
  62. </NormalWidget>
  63. </SideBySide>
  64. </Fragment>
  65. );
  66. });
  67. story('Badge', () => {
  68. return (
  69. <Fragment>
  70. <p>
  71. <JSXNode name="WidgetFrame" /> supports a <code>badgeProps</code> prop. If
  72. passed, a<code>Badge</code> component with the relevant props appears in the
  73. header.
  74. </p>
  75. <SideBySide>
  76. <NormalWidget>
  77. <WidgetFrame
  78. title="count()"
  79. badgeProps={{
  80. text: 'Sampled',
  81. type: 'default',
  82. }}
  83. warnings={[
  84. 'We have automatically converted this widget to use sampled data.',
  85. 'Data for this metrics has not been extracted yet',
  86. ]}
  87. />
  88. </NormalWidget>
  89. </SideBySide>
  90. </Fragment>
  91. );
  92. });
  93. story('Action Menu', () => {
  94. return (
  95. <Fragment>
  96. <p>
  97. <JSXNode name="WidgetFrame" /> supports an action menu. If only one action is
  98. passed, the single action is rendered as a small button. If multiple actions are
  99. passed, they are grouped into a dropdown menu. Menu actions appear on hover or
  100. keyboard focus.
  101. </p>
  102. <SideBySide>
  103. <NormalWidget>
  104. <WidgetFrame
  105. title="Count"
  106. description="This counts up the amount of something that happens."
  107. actions={[
  108. {
  109. key: 'see-more',
  110. label: t('See More'),
  111. onAction: () => {
  112. // eslint-disable-next-line no-console
  113. console.log('See more!');
  114. },
  115. },
  116. ]}
  117. />
  118. </NormalWidget>
  119. <NormalWidget>
  120. <WidgetFrame
  121. title="Count"
  122. description="This is a tough formula to reason about"
  123. actions={[
  124. {
  125. key: 'see-more',
  126. label: t('See More'),
  127. onAction: () => {
  128. // eslint-disable-next-line no-console
  129. console.log('See more!');
  130. },
  131. },
  132. {
  133. key: 'see-less',
  134. label: t('See Less'),
  135. onAction: () => {
  136. // eslint-disable-next-line no-console
  137. console.log('See less!');
  138. },
  139. },
  140. ]}
  141. />
  142. </NormalWidget>
  143. </SideBySide>
  144. </Fragment>
  145. );
  146. });
  147. story('Full Screen View Button', () => {
  148. return (
  149. <Fragment>
  150. <p>
  151. <JSXNode name="WidgetFrame" /> supports a <code>onOpenFullScreenView</code>{' '}
  152. prop. This is a special action that always appears as an individual icon to the
  153. right of the normal actions.
  154. </p>
  155. <SideBySide>
  156. <NormalWidget>
  157. <WidgetFrame title="count()" onFullScreenViewClick={() => {}} />
  158. </NormalWidget>
  159. </SideBySide>
  160. </Fragment>
  161. );
  162. });
  163. });
  164. const NormalWidget = styled('div')`
  165. width: 250px;
  166. height: 100px;
  167. `;