@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.
- package/Makefile +5 -1
- package/package.json +6 -7
- package/src/__mocks__/file.js +10 -0
- package/src/alerts/AlertItem.stories.tsx +49 -0
- package/src/alerts/AlertItem.tsx +85 -0
- package/src/alerts/index.ts +3 -0
- package/src/atoms/Checkbox/Checkbox.stories.tsx +24 -0
- package/src/atoms/Checkbox/index.tsx +127 -0
- package/src/atoms/CheckboxField/CheckboxField.stories.tsx +30 -0
- package/src/atoms/CheckboxField/index.tsx +171 -0
- package/src/atoms/Chip/Chip.stories.tsx +59 -0
- package/src/atoms/Chip/index.tsx +172 -0
- package/src/atoms/Divider/index.tsx +15 -0
- package/src/atoms/InputField/InputField.stories.tsx +77 -0
- package/src/atoms/InputField/index.tsx +383 -0
- package/src/atoms/ListButton/ListButton.stories.tsx +133 -0
- package/src/atoms/ListButton/ListButtonChildren/ListButtonAccordion.tsx +65 -0
- package/src/atoms/ListButton/ListButtonChildren/ListButtonAccordionContainer.tsx +23 -0
- package/src/atoms/ListButton/ListButtonChildren/ListButtonRadioButton.tsx +108 -0
- package/src/atoms/ListButton/ListButtonChildren/index.ts +3 -0
- package/src/atoms/ListButton/index.tsx +72 -0
- package/src/atoms/ListItem/ListItem.stories.tsx +96 -0
- package/src/atoms/ListItem/ListItemChildren/ListItemCustomize.tsx +78 -0
- package/src/atoms/ListItem/ListItemChildren/ListItemDescriptor.tsx +42 -0
- package/src/atoms/ListItem/ListItemChildren/index.ts +2 -0
- package/src/atoms/ListItem/index.tsx +89 -0
- package/src/atoms/MenuList/MenuItem.stories.tsx +20 -0
- package/src/atoms/MenuList/MenuItem.tsx +55 -0
- package/src/atoms/MenuList/MenuList.stories.tsx +31 -0
- package/src/atoms/MenuList/OverflowBtn.stories.tsx +17 -0
- package/src/atoms/MenuList/OverflowBtn.tsx +76 -0
- package/src/atoms/MenuList/index.tsx +50 -0
- package/src/atoms/Snackbar/Snackbar.stories.tsx +67 -0
- package/src/atoms/Snackbar/index.tsx +91 -0
- package/src/atoms/StepMeter/index.tsx +53 -0
- package/src/atoms/StyledText/LegacyStyledText.stories.tsx +106 -0
- package/src/atoms/StyledText/LegacyStyledText.tsx +95 -0
- package/src/atoms/StyledText/StyledText.stories.tsx +46 -0
- package/src/atoms/StyledText/StyledText.tsx +323 -0
- package/src/atoms/StyledText/index.ts +2 -0
- package/src/atoms/Tag/Tag.stories.tsx +48 -0
- package/src/atoms/Tag/index.tsx +116 -0
- package/src/atoms/Toast/ODDToast.stories.tsx +68 -0
- package/src/atoms/Toast/Toast.stories.tsx +55 -0
- package/src/atoms/Toast/index.tsx +439 -0
- package/src/atoms/ToggleGroup/ToggleGroup.stories.tsx +39 -0
- package/src/atoms/ToggleGroup/index.tsx +91 -0
- package/src/atoms/Tooltip/Tooltip.stories.tsx +99 -0
- package/src/atoms/Tooltip/index.tsx +38 -0
- package/src/atoms/buttons/AlertPrimaryButton.tsx +26 -0
- package/src/atoms/buttons/AltPrimaryButton.tsx +31 -0
- package/src/atoms/buttons/EmptySelectorButton.stories.tsx +36 -0
- package/src/atoms/buttons/EmptySelectorButton.tsx +83 -0
- package/src/atoms/buttons/LargeButton.stories.tsx +99 -0
- package/src/atoms/buttons/LargeButton.tsx +320 -0
- package/src/atoms/buttons/PrimaryButton.tsx +36 -0
- package/src/atoms/buttons/RadioButton.stories.tsx +35 -0
- package/src/atoms/buttons/RadioButton.tsx +217 -0
- package/src/atoms/buttons/SecondaryButton.tsx +62 -0
- package/src/atoms/buttons/buttons.stories.tsx +78 -0
- package/src/atoms/buttons/index.ts +6 -0
- package/src/atoms/index.ts +20 -0
- package/src/barrel.ts +10 -0
- package/src/buttons/Button.tsx +96 -0
- package/src/buttons/DeprecatedPrimaryButton.tsx +24 -0
- package/src/buttons/FlatButton.tsx +21 -0
- package/src/buttons/IconButton.tsx +37 -0
- package/src/buttons/OutlineButton.tsx +24 -0
- package/src/buttons/index.ts +7 -0
- package/src/controls/ControlInfo.tsx +13 -0
- package/src/controls/LabeledButton.tsx +28 -0
- package/src/controls/LabeledCheckbox.tsx +35 -0
- package/src/controls/LabeledControl.tsx +24 -0
- package/src/controls/LabeledRadioGroup.tsx +27 -0
- package/src/controls/LabeledSelect.tsx +34 -0
- package/src/controls/LabeledToggle.tsx +35 -0
- package/src/controls/StackedLabeledControl.tsx +28 -0
- package/src/controls/ToggleButton.tsx +25 -0
- package/src/controls/index.ts +10 -0
- package/src/forms/DeprecatedCheckboxField.stories.tsx +31 -0
- package/src/forms/DeprecatedCheckboxField.tsx +94 -0
- package/src/forms/DropdownField.stories.tsx +44 -0
- package/src/forms/DropdownField.tsx +106 -0
- package/src/forms/FormGroup.stories.tsx +31 -0
- package/src/forms/FormGroup.tsx +53 -0
- package/src/forms/InputField.stories.tsx +41 -0
- package/src/forms/LegacyInputField.tsx +123 -0
- package/src/forms/RadioGroup.stories.tsx +44 -0
- package/src/forms/RadioGroup.tsx +87 -0
- package/src/forms/Select.stories.tsx +117 -0
- package/src/forms/Select.tsx +132 -0
- package/src/forms/SelectField.tsx +94 -0
- package/src/forms/ToggleField.stories.tsx +31 -0
- package/src/forms/ToggleField.tsx +59 -0
- package/src/forms/index.ts +8 -0
- package/src/hardware-sim/BaseDeck/BaseDeck.stories.tsx +94 -0
- package/src/hardware-sim/BaseDeck/BaseDeck.tsx +423 -0
- package/src/hardware-sim/BaseDeck/SingleSlotFixture.tsx +199 -0
- package/src/hardware-sim/BaseDeck/SlotBase.tsx +5 -0
- package/src/hardware-sim/BaseDeck/SlotClip.tsx +15 -0
- package/src/hardware-sim/BaseDeck/StagingAreaFixture.tsx +114 -0
- package/src/hardware-sim/BaseDeck/WasteChuteFixture.tsx +114 -0
- package/src/hardware-sim/BaseDeck/WasteChuteStagingAreaFixture.tsx +68 -0
- package/src/hardware-sim/BaseDeck/__fixtures__/index.ts +165 -0
- package/src/hardware-sim/BaseDeck/index.ts +5 -0
- package/src/hardware-sim/BaseDeck/something.test.tsx +7 -0
- package/src/hardware-sim/Deck/DeckFromLayers.tsx +58 -0
- package/src/hardware-sim/Deck/FlexTrash.tsx +128 -0
- package/src/hardware-sim/Deck/MoveLabwareOnDeck.stories.tsx +97 -0
- package/src/hardware-sim/Deck/MoveLabwareOnDeck.tsx +251 -0
- package/src/hardware-sim/Deck/OT2Layers.tsx +153 -0
- package/src/hardware-sim/Deck/RobotCoordsForeignDiv.tsx +46 -0
- package/src/hardware-sim/Deck/RobotCoordsForeignObject.tsx +42 -0
- package/src/hardware-sim/Deck/RobotCoordsText.tsx +32 -0
- package/src/hardware-sim/Deck/RobotWorkSpace.tsx +90 -0
- package/src/hardware-sim/Deck/SlotLabels.tsx +111 -0
- package/src/hardware-sim/Deck/__mocks__/getDeckDefinitions.ts +29 -0
- package/src/hardware-sim/Deck/constants.ts +12 -0
- package/src/hardware-sim/Deck/index.tsx +8 -0
- package/src/hardware-sim/DeckConfigurator/AbsorbanceReaderFixture.tsx +91 -0
- package/src/hardware-sim/DeckConfigurator/DeckConfigurator.stories.tsx +110 -0
- package/src/hardware-sim/DeckConfigurator/EmptyConfigFixture.tsx +131 -0
- package/src/hardware-sim/DeckConfigurator/HeaterShakerFixture.tsx +102 -0
- package/src/hardware-sim/DeckConfigurator/MagneticBlockFixture.tsx +130 -0
- package/src/hardware-sim/DeckConfigurator/StagingAreaConfigFixture.tsx +89 -0
- package/src/hardware-sim/DeckConfigurator/StaticFixture.tsx +54 -0
- package/src/hardware-sim/DeckConfigurator/TemperatureModuleFixture.tsx +103 -0
- package/src/hardware-sim/DeckConfigurator/ThermocyclerFixture.tsx +89 -0
- package/src/hardware-sim/DeckConfigurator/TrashBinConfigFixture.tsx +99 -0
- package/src/hardware-sim/DeckConfigurator/WasteChuteConfigFixture.tsx +96 -0
- package/src/hardware-sim/DeckConfigurator/constants.ts +81 -0
- package/src/hardware-sim/DeckConfigurator/index.tsx +285 -0
- package/src/hardware-sim/DeckSlotLocation/index.tsx +88 -0
- package/src/hardware-sim/Labware/Labware.tsx +173 -0
- package/src/hardware-sim/Labware/LabwareAdapter/Opentrons96DeepWellAdapter.tsx +23 -0
- package/src/hardware-sim/Labware/LabwareAdapter/Opentrons96FlatBottomAdapter.tsx +7 -0
- package/src/hardware-sim/Labware/LabwareAdapter/OpentronsAluminumFlatBottomPlate.tsx +13 -0
- package/src/hardware-sim/Labware/LabwareAdapter/OpentronsAutoclavableDeckRiser.tsx +100 -0
- package/src/hardware-sim/Labware/LabwareAdapter/OpentronsFlex96TiprackAdapter.tsx +13 -0
- package/src/hardware-sim/Labware/LabwareAdapter/OpentronsToughPCRAutoSealingLid.tsx +83 -0
- package/src/hardware-sim/Labware/LabwareAdapter/OpentronsUniversalFlatAdapter.tsx +13 -0
- package/src/hardware-sim/Labware/LabwareAdapter/index.tsx +73 -0
- package/src/hardware-sim/Labware/LabwareRender.stories.tsx +96 -0
- package/src/hardware-sim/Labware/LabwareRender.tsx +173 -0
- package/src/hardware-sim/Labware/LabwareStackRender.tsx +272 -0
- package/src/hardware-sim/Labware/index.ts +6 -0
- package/src/hardware-sim/Labware/labwareInternals/FilledWells.tsx +39 -0
- package/src/hardware-sim/Labware/labwareInternals/LabwareOutline.tsx +133 -0
- package/src/hardware-sim/Labware/labwareInternals/LabwareWellLabels.tsx +118 -0
- package/src/hardware-sim/Labware/labwareInternals/StaticLabware.tsx +121 -0
- package/src/hardware-sim/Labware/labwareInternals/StrokedWells.tsx +38 -0
- package/src/hardware-sim/Labware/labwareInternals/StyledWells.tsx +77 -0
- package/src/hardware-sim/Labware/labwareInternals/Well.tsx +74 -0
- package/src/hardware-sim/Labware/labwareInternals/WellLabels.tsx +121 -0
- package/src/hardware-sim/Labware/labwareInternals/index.ts +8 -0
- package/src/hardware-sim/Labware/labwareInternals/types.ts +18 -0
- package/src/hardware-sim/Module/HeaterShaker.tsx +83 -0
- package/src/hardware-sim/Module/MagneticBlock.tsx +49 -0
- package/src/hardware-sim/Module/MagneticModule.tsx +51 -0
- package/src/hardware-sim/Module/Module.stories.tsx +90 -0
- package/src/hardware-sim/Module/ModuleTag.tsx +38 -0
- package/src/hardware-sim/Module/PlateReader.tsx +208 -0
- package/src/hardware-sim/Module/Temperature.tsx +54 -0
- package/src/hardware-sim/Module/Thermocycler/ThermocyclerGEN1.tsx +248 -0
- package/src/hardware-sim/Module/Thermocycler/ThermocyclerGEN2.tsx +286 -0
- package/src/hardware-sim/Module/Thermocycler/index.tsx +49 -0
- package/src/hardware-sim/Module/index.tsx +227 -0
- package/src/hardware-sim/Pipette/EightEmanatingNozzles.tsx +23 -0
- package/src/hardware-sim/Pipette/EmanatingNozzle.tsx +52 -0
- package/src/hardware-sim/Pipette/PipetteRender.stories.tsx +71 -0
- package/src/hardware-sim/Pipette/PipetteRender.tsx +92 -0
- package/src/hardware-sim/Pipette/constants.ts +10 -0
- package/src/hardware-sim/Pipette/index.ts +1 -0
- package/src/hardware-sim/ProtocolDeck/LabwareInfo.tsx +68 -0
- package/src/hardware-sim/ProtocolDeck/ProtocolDeck.stories.tsx +25 -0
- package/src/hardware-sim/ProtocolDeck/__fixtures__/analysis_QIAseqFX24xv4_8.json +47145 -0
- package/src/hardware-sim/ProtocolDeck/index.tsx +174 -0
- package/src/hardware-sim/ProtocolDeck/types.ts +6 -0
- package/src/hardware-sim/ProtocolDeck/utils/getInitiallyLoadedLabwareByAdapter.ts +33 -0
- package/src/hardware-sim/ProtocolDeck/utils/getLabwareInSlots.ts +155 -0
- package/src/hardware-sim/ProtocolDeck/utils/getLabwareInfoByLiquidId.ts +42 -0
- package/src/hardware-sim/ProtocolDeck/utils/getModulesInSlots.ts +129 -0
- package/src/hardware-sim/ProtocolDeck/utils/getStandardDeckViewLayerBlockList.ts +29 -0
- package/src/hardware-sim/ProtocolDeck/utils/getWellFillFromLabwareId.ts +30 -0
- package/src/hardware-sim/ProtocolDeck/utils/index.ts +3 -0
- package/src/hardware-sim/RobotCoordinateSpace/RobotCoordinateSpace.tsx +28 -0
- package/src/hardware-sim/RobotCoordinateSpace/RobotCoordinateSpaceWithRef.tsx +52 -0
- package/src/hardware-sim/RobotCoordinateSpace/index.ts +2 -0
- package/src/hardware-sim/index.ts +11 -0
- package/src/hardware-sim/utils.ts +18 -0
- package/src/helix-design-system/borders.ts +32 -0
- package/src/helix-design-system/colors.ts +100 -0
- package/src/helix-design-system/index.ts +4 -0
- package/src/helix-design-system/product/index.ts +1 -0
- package/src/helix-design-system/product/typography.ts +151 -0
- package/src/helix-design-system/style.ts +2 -0
- package/src/hooks/index.ts +15 -0
- package/src/hooks/useConditionalConfirm.ts +70 -0
- package/src/hooks/useDrag.ts +90 -0
- package/src/hooks/useIdle.ts +68 -0
- package/src/hooks/useInterval.ts +38 -0
- package/src/hooks/useLongPress.ts +83 -0
- package/src/hooks/useMenuHandleClickOutside.tsx +46 -0
- package/src/hooks/useMountEffect.ts +12 -0
- package/src/hooks/usePrevious.ts +19 -0
- package/src/hooks/useScrolling.ts +33 -0
- package/src/hooks/useSelectDeckLocation/SelectDeckLocation.stories.tsx +55 -0
- package/src/hooks/useSelectDeckLocation/index.tsx +331 -0
- package/src/hooks/useSwipe.ts +86 -0
- package/src/hooks/useTimeout.ts +33 -0
- package/src/hooks/useToggle.ts +27 -0
- package/src/icons/Icon.stories.tsx +37 -0
- package/src/icons/Icon.tsx +79 -0
- package/src/icons/IconList.stories.tsx +108 -0
- package/src/icons/ModuleIcon.tsx +48 -0
- package/src/icons/NotificationIcon.tsx +41 -0
- package/src/icons/icon-data.ts +821 -0
- package/src/icons/index.ts +6 -0
- package/src/images/index.ts +1 -0
- package/src/images/labware/index.ts +1 -0
- package/src/images/labware/measurement-guide/images/depth/depth-plate-flat@3x.png +0 -0
- package/src/images/labware/measurement-guide/images/depth/depth-plate-round@3x.png +0 -0
- package/src/images/labware/measurement-guide/images/depth/depth-plate-v@3x.png +0 -0
- package/src/images/labware/measurement-guide/images/depth/depth-reservoir-and-tubes-flat@3x.png +0 -0
- package/src/images/labware/measurement-guide/images/depth/depth-reservoir-and-tubes-round@3x.png +0 -0
- package/src/images/labware/measurement-guide/images/depth/depth-reservoir-and-tubes-v@3x.png +0 -0
- package/src/images/labware/measurement-guide/images/depth/length-tip-rack@3x.png +0 -0
- package/src/images/labware/measurement-guide/images/dimensions/footprint@3x.png +0 -0
- package/src/images/labware/measurement-guide/images/dimensions/height-alum-block-plate@3x.png +0 -0
- package/src/images/labware/measurement-guide/images/dimensions/height-alum-block-tubes@3x.png +0 -0
- package/src/images/labware/measurement-guide/images/dimensions/height-plate-and-reservoir@3x.png +0 -0
- package/src/images/labware/measurement-guide/images/dimensions/height-tip-rack@3x.png +0 -0
- package/src/images/labware/measurement-guide/images/dimensions/height-tube-rack-irregular@3x.png +0 -0
- package/src/images/labware/measurement-guide/images/dimensions/height-tube-rack@3x.png +0 -0
- package/src/images/labware/measurement-guide/images/offset/offset-reservoir@3x.png +0 -0
- package/src/images/labware/measurement-guide/images/offset/offset-well-circular@3x.png +0 -0
- package/src/images/labware/measurement-guide/images/offset/offset-well-rectangular@3x.png +0 -0
- package/src/images/labware/measurement-guide/images/shape/shape-circular@3x.png +0 -0
- package/src/images/labware/measurement-guide/images/shape/shape-rectangular@3x.png +0 -0
- package/src/images/labware/measurement-guide/images/spacing/spacing-reservoir-multi-row@3x.png +0 -0
- package/src/images/labware/measurement-guide/images/spacing/spacing-reservoir@3x.png +0 -0
- package/src/images/labware/measurement-guide/images/spacing/spacing-well-circular@3x.png +0 -0
- package/src/images/labware/measurement-guide/images/spacing/spacing-well-rectangular@3x.png +0 -0
- package/src/images/labware/measurement-guide/index.ts +272 -0
- package/src/index.ts +2 -0
- package/src/instrument/InstrumentDiagram.stories.tsx +42 -0
- package/src/instrument/InstrumentDiagram.tsx +58 -0
- package/src/instrument/InstrumentGroup.stories.tsx +88 -0
- package/src/instrument/InstrumentGroup.tsx +35 -0
- package/src/instrument/InstrumentInfo.tsx +107 -0
- package/src/instrument/PipetteSelect.stories.tsx +40 -0
- package/src/instrument/PipetteSelect.tsx +170 -0
- package/src/instrument/eight-channel-flex.png +0 -0
- package/src/instrument/index.ts +4 -0
- package/src/instrument/multi-channel_GEN1_800px.png +0 -0
- package/src/instrument/multi-channel_GEN2_800px.png +0 -0
- package/src/instrument/ninety-six-channel-gen1.png +0 -0
- package/src/instrument/pipetteGEN2Multi.png +0 -0
- package/src/instrument/pipetteGEN2Single.png +0 -0
- package/src/instrument/pipetteMulti.png +0 -0
- package/src/instrument/pipetteSingle.png +0 -0
- package/src/instrument/single-channel-flex.png +0 -0
- package/src/instrument/single-channel_GEN2_800px.png +0 -0
- package/src/instrument/single_channel_GEN1_800px.png +0 -0
- package/src/interaction-enhancers/ClickOutside.ts +57 -0
- package/src/interaction-enhancers/HandleKeypress.tsx +69 -0
- package/src/interaction-enhancers/index.ts +4 -0
- package/src/interaction-enhancers/useHover.ts +84 -0
- package/src/interaction-enhancers/useOnClickOutside.ts +42 -0
- package/src/legacy-hardware-sim/LabwareNameOverlay.tsx +22 -0
- package/src/legacy-hardware-sim/ModuleItem.tsx +145 -0
- package/src/legacy-hardware-sim/index.ts +2 -0
- package/src/lists/SidePanelGroup.tsx +48 -0
- package/src/lists/TitledList.tsx +155 -0
- package/src/lists/index.ts +3 -0
- package/src/modals/AlertModal.tsx +89 -0
- package/src/modals/ContinueModal.tsx +32 -0
- package/src/modals/LegacyModal.tsx +59 -0
- package/src/modals/Modal.stories.tsx +52 -0
- package/src/modals/Modal.tsx +96 -0
- package/src/modals/ModalHeader.tsx +100 -0
- package/src/modals/ModalShell.tsx +155 -0
- package/src/modals/Overlay.tsx +38 -0
- package/src/modals/SpinnerModal.tsx +35 -0
- package/src/modals/SpinnerModalPage.tsx +30 -0
- package/src/modals/index.ts +10 -0
- package/src/molecules/Banner/Banner.stories.tsx +41 -0
- package/src/molecules/Banner/index.tsx +147 -0
- package/src/molecules/DeckInfoLabel/DeckInfoLabel.stories.tsx +65 -0
- package/src/molecules/DeckInfoLabel/index.tsx +95 -0
- package/src/molecules/DeckLabel/DeckLabel.stories.tsx +31 -0
- package/src/molecules/DeckLabel/index.tsx +80 -0
- package/src/molecules/DropdownMenu/DropdownMenu.stories.tsx +30 -0
- package/src/molecules/DropdownMenu/index.tsx +343 -0
- package/src/molecules/InfoScreen/InfoScreen.stories.tsx +50 -0
- package/src/molecules/InfoScreen/index.tsx +54 -0
- package/src/molecules/LiquidIcon/LiquidIcon.stories.tsx +53 -0
- package/src/molecules/LiquidIcon/index.tsx +68 -0
- package/src/molecules/ParametersTable/ParametersTable.stories.tsx +172 -0
- package/src/molecules/ParametersTable/index.tsx +198 -0
- package/src/molecules/Tabs/Tabs.stories.tsx +74 -0
- package/src/molecules/Tabs/index.tsx +94 -0
- package/src/molecules/index.ts +8 -0
- package/src/nav/SidePanel.stories.tsx +29 -0
- package/src/nav/SidePanel.tsx +21 -0
- package/src/nav/index.ts +2 -0
- package/src/organisms/DeckLabelSet/DeckLabelSet.stories.tsx +46 -0
- package/src/organisms/DeckLabelSet/index.tsx +69 -0
- package/src/organisms/EndUserAgreementFooter/index.tsx +49 -0
- package/src/organisms/Toolbox/Toolbox.stories.tsx +23 -0
- package/src/organisms/Toolbox/index.tsx +160 -0
- package/src/organisms/index.ts +3 -0
- package/src/primitives/Box.stories.tsx +25 -0
- package/src/primitives/Box.tsx +17 -0
- package/src/primitives/Btn.stories.tsx +105 -0
- package/src/primitives/Btn.tsx +266 -0
- package/src/primitives/Flex.stories.tsx +50 -0
- package/src/primitives/Flex.tsx +17 -0
- package/src/primitives/ForeignObject.tsx +70 -0
- package/src/primitives/Link.stories.tsx +27 -0
- package/src/primitives/Link.tsx +32 -0
- package/src/primitives/README.md +188 -0
- package/src/primitives/Svg.stories.tsx +36 -0
- package/src/primitives/Svg.tsx +68 -0
- package/src/primitives/Text.stories.tsx +17 -0
- package/src/primitives/Text.tsx +18 -0
- package/src/primitives/index.ts +10 -0
- package/src/primitives/style-props.ts +197 -0
- package/src/primitives/types.ts +120 -0
- package/src/robot-types.ts +4 -0
- package/src/slotmap/OT2SlotMap.tsx +73 -0
- package/src/slotmap/index.ts +1 -0
- package/src/structure/Card.stories.tsx +28 -0
- package/src/structure/Card.tsx +64 -0
- package/src/structure/LabeledValue.stories.tsx +17 -0
- package/src/structure/LabeledValue.tsx +31 -0
- package/src/structure/Pill.tsx +43 -0
- package/src/structure/Splash.stories.tsx +24 -0
- package/src/structure/Splash.tsx +22 -0
- package/src/structure/TitleBar.stories.tsx +42 -0
- package/src/structure/TitleBar.tsx +81 -0
- package/src/structure/index.ts +7 -0
- package/src/styles/borders.ts +16 -0
- package/src/styles/colors.ts +58 -0
- package/src/styles/cursor.ts +12 -0
- package/src/styles/flexbox.ts +39 -0
- package/src/styles/index.ts +8 -0
- package/src/styles/layout.ts +31 -0
- package/src/styles/position.ts +5 -0
- package/src/styles/spacing.ts +11 -0
- package/src/styles/typography.ts +90 -0
- package/src/testing/utils/index.ts +2 -0
- package/src/testing/utils/matchers.ts +31 -0
- package/src/testing/utils/renderWithProviders.tsx +53 -0
- package/src/tooltips/DeprecatedTooltip.tsx +105 -0
- package/src/tooltips/HoverTooltip.tsx +83 -0
- package/src/tooltips/LegacyTooltip.stories.tsx +98 -0
- package/src/tooltips/LegacyTooltip.tsx +151 -0
- package/src/tooltips/constants.ts +28 -0
- package/src/tooltips/index.ts +10 -0
- package/src/tooltips/styles.ts +20 -0
- package/src/tooltips/types.ts +73 -0
- package/src/tooltips/useHoverTooltip.ts +47 -0
- package/src/tooltips/usePopper.ts +87 -0
- package/src/tooltips/useTooltip.ts +100 -0
- package/src/ui-style-constants/index.ts +4 -0
- package/src/ui-style-constants/responsiveness.ts +15 -0
- package/src/ui-style-constants/spacing.ts +18 -0
- package/src/ui-style-constants/typography.ts +258 -0
- package/src/ui-style-constants/viewport.ts +18 -0
- package/src/utils.ts +56 -0
- package/{vite.config.ts → vite.config.mts} +2 -0
- package/lib/index.mjs +0 -19869
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type * as React from 'react'
|
|
2
|
+
import cx from 'classnames'
|
|
3
|
+
import { Icon } from '../icons'
|
|
4
|
+
|
|
5
|
+
import styles from './forms.module.css'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Checkbox Field Properties.
|
|
9
|
+
*/
|
|
10
|
+
export interface DeprecatedCheckboxFieldProps {
|
|
11
|
+
/** change handler */
|
|
12
|
+
onChange: React.ChangeEventHandler
|
|
13
|
+
/** checkbox is checked if value is true */
|
|
14
|
+
value?: boolean
|
|
15
|
+
/** classes to apply */
|
|
16
|
+
className?: string
|
|
17
|
+
/** classes to apply to inner label text div. Deprecated. use labelProps.className */
|
|
18
|
+
labelTextClassName?: string | null | undefined
|
|
19
|
+
/** name of field in form */
|
|
20
|
+
name?: string
|
|
21
|
+
/** label text for checkbox */
|
|
22
|
+
label?: string
|
|
23
|
+
/** if is included, checkbox will use error style. The content of the string is ignored. */
|
|
24
|
+
error?: string | null | undefined
|
|
25
|
+
/** checkbox is disabled if value is true */
|
|
26
|
+
disabled?: boolean
|
|
27
|
+
/** html tabindex property */
|
|
28
|
+
tabIndex?: number
|
|
29
|
+
/** props passed into label div. TODO IMMEDIATELY what is the Flow type? */
|
|
30
|
+
labelProps?: React.ComponentProps<'div'>
|
|
31
|
+
/** if true, render indeterminate icon */
|
|
32
|
+
isIndeterminate?: boolean
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Checkbox Form Field
|
|
37
|
+
* @deprecated
|
|
38
|
+
*/
|
|
39
|
+
export function DeprecatedCheckboxField(
|
|
40
|
+
props: DeprecatedCheckboxFieldProps
|
|
41
|
+
): JSX.Element {
|
|
42
|
+
const error = props.error != null
|
|
43
|
+
const outerClassName = cx(styles.form_field, props.className, {
|
|
44
|
+
[styles.checkbox_disabled]: props.disabled,
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
const innerDivClassName = cx(styles.checkbox_icon, {
|
|
48
|
+
[styles.error]: error,
|
|
49
|
+
[styles.checkbox_disabled]: props.disabled,
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
// TODO(bc, 2021-03-09): this usage of the indeterminate prop of input
|
|
53
|
+
// is in react types for input el. Remove ts expect error below and replace with
|
|
54
|
+
// ref on input el (see: Dan Abramov https://github.com/facebook/react/issues/1798#issuecomment-333414857)
|
|
55
|
+
const indeterminate = props.isIndeterminate ? 'true' : undefined
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<label className={outerClassName}>
|
|
59
|
+
<div className={innerDivClassName}>
|
|
60
|
+
<Icon
|
|
61
|
+
name={
|
|
62
|
+
props.isIndeterminate
|
|
63
|
+
? 'minus-box'
|
|
64
|
+
: props.value
|
|
65
|
+
? 'ot-checkbox'
|
|
66
|
+
: 'checkbox-blank-outline'
|
|
67
|
+
}
|
|
68
|
+
width="100%"
|
|
69
|
+
/>
|
|
70
|
+
</div>
|
|
71
|
+
<input
|
|
72
|
+
className={cx(styles.input_field, styles.accessibly_hidden)}
|
|
73
|
+
type="checkbox"
|
|
74
|
+
name={props.name}
|
|
75
|
+
checked={props.value || false}
|
|
76
|
+
disabled={props.disabled}
|
|
77
|
+
onChange={props.onChange}
|
|
78
|
+
tabIndex={props.tabIndex}
|
|
79
|
+
/* @ts-expect-error */
|
|
80
|
+
indeterminate={indeterminate}
|
|
81
|
+
/>
|
|
82
|
+
<div
|
|
83
|
+
{...props.labelProps}
|
|
84
|
+
className={cx(
|
|
85
|
+
props.labelTextClassName,
|
|
86
|
+
props.labelProps?.className,
|
|
87
|
+
styles.label_text
|
|
88
|
+
)}
|
|
89
|
+
>
|
|
90
|
+
{props.label}
|
|
91
|
+
</div>
|
|
92
|
+
</label>
|
|
93
|
+
)
|
|
94
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
|
|
3
|
+
import { DropdownField as DropdownFieldComponent } from './DropdownField'
|
|
4
|
+
|
|
5
|
+
import type { Story, Meta } from '@storybook/react'
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
title: 'Library/Molecules/Forms/Dropdown Field',
|
|
9
|
+
argTypes: { onChange: { action: 'clicked' } },
|
|
10
|
+
} as Meta
|
|
11
|
+
|
|
12
|
+
const Template: Story<
|
|
13
|
+
React.ComponentProps<typeof DropdownFieldComponent>
|
|
14
|
+
> = args => {
|
|
15
|
+
const [selectedValue, setSelectedValue] = React.useState<string | null>(null)
|
|
16
|
+
return (
|
|
17
|
+
<DropdownFieldComponent
|
|
18
|
+
{...args}
|
|
19
|
+
onChange={e => {
|
|
20
|
+
setSelectedValue(e.target.value)
|
|
21
|
+
args.onChange(e)
|
|
22
|
+
}}
|
|
23
|
+
value={selectedValue}
|
|
24
|
+
/>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
export const DropdownField = Template.bind({})
|
|
28
|
+
DropdownField.parameters = {
|
|
29
|
+
docs: {
|
|
30
|
+
description: {
|
|
31
|
+
component:
|
|
32
|
+
'`DropdownField` is similar to `SelectField`, but more normal. It uses a `<select>` component and has an onChange/onBlur/etc that use DOM events. When `value` prop is truthy, the "blank" option isn\'t shown. When `value` is falsey, the "blank" option appears and is selected. You can\'t get back to blank state once you\'re selected something without external state manipulation. This is similar to how `RadioGroup` works. In order to always allow the user to select a blank value, add an option object to the `options` prop with a blank (empty string) value.',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
}
|
|
36
|
+
DropdownField.args = {
|
|
37
|
+
options: [
|
|
38
|
+
{ name: '', value: '' },
|
|
39
|
+
{ name: 'DNA', value: 'dna' },
|
|
40
|
+
{ name: 'RNA', value: 'rna' },
|
|
41
|
+
{ name: 'Protein', value: 'protein' },
|
|
42
|
+
],
|
|
43
|
+
isIndeterminate: false,
|
|
44
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type * as React from 'react'
|
|
2
|
+
import cx from 'classnames'
|
|
3
|
+
|
|
4
|
+
import { Icon } from '..'
|
|
5
|
+
import styles from './forms.module.css'
|
|
6
|
+
|
|
7
|
+
export interface LegacyDropdownOption {
|
|
8
|
+
name: string
|
|
9
|
+
value: string
|
|
10
|
+
disabled?: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type Options = LegacyDropdownOption[]
|
|
14
|
+
|
|
15
|
+
export interface DropdownFieldProps {
|
|
16
|
+
/** change handler */
|
|
17
|
+
onChange: React.ChangeEventHandler<HTMLSelectElement>
|
|
18
|
+
/** focus handler */
|
|
19
|
+
onFocus?: React.FocusEventHandler<HTMLSelectElement>
|
|
20
|
+
/** blur handler */
|
|
21
|
+
onBlur?: React.FocusEventHandler<HTMLSelectElement>
|
|
22
|
+
/** value that is selected */
|
|
23
|
+
value?: string | null | undefined
|
|
24
|
+
/** optional id for the <select> element */
|
|
25
|
+
id?: string
|
|
26
|
+
/** name of field in form */
|
|
27
|
+
name?: string
|
|
28
|
+
/** Array of {name, value} data */
|
|
29
|
+
options: Options
|
|
30
|
+
/** classes to apply */
|
|
31
|
+
className?: string
|
|
32
|
+
/** optional caption. hidden when `error` is given */
|
|
33
|
+
caption?: string
|
|
34
|
+
/** if included, DropdownField will use error style and display error instead of caption */
|
|
35
|
+
error?: string | null | undefined
|
|
36
|
+
/** dropdown is disabled if value is true */
|
|
37
|
+
disabled?: boolean
|
|
38
|
+
/** html tabindex property */
|
|
39
|
+
tabIndex?: number
|
|
40
|
+
/** automatically focus field on render */
|
|
41
|
+
autoFocus?: boolean
|
|
42
|
+
/** if true, render indeterminate unselectable option */
|
|
43
|
+
isIndeterminate?: boolean
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const BLANK_OPTION: LegacyDropdownOption = { name: '', value: '' }
|
|
47
|
+
const INDETERMINATE_OPTION: LegacyDropdownOption = {
|
|
48
|
+
name: '-',
|
|
49
|
+
value: '',
|
|
50
|
+
disabled: true,
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function DropdownField(props: DropdownFieldProps): JSX.Element {
|
|
54
|
+
let options = []
|
|
55
|
+
// add in disabled, unselectable "-" mixed option when isIndeterminate is true
|
|
56
|
+
// add in "blank" option if there is no `value`, unless `options` already has a blank option
|
|
57
|
+
if (props.isIndeterminate) {
|
|
58
|
+
options = [INDETERMINATE_OPTION, ...props.options]
|
|
59
|
+
} else if (props.value || props.options.some(opt => opt.value === '')) {
|
|
60
|
+
options = props.options
|
|
61
|
+
} else {
|
|
62
|
+
options = [BLANK_OPTION, ...props.options]
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const error = props.error != null
|
|
66
|
+
const className = cx(props.className, {
|
|
67
|
+
[styles.error]: error,
|
|
68
|
+
[styles.dropdown_disabled]: props.disabled,
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<div className={className}>
|
|
73
|
+
<div className={styles.dropdown_field}>
|
|
74
|
+
<select
|
|
75
|
+
id={props.id}
|
|
76
|
+
value={props.value || ''}
|
|
77
|
+
name={props.name}
|
|
78
|
+
onChange={props.onChange}
|
|
79
|
+
onBlur={props.onBlur}
|
|
80
|
+
onFocus={props.onFocus}
|
|
81
|
+
disabled={props.disabled}
|
|
82
|
+
className={styles.dropdown}
|
|
83
|
+
tabIndex={props.tabIndex}
|
|
84
|
+
autoFocus={props.autoFocus}
|
|
85
|
+
>
|
|
86
|
+
{options.map(opt => (
|
|
87
|
+
<option
|
|
88
|
+
key={opt.value}
|
|
89
|
+
value={opt.value}
|
|
90
|
+
disabled={Boolean(opt.disabled)}
|
|
91
|
+
>
|
|
92
|
+
{opt.name}
|
|
93
|
+
</option>
|
|
94
|
+
))}
|
|
95
|
+
</select>
|
|
96
|
+
|
|
97
|
+
<div className={styles.dropdown_icon}>
|
|
98
|
+
<Icon name="menu-down-pd" width="100%" />
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
<div className={styles.input_caption}>
|
|
102
|
+
<span>{error ? props.error : props.caption}</span>
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
)
|
|
106
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type * as React from 'react'
|
|
2
|
+
|
|
3
|
+
import { FormGroup as FormGroupComponent } from './FormGroup'
|
|
4
|
+
import { DeprecatedCheckboxField } from './DeprecatedCheckboxField.stories'
|
|
5
|
+
|
|
6
|
+
import type { Story, Meta } from '@storybook/react'
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
title: 'Library/Molecules/Forms/Form Group',
|
|
10
|
+
argTypes: { onChange: { action: 'clicked' } },
|
|
11
|
+
} as Meta
|
|
12
|
+
|
|
13
|
+
const Template: Story<
|
|
14
|
+
React.ComponentProps<typeof FormGroupComponent>
|
|
15
|
+
> = args => <FormGroupComponent {...args} />
|
|
16
|
+
export const FormGroup = Template.bind({})
|
|
17
|
+
FormGroup.args = {
|
|
18
|
+
label: 'This is a FormGroup',
|
|
19
|
+
children: [
|
|
20
|
+
<DeprecatedCheckboxField
|
|
21
|
+
onChange={e => {}}
|
|
22
|
+
key="first"
|
|
23
|
+
label="first field"
|
|
24
|
+
/>,
|
|
25
|
+
<DeprecatedCheckboxField
|
|
26
|
+
onChange={e => {}}
|
|
27
|
+
key="second"
|
|
28
|
+
label="second field"
|
|
29
|
+
/>,
|
|
30
|
+
],
|
|
31
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type * as React from 'react'
|
|
2
|
+
import cx from 'classnames'
|
|
3
|
+
import { Icon } from '../icons'
|
|
4
|
+
import styles from './forms.module.css'
|
|
5
|
+
import type { HoverTooltipHandlers } from '../tooltips'
|
|
6
|
+
|
|
7
|
+
export interface FormGroupProps {
|
|
8
|
+
/** text label */
|
|
9
|
+
label?: string
|
|
10
|
+
/** form content */
|
|
11
|
+
children?: React.ReactNode
|
|
12
|
+
/** classes to apply */
|
|
13
|
+
className?: string | null | undefined
|
|
14
|
+
/** if is included, FormGroup title will use error style. The content of the string is ignored. */
|
|
15
|
+
error?: string | null | undefined
|
|
16
|
+
/** enable disabled style. Overridden by truthy `error` */
|
|
17
|
+
disabled?: boolean | null | undefined
|
|
18
|
+
/** handlers for HoverTooltipComponent */
|
|
19
|
+
hoverTooltipHandlers?: HoverTooltipHandlers | null | undefined
|
|
20
|
+
/** boolean indicating formGroup used in pipette Settings slideout */
|
|
21
|
+
isPipetteSettingsSlideout?: boolean
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function FormGroup(props: FormGroupProps): JSX.Element {
|
|
25
|
+
const error = props.error != null
|
|
26
|
+
const className = cx(props.className, {
|
|
27
|
+
[styles.error]: error,
|
|
28
|
+
[styles.disabled]: !error && props.disabled,
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<div className={className}>
|
|
33
|
+
{props.label && (
|
|
34
|
+
<div
|
|
35
|
+
{...props.hoverTooltipHandlers}
|
|
36
|
+
className={
|
|
37
|
+
props.isPipetteSettingsSlideout
|
|
38
|
+
? styles.form_group_label_pipette_settings_slideout
|
|
39
|
+
: styles.form_group_label
|
|
40
|
+
}
|
|
41
|
+
>
|
|
42
|
+
{error && (
|
|
43
|
+
<div className={styles.error_icon}>
|
|
44
|
+
<Icon name="alert" />
|
|
45
|
+
</div>
|
|
46
|
+
)}
|
|
47
|
+
{props.label}
|
|
48
|
+
</div>
|
|
49
|
+
)}
|
|
50
|
+
{props.children}
|
|
51
|
+
</div>
|
|
52
|
+
)
|
|
53
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { Box, SIZE_6 } from '@opentrons/components'
|
|
3
|
+
|
|
4
|
+
import { LegacyInputField as InputFieldComponent } from './LegacyInputField'
|
|
5
|
+
|
|
6
|
+
import type { Story, Meta } from '@storybook/react'
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
title: 'Library/Molecules/Forms/Input Field',
|
|
10
|
+
} as Meta
|
|
11
|
+
|
|
12
|
+
const Template: Story<React.ComponentProps<typeof InputFieldComponent>> = ({
|
|
13
|
+
value,
|
|
14
|
+
onChange,
|
|
15
|
+
...args
|
|
16
|
+
}) => {
|
|
17
|
+
const [controlledValue, setControlledValue] = React.useState('')
|
|
18
|
+
const secondaryCaption = controlledValue.length + '/12'
|
|
19
|
+
const error = controlledValue.length > 12 ? 'Too many characters' : undefined
|
|
20
|
+
return (
|
|
21
|
+
<Box width={SIZE_6}>
|
|
22
|
+
<InputFieldComponent
|
|
23
|
+
{...args}
|
|
24
|
+
error={error}
|
|
25
|
+
secondaryCaption={secondaryCaption}
|
|
26
|
+
value={controlledValue}
|
|
27
|
+
onChange={e => {
|
|
28
|
+
setControlledValue(e.target.value)
|
|
29
|
+
}}
|
|
30
|
+
/>
|
|
31
|
+
</Box>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
export const InputField = Template.bind({})
|
|
35
|
+
InputField.args = {
|
|
36
|
+
label: 'Input field',
|
|
37
|
+
placeholder: 'Placeholder Text',
|
|
38
|
+
units: 'μL',
|
|
39
|
+
caption: 'caption here',
|
|
40
|
+
isIndeterminate: false,
|
|
41
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import type * as React from 'react'
|
|
2
|
+
import cx from 'classnames'
|
|
3
|
+
import { Icon } from '../icons'
|
|
4
|
+
import styles from './forms.module.css'
|
|
5
|
+
|
|
6
|
+
export const INPUT_TYPE_TEXT: 'text' = 'text'
|
|
7
|
+
export const INPUT_TYPE_PASSWORD: 'password' = 'password'
|
|
8
|
+
|
|
9
|
+
// TODO: Ian 2018-09-14 remove 'label' prop when IngredientPropertiesForm gets updated
|
|
10
|
+
|
|
11
|
+
export interface LegacyInputFieldProps {
|
|
12
|
+
/** field is disabled if value is true */
|
|
13
|
+
disabled?: boolean
|
|
14
|
+
/** change handler */
|
|
15
|
+
onChange?: React.ChangeEventHandler<HTMLInputElement>
|
|
16
|
+
/** classes to apply to outer element */
|
|
17
|
+
className?: string
|
|
18
|
+
/** inline label text. DEPRECATED */
|
|
19
|
+
label?: string
|
|
20
|
+
/** classes to apply to inner label text div */
|
|
21
|
+
labelTextClassName?: string | null | undefined
|
|
22
|
+
/** name of field in form */
|
|
23
|
+
name?: string
|
|
24
|
+
/** optional ID of <input> element */
|
|
25
|
+
id?: string
|
|
26
|
+
/** placeholder text */
|
|
27
|
+
placeholder?: string
|
|
28
|
+
/** optional suffix component, appears to the right of input text */
|
|
29
|
+
units?: React.ReactNode // TODO: Ian 2018-10-30 rename to 'suffix'
|
|
30
|
+
/** current value of text in box, defaults to '' */
|
|
31
|
+
value?: string | null | undefined
|
|
32
|
+
/** if included, InputField will use error style and display error instead of caption */
|
|
33
|
+
error?: string | null | undefined
|
|
34
|
+
/** optional caption. hidden when `error` is given */
|
|
35
|
+
caption?: string | null | undefined
|
|
36
|
+
/** appears to the right of the caption. Used for character limits, eg '0/45' */
|
|
37
|
+
secondaryCaption?: string | null | undefined
|
|
38
|
+
/** optional input type (default "text") */
|
|
39
|
+
type?: typeof INPUT_TYPE_TEXT | typeof INPUT_TYPE_PASSWORD
|
|
40
|
+
/** mouse click handler */
|
|
41
|
+
onClick?: (event: React.MouseEvent<HTMLInputElement>) => unknown
|
|
42
|
+
/** focus handler */
|
|
43
|
+
onFocus?: (event: React.FocusEvent<HTMLInputElement>) => unknown
|
|
44
|
+
/** blur handler */
|
|
45
|
+
onBlur?: (event: React.FocusEvent<HTMLInputElement>) => unknown
|
|
46
|
+
/** makes input field read-only */
|
|
47
|
+
readOnly?: boolean | undefined
|
|
48
|
+
/** html tabindex property */
|
|
49
|
+
tabIndex?: number
|
|
50
|
+
/** automatically focus field on render */
|
|
51
|
+
autoFocus?: boolean
|
|
52
|
+
/** if true, clear out value and add '-' placeholder */
|
|
53
|
+
isIndeterminate?: boolean
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @deprecated Use `InputField`
|
|
58
|
+
*/
|
|
59
|
+
|
|
60
|
+
export function LegacyInputField(props: LegacyInputFieldProps): JSX.Element {
|
|
61
|
+
const error = props.error != null
|
|
62
|
+
const labelClass = cx(styles.form_field, props.className, {
|
|
63
|
+
[styles.error]: error,
|
|
64
|
+
[styles.disabled]: props.disabled,
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
if (!props.label) {
|
|
68
|
+
return (
|
|
69
|
+
<div className={labelClass}>
|
|
70
|
+
<Input {...props} />
|
|
71
|
+
</div>
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<label className={labelClass}>
|
|
77
|
+
<div className={cx(props.labelTextClassName, styles.label_text)}>
|
|
78
|
+
{props.label && error && (
|
|
79
|
+
<div className={styles.error_icon}>
|
|
80
|
+
<Icon name="alert" />
|
|
81
|
+
</div>
|
|
82
|
+
)}
|
|
83
|
+
{props.label}
|
|
84
|
+
</div>
|
|
85
|
+
<Input {...props} />
|
|
86
|
+
</label>
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// TODO(mc, 2018-02-21): maybe simplify further and split out?
|
|
91
|
+
function Input(props: LegacyInputFieldProps): JSX.Element {
|
|
92
|
+
const error = props.error != null
|
|
93
|
+
const value = props.isIndeterminate ? '' : props.value ?? ''
|
|
94
|
+
const placeHolder = props.isIndeterminate ? '-' : props.placeholder
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<div className={styles.input_field_container}>
|
|
98
|
+
<div className={styles.input_field}>
|
|
99
|
+
<input
|
|
100
|
+
disabled={props.disabled}
|
|
101
|
+
id={props.id}
|
|
102
|
+
type={props.type ?? INPUT_TYPE_TEXT}
|
|
103
|
+
value={value}
|
|
104
|
+
name={props.name}
|
|
105
|
+
placeholder={placeHolder}
|
|
106
|
+
onChange={props.disabled ? undefined : props.onChange}
|
|
107
|
+
onFocus={props.disabled ? undefined : props.onFocus}
|
|
108
|
+
onBlur={props.onBlur}
|
|
109
|
+
onClick={props.disabled ? undefined : props.onClick}
|
|
110
|
+
readOnly={props.readOnly}
|
|
111
|
+
tabIndex={props.tabIndex}
|
|
112
|
+
autoFocus={props.autoFocus}
|
|
113
|
+
/>
|
|
114
|
+
{props.units && <div className={styles.suffix}>{props.units}</div>}
|
|
115
|
+
</div>
|
|
116
|
+
{/* TODO(mc, 2018-10-20): do not render if no caption */}
|
|
117
|
+
<div className={styles.input_caption}>
|
|
118
|
+
<span>{error ? props.error : props.caption}</span>
|
|
119
|
+
<span className={styles.right}>{props.secondaryCaption}</span>
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
)
|
|
123
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { Box, SIZE_6 } from '@opentrons/components'
|
|
3
|
+
|
|
4
|
+
import { RadioGroup as RadioGroupComponent } from './RadioGroup'
|
|
5
|
+
|
|
6
|
+
import type { Story, Meta } from '@storybook/react'
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
title: 'Library/Molecules/Forms/Radio Group',
|
|
10
|
+
} as Meta
|
|
11
|
+
|
|
12
|
+
const OPTIONS = [
|
|
13
|
+
{ name: 'Hazelnut', value: 'hazelnut' },
|
|
14
|
+
{ name: 'Chocolate', value: 'chocolate' },
|
|
15
|
+
{ name: 'Ginger', value: 'ginger' },
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
const Template: Story<React.ComponentProps<typeof RadioGroupComponent>> = ({
|
|
19
|
+
value,
|
|
20
|
+
onChange,
|
|
21
|
+
...args
|
|
22
|
+
}) => {
|
|
23
|
+
const [controlledValue, setControlledValue] = React.useState<string>(
|
|
24
|
+
args?.options?.[0] != null ? args.options[0].value : ''
|
|
25
|
+
)
|
|
26
|
+
return (
|
|
27
|
+
<Box width={SIZE_6}>
|
|
28
|
+
<RadioGroupComponent
|
|
29
|
+
{...args}
|
|
30
|
+
value={controlledValue}
|
|
31
|
+
onChange={e => {
|
|
32
|
+
setControlledValue(
|
|
33
|
+
'value' in e.target ? (e.target.value as string) : ''
|
|
34
|
+
)
|
|
35
|
+
}}
|
|
36
|
+
/>
|
|
37
|
+
</Box>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
export const RadioGroup = Template.bind({})
|
|
41
|
+
RadioGroup.args = {
|
|
42
|
+
options: OPTIONS,
|
|
43
|
+
inline: false,
|
|
44
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type * as React from 'react'
|
|
2
|
+
import cx from 'classnames'
|
|
3
|
+
import { Icon } from '../icons'
|
|
4
|
+
import styles from './forms.module.css'
|
|
5
|
+
|
|
6
|
+
export interface RadioOption {
|
|
7
|
+
name: string
|
|
8
|
+
value: string
|
|
9
|
+
children?: React.ReactNode
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface RadioGroupProps {
|
|
13
|
+
/** blur handler */
|
|
14
|
+
onBlur?: React.FocusEventHandler<HTMLInputElement>
|
|
15
|
+
/** change handler */
|
|
16
|
+
onChange: React.ChangeEventHandler
|
|
17
|
+
/** value that is checked */
|
|
18
|
+
value?: string
|
|
19
|
+
/** Array of {name, value} data with optional children */
|
|
20
|
+
options?: RadioOption[]
|
|
21
|
+
/** Show radio buttons inline instead of stacked */
|
|
22
|
+
inline?: boolean
|
|
23
|
+
/** classes to apply to outer div */
|
|
24
|
+
className?: string
|
|
25
|
+
/** classes to apply to inner label text div */
|
|
26
|
+
labelTextClassName?: string | null | undefined
|
|
27
|
+
/** if is included, RadioGroup will use error style. The content of the string is ignored. */
|
|
28
|
+
error?: string | null | undefined
|
|
29
|
+
/** 'name' attr of input */
|
|
30
|
+
name?: string
|
|
31
|
+
/** optional prop to turn radio field blue when checked */
|
|
32
|
+
useBlueChecked?: boolean
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function RadioGroup(props: RadioGroupProps): JSX.Element {
|
|
36
|
+
const error = props.error != null
|
|
37
|
+
|
|
38
|
+
const outerClassName = cx({
|
|
39
|
+
[styles.inline]: props.inline,
|
|
40
|
+
[styles.error]: error,
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
const itemClassName = cx(styles.form_field, props.className, {
|
|
44
|
+
[styles.inline_item]: props.inline,
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<div className={outerClassName}>
|
|
49
|
+
{props.options?.map(radio => {
|
|
50
|
+
const useStyleUpdates =
|
|
51
|
+
props.useBlueChecked && radio.value === props.value
|
|
52
|
+
return (
|
|
53
|
+
<label key={radio.value} id={radio.value} className={itemClassName}>
|
|
54
|
+
<div
|
|
55
|
+
className={cx(styles.checkbox_icon, {
|
|
56
|
+
[styles.checked]: useStyleUpdates,
|
|
57
|
+
})}
|
|
58
|
+
>
|
|
59
|
+
<Icon
|
|
60
|
+
name={
|
|
61
|
+
radio.value === props.value
|
|
62
|
+
? 'radiobox-marked'
|
|
63
|
+
: 'radiobox-blank'
|
|
64
|
+
}
|
|
65
|
+
width={props.useBlueChecked ? '75%' : '100%'}
|
|
66
|
+
/>
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<input
|
|
70
|
+
className={cx(styles.input_field, styles.accessibly_hidden)}
|
|
71
|
+
type="radio"
|
|
72
|
+
name={props.name}
|
|
73
|
+
value={radio.value}
|
|
74
|
+
checked={radio.value === props.value}
|
|
75
|
+
onBlur={props.onBlur}
|
|
76
|
+
onChange={props.onChange}
|
|
77
|
+
/>
|
|
78
|
+
<div className={cx(props.labelTextClassName, styles.label_text)}>
|
|
79
|
+
{radio.name}
|
|
80
|
+
</div>
|
|
81
|
+
{radio.children}
|
|
82
|
+
</label>
|
|
83
|
+
)
|
|
84
|
+
})}
|
|
85
|
+
</div>
|
|
86
|
+
)
|
|
87
|
+
}
|