@opentrons/components 0.1.6-alpha.2 → 0.1.6-alpha.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (373) hide show
  1. package/Makefile +5 -1
  2. package/package.json +6 -7
  3. package/src/__mocks__/file.js +10 -0
  4. package/src/alerts/AlertItem.stories.tsx +49 -0
  5. package/src/alerts/AlertItem.tsx +85 -0
  6. package/src/alerts/index.ts +3 -0
  7. package/src/atoms/Checkbox/Checkbox.stories.tsx +24 -0
  8. package/src/atoms/Checkbox/index.tsx +127 -0
  9. package/src/atoms/CheckboxField/CheckboxField.stories.tsx +30 -0
  10. package/src/atoms/CheckboxField/index.tsx +171 -0
  11. package/src/atoms/Chip/Chip.stories.tsx +59 -0
  12. package/src/atoms/Chip/index.tsx +172 -0
  13. package/src/atoms/Divider/index.tsx +15 -0
  14. package/src/atoms/InputField/InputField.stories.tsx +77 -0
  15. package/src/atoms/InputField/index.tsx +383 -0
  16. package/src/atoms/ListButton/ListButton.stories.tsx +133 -0
  17. package/src/atoms/ListButton/ListButtonChildren/ListButtonAccordion.tsx +65 -0
  18. package/src/atoms/ListButton/ListButtonChildren/ListButtonAccordionContainer.tsx +23 -0
  19. package/src/atoms/ListButton/ListButtonChildren/ListButtonRadioButton.tsx +108 -0
  20. package/src/atoms/ListButton/ListButtonChildren/index.ts +3 -0
  21. package/src/atoms/ListButton/index.tsx +72 -0
  22. package/src/atoms/ListItem/ListItem.stories.tsx +96 -0
  23. package/src/atoms/ListItem/ListItemChildren/ListItemCustomize.tsx +78 -0
  24. package/src/atoms/ListItem/ListItemChildren/ListItemDescriptor.tsx +42 -0
  25. package/src/atoms/ListItem/ListItemChildren/index.ts +2 -0
  26. package/src/atoms/ListItem/index.tsx +89 -0
  27. package/src/atoms/MenuList/MenuItem.stories.tsx +20 -0
  28. package/src/atoms/MenuList/MenuItem.tsx +55 -0
  29. package/src/atoms/MenuList/MenuList.stories.tsx +31 -0
  30. package/src/atoms/MenuList/OverflowBtn.stories.tsx +17 -0
  31. package/src/atoms/MenuList/OverflowBtn.tsx +76 -0
  32. package/src/atoms/MenuList/index.tsx +50 -0
  33. package/src/atoms/Snackbar/Snackbar.stories.tsx +67 -0
  34. package/src/atoms/Snackbar/index.tsx +91 -0
  35. package/src/atoms/StepMeter/index.tsx +53 -0
  36. package/src/atoms/StyledText/LegacyStyledText.stories.tsx +106 -0
  37. package/src/atoms/StyledText/LegacyStyledText.tsx +95 -0
  38. package/src/atoms/StyledText/StyledText.stories.tsx +46 -0
  39. package/src/atoms/StyledText/StyledText.tsx +323 -0
  40. package/src/atoms/StyledText/index.ts +2 -0
  41. package/src/atoms/Tag/Tag.stories.tsx +48 -0
  42. package/src/atoms/Tag/index.tsx +116 -0
  43. package/src/atoms/Toast/ODDToast.stories.tsx +68 -0
  44. package/src/atoms/Toast/Toast.stories.tsx +55 -0
  45. package/src/atoms/Toast/index.tsx +439 -0
  46. package/src/atoms/ToggleGroup/ToggleGroup.stories.tsx +39 -0
  47. package/src/atoms/ToggleGroup/index.tsx +91 -0
  48. package/src/atoms/Tooltip/Tooltip.stories.tsx +99 -0
  49. package/src/atoms/Tooltip/index.tsx +38 -0
  50. package/src/atoms/buttons/AlertPrimaryButton.tsx +26 -0
  51. package/src/atoms/buttons/AltPrimaryButton.tsx +31 -0
  52. package/src/atoms/buttons/EmptySelectorButton.stories.tsx +36 -0
  53. package/src/atoms/buttons/EmptySelectorButton.tsx +83 -0
  54. package/src/atoms/buttons/LargeButton.stories.tsx +99 -0
  55. package/src/atoms/buttons/LargeButton.tsx +320 -0
  56. package/src/atoms/buttons/PrimaryButton.tsx +36 -0
  57. package/src/atoms/buttons/RadioButton.stories.tsx +35 -0
  58. package/src/atoms/buttons/RadioButton.tsx +217 -0
  59. package/src/atoms/buttons/SecondaryButton.tsx +62 -0
  60. package/src/atoms/buttons/buttons.stories.tsx +78 -0
  61. package/src/atoms/buttons/index.ts +6 -0
  62. package/src/atoms/index.ts +20 -0
  63. package/src/barrel.ts +10 -0
  64. package/src/buttons/Button.tsx +96 -0
  65. package/src/buttons/DeprecatedPrimaryButton.tsx +24 -0
  66. package/src/buttons/FlatButton.tsx +21 -0
  67. package/src/buttons/IconButton.tsx +37 -0
  68. package/src/buttons/OutlineButton.tsx +24 -0
  69. package/src/buttons/index.ts +7 -0
  70. package/src/controls/ControlInfo.tsx +13 -0
  71. package/src/controls/LabeledButton.tsx +28 -0
  72. package/src/controls/LabeledCheckbox.tsx +35 -0
  73. package/src/controls/LabeledControl.tsx +24 -0
  74. package/src/controls/LabeledRadioGroup.tsx +27 -0
  75. package/src/controls/LabeledSelect.tsx +34 -0
  76. package/src/controls/LabeledToggle.tsx +35 -0
  77. package/src/controls/StackedLabeledControl.tsx +28 -0
  78. package/src/controls/ToggleButton.tsx +25 -0
  79. package/src/controls/index.ts +10 -0
  80. package/src/forms/DeprecatedCheckboxField.stories.tsx +31 -0
  81. package/src/forms/DeprecatedCheckboxField.tsx +94 -0
  82. package/src/forms/DropdownField.stories.tsx +44 -0
  83. package/src/forms/DropdownField.tsx +106 -0
  84. package/src/forms/FormGroup.stories.tsx +31 -0
  85. package/src/forms/FormGroup.tsx +53 -0
  86. package/src/forms/InputField.stories.tsx +41 -0
  87. package/src/forms/LegacyInputField.tsx +123 -0
  88. package/src/forms/RadioGroup.stories.tsx +44 -0
  89. package/src/forms/RadioGroup.tsx +87 -0
  90. package/src/forms/Select.stories.tsx +117 -0
  91. package/src/forms/Select.tsx +132 -0
  92. package/src/forms/SelectField.tsx +94 -0
  93. package/src/forms/ToggleField.stories.tsx +31 -0
  94. package/src/forms/ToggleField.tsx +59 -0
  95. package/src/forms/index.ts +8 -0
  96. package/src/hardware-sim/BaseDeck/BaseDeck.stories.tsx +94 -0
  97. package/src/hardware-sim/BaseDeck/BaseDeck.tsx +423 -0
  98. package/src/hardware-sim/BaseDeck/SingleSlotFixture.tsx +199 -0
  99. package/src/hardware-sim/BaseDeck/SlotBase.tsx +5 -0
  100. package/src/hardware-sim/BaseDeck/SlotClip.tsx +15 -0
  101. package/src/hardware-sim/BaseDeck/StagingAreaFixture.tsx +114 -0
  102. package/src/hardware-sim/BaseDeck/WasteChuteFixture.tsx +114 -0
  103. package/src/hardware-sim/BaseDeck/WasteChuteStagingAreaFixture.tsx +68 -0
  104. package/src/hardware-sim/BaseDeck/__fixtures__/index.ts +165 -0
  105. package/src/hardware-sim/BaseDeck/index.ts +5 -0
  106. package/src/hardware-sim/BaseDeck/something.test.tsx +7 -0
  107. package/src/hardware-sim/Deck/DeckFromLayers.tsx +58 -0
  108. package/src/hardware-sim/Deck/FlexTrash.tsx +128 -0
  109. package/src/hardware-sim/Deck/MoveLabwareOnDeck.stories.tsx +97 -0
  110. package/src/hardware-sim/Deck/MoveLabwareOnDeck.tsx +251 -0
  111. package/src/hardware-sim/Deck/OT2Layers.tsx +153 -0
  112. package/src/hardware-sim/Deck/RobotCoordsForeignDiv.tsx +46 -0
  113. package/src/hardware-sim/Deck/RobotCoordsForeignObject.tsx +42 -0
  114. package/src/hardware-sim/Deck/RobotCoordsText.tsx +32 -0
  115. package/src/hardware-sim/Deck/RobotWorkSpace.tsx +90 -0
  116. package/src/hardware-sim/Deck/SlotLabels.tsx +111 -0
  117. package/src/hardware-sim/Deck/__mocks__/getDeckDefinitions.ts +29 -0
  118. package/src/hardware-sim/Deck/constants.ts +12 -0
  119. package/src/hardware-sim/Deck/index.tsx +8 -0
  120. package/src/hardware-sim/DeckConfigurator/AbsorbanceReaderFixture.tsx +91 -0
  121. package/src/hardware-sim/DeckConfigurator/DeckConfigurator.stories.tsx +110 -0
  122. package/src/hardware-sim/DeckConfigurator/EmptyConfigFixture.tsx +131 -0
  123. package/src/hardware-sim/DeckConfigurator/HeaterShakerFixture.tsx +102 -0
  124. package/src/hardware-sim/DeckConfigurator/MagneticBlockFixture.tsx +130 -0
  125. package/src/hardware-sim/DeckConfigurator/StagingAreaConfigFixture.tsx +89 -0
  126. package/src/hardware-sim/DeckConfigurator/StaticFixture.tsx +54 -0
  127. package/src/hardware-sim/DeckConfigurator/TemperatureModuleFixture.tsx +103 -0
  128. package/src/hardware-sim/DeckConfigurator/ThermocyclerFixture.tsx +89 -0
  129. package/src/hardware-sim/DeckConfigurator/TrashBinConfigFixture.tsx +99 -0
  130. package/src/hardware-sim/DeckConfigurator/WasteChuteConfigFixture.tsx +96 -0
  131. package/src/hardware-sim/DeckConfigurator/constants.ts +81 -0
  132. package/src/hardware-sim/DeckConfigurator/index.tsx +285 -0
  133. package/src/hardware-sim/DeckSlotLocation/index.tsx +88 -0
  134. package/src/hardware-sim/Labware/Labware.tsx +173 -0
  135. package/src/hardware-sim/Labware/LabwareAdapter/Opentrons96DeepWellAdapter.tsx +23 -0
  136. package/src/hardware-sim/Labware/LabwareAdapter/Opentrons96FlatBottomAdapter.tsx +7 -0
  137. package/src/hardware-sim/Labware/LabwareAdapter/OpentronsAluminumFlatBottomPlate.tsx +13 -0
  138. package/src/hardware-sim/Labware/LabwareAdapter/OpentronsAutoclavableDeckRiser.tsx +100 -0
  139. package/src/hardware-sim/Labware/LabwareAdapter/OpentronsFlex96TiprackAdapter.tsx +13 -0
  140. package/src/hardware-sim/Labware/LabwareAdapter/OpentronsToughPCRAutoSealingLid.tsx +83 -0
  141. package/src/hardware-sim/Labware/LabwareAdapter/OpentronsUniversalFlatAdapter.tsx +13 -0
  142. package/src/hardware-sim/Labware/LabwareAdapter/index.tsx +73 -0
  143. package/src/hardware-sim/Labware/LabwareRender.stories.tsx +96 -0
  144. package/src/hardware-sim/Labware/LabwareRender.tsx +173 -0
  145. package/src/hardware-sim/Labware/LabwareStackRender.tsx +272 -0
  146. package/src/hardware-sim/Labware/index.ts +6 -0
  147. package/src/hardware-sim/Labware/labwareInternals/FilledWells.tsx +39 -0
  148. package/src/hardware-sim/Labware/labwareInternals/LabwareOutline.tsx +133 -0
  149. package/src/hardware-sim/Labware/labwareInternals/LabwareWellLabels.tsx +118 -0
  150. package/src/hardware-sim/Labware/labwareInternals/StaticLabware.tsx +121 -0
  151. package/src/hardware-sim/Labware/labwareInternals/StrokedWells.tsx +38 -0
  152. package/src/hardware-sim/Labware/labwareInternals/StyledWells.tsx +77 -0
  153. package/src/hardware-sim/Labware/labwareInternals/Well.tsx +74 -0
  154. package/src/hardware-sim/Labware/labwareInternals/WellLabels.tsx +121 -0
  155. package/src/hardware-sim/Labware/labwareInternals/index.ts +8 -0
  156. package/src/hardware-sim/Labware/labwareInternals/types.ts +18 -0
  157. package/src/hardware-sim/Module/HeaterShaker.tsx +83 -0
  158. package/src/hardware-sim/Module/MagneticBlock.tsx +49 -0
  159. package/src/hardware-sim/Module/MagneticModule.tsx +51 -0
  160. package/src/hardware-sim/Module/Module.stories.tsx +90 -0
  161. package/src/hardware-sim/Module/ModuleTag.tsx +38 -0
  162. package/src/hardware-sim/Module/PlateReader.tsx +208 -0
  163. package/src/hardware-sim/Module/Temperature.tsx +54 -0
  164. package/src/hardware-sim/Module/Thermocycler/ThermocyclerGEN1.tsx +248 -0
  165. package/src/hardware-sim/Module/Thermocycler/ThermocyclerGEN2.tsx +286 -0
  166. package/src/hardware-sim/Module/Thermocycler/index.tsx +49 -0
  167. package/src/hardware-sim/Module/index.tsx +227 -0
  168. package/src/hardware-sim/Pipette/EightEmanatingNozzles.tsx +23 -0
  169. package/src/hardware-sim/Pipette/EmanatingNozzle.tsx +52 -0
  170. package/src/hardware-sim/Pipette/PipetteRender.stories.tsx +71 -0
  171. package/src/hardware-sim/Pipette/PipetteRender.tsx +92 -0
  172. package/src/hardware-sim/Pipette/constants.ts +10 -0
  173. package/src/hardware-sim/Pipette/index.ts +1 -0
  174. package/src/hardware-sim/ProtocolDeck/LabwareInfo.tsx +68 -0
  175. package/src/hardware-sim/ProtocolDeck/ProtocolDeck.stories.tsx +25 -0
  176. package/src/hardware-sim/ProtocolDeck/__fixtures__/analysis_QIAseqFX24xv4_8.json +47145 -0
  177. package/src/hardware-sim/ProtocolDeck/index.tsx +174 -0
  178. package/src/hardware-sim/ProtocolDeck/types.ts +6 -0
  179. package/src/hardware-sim/ProtocolDeck/utils/getInitiallyLoadedLabwareByAdapter.ts +33 -0
  180. package/src/hardware-sim/ProtocolDeck/utils/getLabwareInSlots.ts +155 -0
  181. package/src/hardware-sim/ProtocolDeck/utils/getLabwareInfoByLiquidId.ts +42 -0
  182. package/src/hardware-sim/ProtocolDeck/utils/getModulesInSlots.ts +129 -0
  183. package/src/hardware-sim/ProtocolDeck/utils/getStandardDeckViewLayerBlockList.ts +29 -0
  184. package/src/hardware-sim/ProtocolDeck/utils/getWellFillFromLabwareId.ts +30 -0
  185. package/src/hardware-sim/ProtocolDeck/utils/index.ts +3 -0
  186. package/src/hardware-sim/RobotCoordinateSpace/RobotCoordinateSpace.tsx +28 -0
  187. package/src/hardware-sim/RobotCoordinateSpace/RobotCoordinateSpaceWithRef.tsx +52 -0
  188. package/src/hardware-sim/RobotCoordinateSpace/index.ts +2 -0
  189. package/src/hardware-sim/index.ts +11 -0
  190. package/src/hardware-sim/utils.ts +18 -0
  191. package/src/helix-design-system/borders.ts +32 -0
  192. package/src/helix-design-system/colors.ts +100 -0
  193. package/src/helix-design-system/index.ts +4 -0
  194. package/src/helix-design-system/product/index.ts +1 -0
  195. package/src/helix-design-system/product/typography.ts +151 -0
  196. package/src/helix-design-system/style.ts +2 -0
  197. package/src/hooks/index.ts +15 -0
  198. package/src/hooks/useConditionalConfirm.ts +70 -0
  199. package/src/hooks/useDrag.ts +90 -0
  200. package/src/hooks/useIdle.ts +68 -0
  201. package/src/hooks/useInterval.ts +38 -0
  202. package/src/hooks/useLongPress.ts +83 -0
  203. package/src/hooks/useMenuHandleClickOutside.tsx +46 -0
  204. package/src/hooks/useMountEffect.ts +12 -0
  205. package/src/hooks/usePrevious.ts +19 -0
  206. package/src/hooks/useScrolling.ts +33 -0
  207. package/src/hooks/useSelectDeckLocation/SelectDeckLocation.stories.tsx +55 -0
  208. package/src/hooks/useSelectDeckLocation/index.tsx +331 -0
  209. package/src/hooks/useSwipe.ts +86 -0
  210. package/src/hooks/useTimeout.ts +33 -0
  211. package/src/hooks/useToggle.ts +27 -0
  212. package/src/icons/Icon.stories.tsx +37 -0
  213. package/src/icons/Icon.tsx +79 -0
  214. package/src/icons/IconList.stories.tsx +108 -0
  215. package/src/icons/ModuleIcon.tsx +48 -0
  216. package/src/icons/NotificationIcon.tsx +41 -0
  217. package/src/icons/icon-data.ts +821 -0
  218. package/src/icons/index.ts +6 -0
  219. package/src/images/index.ts +1 -0
  220. package/src/images/labware/index.ts +1 -0
  221. package/src/images/labware/measurement-guide/images/depth/depth-plate-flat@3x.png +0 -0
  222. package/src/images/labware/measurement-guide/images/depth/depth-plate-round@3x.png +0 -0
  223. package/src/images/labware/measurement-guide/images/depth/depth-plate-v@3x.png +0 -0
  224. package/src/images/labware/measurement-guide/images/depth/depth-reservoir-and-tubes-flat@3x.png +0 -0
  225. package/src/images/labware/measurement-guide/images/depth/depth-reservoir-and-tubes-round@3x.png +0 -0
  226. package/src/images/labware/measurement-guide/images/depth/depth-reservoir-and-tubes-v@3x.png +0 -0
  227. package/src/images/labware/measurement-guide/images/depth/length-tip-rack@3x.png +0 -0
  228. package/src/images/labware/measurement-guide/images/dimensions/footprint@3x.png +0 -0
  229. package/src/images/labware/measurement-guide/images/dimensions/height-alum-block-plate@3x.png +0 -0
  230. package/src/images/labware/measurement-guide/images/dimensions/height-alum-block-tubes@3x.png +0 -0
  231. package/src/images/labware/measurement-guide/images/dimensions/height-plate-and-reservoir@3x.png +0 -0
  232. package/src/images/labware/measurement-guide/images/dimensions/height-tip-rack@3x.png +0 -0
  233. package/src/images/labware/measurement-guide/images/dimensions/height-tube-rack-irregular@3x.png +0 -0
  234. package/src/images/labware/measurement-guide/images/dimensions/height-tube-rack@3x.png +0 -0
  235. package/src/images/labware/measurement-guide/images/offset/offset-reservoir@3x.png +0 -0
  236. package/src/images/labware/measurement-guide/images/offset/offset-well-circular@3x.png +0 -0
  237. package/src/images/labware/measurement-guide/images/offset/offset-well-rectangular@3x.png +0 -0
  238. package/src/images/labware/measurement-guide/images/shape/shape-circular@3x.png +0 -0
  239. package/src/images/labware/measurement-guide/images/shape/shape-rectangular@3x.png +0 -0
  240. package/src/images/labware/measurement-guide/images/spacing/spacing-reservoir-multi-row@3x.png +0 -0
  241. package/src/images/labware/measurement-guide/images/spacing/spacing-reservoir@3x.png +0 -0
  242. package/src/images/labware/measurement-guide/images/spacing/spacing-well-circular@3x.png +0 -0
  243. package/src/images/labware/measurement-guide/images/spacing/spacing-well-rectangular@3x.png +0 -0
  244. package/src/images/labware/measurement-guide/index.ts +272 -0
  245. package/src/index.ts +2 -0
  246. package/src/instrument/InstrumentDiagram.stories.tsx +42 -0
  247. package/src/instrument/InstrumentDiagram.tsx +58 -0
  248. package/src/instrument/InstrumentGroup.stories.tsx +88 -0
  249. package/src/instrument/InstrumentGroup.tsx +35 -0
  250. package/src/instrument/InstrumentInfo.tsx +107 -0
  251. package/src/instrument/PipetteSelect.stories.tsx +40 -0
  252. package/src/instrument/PipetteSelect.tsx +170 -0
  253. package/src/instrument/eight-channel-flex.png +0 -0
  254. package/src/instrument/index.ts +4 -0
  255. package/src/instrument/multi-channel_GEN1_800px.png +0 -0
  256. package/src/instrument/multi-channel_GEN2_800px.png +0 -0
  257. package/src/instrument/ninety-six-channel-gen1.png +0 -0
  258. package/src/instrument/pipetteGEN2Multi.png +0 -0
  259. package/src/instrument/pipetteGEN2Single.png +0 -0
  260. package/src/instrument/pipetteMulti.png +0 -0
  261. package/src/instrument/pipetteSingle.png +0 -0
  262. package/src/instrument/single-channel-flex.png +0 -0
  263. package/src/instrument/single-channel_GEN2_800px.png +0 -0
  264. package/src/instrument/single_channel_GEN1_800px.png +0 -0
  265. package/src/interaction-enhancers/ClickOutside.ts +57 -0
  266. package/src/interaction-enhancers/HandleKeypress.tsx +69 -0
  267. package/src/interaction-enhancers/index.ts +4 -0
  268. package/src/interaction-enhancers/useHover.ts +84 -0
  269. package/src/interaction-enhancers/useOnClickOutside.ts +42 -0
  270. package/src/legacy-hardware-sim/LabwareNameOverlay.tsx +22 -0
  271. package/src/legacy-hardware-sim/ModuleItem.tsx +145 -0
  272. package/src/legacy-hardware-sim/index.ts +2 -0
  273. package/src/lists/SidePanelGroup.tsx +48 -0
  274. package/src/lists/TitledList.tsx +155 -0
  275. package/src/lists/index.ts +3 -0
  276. package/src/modals/AlertModal.tsx +89 -0
  277. package/src/modals/ContinueModal.tsx +32 -0
  278. package/src/modals/LegacyModal.tsx +59 -0
  279. package/src/modals/Modal.stories.tsx +52 -0
  280. package/src/modals/Modal.tsx +96 -0
  281. package/src/modals/ModalHeader.tsx +100 -0
  282. package/src/modals/ModalShell.tsx +155 -0
  283. package/src/modals/Overlay.tsx +38 -0
  284. package/src/modals/SpinnerModal.tsx +35 -0
  285. package/src/modals/SpinnerModalPage.tsx +30 -0
  286. package/src/modals/index.ts +10 -0
  287. package/src/molecules/Banner/Banner.stories.tsx +41 -0
  288. package/src/molecules/Banner/index.tsx +147 -0
  289. package/src/molecules/DeckInfoLabel/DeckInfoLabel.stories.tsx +65 -0
  290. package/src/molecules/DeckInfoLabel/index.tsx +95 -0
  291. package/src/molecules/DeckLabel/DeckLabel.stories.tsx +31 -0
  292. package/src/molecules/DeckLabel/index.tsx +80 -0
  293. package/src/molecules/DropdownMenu/DropdownMenu.stories.tsx +30 -0
  294. package/src/molecules/DropdownMenu/index.tsx +343 -0
  295. package/src/molecules/InfoScreen/InfoScreen.stories.tsx +50 -0
  296. package/src/molecules/InfoScreen/index.tsx +54 -0
  297. package/src/molecules/LiquidIcon/LiquidIcon.stories.tsx +53 -0
  298. package/src/molecules/LiquidIcon/index.tsx +68 -0
  299. package/src/molecules/ParametersTable/ParametersTable.stories.tsx +172 -0
  300. package/src/molecules/ParametersTable/index.tsx +198 -0
  301. package/src/molecules/Tabs/Tabs.stories.tsx +74 -0
  302. package/src/molecules/Tabs/index.tsx +94 -0
  303. package/src/molecules/index.ts +8 -0
  304. package/src/nav/SidePanel.stories.tsx +29 -0
  305. package/src/nav/SidePanel.tsx +21 -0
  306. package/src/nav/index.ts +2 -0
  307. package/src/organisms/DeckLabelSet/DeckLabelSet.stories.tsx +46 -0
  308. package/src/organisms/DeckLabelSet/index.tsx +69 -0
  309. package/src/organisms/EndUserAgreementFooter/index.tsx +49 -0
  310. package/src/organisms/Toolbox/Toolbox.stories.tsx +23 -0
  311. package/src/organisms/Toolbox/index.tsx +160 -0
  312. package/src/organisms/index.ts +3 -0
  313. package/src/primitives/Box.stories.tsx +25 -0
  314. package/src/primitives/Box.tsx +17 -0
  315. package/src/primitives/Btn.stories.tsx +105 -0
  316. package/src/primitives/Btn.tsx +266 -0
  317. package/src/primitives/Flex.stories.tsx +50 -0
  318. package/src/primitives/Flex.tsx +17 -0
  319. package/src/primitives/ForeignObject.tsx +70 -0
  320. package/src/primitives/Link.stories.tsx +27 -0
  321. package/src/primitives/Link.tsx +32 -0
  322. package/src/primitives/README.md +188 -0
  323. package/src/primitives/Svg.stories.tsx +36 -0
  324. package/src/primitives/Svg.tsx +68 -0
  325. package/src/primitives/Text.stories.tsx +17 -0
  326. package/src/primitives/Text.tsx +18 -0
  327. package/src/primitives/index.ts +10 -0
  328. package/src/primitives/style-props.ts +197 -0
  329. package/src/primitives/types.ts +120 -0
  330. package/src/robot-types.ts +4 -0
  331. package/src/slotmap/OT2SlotMap.tsx +73 -0
  332. package/src/slotmap/index.ts +1 -0
  333. package/src/structure/Card.stories.tsx +28 -0
  334. package/src/structure/Card.tsx +64 -0
  335. package/src/structure/LabeledValue.stories.tsx +17 -0
  336. package/src/structure/LabeledValue.tsx +31 -0
  337. package/src/structure/Pill.tsx +43 -0
  338. package/src/structure/Splash.stories.tsx +24 -0
  339. package/src/structure/Splash.tsx +22 -0
  340. package/src/structure/TitleBar.stories.tsx +42 -0
  341. package/src/structure/TitleBar.tsx +81 -0
  342. package/src/structure/index.ts +7 -0
  343. package/src/styles/borders.ts +16 -0
  344. package/src/styles/colors.ts +58 -0
  345. package/src/styles/cursor.ts +12 -0
  346. package/src/styles/flexbox.ts +39 -0
  347. package/src/styles/index.ts +8 -0
  348. package/src/styles/layout.ts +31 -0
  349. package/src/styles/position.ts +5 -0
  350. package/src/styles/spacing.ts +11 -0
  351. package/src/styles/typography.ts +90 -0
  352. package/src/testing/utils/index.ts +2 -0
  353. package/src/testing/utils/matchers.ts +31 -0
  354. package/src/testing/utils/renderWithProviders.tsx +53 -0
  355. package/src/tooltips/DeprecatedTooltip.tsx +105 -0
  356. package/src/tooltips/HoverTooltip.tsx +83 -0
  357. package/src/tooltips/LegacyTooltip.stories.tsx +98 -0
  358. package/src/tooltips/LegacyTooltip.tsx +151 -0
  359. package/src/tooltips/constants.ts +28 -0
  360. package/src/tooltips/index.ts +10 -0
  361. package/src/tooltips/styles.ts +20 -0
  362. package/src/tooltips/types.ts +73 -0
  363. package/src/tooltips/useHoverTooltip.ts +47 -0
  364. package/src/tooltips/usePopper.ts +87 -0
  365. package/src/tooltips/useTooltip.ts +100 -0
  366. package/src/ui-style-constants/index.ts +4 -0
  367. package/src/ui-style-constants/responsiveness.ts +15 -0
  368. package/src/ui-style-constants/spacing.ts +18 -0
  369. package/src/ui-style-constants/typography.ts +258 -0
  370. package/src/ui-style-constants/viewport.ts +18 -0
  371. package/src/utils.ts +56 -0
  372. package/{vite.config.ts → vite.config.mts} +2 -0
  373. package/lib/index.mjs +0 -19869
@@ -0,0 +1,83 @@
1
+ import * as React from 'react'
2
+
3
+ import { DeprecatedTooltip } from './DeprecatedTooltip'
4
+
5
+ import type { DeprecatedTooltipProps } from './DeprecatedTooltip'
6
+
7
+ const OPEN_DELAY_MS = 300
8
+ const CLOSE_DELAY_MS = 0
9
+
10
+ interface MouseHandlers {
11
+ onMouseEnter: () => void
12
+ onMouseLeave: () => void
13
+ }
14
+
15
+ export type HoverTooltipHandlers = React.PropsWithRef<MouseHandlers>
16
+
17
+ export type HoverTooltipProps = DeprecatedTooltipProps
18
+
19
+ interface HoverTooltipState {
20
+ isOpen: boolean
21
+ }
22
+
23
+ /**
24
+ * Tooltip component that triggers on `MouseEnter` and `MouseLeave`. See
25
+ * `Tooltip` for full props list.
26
+ *
27
+ * `props.children` is a function that receives the following props object:
28
+ * ```js
29
+ * type HoverTooltipHandlers = {
30
+ * ref: React.Ref<*>,
31
+ * onMouseEnter: (React.MouseEvent) => void,
32
+ * onMouseLeave: (React.MouseEvent) => void,
33
+ * }
34
+ * ```
35
+ *
36
+ * @deprecated Use `Tooltip` and `useHoverTooltip` instead
37
+ */
38
+ export class HoverTooltip extends React.Component<
39
+ HoverTooltipProps,
40
+ HoverTooltipState
41
+ > {
42
+ openTimeout: number | null
43
+ closeTimeout: number | null
44
+
45
+ constructor(props: HoverTooltipProps) {
46
+ super(props)
47
+ this.openTimeout = null
48
+ this.closeTimeout = null
49
+ this.state = { isOpen: false }
50
+ }
51
+
52
+ componentWillUnmount(): void {
53
+ if (this.closeTimeout) clearTimeout(this.closeTimeout)
54
+ if (this.openTimeout) clearTimeout(this.openTimeout)
55
+ }
56
+
57
+ delayedOpen: () => void = () => {
58
+ if (this.closeTimeout) clearTimeout(this.closeTimeout)
59
+ this.openTimeout = window.setTimeout(() => {
60
+ this.setState({ isOpen: true })
61
+ }, OPEN_DELAY_MS)
62
+ }
63
+
64
+ delayedClose: () => void = () => {
65
+ if (this.openTimeout) clearTimeout(this.openTimeout)
66
+ this.closeTimeout = window.setTimeout(() => {
67
+ this.setState({ isOpen: false })
68
+ }, CLOSE_DELAY_MS)
69
+ }
70
+
71
+ render(): JSX.Element {
72
+ return (
73
+ <DeprecatedTooltip
74
+ open={this.state.isOpen}
75
+ childProps={{
76
+ onMouseEnter: this.delayedOpen,
77
+ onMouseLeave: this.delayedClose,
78
+ }}
79
+ {...this.props}
80
+ />
81
+ )
82
+ }
83
+ }
@@ -0,0 +1,98 @@
1
+ import type * as React from 'react'
2
+ import { LegacyTooltip } from './LegacyTooltip'
3
+ import { useTooltip } from './useTooltip'
4
+ import { useHoverTooltip } from './useHoverTooltip'
5
+ import {
6
+ Box,
7
+ Flex,
8
+ JUSTIFY_CENTER,
9
+ ALIGN_CENTER,
10
+ SIZE_4,
11
+ SIZE_3,
12
+ C_LIGHT_GRAY,
13
+ C_MED_GRAY,
14
+ } from '@opentrons/components'
15
+
16
+ import type { Story, Meta } from '@storybook/react'
17
+
18
+ export default {
19
+ title: 'Library/Atoms/LegacyTooltip',
20
+ decorators: [
21
+ Story => (
22
+ <Flex
23
+ justifyContent={JUSTIFY_CENTER}
24
+ alignItems={ALIGN_CENTER}
25
+ height={SIZE_4}
26
+ width="100%"
27
+ backgroundColor={C_LIGHT_GRAY}
28
+ >
29
+ <Story />
30
+ </Flex>
31
+ ),
32
+ ],
33
+ } as Meta
34
+
35
+ const Template: Story<React.ComponentProps<typeof LegacyTooltip>> = args => (
36
+ <LegacyTooltip {...args} />
37
+ )
38
+ export const Basic = Template.bind({})
39
+ Basic.args = {
40
+ visible: true,
41
+ children: 'This is a simple tooltip atom.',
42
+ id: 'string-usually-provided-by-useTooltip-hook',
43
+ placement: 'auto',
44
+ style: {},
45
+ arrowRef: () => null,
46
+ arrowStyle: {},
47
+ }
48
+
49
+ const StatefulTemplate: Story<
50
+ React.ComponentProps<typeof LegacyTooltip>
51
+ > = args => {
52
+ const { visible, children, placement } = args
53
+ const [targetProps, tooltipProps] = useTooltip({ placement })
54
+ return (
55
+ <>
56
+ <Box
57
+ height={SIZE_3}
58
+ width={SIZE_3}
59
+ backgroundColor={C_MED_GRAY}
60
+ {...targetProps}
61
+ >
62
+ Target
63
+ </Box>
64
+ <LegacyTooltip {...tooltipProps} {...{ visible, children }} />
65
+ </>
66
+ )
67
+ }
68
+ export const WithUseTooltip = StatefulTemplate.bind({})
69
+ WithUseTooltip.args = {
70
+ visible: true,
71
+ children:
72
+ 'This is a tooltip that takes advantage of the useTooltip hook to anchor itself to a target.',
73
+ }
74
+
75
+ const HoverTemplate: Story<
76
+ React.ComponentProps<typeof LegacyTooltip>
77
+ > = args => {
78
+ const { children } = args
79
+ const [targetProps, tooltipProps] = useHoverTooltip()
80
+ return (
81
+ <>
82
+ <Box
83
+ height={SIZE_3}
84
+ width={SIZE_3}
85
+ backgroundColor={C_MED_GRAY}
86
+ {...targetProps}
87
+ >
88
+ Target
89
+ </Box>
90
+ <LegacyTooltip {...tooltipProps}>{children}</LegacyTooltip>
91
+ </>
92
+ )
93
+ }
94
+ export const WithUseHoverTooltip = HoverTemplate.bind({})
95
+ WithUseHoverTooltip.args = {
96
+ children:
97
+ 'This is a tooltip that takes advantage of the useHoverTooltip hook, and only appears when the target is hovered.',
98
+ }
@@ -0,0 +1,151 @@
1
+ import * as React from 'react'
2
+ import { css } from 'styled-components'
3
+
4
+ import { BORDERS, COLORS } from '../helix-design-system'
5
+ import { fontSizeH4 } from '../ui-style-constants/typography'
6
+ import { spacing8 } from '../ui-style-constants/spacing'
7
+ import { ARROW_SIZE_PX } from './styles'
8
+ import { Box } from '../primitives'
9
+ import { CURSOR_POINTER } from '../styles'
10
+
11
+ import type { CSSProperties } from 'react'
12
+ import type { FlattenSimpleInterpolation } from 'styled-components'
13
+ import type { Placement } from './types'
14
+ import type { StyleProps } from '../primitives'
15
+
16
+ export interface LegacyTooltipProps extends StyleProps {
17
+ /** Whether or not the tooltip should be rendered */
18
+ visible: boolean
19
+ /** Contents of the tooltip */
20
+ children?: React.ReactNode
21
+ /**
22
+ * Tooltip element ID (provided by useTooltip). Will match
23
+ * targetProps.aria-describedby
24
+ */
25
+ id: string
26
+ /** Actual tooltip placement, if known (provided by useTooltip) */
27
+ placement: Placement | null
28
+ /** Inline styles to apply to the tooltip element (provided by useTooltip) */
29
+ style: CSSProperties
30
+ /** React function ref for tooltip's arrow element (provided by useTooltip) */
31
+ arrowRef: React.RefCallback<HTMLElement | null>
32
+ /** Inline styles to apply to arrow element (provided by useTooltip) */
33
+ arrowStyle: CSSProperties
34
+ }
35
+
36
+ /**
37
+ * Tooltip component that renders based on its `visible` prop. For use with the
38
+ * `useTooltip` and `useHoverTooltip` hooks. See examples in `Tooltip.md`.
39
+ */
40
+ export const LegacyTooltip = React.forwardRef(function TooltipComponent(
41
+ props: LegacyTooltipProps,
42
+ ref: React.ForwardedRef<HTMLDivElement>
43
+ ) {
44
+ const {
45
+ visible,
46
+ placement,
47
+ id,
48
+ style,
49
+ arrowRef,
50
+ arrowStyle,
51
+ children,
52
+ width,
53
+ fontSize = fontSizeH4,
54
+ backgroundColor = COLORS.grey50,
55
+ ...boxProps
56
+ } = props
57
+
58
+ const TOOLTIP_CSS = css`
59
+ position: absolute;
60
+ z-index: 9001;
61
+ padding: ${spacing8};
62
+ color: ${COLORS.white};
63
+ filter: drop-shadow(0px 1px 3px rgba(0, 0, 0, 0.2));
64
+ cursor: ${CURSOR_POINTER};
65
+ font-size: ${fontSize};
66
+ border-radius: ${BORDERS.borderRadius4};
67
+ `
68
+
69
+ return visible ? (
70
+ <Box
71
+ role="tooltip"
72
+ id={id}
73
+ style={style}
74
+ ref={ref}
75
+ css={TOOLTIP_CSS}
76
+ width={width}
77
+ backgroundColor={backgroundColor}
78
+ {...boxProps}
79
+ >
80
+ {children}
81
+ <Arrow {...{ arrowRef, arrowStyle, placement, backgroundColor }} />
82
+ </Box>
83
+ ) : null
84
+ })
85
+
86
+ export interface ArrowProps {
87
+ placement: Placement | null
88
+ arrowRef: React.RefCallback<HTMLElement>
89
+ arrowStyle: CSSProperties
90
+ backgroundColor: string
91
+ }
92
+
93
+ export function Arrow(props: ArrowProps): JSX.Element {
94
+ // shift arrows off the element
95
+ const ARROW_ANCHOR_OFFSET = `-${ARROW_SIZE_PX}px;`
96
+
97
+ // use borders to create arrows
98
+ const ARROW_CSS_BASE = css`
99
+ position: absolute;
100
+ border-width: ${ARROW_SIZE_PX}px;
101
+ border-style: solid;
102
+ border-color: transparent;
103
+ `
104
+
105
+ // arrow pointing down from the top tooltip
106
+ const ARROW_CSS_TOP = css`
107
+ ${ARROW_CSS_BASE}
108
+ bottom: ${ARROW_ANCHOR_OFFSET};
109
+ border-bottom-style: none;
110
+ border-top-color: ${props.backgroundColor};
111
+ `
112
+
113
+ // arrow pointing left from the right tooltip
114
+ const ARROW_CSS_RIGHT = css`
115
+ ${ARROW_CSS_BASE}
116
+ left: ${ARROW_ANCHOR_OFFSET};
117
+ border-left-style: none;
118
+ border-right-color: ${props.backgroundColor};
119
+ `
120
+
121
+ // arrow pointing up from the bottom tooltip
122
+ const ARROW_CSS_BOTTOM = css`
123
+ ${ARROW_CSS_BASE}
124
+ top: ${ARROW_ANCHOR_OFFSET};
125
+ border-top-style: none;
126
+ border-bottom-color: ${props.backgroundColor};
127
+ `
128
+
129
+ // arrow pointing right from the left tooltip
130
+ const ARROW_CSS_LEFT = css`
131
+ ${ARROW_CSS_BASE}
132
+ right: ${ARROW_ANCHOR_OFFSET};
133
+ border-right-style: none;
134
+ border-left-color: ${props.backgroundColor};
135
+ `
136
+
137
+ const ARROW_CSS_BY_PLACEMENT_BASE: Record<
138
+ string,
139
+ FlattenSimpleInterpolation
140
+ > = {
141
+ top: ARROW_CSS_TOP,
142
+ right: ARROW_CSS_RIGHT,
143
+ bottom: ARROW_CSS_BOTTOM,
144
+ left: ARROW_CSS_LEFT,
145
+ }
146
+ const placement = props.placement ?? ''
147
+ const placementBase = placement.split('-')[0]
148
+ const arrowCss = ARROW_CSS_BY_PLACEMENT_BASE[placementBase]
149
+
150
+ return <div ref={props.arrowRef} style={props.arrowStyle} css={arrowCss} />
151
+ }
@@ -0,0 +1,28 @@
1
+ // placement constants
2
+ // NOTE: these aren't exported from Popper, but they are copied from:
3
+ // @popperjs/core/src/enums.js
4
+ export const TOOLTIP_AUTO: 'auto' = 'auto'
5
+ export const TOOLTIP_AUTO_START: 'auto-start' = 'auto-start'
6
+ export const TOOLTIP_AUTO_END: 'auto-end' = 'auto-end'
7
+
8
+ export const TOOLTIP_TOP: 'top' = 'top'
9
+ export const TOOLTIP_TOP_START: 'top-start' = 'top-start'
10
+ export const TOOLTIP_TOP_END: 'top-end' = 'top-end'
11
+
12
+ export const TOOLTIP_RIGHT: 'right' = 'right'
13
+ export const TOOLTIP_RIGHT_START: 'right-start' = 'right-start'
14
+ export const TOOLTIP_RIGHT_END: 'right-end' = 'right-end'
15
+
16
+ export const TOOLTIP_BOTTOM: 'bottom' = 'bottom'
17
+ export const TOOLTIP_BOTTOM_START: 'bottom-start' = 'bottom-start'
18
+ export const TOOLTIP_BOTTOM_END: 'bottom-end' = 'bottom-end'
19
+
20
+ export const TOOLTIP_LEFT: 'left' = 'left'
21
+ export const TOOLTIP_LEFT_START: 'left-start' = 'left-start'
22
+ export const TOOLTIP_LEFT_END: 'left-end' = 'left-end'
23
+
24
+ // strategy constants
25
+ // NOTE: these aren't exported from Popper, but they are copied from:
26
+ // @popperjs/core/src/types.js
27
+ export const TOOLTIP_ABSOLUTE: 'absolute' = 'absolute'
28
+ export const TOOLTIP_FIXED: 'fixed' = 'fixed'
@@ -0,0 +1,10 @@
1
+ // tooltip components
2
+
3
+ export * from './DeprecatedTooltip'
4
+ export * from './HoverTooltip'
5
+ export * from './LegacyTooltip'
6
+ export * from './useTooltip'
7
+ export * from './useHoverTooltip'
8
+ export * from './usePopper'
9
+ export * from './constants'
10
+ export * from './types'
@@ -0,0 +1,20 @@
1
+ // common style constants
2
+
3
+ export const INITIAL_TOOLTIP_STYLE = {
4
+ // copied from @popperjs/core/src/modifiers/applyStyles.js
5
+ position: 'absolute',
6
+ left: '0',
7
+ top: '0',
8
+ margin: '0',
9
+ } as const
10
+
11
+ export const INITIAL_ARROW_STYLE = {
12
+ // copied from @popperjs/core/src/modifiers/applyStyles.js
13
+ position: 'absolute',
14
+ } as const
15
+
16
+ export const TOOLTIP_OFFSET_PX = 8
17
+
18
+ export const ARROW_OFFSET_PX = 4
19
+
20
+ export const ARROW_SIZE_PX = TOOLTIP_OFFSET_PX - ARROW_OFFSET_PX
@@ -0,0 +1,73 @@
1
+ import type { CSSProperties } from 'react'
2
+
3
+ import type { Instance, Options, Modifier } from '@popperjs/core/lib/types'
4
+
5
+ import type { UseHoverOptions, HoverHandlers } from '../interaction-enhancers'
6
+
7
+ export type Placement = Options['placement']
8
+
9
+ export type Strategy = Options['strategy']
10
+
11
+ export type PopperInstance = Instance
12
+
13
+ export type PopperOptions = Options
14
+
15
+ export type PopperModifer<T> = Modifier<T>
16
+
17
+ export type HandleStateUpdate = (
18
+ placement: Placement,
19
+ styles: {
20
+ popper?: CSSProperties
21
+ arrow?: CSSProperties
22
+ }
23
+ ) => void
24
+
25
+ export interface UsePopperOptions {
26
+ target: Element | null
27
+ tooltip: HTMLElement | null
28
+ arrow: HTMLElement | null
29
+ onStateUpdate: HandleStateUpdate
30
+ placement?: Placement | null
31
+ strategy?: Strategy | null
32
+ offset?: number
33
+ }
34
+
35
+ export type UsePopperResult = Instance | null
36
+
37
+ export interface UseTooltipOptions {
38
+ placement?: Placement
39
+ strategy?: Strategy
40
+ offset?: number
41
+ }
42
+
43
+ export interface UseTooltipResultTargetProps {
44
+ ref: React.RefCallback<Element | null>
45
+ 'aria-describedby': string
46
+ }
47
+
48
+ export interface UseTooltipResultTooltipProps {
49
+ id: string
50
+ ref: React.RefCallback<HTMLElement | null>
51
+ placement: Placement | null
52
+ style: CSSProperties
53
+ arrowRef: React.RefCallback<HTMLElement | null>
54
+ arrowStyle: CSSProperties
55
+ }
56
+
57
+ export type UseTooltipResult = [
58
+ UseTooltipResultTargetProps,
59
+ UseTooltipResultTooltipProps
60
+ ]
61
+
62
+ export type UseHoverTooltipOptions = Partial<
63
+ UseTooltipOptions & UseHoverOptions
64
+ >
65
+
66
+ export interface UseHoverTooltipTargetProps
67
+ extends UseTooltipResultTargetProps,
68
+ HoverHandlers {}
69
+
70
+ export type UseHoverTooltipResult = [
71
+ UseHoverTooltipTargetProps,
72
+ UseTooltipResultTooltipProps & { visible: boolean }
73
+ ]
@@ -0,0 +1,47 @@
1
+ import { useHover } from '../interaction-enhancers'
2
+ import { useTooltip } from './useTooltip'
3
+
4
+ import type { UseHoverTooltipOptions, UseHoverTooltipResult } from './types'
5
+
6
+ const ENTER_DELAY_MS = 300
7
+ const LEAVE_DELAY_MS = 0
8
+
9
+ /**
10
+ * Hook to position a tooltip component relative to a target component on hover.
11
+ * Adds a default `enterDelay` of 300 ms before the tooltip will show
12
+ *
13
+ * @param {UseHoverTooltipOptions} [options={}] (change default options (see `useTooltip` and `useHover`))
14
+ * @returns {UseHoverTooltipResult}
15
+ * @example
16
+ * ```js
17
+ * import { useHoverTooltip, Tooltip } from '@opentrons/components'
18
+ *
19
+ * export function HelloWorld() {
20
+ * const [targetProps, tooltipProps] = useHoverTooltip()
21
+ *
22
+ * return (
23
+ * <>
24
+ * <span {...targetProps}>Hello</span>
25
+ * <Tooltip {...tooltipProps}>World</Tooltip>
26
+ * </>
27
+ * )
28
+ * }
29
+ * ```
30
+ */
31
+ export function useHoverTooltip(
32
+ options: UseHoverTooltipOptions = {}
33
+ ): UseHoverTooltipResult {
34
+ const {
35
+ enterDelay = ENTER_DELAY_MS,
36
+ leaveDelay = LEAVE_DELAY_MS,
37
+ ...useTooltipOptions
38
+ } = options
39
+
40
+ const [targetProps, tooltipProps] = useTooltip(useTooltipOptions)
41
+ const [visible, hoverHandlers] = useHover({ enterDelay, leaveDelay })
42
+
43
+ return [
44
+ { ...targetProps, ...hoverHandlers },
45
+ { ...tooltipProps, visible },
46
+ ]
47
+ }
@@ -0,0 +1,87 @@
1
+ import { useRef, useLayoutEffect } from 'react'
2
+ import { createPopper } from '@popperjs/core'
3
+
4
+ import type {
5
+ UsePopperOptions,
6
+ UsePopperResult,
7
+ PopperOptions,
8
+ PopperModifer,
9
+ HandleStateUpdate,
10
+ } from './types'
11
+
12
+ const DISABLED_APPLY_STYLES_MODIFIER = {
13
+ name: 'applyStyles',
14
+ enabled: false,
15
+ }
16
+
17
+ const makeUpdateStateModifier = (
18
+ handleStateUpdate: HandleStateUpdate
19
+ ): PopperModifer<{}> => ({
20
+ name: 'updateUsePopperState',
21
+ enabled: true,
22
+ phase: 'write',
23
+ fn: ({ state }) => {
24
+ handleStateUpdate(state.placement, state.styles)
25
+ },
26
+ })
27
+
28
+ const makeOffsetModifier = (offset: number): Partial<PopperModifer<{}>> => ({
29
+ name: 'offset',
30
+ options: { offset: [0, offset] },
31
+ })
32
+
33
+ const makeArrowModifier = (arrow: Element): Partial<PopperModifer<{}>> => ({
34
+ name: 'arrow',
35
+ options: { element: arrow },
36
+ })
37
+
38
+ export function usePopper(options: UsePopperOptions): UsePopperResult {
39
+ const {
40
+ target,
41
+ tooltip,
42
+ arrow,
43
+ placement,
44
+ strategy,
45
+ offset,
46
+ onStateUpdate,
47
+ } = options
48
+
49
+ const popperRef = useRef<UsePopperResult | null>(null)
50
+
51
+ // useLayoutEffect instead of useEffect to avoid positioning flash
52
+ useLayoutEffect(() => {
53
+ if (target && tooltip) {
54
+ const options: Partial<PopperOptions> &
55
+ Pick<PopperOptions, 'modifiers'> = {
56
+ modifiers: [
57
+ DISABLED_APPLY_STYLES_MODIFIER,
58
+ makeUpdateStateModifier(onStateUpdate),
59
+ ],
60
+ }
61
+
62
+ if (offset != null) {
63
+ options.modifiers.push(makeOffsetModifier(offset))
64
+ }
65
+
66
+ if (arrow) {
67
+ options.modifiers.push(makeArrowModifier(arrow))
68
+ }
69
+
70
+ if (placement != null) options.placement = placement
71
+ if (strategy != null) options.strategy = strategy
72
+
73
+ const popperInstance = createPopper(target, tooltip, options)
74
+
75
+ // immediately force a synchronous update to avoid positioning flash
76
+ popperInstance.forceUpdate()
77
+ popperRef.current = popperInstance
78
+
79
+ return () => {
80
+ popperInstance.destroy()
81
+ popperRef.current = null
82
+ }
83
+ }
84
+ }, [target, tooltip, arrow, placement, strategy, offset, onStateUpdate])
85
+
86
+ return popperRef.current
87
+ }
@@ -0,0 +1,100 @@
1
+ import { useState, useCallback, useRef } from 'react'
2
+ import uniqueId from 'lodash/uniqueId'
3
+ import { usePopper } from './usePopper'
4
+ import * as Styles from './styles'
5
+
6
+ import type { CSSProperties } from 'react'
7
+ import type { UseTooltipOptions, UseTooltipResult, Placement } from './types'
8
+
9
+ interface TooltipState {
10
+ placement: Placement | null
11
+ tooltipStyle: CSSProperties
12
+ arrowStyle: CSSProperties
13
+ }
14
+
15
+ const TOOLTIP_ID_PREFIX = 'Tooltip__'
16
+
17
+ /**
18
+ * Hook to position a tooltip component relative to a target component
19
+ *
20
+ * @param {UseTooltipOptions} [options={}] (change the default `position`, `strategy`, or `offset` of the tooltip)
21
+ * @returns {UseTooltipResult}
22
+ * @example
23
+ * ```js
24
+ * import {
25
+ * useTooltip,
26
+ * Tooltip,
27
+ * TOOLTIP_TOP,
28
+ * TOOLTIP_FIXED
29
+ * } from '@opentrons/components'
30
+ *
31
+ * export function HelloWorld() {
32
+ * const [targetProps, tooltipProps] = useTooltip({
33
+ * position: TOOLTIP_TOP,
34
+ * strategy: TOOLTIP_FIXED
35
+ * })
36
+ *
37
+ * return (
38
+ * <>
39
+ * <span {...targetProps}>Hello</span>
40
+ * <Tooltip visible={true} {...tooltipProps}>World</Tooltip>
41
+ * </>
42
+ * )
43
+ * }
44
+ * ```
45
+ */
46
+ export function useTooltip(options: UseTooltipOptions = {}): UseTooltipResult {
47
+ const { placement, strategy, offset = Styles.TOOLTIP_OFFSET_PX } = options
48
+ const tooltipId = useRef(uniqueId(TOOLTIP_ID_PREFIX)).current
49
+ const [target, targetRef] = useState<Element | null>(null)
50
+ const [tooltip, tooltipRef] = useState<HTMLElement | null>(null)
51
+ const [arrow, arrowRef] = useState<HTMLElement | null>(null)
52
+ const [tooltipState, setTooltipState] = useState<TooltipState>({
53
+ placement: null,
54
+ tooltipStyle: Styles.INITIAL_TOOLTIP_STYLE,
55
+ arrowStyle: Styles.INITIAL_ARROW_STYLE,
56
+ })
57
+
58
+ const onStateUpdate = useCallback(
59
+ (
60
+ placement: Placement | null,
61
+ styles: {
62
+ popper?: CSSProperties
63
+ arrow?: CSSProperties
64
+ }
65
+ ) => {
66
+ setTooltipState({
67
+ placement,
68
+ tooltipStyle: styles.popper ?? Styles.INITIAL_TOOLTIP_STYLE,
69
+ arrowStyle: styles.arrow ?? Styles.INITIAL_ARROW_STYLE,
70
+ })
71
+ },
72
+ []
73
+ )
74
+
75
+ usePopper({
76
+ target,
77
+ tooltip,
78
+ arrow,
79
+ placement,
80
+ strategy,
81
+ offset,
82
+ onStateUpdate,
83
+ })
84
+
85
+ const targetProps = {
86
+ ref: targetRef,
87
+ 'aria-describedby': tooltipId,
88
+ }
89
+
90
+ const tooltipProps = {
91
+ id: tooltipId,
92
+ ref: tooltipRef,
93
+ style: tooltipState.tooltipStyle,
94
+ arrowStyle: tooltipState.arrowStyle,
95
+ placement: tooltipState.placement,
96
+ arrowRef,
97
+ }
98
+
99
+ return [targetProps, tooltipProps]
100
+ }