@12-apps/ui 6.26.0 → 6.27.0
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/dist/_internal/components/data-display/Alert/Alert.js +4 -4
- package/dist/_internal/components/data-display/Alert/Alert.metrics.js +2 -2
- package/dist/_internal/components/data-display/Alert/Alert.styles.js +3 -3
- package/dist/_internal/components/data-display/Avatar/Avatar.js +3 -3
- package/dist/_internal/components/data-display/Avatar/Avatar.view.js +2 -2
- package/dist/_internal/components/data-display/Badge/Badge.animations.js +3 -3
- package/dist/_internal/components/data-display/Badge/Badge.js +7 -7
- package/dist/_internal/components/data-display/Badge/Badge.metrics.js +2 -2
- package/dist/_internal/components/data-display/Badge/Badge.styles.js +5 -5
- package/dist/_internal/components/data-display/Badge/Badge.variants.js +3 -3
- package/dist/_internal/components/data-display/Badge/BadgeContent.js +6 -6
- package/dist/_internal/components/data-display/Banner/Banner.js +4 -4
- package/dist/_internal/components/data-display/Banner/Banner.styles.js +3 -3
- package/dist/_internal/components/data-display/CardKit/CardKebab.js +4 -4
- package/dist/_internal/components/data-display/CardKit/card-actions-context.js +5 -5
- package/dist/_internal/components/data-display/CardKit/use-remove-confirm.js +9 -9
- package/dist/_internal/components/data-display/CardKit/use-row-confirm.js +4 -4
- package/dist/_internal/components/data-display/Carousel/Carousel.chrome.js +1 -1
- package/dist/_internal/components/data-display/Carousel/Carousel.js +1 -1
- package/dist/_internal/components/data-display/Carousel/Carousel.parts.js +1 -1
- package/dist/_internal/components/data-display/Carousel/Carousel.styles.js +1 -1
- package/dist/_internal/components/data-display/Chart/Chart.js +5 -5
- package/dist/_internal/components/data-display/Chart/SpecChart.js +6 -6
- package/dist/_internal/components/data-display/Chart/chart-context.js +3 -3
- package/dist/_internal/components/data-display/Chart/chart-internals.js +1 -1
- package/dist/_internal/components/data-display/Chart/chart-renderers.js +4 -4
- package/dist/_internal/components/data-display/DataViews/DataViewsBoard.js +4 -4
- package/dist/_internal/components/data-display/DataViews/DataViewsGrid.js +37 -37
- package/dist/_internal/components/data-display/DataViews/DataViewsTableBase.js +54 -53
- package/dist/_internal/components/data-display/DataViews/DeleteViewDialog.js +6 -6
- package/dist/_internal/components/data-display/DataViews/ManageViewsDialog.js +7 -7
- package/dist/_internal/components/data-display/DataViews/SaveViewModal.js +12 -11
- package/dist/_internal/components/data-display/DataViews/base-card.js +9 -9
- package/dist/_internal/components/data-display/DataViews/base-list-card-geometry.js +12 -12
- package/dist/_internal/components/data-display/DataViews/base-list-card-gutters.js +3 -3
- package/dist/_internal/components/data-display/DataViews/base-list-card-slots.js +8 -8
- package/dist/_internal/components/data-display/DataViews/base-list-card.js +16 -16
- package/dist/_internal/components/data-display/DataViews/card-surface.js +4 -4
- package/dist/_internal/components/data-display/DataViews/data-views-category-pill.js +5 -5
- package/dist/_internal/components/data-display/DataViews/data-views-columns-tab.js +4 -4
- package/dist/_internal/components/data-display/DataViews/data-views-columns.js +5 -5
- package/dist/_internal/components/data-display/DataViews/data-views-display-panel.js +11 -11
- package/dist/_internal/components/data-display/DataViews/data-views-display-tabs.js +6 -6
- package/dist/_internal/components/data-display/DataViews/data-views-empty.js +6 -6
- package/dist/_internal/components/data-display/DataViews/data-views-export.js +6 -6
- package/dist/_internal/components/data-display/DataViews/data-views-filter-panel.js +6 -6
- package/dist/_internal/components/data-display/DataViews/data-views-grid-bodies.js +12 -12
- package/dist/_internal/components/data-display/DataViews/data-views-grid-helpers.js +4 -4
- package/dist/_internal/components/data-display/DataViews/data-views-grid-parts.js +34 -34
- package/dist/_internal/components/data-display/DataViews/data-views-header-row.js +4 -4
- package/dist/_internal/components/data-display/DataViews/data-views-inline-bar.js +13 -13
- package/dist/_internal/components/data-display/DataViews/data-views-layout-context.js +2 -2
- package/dist/_internal/components/data-display/DataViews/data-views-more-fields.js +4 -4
- package/dist/_internal/components/data-display/DataViews/data-views-more-filters.js +7 -7
- package/dist/_internal/components/data-display/DataViews/data-views-scope-tabs.js +3 -3
- package/dist/_internal/components/data-display/DataViews/data-views-select-all-strip.js +6 -6
- package/dist/_internal/components/data-display/DataViews/data-views-shell-toolbar.js +15 -15
- package/dist/_internal/components/data-display/DataViews/data-views-table-parts.js +18 -17
- package/dist/_internal/components/data-display/DataViews/data-views-toolbar.js +14 -14
- package/dist/_internal/components/data-display/DataViews/data-views-view-nav.js +6 -6
- package/dist/_internal/components/data-display/DataViews/list-card-rails.js +3 -3
- package/dist/_internal/components/data-display/DataViews/save-view-preview.js +4 -4
- package/dist/_internal/components/data-display/DataViews/use-data-views-state.js +7 -7
- package/dist/_internal/components/data-display/DataViews/use-saved-views-controller.js +2 -2
- package/dist/_internal/components/data-display/DescriptionItem/DescriptionItem.js +4 -4
- package/dist/_internal/components/data-display/FleetMap/FleetBody.js +11 -11
- package/dist/_internal/components/data-display/FleetMap/FleetCanvas.js +8 -8
- package/dist/_internal/components/data-display/FleetMap/FleetMap.js +13 -13
- package/dist/_internal/components/data-display/FleetMap/FleetRoster.js +2 -2
- package/dist/_internal/components/data-display/Lightbox/Lightbox.js +1 -1
- package/dist/_internal/components/data-display/MapPreview/MapDecorations.js +2 -2
- package/dist/_internal/components/data-display/MapPreview/MapPreview.hooks.js +2 -2
- package/dist/_internal/components/data-display/MapPreview/MapPreview.js +7 -7
- package/dist/_internal/components/data-display/MapPreview/MapTiles.js +2 -2
- package/dist/_internal/components/data-display/MapPreview/StaticMapView.js +4 -4
- package/dist/_internal/components/data-display/MapPreview/useMapPreview.js +3 -3
- package/dist/_internal/components/data-display/Progress/Progress.js +4 -4
- package/dist/_internal/components/data-display/Progress/Progress.metrics.js +2 -2
- package/dist/_internal/components/data-display/Progress/Progress.styles.js +3 -3
- package/dist/_internal/components/data-display/Sheet/Sheet.body.js +1 -1
- package/dist/_internal/components/data-display/Sheet/Sheet.js +4 -4
- package/dist/_internal/components/data-display/Sheet/Sheet.styles.js +1 -1
- package/dist/_internal/components/data-display/Table/Table.js +2 -2
- package/dist/_internal/components/data-display/index.js +43 -43
- package/dist/_internal/components/feedback/ConfirmAction/ConfirmButton.js +4 -4
- package/dist/_internal/components/feedback/index.js +4 -4
- package/dist/_internal/components/form/AddressAutocomplete/AddressAutocomplete.hooks.js +2 -2
- package/dist/_internal/components/form/AddressAutocomplete/AddressAutocomplete.js +5 -5
- package/dist/_internal/components/form/Autocomplete/Autocomplete.js +2 -2
- package/dist/_internal/components/form/Button/Button.js +3 -3
- package/dist/_internal/components/form/Button/Button.styles.js +2 -2
- package/dist/_internal/components/form/Calendar/Calendar.hooks.js +2 -2
- package/dist/_internal/components/form/Calendar/Calendar.js +3 -3
- package/dist/_internal/components/form/CategorySelect/CategoryPanel.js +1 -1
- package/dist/_internal/components/form/CategorySelect/CategorySelect.js +4 -4
- package/dist/_internal/components/form/Checkbox/Checkbox.js +2 -2
- package/dist/_internal/components/form/Command/Command.js +4 -4
- package/dist/_internal/components/form/Command/Command.styles.js +1 -1
- package/dist/_internal/components/form/DateRangePicker/DateRangePicker.js +5 -5
- package/dist/_internal/components/form/Label/Label.js +1 -1
- package/dist/_internal/components/form/Label/Label.styles.js +1 -1
- package/dist/_internal/components/form/Menubar/Menubar.item.js +1 -1
- package/dist/_internal/components/form/Menubar/Menubar.js +1 -1
- package/dist/_internal/components/form/Menubar/Menubar.styles.js +1 -1
- package/dist/_internal/components/form/Menubar/Menubar.toolbar.js +1 -1
- package/dist/_internal/components/form/PhoneInput/PhoneInput.hooks.js +2 -2
- package/dist/_internal/components/form/PhoneInput/PhoneInput.js +3 -3
- package/dist/_internal/components/form/RichTextEditor/RichTextEditor.js +2 -2
- package/dist/_internal/components/form/Switch/Switch.ids.js +8 -0
- package/dist/_internal/components/form/Switch/Switch.ids.js.map +1 -0
- package/dist/_internal/components/form/Switch/Switch.js +6 -5
- package/dist/_internal/components/form/Switch/Switch.metrics.js +5 -1
- package/dist/_internal/components/form/Switch/Switch.parts.js +6 -8
- package/dist/_internal/components/form/Switch/Switch.styles.js +5 -3
- package/dist/_internal/components/form/index.js +34 -33
- package/dist/_internal/components/form/total-form/Fields/CategoryField.js +5 -5
- package/dist/_internal/components/form/total-form/Fields/index.js +6 -6
- package/dist/_internal/components/form/total-form/SubmitButton.js +4 -4
- package/dist/_internal/components/index.js +82 -81
- package/dist/_internal/components/layout/Box/Box.js +4 -4
- package/dist/_internal/components/layout/Stack/Stack.js +5 -5
- package/dist/_internal/components/navigation/AppHeader/AppHeader.details.js +7 -7
- package/dist/_internal/components/navigation/AppHeader/AppHeader.identity.js +1 -1
- package/dist/_internal/components/navigation/index.js +7 -7
- package/dist/_internal/components/typography/Heading/Heading.js +4 -4
- package/dist/_internal/components/typography/Heading/Heading.metrics.js +2 -2
- package/dist/_internal/components/typography/Heading/Heading.styles.js +3 -3
- package/dist/_internal/components/typography/Paragraph/Paragraph.js +2 -2
- package/dist/_internal/components/typography/Text/Text.js +3 -3
- package/dist/_internal/components/typography/Text/Text.metrics.js +2 -2
- package/dist/_internal/components/typography/index.js +7 -7
- package/dist/_internal/icons/Icon.js +4 -4
- package/dist/_internal/provider/UiProvider.js +3 -3
- package/dist/_internal/provider/mui-bridge.js +2 -2
- package/dist/_internal/provider/use-ui-theme.js +3 -3
- package/dist/_internal/social-login-button/social-login-button.js +9 -9
- package/dist/_internal/tokens/theme.js +3 -1
- package/dist/_internal/user-avatar/user-avatar.js +8 -8
- package/dist/charts.js +6 -6
- package/dist/{chunk-2GI7ANEL.js → chunk-22X7TT6Z.js} +4 -4
- package/dist/{chunk-WR5JFDQ5.js → chunk-27BL3DNT.js} +8 -8
- package/dist/{chunk-E55CJV65.js → chunk-2KVQIGVE.js} +2 -2
- package/dist/{chunk-BB2OUERT.js → chunk-2LSCK45B.js} +7 -4
- package/dist/chunk-2LSCK45B.js.map +1 -0
- package/dist/{chunk-W3FAKT3D.js → chunk-2SWQ6HIK.js} +4 -4
- package/dist/{chunk-ISW5K72V.js → chunk-2ZRZTGWP.js} +5 -5
- package/dist/{chunk-I5SBTNV2.js → chunk-3GB6KWHH.js} +2 -2
- package/dist/{chunk-ZEG2LNBY.js → chunk-3PJLT5FX.js} +2 -2
- package/dist/{chunk-CXLAJZSE.js → chunk-3VZT2FAI.js} +3 -3
- package/dist/{chunk-MLCFODJO.js → chunk-3W2IS5RH.js} +5 -1
- package/dist/{chunk-MLCFODJO.js.map → chunk-3W2IS5RH.js.map} +1 -1
- package/dist/{chunk-PFDM2OIP.js → chunk-45OHGD2B.js} +4 -4
- package/dist/{chunk-BH5BXLGI.js → chunk-4A2Q22HO.js} +3 -3
- package/dist/{chunk-46UPILLK.js → chunk-4ETQRBZC.js} +4 -4
- package/dist/{chunk-TWY5FOBY.js → chunk-5QUSX3TC.js} +5 -5
- package/dist/{chunk-AVGTTWTE.js → chunk-65DLYC4S.js} +4 -4
- package/dist/{chunk-TVPPA4RD.js → chunk-65METCKT.js} +16 -16
- package/dist/{chunk-OQFSYMHJ.js → chunk-67ALTEWH.js} +2 -2
- package/dist/{chunk-OGGHD64H.js → chunk-6SK3MTYJ.js} +2 -2
- package/dist/{chunk-OE2ZVL67.js → chunk-6VHCSPKK.js} +3 -3
- package/dist/{chunk-WAPJ2DL3.js → chunk-72T5PAW7.js} +4 -4
- package/dist/{chunk-SLVQ33AN.js → chunk-77DF5LKI.js} +2 -2
- package/dist/{chunk-7KWBGMQC.js → chunk-77OXG6DH.js} +5 -5
- package/dist/{chunk-Y3KRUT7O.js → chunk-7AIHK2XM.js} +2 -2
- package/dist/{chunk-MHV5Y5MR.js → chunk-7KEGJH3Q.js} +3 -3
- package/dist/{chunk-KMXAPYU2.js → chunk-7NEUPEV5.js} +2 -2
- package/dist/{chunk-67L7HMEP.js → chunk-7Z2AQEC5.js} +2 -2
- package/dist/{chunk-PQECNGDE.js → chunk-AGYGNNOM.js} +2 -2
- package/dist/{chunk-ZTF5C2GA.js → chunk-B5SW7I5W.js} +2 -2
- package/dist/{chunk-TXHJX2NG.js → chunk-BGYLL467.js} +4 -4
- package/dist/{chunk-R7R3LOKW.js → chunk-CA7TA36R.js} +2 -2
- package/dist/{chunk-FPFUXRD2.js → chunk-CKJI7JO5.js} +2 -2
- package/dist/{chunk-HMV4QMXS.js → chunk-CMN26J5Y.js} +4 -4
- package/dist/{chunk-KVEHH4SA.js → chunk-DB2MAYPK.js} +2 -2
- package/dist/{chunk-2ECT4IY2.js → chunk-DIHVWBQV.js} +36 -17
- package/dist/chunk-DIHVWBQV.js.map +1 -0
- package/dist/{chunk-V4FKHLEB.js → chunk-DTIB5KWP.js} +3 -3
- package/dist/{chunk-MESRKY67.js → chunk-DW6GBMLQ.js} +3 -3
- package/dist/{chunk-JO6BBSGY.js → chunk-DWJBOR47.js} +3 -3
- package/dist/{chunk-YW5T6KZ5.js → chunk-DYESJJ3Q.js} +9 -9
- package/dist/{chunk-TZDDL3DR.js → chunk-ECMJ5VPW.js} +2 -2
- package/dist/{chunk-OH3YGJT5.js → chunk-EMNGIYH6.js} +5 -5
- package/dist/{chunk-CZJLWCEG.js → chunk-EPNCYUQ7.js} +4 -4
- package/dist/{chunk-JZXWCEH5.js → chunk-EQA4VQEO.js} +2 -2
- package/dist/{chunk-3N6EK6K5.js → chunk-ERX4XIYC.js} +2 -2
- package/dist/{chunk-TTLI6PF7.js → chunk-FF3R67WD.js} +5 -5
- package/dist/{chunk-4Y6SPFKW.js → chunk-FOF2RAVQ.js} +4 -4
- package/dist/{chunk-KLREH4X6.js → chunk-G2JPUHEJ.js} +2 -2
- package/dist/{chunk-4J5EN4FQ.js → chunk-GBX5ACPF.js} +5 -5
- package/dist/{chunk-ZZMZF7PZ.js → chunk-GQJ4NCZ6.js} +3 -3
- package/dist/{chunk-IPVYEPXO.js → chunk-GSTRPZS4.js} +5 -5
- package/dist/{chunk-HFXTAEYY.js → chunk-GTLJYAEG.js} +2 -2
- package/dist/{chunk-M4LFDGI6.js → chunk-GYQT47YZ.js} +2 -2
- package/dist/{chunk-JSH3HFDQ.js → chunk-H3BQFEN5.js} +2 -2
- package/dist/{chunk-OV4WREMW.js → chunk-HKB5C2KY.js} +7 -7
- package/dist/{chunk-BLBOYCOV.js → chunk-HKV4MQ2W.js} +5 -5
- package/dist/{chunk-4MGFUPQT.js → chunk-HOJL2GKW.js} +4 -4
- package/dist/{chunk-HR7YTBR7.js → chunk-IASDP44E.js} +4 -4
- package/dist/{chunk-YMRI5QKG.js → chunk-IV5QQLCS.js} +2 -2
- package/dist/{chunk-JUHUKZGU.js → chunk-JD3D6Y4U.js} +2 -2
- package/dist/{chunk-FR67FG2U.js → chunk-JFRKBSWI.js} +35 -25
- package/dist/chunk-JFRKBSWI.js.map +1 -0
- package/dist/{chunk-AXTLFK4T.js → chunk-KAV63FBG.js} +2 -2
- package/dist/{chunk-2PBGVMM2.js → chunk-KOFO6QZY.js} +2 -2
- package/dist/{chunk-RP5FK3SO.js → chunk-L7LCSZ3H.js} +3 -3
- package/dist/{chunk-MNXVXW4T.js → chunk-L7S6N67X.js} +2 -2
- package/dist/{chunk-JXPHU3K5.js → chunk-LGJ2H4AH.js} +5 -5
- package/dist/{chunk-W4YWU7LQ.js → chunk-LO2B7FDQ.js} +2 -2
- package/dist/{chunk-PWR7K5OP.js → chunk-LV4UTYAD.js} +2 -2
- package/dist/{chunk-OG2FP6SE.js → chunk-M4NFXC5R.js} +4 -4
- package/dist/{chunk-ZPIMPOHV.js → chunk-M7E66OSC.js} +4 -4
- package/dist/{chunk-OGGPQVIG.js → chunk-MDTSMJ7C.js} +3 -3
- package/dist/{chunk-YDI6IJ6F.js → chunk-MI2MVH3I.js} +4 -4
- package/dist/{chunk-UIZH4DAE.js → chunk-MQPT254A.js} +4 -4
- package/dist/{chunk-EWT3WMVY.js → chunk-MYH7VISV.js} +5 -5
- package/dist/{chunk-7NSX7A5H.js → chunk-N5PY7IXI.js} +3 -3
- package/dist/{chunk-BHIGHSXA.js → chunk-NNXZ5RK5.js} +4 -4
- package/dist/{chunk-EQ7PWGBN.js → chunk-O7HLQTB7.js} +3 -3
- package/dist/{chunk-DW5FRWRQ.js → chunk-OAWEUKUC.js} +2 -2
- package/dist/{chunk-O4VCZTK4.js → chunk-OGHW7RQC.js} +2 -2
- package/dist/{chunk-XR6WBW23.js → chunk-OVGASVPW.js} +2 -2
- package/dist/{chunk-HEBQS7QP.js → chunk-OXYR2HVK.js} +3 -3
- package/dist/{chunk-TNVO2DTB.js → chunk-P7FQUGED.js} +5 -5
- package/dist/{chunk-343TTIHD.js → chunk-PENJBKPH.js} +3 -3
- package/dist/{chunk-2RQINU5T.js → chunk-PKFFJAQ6.js} +2 -2
- package/dist/{chunk-M4LQRQFL.js → chunk-PW2WLDX3.js} +2 -2
- package/dist/{chunk-WRDPWEIC.js → chunk-Q3GSDSK2.js} +6 -6
- package/dist/{chunk-VNTOBLIB.js → chunk-Q3OFOOO7.js} +2 -2
- package/dist/{chunk-GGI7GM5O.js → chunk-QE2C35TO.js} +4 -4
- package/dist/{chunk-NQN5Z36J.js → chunk-QLI7ES7Z.js} +10 -1
- package/dist/chunk-QLI7ES7Z.js.map +1 -0
- package/dist/{chunk-CT5K725B.js → chunk-QQLGSMGE.js} +2 -2
- package/dist/{chunk-7MN6I5NK.js → chunk-QXFPTRHB.js} +3 -3
- package/dist/{chunk-CZPU5TW3.js → chunk-RFZU5BTG.js} +2 -2
- package/dist/{chunk-JB67KPGM.js → chunk-RRO2EOJB.js} +4 -4
- package/dist/{chunk-MZQTHSLN.js → chunk-S7HRED4D.js} +2 -2
- package/dist/{chunk-NYEA7JAI.js → chunk-SC72DRTX.js} +6 -6
- package/dist/{chunk-JWW2Z3RH.js → chunk-SMZBGHR2.js} +7 -7
- package/dist/{chunk-EZSEAYYT.js → chunk-SSWZHR46.js} +5 -5
- package/dist/{chunk-NA7MIEG6.js → chunk-SZETT7QV.js} +2 -2
- package/dist/chunk-SZS7VZJN.js +25 -0
- package/dist/chunk-SZS7VZJN.js.map +1 -0
- package/dist/{chunk-2HPP6RVC.js → chunk-TQOPF7LD.js} +2 -2
- package/dist/{chunk-OLVZ6TOV.js → chunk-TUO47RL2.js} +4 -4
- package/dist/{chunk-N5IVVLTH.js → chunk-UG76BO5K.js} +79 -19
- package/dist/chunk-UG76BO5K.js.map +1 -0
- package/dist/{chunk-4IVDVZZ2.js → chunk-UGL6SJN6.js} +3 -3
- package/dist/{chunk-QJRDDVZ2.js → chunk-V5P5Q6HM.js} +3 -3
- package/dist/{chunk-73NJCGQG.js → chunk-VIK3HAUQ.js} +2 -2
- package/dist/{chunk-7LCXGJN5.js → chunk-VK4ULJFH.js} +2 -2
- package/dist/{chunk-QYNCPS5W.js → chunk-WBKWIFXA.js} +6 -6
- package/dist/{chunk-X4Z62ZQY.js → chunk-WETAIIKC.js} +2 -2
- package/dist/{chunk-GMTM6EN7.js → chunk-WKF54CCK.js} +7 -7
- package/dist/{chunk-KT6HWAEN.js → chunk-WZUNBSS7.js} +2 -2
- package/dist/{chunk-Y2B3I3IH.js → chunk-X5RDHO6G.js} +2 -2
- package/dist/{chunk-TXKZEKJN.js → chunk-XNOSTV5F.js} +2 -2
- package/dist/{chunk-7JXLGOM2.js → chunk-Y55ILY2F.js} +3 -3
- package/dist/{chunk-HI2OFZSZ.js → chunk-YPILHGEO.js} +2 -2
- package/dist/{chunk-V3PLFYKO.js → chunk-ZAJO2B75.js} +2 -2
- package/dist/data-display/Alert.js +4 -4
- package/dist/data-display/Avatar.js +3 -3
- package/dist/data-display/Badge.js +7 -7
- package/dist/data-display/Banner.js +4 -4
- package/dist/data-display/CardKit.js +13 -13
- package/dist/data-display/Carousel.js +1 -1
- package/dist/data-display/Chart.js +6 -6
- package/dist/data-display/DataViews.js +68 -67
- package/dist/data-display/DescriptionItem.js +4 -4
- package/dist/data-display/FleetMap.js +13 -13
- package/dist/data-display/Lightbox.js +1 -1
- package/dist/data-display/MapPreview.js +7 -7
- package/dist/data-display/Progress.js +4 -4
- package/dist/data-display/Sheet.js +4 -4
- package/dist/data-display/Table.js +2 -2
- package/dist/feedback/ConfirmAction.js +4 -4
- package/dist/form/AddressAutocomplete.js +5 -5
- package/dist/form/Autocomplete.js +2 -2
- package/dist/form/Button.js +3 -3
- package/dist/form/Calendar.js +3 -3
- package/dist/form/CategorySelect.js +4 -4
- package/dist/form/Checkbox.js +2 -2
- package/dist/form/Command.js +4 -4
- package/dist/form/DateRangePicker.js +10 -10
- package/dist/form/Label.js +1 -1
- package/dist/form/Menubar.js +1 -1
- package/dist/form/PhoneInput.js +3 -3
- package/dist/form/RichTextEditor.js +2 -2
- package/dist/form/Switch.js +6 -5
- package/dist/form/total-form.js +10 -10
- package/dist/icons.js +4 -4
- package/dist/layout/Box.js +4 -4
- package/dist/layout/Stack.js +5 -5
- package/dist/native/chunks/{chunk-2R2R35C5.js → chunk-2SBTJSQE.js} +5 -5
- package/dist/native/chunks/{chunk-WL5LXVCK.js → chunk-6L4UZBQP.js} +3 -3
- package/dist/native/chunks/{chunk-LEMMXZFN.js → chunk-MP3UDWTT.js} +10 -1
- package/dist/native/chunks/{chunk-LEMMXZFN.js.map → chunk-MP3UDWTT.js.map} +1 -1
- package/dist/native/chunks/{chunk-GW7TQ7HO.js → chunk-QEQZ5AF6.js} +3 -3
- package/dist/native/chunks/{chunk-7LTVGW23.js → chunk-UII3IFLP.js} +2 -2
- package/dist/native/chunks/{chunk-75JQYVDZ.js → chunk-UYREIOEM.js} +2 -2
- package/dist/native/chunks/{chunk-GWGIWQO7.js → chunk-XI7HTAVN.js} +2 -2
- package/dist/native/chunks/{chunk-QYUD3S6F.js → chunk-ZOP7UAZK.js} +2 -2
- package/dist/native/data-display/Alert.js +3 -3
- package/dist/native/data-display/Avatar.js +3 -3
- package/dist/native/data-display/Badge.js +3 -3
- package/dist/native/data-display/Chip.js +3 -3
- package/dist/native/data-display/EmptyState.js +5 -5
- package/dist/native/data-display/ErrorState.js +4 -4
- package/dist/native/data-display/FleetMap.js +6 -6
- package/dist/native/data-display/LoadingState.js +2 -2
- package/dist/native/data-display/Progress.js +2 -2
- package/dist/native/feedback/Dialog.js +3 -3
- package/dist/native/form/Button.js +3 -3
- package/dist/native/form/Checkbox.js +3 -3
- package/dist/native/form/Input.js +3 -3
- package/dist/native/form/Select.js +4 -4
- package/dist/native/form/Switch.js +26 -8
- package/dist/native/form/Switch.js.map +1 -1
- package/dist/native/icons.js +3 -3
- package/dist/native/layout/Box.js +3 -3
- package/dist/native/layout/Card.js +2 -2
- package/dist/native/layout/Container.js +2 -2
- package/dist/native/layout/Skeleton.js +3 -3
- package/dist/native/layout/Spacer.js +2 -2
- package/dist/native/layout/Stack.js +3 -3
- package/dist/native/provider.js +2 -2
- package/dist/native/tokens.js +3 -1
- package/dist/native/typography/Heading.js +2 -2
- package/dist/native/typography/Paragraph.js +2 -2
- package/dist/native/typography/Text.js +2 -2
- package/dist/navigation/AppHeader.js +7 -7
- package/dist/provider.js +4 -4
- package/dist/social-login-button.js +9 -9
- package/dist/tokens.js +3 -1
- package/dist/types/components/form/Button/Button.styles.d.ts.map +1 -1
- package/dist/types/components/form/Switch/Switch.d.ts.map +1 -1
- package/dist/types/components/form/Switch/Switch.ids.d.ts +42 -0
- package/dist/types/components/form/Switch/Switch.ids.d.ts.map +1 -0
- package/dist/types/components/form/Switch/Switch.metrics.d.ts +19 -0
- package/dist/types/components/form/Switch/Switch.metrics.d.ts.map +1 -1
- package/dist/types/components/form/Switch/Switch.parts.d.ts +31 -11
- package/dist/types/components/form/Switch/Switch.parts.d.ts.map +1 -1
- package/dist/types/components/form/Switch/Switch.styles.d.ts +6 -0
- package/dist/types/components/form/Switch/Switch.styles.d.ts.map +1 -1
- package/dist/types/tokens/theme.d.ts +38 -0
- package/dist/types/tokens/theme.d.ts.map +1 -1
- package/dist/types-native/components/form/Switch/Switch.look.native.d.ts +26 -2
- package/dist/types-native/components/form/Switch/Switch.look.native.d.ts.map +1 -1
- package/dist/types-native/components/form/Switch/Switch.metrics.d.ts +19 -0
- package/dist/types-native/components/form/Switch/Switch.metrics.d.ts.map +1 -1
- package/dist/types-native/components/form/Switch/Switch.native.d.ts.map +1 -1
- package/dist/types-native/tokens/theme.d.ts +38 -0
- package/dist/types-native/tokens/theme.d.ts.map +1 -1
- package/dist/typography/Heading.js +4 -4
- package/dist/typography/Paragraph.js +2 -2
- package/dist/typography/Text.js +3 -3
- package/dist/user-avatar.js +8 -8
- package/package.json +1 -1
- package/src/components/form/Button/Button.md +8 -0
- package/src/components/form/Button/Button.styles.ts +24 -3
- package/src/components/form/Switch/Switch.ids.ts +63 -0
- package/src/components/form/Switch/Switch.look.native.ts +45 -2
- package/src/components/form/Switch/Switch.md +34 -9
- package/src/components/form/Switch/Switch.metrics.ts +21 -0
- package/src/components/form/Switch/Switch.native.tsx +19 -6
- package/src/components/form/Switch/Switch.parts.tsx +150 -17
- package/src/components/form/Switch/Switch.styles.ts +59 -6
- package/src/components/form/Switch/Switch.tsx +32 -30
- package/src/tokens/theme.ts +50 -0
- package/dist/chunk-2ECT4IY2.js.map +0 -1
- package/dist/chunk-BB2OUERT.js.map +0 -1
- package/dist/chunk-FR67FG2U.js.map +0 -1
- package/dist/chunk-N5IVVLTH.js.map +0 -1
- package/dist/chunk-NQN5Z36J.js.map +0 -1
- /package/dist/{chunk-2GI7ANEL.js.map → chunk-22X7TT6Z.js.map} +0 -0
- /package/dist/{chunk-WR5JFDQ5.js.map → chunk-27BL3DNT.js.map} +0 -0
- /package/dist/{chunk-E55CJV65.js.map → chunk-2KVQIGVE.js.map} +0 -0
- /package/dist/{chunk-W3FAKT3D.js.map → chunk-2SWQ6HIK.js.map} +0 -0
- /package/dist/{chunk-ISW5K72V.js.map → chunk-2ZRZTGWP.js.map} +0 -0
- /package/dist/{chunk-I5SBTNV2.js.map → chunk-3GB6KWHH.js.map} +0 -0
- /package/dist/{chunk-ZEG2LNBY.js.map → chunk-3PJLT5FX.js.map} +0 -0
- /package/dist/{chunk-CXLAJZSE.js.map → chunk-3VZT2FAI.js.map} +0 -0
- /package/dist/{chunk-PFDM2OIP.js.map → chunk-45OHGD2B.js.map} +0 -0
- /package/dist/{chunk-BH5BXLGI.js.map → chunk-4A2Q22HO.js.map} +0 -0
- /package/dist/{chunk-46UPILLK.js.map → chunk-4ETQRBZC.js.map} +0 -0
- /package/dist/{chunk-TWY5FOBY.js.map → chunk-5QUSX3TC.js.map} +0 -0
- /package/dist/{chunk-AVGTTWTE.js.map → chunk-65DLYC4S.js.map} +0 -0
- /package/dist/{chunk-TVPPA4RD.js.map → chunk-65METCKT.js.map} +0 -0
- /package/dist/{chunk-OQFSYMHJ.js.map → chunk-67ALTEWH.js.map} +0 -0
- /package/dist/{chunk-OGGHD64H.js.map → chunk-6SK3MTYJ.js.map} +0 -0
- /package/dist/{chunk-OE2ZVL67.js.map → chunk-6VHCSPKK.js.map} +0 -0
- /package/dist/{chunk-WAPJ2DL3.js.map → chunk-72T5PAW7.js.map} +0 -0
- /package/dist/{chunk-SLVQ33AN.js.map → chunk-77DF5LKI.js.map} +0 -0
- /package/dist/{chunk-7KWBGMQC.js.map → chunk-77OXG6DH.js.map} +0 -0
- /package/dist/{chunk-Y3KRUT7O.js.map → chunk-7AIHK2XM.js.map} +0 -0
- /package/dist/{chunk-MHV5Y5MR.js.map → chunk-7KEGJH3Q.js.map} +0 -0
- /package/dist/{chunk-KMXAPYU2.js.map → chunk-7NEUPEV5.js.map} +0 -0
- /package/dist/{chunk-67L7HMEP.js.map → chunk-7Z2AQEC5.js.map} +0 -0
- /package/dist/{chunk-PQECNGDE.js.map → chunk-AGYGNNOM.js.map} +0 -0
- /package/dist/{chunk-ZTF5C2GA.js.map → chunk-B5SW7I5W.js.map} +0 -0
- /package/dist/{chunk-TXHJX2NG.js.map → chunk-BGYLL467.js.map} +0 -0
- /package/dist/{chunk-R7R3LOKW.js.map → chunk-CA7TA36R.js.map} +0 -0
- /package/dist/{chunk-FPFUXRD2.js.map → chunk-CKJI7JO5.js.map} +0 -0
- /package/dist/{chunk-HMV4QMXS.js.map → chunk-CMN26J5Y.js.map} +0 -0
- /package/dist/{chunk-KVEHH4SA.js.map → chunk-DB2MAYPK.js.map} +0 -0
- /package/dist/{chunk-V4FKHLEB.js.map → chunk-DTIB5KWP.js.map} +0 -0
- /package/dist/{chunk-MESRKY67.js.map → chunk-DW6GBMLQ.js.map} +0 -0
- /package/dist/{chunk-JO6BBSGY.js.map → chunk-DWJBOR47.js.map} +0 -0
- /package/dist/{chunk-YW5T6KZ5.js.map → chunk-DYESJJ3Q.js.map} +0 -0
- /package/dist/{chunk-TZDDL3DR.js.map → chunk-ECMJ5VPW.js.map} +0 -0
- /package/dist/{chunk-OH3YGJT5.js.map → chunk-EMNGIYH6.js.map} +0 -0
- /package/dist/{chunk-CZJLWCEG.js.map → chunk-EPNCYUQ7.js.map} +0 -0
- /package/dist/{chunk-JZXWCEH5.js.map → chunk-EQA4VQEO.js.map} +0 -0
- /package/dist/{chunk-3N6EK6K5.js.map → chunk-ERX4XIYC.js.map} +0 -0
- /package/dist/{chunk-TTLI6PF7.js.map → chunk-FF3R67WD.js.map} +0 -0
- /package/dist/{chunk-4Y6SPFKW.js.map → chunk-FOF2RAVQ.js.map} +0 -0
- /package/dist/{chunk-KLREH4X6.js.map → chunk-G2JPUHEJ.js.map} +0 -0
- /package/dist/{chunk-4J5EN4FQ.js.map → chunk-GBX5ACPF.js.map} +0 -0
- /package/dist/{chunk-ZZMZF7PZ.js.map → chunk-GQJ4NCZ6.js.map} +0 -0
- /package/dist/{chunk-IPVYEPXO.js.map → chunk-GSTRPZS4.js.map} +0 -0
- /package/dist/{chunk-HFXTAEYY.js.map → chunk-GTLJYAEG.js.map} +0 -0
- /package/dist/{chunk-M4LFDGI6.js.map → chunk-GYQT47YZ.js.map} +0 -0
- /package/dist/{chunk-JSH3HFDQ.js.map → chunk-H3BQFEN5.js.map} +0 -0
- /package/dist/{chunk-OV4WREMW.js.map → chunk-HKB5C2KY.js.map} +0 -0
- /package/dist/{chunk-BLBOYCOV.js.map → chunk-HKV4MQ2W.js.map} +0 -0
- /package/dist/{chunk-4MGFUPQT.js.map → chunk-HOJL2GKW.js.map} +0 -0
- /package/dist/{chunk-HR7YTBR7.js.map → chunk-IASDP44E.js.map} +0 -0
- /package/dist/{chunk-YMRI5QKG.js.map → chunk-IV5QQLCS.js.map} +0 -0
- /package/dist/{chunk-JUHUKZGU.js.map → chunk-JD3D6Y4U.js.map} +0 -0
- /package/dist/{chunk-AXTLFK4T.js.map → chunk-KAV63FBG.js.map} +0 -0
- /package/dist/{chunk-2PBGVMM2.js.map → chunk-KOFO6QZY.js.map} +0 -0
- /package/dist/{chunk-RP5FK3SO.js.map → chunk-L7LCSZ3H.js.map} +0 -0
- /package/dist/{chunk-MNXVXW4T.js.map → chunk-L7S6N67X.js.map} +0 -0
- /package/dist/{chunk-JXPHU3K5.js.map → chunk-LGJ2H4AH.js.map} +0 -0
- /package/dist/{chunk-W4YWU7LQ.js.map → chunk-LO2B7FDQ.js.map} +0 -0
- /package/dist/{chunk-PWR7K5OP.js.map → chunk-LV4UTYAD.js.map} +0 -0
- /package/dist/{chunk-OG2FP6SE.js.map → chunk-M4NFXC5R.js.map} +0 -0
- /package/dist/{chunk-ZPIMPOHV.js.map → chunk-M7E66OSC.js.map} +0 -0
- /package/dist/{chunk-OGGPQVIG.js.map → chunk-MDTSMJ7C.js.map} +0 -0
- /package/dist/{chunk-YDI6IJ6F.js.map → chunk-MI2MVH3I.js.map} +0 -0
- /package/dist/{chunk-UIZH4DAE.js.map → chunk-MQPT254A.js.map} +0 -0
- /package/dist/{chunk-EWT3WMVY.js.map → chunk-MYH7VISV.js.map} +0 -0
- /package/dist/{chunk-7NSX7A5H.js.map → chunk-N5PY7IXI.js.map} +0 -0
- /package/dist/{chunk-BHIGHSXA.js.map → chunk-NNXZ5RK5.js.map} +0 -0
- /package/dist/{chunk-EQ7PWGBN.js.map → chunk-O7HLQTB7.js.map} +0 -0
- /package/dist/{chunk-DW5FRWRQ.js.map → chunk-OAWEUKUC.js.map} +0 -0
- /package/dist/{chunk-O4VCZTK4.js.map → chunk-OGHW7RQC.js.map} +0 -0
- /package/dist/{chunk-XR6WBW23.js.map → chunk-OVGASVPW.js.map} +0 -0
- /package/dist/{chunk-HEBQS7QP.js.map → chunk-OXYR2HVK.js.map} +0 -0
- /package/dist/{chunk-TNVO2DTB.js.map → chunk-P7FQUGED.js.map} +0 -0
- /package/dist/{chunk-343TTIHD.js.map → chunk-PENJBKPH.js.map} +0 -0
- /package/dist/{chunk-2RQINU5T.js.map → chunk-PKFFJAQ6.js.map} +0 -0
- /package/dist/{chunk-M4LQRQFL.js.map → chunk-PW2WLDX3.js.map} +0 -0
- /package/dist/{chunk-WRDPWEIC.js.map → chunk-Q3GSDSK2.js.map} +0 -0
- /package/dist/{chunk-VNTOBLIB.js.map → chunk-Q3OFOOO7.js.map} +0 -0
- /package/dist/{chunk-GGI7GM5O.js.map → chunk-QE2C35TO.js.map} +0 -0
- /package/dist/{chunk-CT5K725B.js.map → chunk-QQLGSMGE.js.map} +0 -0
- /package/dist/{chunk-7MN6I5NK.js.map → chunk-QXFPTRHB.js.map} +0 -0
- /package/dist/{chunk-CZPU5TW3.js.map → chunk-RFZU5BTG.js.map} +0 -0
- /package/dist/{chunk-JB67KPGM.js.map → chunk-RRO2EOJB.js.map} +0 -0
- /package/dist/{chunk-MZQTHSLN.js.map → chunk-S7HRED4D.js.map} +0 -0
- /package/dist/{chunk-NYEA7JAI.js.map → chunk-SC72DRTX.js.map} +0 -0
- /package/dist/{chunk-JWW2Z3RH.js.map → chunk-SMZBGHR2.js.map} +0 -0
- /package/dist/{chunk-EZSEAYYT.js.map → chunk-SSWZHR46.js.map} +0 -0
- /package/dist/{chunk-NA7MIEG6.js.map → chunk-SZETT7QV.js.map} +0 -0
- /package/dist/{chunk-2HPP6RVC.js.map → chunk-TQOPF7LD.js.map} +0 -0
- /package/dist/{chunk-OLVZ6TOV.js.map → chunk-TUO47RL2.js.map} +0 -0
- /package/dist/{chunk-4IVDVZZ2.js.map → chunk-UGL6SJN6.js.map} +0 -0
- /package/dist/{chunk-QJRDDVZ2.js.map → chunk-V5P5Q6HM.js.map} +0 -0
- /package/dist/{chunk-73NJCGQG.js.map → chunk-VIK3HAUQ.js.map} +0 -0
- /package/dist/{chunk-7LCXGJN5.js.map → chunk-VK4ULJFH.js.map} +0 -0
- /package/dist/{chunk-QYNCPS5W.js.map → chunk-WBKWIFXA.js.map} +0 -0
- /package/dist/{chunk-X4Z62ZQY.js.map → chunk-WETAIIKC.js.map} +0 -0
- /package/dist/{chunk-GMTM6EN7.js.map → chunk-WKF54CCK.js.map} +0 -0
- /package/dist/{chunk-KT6HWAEN.js.map → chunk-WZUNBSS7.js.map} +0 -0
- /package/dist/{chunk-Y2B3I3IH.js.map → chunk-X5RDHO6G.js.map} +0 -0
- /package/dist/{chunk-TXKZEKJN.js.map → chunk-XNOSTV5F.js.map} +0 -0
- /package/dist/{chunk-7JXLGOM2.js.map → chunk-Y55ILY2F.js.map} +0 -0
- /package/dist/{chunk-HI2OFZSZ.js.map → chunk-YPILHGEO.js.map} +0 -0
- /package/dist/{chunk-V3PLFYKO.js.map → chunk-ZAJO2B75.js.map} +0 -0
- /package/dist/native/chunks/{chunk-2R2R35C5.js.map → chunk-2SBTJSQE.js.map} +0 -0
- /package/dist/native/chunks/{chunk-WL5LXVCK.js.map → chunk-6L4UZBQP.js.map} +0 -0
- /package/dist/native/chunks/{chunk-GW7TQ7HO.js.map → chunk-QEQZ5AF6.js.map} +0 -0
- /package/dist/native/chunks/{chunk-7LTVGW23.js.map → chunk-UII3IFLP.js.map} +0 -0
- /package/dist/native/chunks/{chunk-75JQYVDZ.js.map → chunk-UYREIOEM.js.map} +0 -0
- /package/dist/native/chunks/{chunk-GWGIWQO7.js.map → chunk-XI7HTAVN.js.map} +0 -0
- /package/dist/native/chunks/{chunk-QYUD3S6F.js.map → chunk-ZOP7UAZK.js.map} +0 -0
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
IOS_THUMB_SHADOW,
|
|
7
7
|
MUI_SHADOWS,
|
|
8
8
|
NEUTRAL_CONTRAST,
|
|
9
|
+
RESTING_THUMB,
|
|
9
10
|
NEUTRAL_FALLBACK,
|
|
10
11
|
NEUTRAL_GREY,
|
|
11
12
|
SWITCH_BLACK,
|
|
@@ -23,6 +24,7 @@ import {
|
|
|
23
24
|
type SwitchLook,
|
|
24
25
|
} from './Switch.metrics';
|
|
25
26
|
import { alpha } from '../../../tokens/color';
|
|
27
|
+
import { inkOver } from '../../../tokens/theme';
|
|
26
28
|
import type { UiTheme } from '../../../tokens/theme';
|
|
27
29
|
import type { ColorValue } from '../../../tokens/vocabulary';
|
|
28
30
|
|
|
@@ -111,6 +113,31 @@ export function trackStyle(
|
|
|
111
113
|
return base;
|
|
112
114
|
}
|
|
113
115
|
|
|
116
|
+
/**
|
|
117
|
+
* The ink on the CHECKED track — the thumb, and the `on` wording (FUT-1924).
|
|
118
|
+
*
|
|
119
|
+
* Both halves of the component had a stated `#fff` here, and the checked track
|
|
120
|
+
* is the one surface a tenant chooses: a pale brand got a white knob on a pale
|
|
121
|
+
* bar, which reads as OFF while it is on.
|
|
122
|
+
*
|
|
123
|
+
* **The fills are THIS renderer's, not the web's, and they differ.** The web
|
|
124
|
+
* paints a real three-stop gradient and hands `checkedInk` all three
|
|
125
|
+
* (`Switch.styles.ts`); React Native has no gradient without a dependency, so
|
|
126
|
+
* `trackStyle` shows `gradientFirstStop` — `palette.light`, FLAT — and
|
|
127
|
+
* `NATIVE-NOTES.md` records that as a known divergence. Passing the web's set
|
|
128
|
+
* here would judge the ink against two fills native never draws, and the two
|
|
129
|
+
* renderers then disagree on the same palette: measured on `#00897b`, the web
|
|
130
|
+
* answers white and this answered dark ink, because `main` and `dark` were in
|
|
131
|
+
* the list and only `light` is on screen.
|
|
132
|
+
*
|
|
133
|
+
* So the gradient case is ONE fill, which is the one it paints.
|
|
134
|
+
*/
|
|
135
|
+
export function checkedInk(paint: SwitchPaint, palette: SwitchPalette): string {
|
|
136
|
+
const fills = [paint.gradient ? palette.light || palette.main : palette.main];
|
|
137
|
+
|
|
138
|
+
return inkOver(fills, palette.contrastText || NEUTRAL_CONTRAST);
|
|
139
|
+
}
|
|
140
|
+
|
|
114
141
|
/** The web's two gradients, at the stop a flat fill can show. */
|
|
115
142
|
function gradientFirstStop(palette: SwitchPalette, checked: boolean): string {
|
|
116
143
|
if (checked) return palette.light || palette.main;
|
|
@@ -125,10 +152,26 @@ const disabledTrackOpacity = (state: SwitchState): number => {
|
|
|
125
152
|
/** React Native has no `StyleSheet.absoluteFillObject` constant worth importing for four keys. */
|
|
126
153
|
const StyleSheetAbsoluteFill = { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 } as const;
|
|
127
154
|
|
|
128
|
-
/**
|
|
155
|
+
/** Disabled greys out; checked takes the track's ink; resting stays white. */
|
|
156
|
+
function thumbFill(
|
|
157
|
+
paint: SwitchPaint,
|
|
158
|
+
palette: SwitchPalette,
|
|
159
|
+
state: SwitchState,
|
|
160
|
+
theme: UiTheme,
|
|
161
|
+
): string {
|
|
162
|
+
if (state.disabled) return theme.palette.grey[DISABLED.thumbGrey] ?? RESTING_THUMB;
|
|
163
|
+
return state.checked ? checkedInk(paint, palette) : RESTING_THUMB;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* The knob: round for iOS and the default, squarer for Android and Material.
|
|
168
|
+
* White while resting, the checked track's own ink once on — see
|
|
169
|
+
* {@link RESTING_THUMB} and {@link checkedInk}.
|
|
170
|
+
*/
|
|
129
171
|
export function thumbStyle(
|
|
130
172
|
theme: UiTheme,
|
|
131
173
|
paint: SwitchPaint,
|
|
174
|
+
palette: SwitchPalette,
|
|
132
175
|
geometry: SwitchGeometry,
|
|
133
176
|
look: SwitchLook,
|
|
134
177
|
state: SwitchState,
|
|
@@ -138,7 +181,7 @@ export function thumbStyle(
|
|
|
138
181
|
width: geometry.thumbSize,
|
|
139
182
|
height: geometry.thumbSize,
|
|
140
183
|
borderRadius: thumbRadius(look, geometry.thumbSize),
|
|
141
|
-
backgroundColor:
|
|
184
|
+
backgroundColor: thumbFill(paint, palette, state, theme),
|
|
142
185
|
boxShadow: look === 'ios' ? IOS_THUMB_SHADOW : (MUI_SHADOWS[THUMB_ELEVATION[look]] ?? 'none'),
|
|
143
186
|
alignItems: 'center',
|
|
144
187
|
justifyContent: 'center',
|
|
@@ -273,15 +273,28 @@ import Close from '@mui/icons-material/Close';
|
|
|
273
273
|
|
|
274
274
|
## Accessibility
|
|
275
275
|
|
|
276
|
-
The
|
|
277
|
-
|
|
278
|
-
-
|
|
279
|
-
|
|
280
|
-
- **
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
-
|
|
276
|
+
- **The label names the control.** `label` renders a real `<label for>` pointing
|
|
277
|
+
at the input, so the switch announces by its visible words and clicking those
|
|
278
|
+
words toggles it. Pass `aria-label` only where there is no visible label —
|
|
279
|
+
with one, it would override the text on screen.
|
|
280
|
+
- **The id is minted for you.** An explicit `id` (or `inputProps.id`) wins;
|
|
281
|
+
otherwise each instance gets its own from `useId`. Do not derive one from a
|
|
282
|
+
test id: two call sites sharing a test id would share a `for`, and the second
|
|
283
|
+
label would toggle the first control.
|
|
284
|
+
- **`description` and `helperText` are described, not named.** Both are linked
|
|
285
|
+
by `aria-describedby` and stay out of the accessible name — a two-line
|
|
286
|
+
explanation read as the control's NAME is worse than no description at all. A
|
|
287
|
+
caller's own `aria-describedby` is kept alongside them, not replaced.
|
|
288
|
+
- **Keyboard:** `Tab` to reach it, `Space` to toggle, with a visible focus ring.
|
|
289
|
+
- **It announces as a checkbox, not as a switch.** MUI's `SwitchBase` renders an
|
|
290
|
+
`<input type="checkbox">` and this component does not override the role.
|
|
291
|
+
Earlier revisions of this document claimed `role="switch"`; that was never
|
|
292
|
+
true. Announcing as a checkbox is correct and understood — do not "fix" it by
|
|
293
|
+
hand-setting the role without also handling `aria-checked`.
|
|
294
|
+
- **The tap target is the LABEL.** `SWITCH_SIZES.xl`, the largest, is 34px tall
|
|
295
|
+
against the 40px floor, so no `size` clears it. The label carries the floor
|
|
296
|
+
instead (`TAP_TARGET_MIN`), which is why an unlabelled `Switch` at a phone
|
|
297
|
+
width still wants a target around it drawn by the caller.
|
|
285
298
|
|
|
286
299
|
### Keyboard Shortcuts
|
|
287
300
|
|
|
@@ -373,6 +386,18 @@ The Switch component follows WCAG 2.1 AA guidelines:
|
|
|
373
386
|
/>
|
|
374
387
|
```
|
|
375
388
|
|
|
389
|
+
## Ink on the track
|
|
390
|
+
|
|
391
|
+
The thumb, the `on` wording of the `label` variant and the on-icon all take
|
|
392
|
+
their colour from the palette, NOT from a stated white. The checked track is
|
|
393
|
+
`palette.main` — the one surface a white-labelled host picks — so a pale brand
|
|
394
|
+
gets dark ink and reads as ON, where a white knob on a pale bar reads as OFF.
|
|
395
|
+
Under `gradient` the whole bar (`light → main → dark`) is considered, not just
|
|
396
|
+
the colour in the middle of it.
|
|
397
|
+
|
|
398
|
+
The RESTING thumb stays white by design: that track is `action.disabled` washed
|
|
399
|
+
over the page, which no tenant chooses.
|
|
400
|
+
|
|
376
401
|
## Theming
|
|
377
402
|
|
|
378
403
|
The Switch component integrates with MUI's theme system:
|
|
@@ -168,6 +168,15 @@ export const SWITCH_HELPER = { fontSize: 12, lineHeight: 1.66, marginTopUnits: 1
|
|
|
168
168
|
/** The label row: 16px from the control beside it, 8px above or below it. */
|
|
169
169
|
export const LABEL_GAP_UNITS = { beside: 2, stacked: 1 } as const;
|
|
170
170
|
|
|
171
|
+
/**
|
|
172
|
+
* The minimum height of a touch target, in px (FUT-1905).
|
|
173
|
+
*
|
|
174
|
+
* No entry in {@link SWITCH_SIZES} reaches it — `xl`, the largest, is 34px tall
|
|
175
|
+
* and `md` is 26 — so a consumer cannot buy a legal target by passing a bigger
|
|
176
|
+
* `size`. The label is what clears it: see `SwitchLabel` in `Switch.parts.tsx`.
|
|
177
|
+
*/
|
|
178
|
+
export const TAP_TARGET_MIN = 40;
|
|
179
|
+
|
|
171
180
|
/**
|
|
172
181
|
* `neutral`'s three greys, and the literals the web falls back to for a theme
|
|
173
182
|
* whose grey ramp omits a step. Same three steps `Button` draws its neutral
|
|
@@ -177,6 +186,18 @@ export const NEUTRAL_GREY = { main: 700, dark: 800, light: 500 } as const;
|
|
|
177
186
|
export const NEUTRAL_FALLBACK = { main: '#616161', dark: '#424242', light: '#9e9e9e' } as const;
|
|
178
187
|
export const NEUTRAL_CONTRAST = '#fff';
|
|
179
188
|
|
|
189
|
+
/**
|
|
190
|
+
* The RESTING thumb — the knob while the switch is off (FUT-1924).
|
|
191
|
+
*
|
|
192
|
+
* It stays white, and the reason is worth stating because the checked thumb no
|
|
193
|
+
* longer is: the resting track is `theme.palette.action.disabled` washed over
|
|
194
|
+
* the page, which no tenant picks, and a white knob on it is the conventional
|
|
195
|
+
* look in both modes. The CHECKED track is `palette.main`, a colour the tenant
|
|
196
|
+
* does pick, and that is where a stated white was a defect. See `checkedInk`
|
|
197
|
+
* in `Switch.styles.ts` and its native twin.
|
|
198
|
+
*/
|
|
199
|
+
export const RESTING_THUMB = '#fff';
|
|
200
|
+
|
|
180
201
|
/** Hover: the thumb lifts a shade and takes a halo of the hue. */
|
|
181
202
|
export const SWITCH_HOVER = { thumbScale: 1.05, elevation: 4, blur: 12, alpha: 0.2 } as const;
|
|
182
203
|
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
descriptionTextStyle,
|
|
18
18
|
helperTextStyle,
|
|
19
19
|
labelTextStyle,
|
|
20
|
+
checkedInk,
|
|
20
21
|
switchPalette,
|
|
21
22
|
thumbStyle,
|
|
22
23
|
trackStyle,
|
|
@@ -45,9 +46,6 @@ import type { UiTheme } from '../../../tokens/theme';
|
|
|
45
46
|
|
|
46
47
|
const nativeDriver = Platform.OS !== 'web';
|
|
47
48
|
|
|
48
|
-
/** The web writes the `on` wording in white, whatever the hue behind it. */
|
|
49
|
-
const TRACK_LABEL_ON_INK = '#fff';
|
|
50
|
-
|
|
51
49
|
/** A 0→1 value that follows `on`, over MUI's 300ms curve unless animation is off. */
|
|
52
50
|
function useProgress(on: boolean, animated: boolean): Animated.Value {
|
|
53
51
|
const progress = React.useRef(new Animated.Value(on ? 1 : 0)).current;
|
|
@@ -167,7 +165,16 @@ interface ControlProps {
|
|
|
167
165
|
testID: string;
|
|
168
166
|
}
|
|
169
167
|
|
|
170
|
-
/**
|
|
168
|
+
/**
|
|
169
|
+
* The track, the thumb, and everything overlaid on them.
|
|
170
|
+
*
|
|
171
|
+
* The control carries its own NAME (FUT-1905). React Native has no `<label
|
|
172
|
+
* for>` to wire the words beside it with, so the name has to be stated on the
|
|
173
|
+
* pressable itself or the control announces as "checkbox, checked" and nothing
|
|
174
|
+
* else — which is the defect the web half of this ticket fixed, still live
|
|
175
|
+
* here. A caller's own `aria-label` wins, because a caller that wrote one meant
|
|
176
|
+
* it to differ from the visible words.
|
|
177
|
+
*/
|
|
171
178
|
function SwitchControl({ props, theme, checked, inactive, onToggle, rest, testID }: ControlProps): React.JSX.Element {
|
|
172
179
|
const { variant, color, size, animated, loading, onIcon, offIcon, onText, offText } = props;
|
|
173
180
|
const geometry: SwitchGeometry = geometryOf(size, props.trackWidth, props.trackHeight);
|
|
@@ -184,6 +191,7 @@ function SwitchControl({ props, theme, checked, inactive, onToggle, rest, testID
|
|
|
184
191
|
<Pressable
|
|
185
192
|
testID={testID}
|
|
186
193
|
role="checkbox"
|
|
194
|
+
aria-label={(rest['aria-label'] as string | undefined) ?? props.label}
|
|
187
195
|
aria-checked={checked}
|
|
188
196
|
aria-disabled={inactive}
|
|
189
197
|
disabled={inactive}
|
|
@@ -196,7 +204,12 @@ function SwitchControl({ props, theme, checked, inactive, onToggle, rest, testID
|
|
|
196
204
|
>
|
|
197
205
|
<View style={trackStyle(theme, paint, palette, geometry, look, state)} />
|
|
198
206
|
{showsTrackLabels(variant, onText, offText) ? (
|
|
199
|
-
<TrackLabels
|
|
207
|
+
<TrackLabels
|
|
208
|
+
theme={theme}
|
|
209
|
+
onText={onText}
|
|
210
|
+
offText={offText}
|
|
211
|
+
contrastText={checkedInk(paint, palette)}
|
|
212
|
+
/>
|
|
200
213
|
) : null}
|
|
201
214
|
{onIcon == null ? null : (
|
|
202
215
|
<SwitchIcon icon={onIcon} shown={checked} animated={animated} size={iconSize} side="on" width={geometry.width} />
|
|
@@ -206,7 +219,7 @@ function SwitchControl({ props, theme, checked, inactive, onToggle, rest, testID
|
|
|
206
219
|
)}
|
|
207
220
|
<Animated.View
|
|
208
221
|
style={[
|
|
209
|
-
thumbStyle(theme, paint, geometry, look, state),
|
|
222
|
+
thumbStyle(theme, paint, palette, geometry, look, state),
|
|
210
223
|
{ top: geometry.padding, left: restX, opacity: pulse.opacity },
|
|
211
224
|
{
|
|
212
225
|
transform: [
|
|
@@ -2,11 +2,11 @@ import Box from '@mui/material/Box/index.js';
|
|
|
2
2
|
import FormHelperText from '@mui/material/FormHelperText/index.js';
|
|
3
3
|
import MuiSwitch from '@mui/material/Switch/index.js';
|
|
4
4
|
import Typography from '@mui/material/Typography/index.js';
|
|
5
|
-
import { styled } from '@mui/material/styles/index.js';
|
|
5
|
+
import { styled, useTheme } from '@mui/material/styles/index.js';
|
|
6
6
|
import React from 'react';
|
|
7
7
|
|
|
8
|
-
import { LABEL_GAP_UNITS, SWITCH_ICON_SIZES } from './Switch.metrics';
|
|
9
|
-
import { switchSx } from './Switch.styles';
|
|
8
|
+
import { LABEL_GAP_UNITS, SWITCH_ICON_SIZES, TAP_TARGET_MIN } from './Switch.metrics';
|
|
9
|
+
import { onTrackInk, switchSx } from './Switch.styles';
|
|
10
10
|
import type { SwitchFlags } from './Switch.styles';
|
|
11
11
|
import type { SwitchProps } from './Switch.types';
|
|
12
12
|
import type { SizeValue } from '../../../tokens/vocabulary';
|
|
@@ -54,7 +54,7 @@ const StyledLabelContainer = styled(Box, {
|
|
|
54
54
|
* A plain wrapper over the styled row. Exporting the styled component itself
|
|
55
55
|
* needs a @mui/system reference tsc calls unportable (TS2742).
|
|
56
56
|
*/
|
|
57
|
-
|
|
57
|
+
const LabelContainer: React.FC<{
|
|
58
58
|
labelPosition?: string;
|
|
59
59
|
error?: boolean;
|
|
60
60
|
children: React.ReactNode;
|
|
@@ -71,6 +71,8 @@ export interface SwitchIconProps {
|
|
|
71
71
|
animated: boolean;
|
|
72
72
|
size: string;
|
|
73
73
|
side: 'on' | 'off';
|
|
74
|
+
/** The ink for the ON icon, which sits on the brand-filled track (FUT-1924). */
|
|
75
|
+
onInk: string;
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
/**
|
|
@@ -78,7 +80,14 @@ export interface SwitchIconProps {
|
|
|
78
80
|
* edge when checked and the off icon to the right when unchecked; they are
|
|
79
81
|
* mirror images, so they share this component rather than being written twice.
|
|
80
82
|
*/
|
|
81
|
-
export const SwitchIcon: React.FC<SwitchIconProps> = ({
|
|
83
|
+
export const SwitchIcon: React.FC<SwitchIconProps> = ({
|
|
84
|
+
icon,
|
|
85
|
+
shown,
|
|
86
|
+
animated,
|
|
87
|
+
size,
|
|
88
|
+
side,
|
|
89
|
+
onInk,
|
|
90
|
+
}) => {
|
|
82
91
|
const isOn = side === 'on';
|
|
83
92
|
const translate = isOn ? 'translate(-50%, -50%)' : 'translate(50%, -50%)';
|
|
84
93
|
|
|
@@ -93,7 +102,7 @@ export const SwitchIcon: React.FC<SwitchIconProps> = ({ icon, shown, animated, s
|
|
|
93
102
|
transform: `${translate} scale(${shown && animated ? 1 : 0.8})`,
|
|
94
103
|
pointerEvents: 'none',
|
|
95
104
|
zIndex: 2,
|
|
96
|
-
color: isOn ?
|
|
105
|
+
color: isOn ? onInk : 'text.secondary',
|
|
97
106
|
fontSize: SWITCH_ICON_SIZES[size as SizeValue] ?? SWITCH_ICON_SIZES.md,
|
|
98
107
|
}}
|
|
99
108
|
>
|
|
@@ -111,6 +120,12 @@ export interface SwitchControlProps extends SwitchFlags {
|
|
|
111
120
|
size: string;
|
|
112
121
|
dataTestId?: string;
|
|
113
122
|
switchRef?: React.Ref<HTMLButtonElement>;
|
|
123
|
+
/** The id the label points at — always set, so the input always has one. */
|
|
124
|
+
inputId: string;
|
|
125
|
+
/** The caller's own `inputProps`, merged rather than spread over (FUT-1905). */
|
|
126
|
+
inputProps?: React.InputHTMLAttributes<HTMLInputElement>;
|
|
127
|
+
/** The description's id, appended to whatever the caller described it by. */
|
|
128
|
+
describedBy?: string;
|
|
114
129
|
rest: Record<string, unknown>;
|
|
115
130
|
}
|
|
116
131
|
|
|
@@ -124,13 +139,15 @@ export const SwitchControl: React.FC<SwitchControlProps> = ({
|
|
|
124
139
|
size,
|
|
125
140
|
dataTestId,
|
|
126
141
|
switchRef,
|
|
142
|
+
inputId,
|
|
143
|
+
inputProps,
|
|
144
|
+
describedBy,
|
|
127
145
|
rest,
|
|
128
146
|
...flags
|
|
129
147
|
}) => {
|
|
130
|
-
const props = rest as Record<string, unknown> & {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
};
|
|
148
|
+
const props = rest as Record<string, unknown> & { disabled?: boolean };
|
|
149
|
+
const theme = useTheme();
|
|
150
|
+
const onInk = onTrackInk(theme, flags);
|
|
134
151
|
|
|
135
152
|
return (
|
|
136
153
|
<Box sx={{ position: 'relative', display: 'inline-flex' }}>
|
|
@@ -140,15 +157,31 @@ export const SwitchControl: React.FC<SwitchControlProps> = ({
|
|
|
140
157
|
checked={checked}
|
|
141
158
|
onChange={onChange}
|
|
142
159
|
disabled={Boolean(flags.loading) || props.disabled}
|
|
160
|
+
{...props}
|
|
161
|
+
/*
|
|
162
|
+
AFTER `props`, not before it (FUT-1905). `inputProps` used to be
|
|
163
|
+
written first and `{...props}` spread over it, so a caller passing
|
|
164
|
+
`inputProps` of its own silently replaced the whole object — losing
|
|
165
|
+
the `data-testid` every spec finds this control by, and the `id` the
|
|
166
|
+
label points at.
|
|
167
|
+
|
|
168
|
+
The order inside is the contract. Everything the component DEFAULTS
|
|
169
|
+
goes first, so a caller's own key still wins — that is what it could
|
|
170
|
+
do before, and a fix for a clobber must not become a clobber the
|
|
171
|
+
other way. Only the two the component OWNS come last: the `id`, which
|
|
172
|
+
already resolved the caller's spelling of it (`switchIds`), and
|
|
173
|
+
`aria-describedby`, which by then already CONTAINS whatever the
|
|
174
|
+
caller passed, in either spelling.
|
|
175
|
+
*/
|
|
143
176
|
inputProps={
|
|
144
177
|
{
|
|
145
178
|
'aria-label': props['aria-label'],
|
|
146
|
-
'aria-describedby': props['aria-describedby'],
|
|
147
|
-
...props.inputProps,
|
|
148
179
|
'data-testid': dataTestId || 'switch',
|
|
180
|
+
...inputProps,
|
|
181
|
+
id: inputId,
|
|
182
|
+
'aria-describedby': describedBy,
|
|
149
183
|
} as React.InputHTMLAttributes<HTMLInputElement>
|
|
150
184
|
}
|
|
151
|
-
{...props}
|
|
152
185
|
/>
|
|
153
186
|
|
|
154
187
|
{onIcon && (
|
|
@@ -158,6 +191,7 @@ export const SwitchControl: React.FC<SwitchControlProps> = ({
|
|
|
158
191
|
animated={animated}
|
|
159
192
|
size={size}
|
|
160
193
|
side="on"
|
|
194
|
+
onInk={onInk}
|
|
161
195
|
/>
|
|
162
196
|
)}
|
|
163
197
|
{offIcon && (
|
|
@@ -167,19 +201,30 @@ export const SwitchControl: React.FC<SwitchControlProps> = ({
|
|
|
167
201
|
animated={animated}
|
|
168
202
|
size={size}
|
|
169
203
|
side="off"
|
|
204
|
+
onInk={onInk}
|
|
170
205
|
/>
|
|
171
206
|
)}
|
|
172
207
|
</Box>
|
|
173
208
|
);
|
|
174
209
|
};
|
|
175
210
|
|
|
211
|
+
/**
|
|
212
|
+
* The helper line, which is where a validation message lands — so it is
|
|
213
|
+
* `aria-describedby`'d like the description (FUT-1905).
|
|
214
|
+
*
|
|
215
|
+
* It carried no `id` and nothing pointed at it, which means an `error` state
|
|
216
|
+
* announced as "checkbox, checked" and nothing else: the one sentence saying
|
|
217
|
+
* WHY was on screen and outside the accessibility tree.
|
|
218
|
+
*/
|
|
176
219
|
export const SwitchHelper: React.FC<{
|
|
177
220
|
helperText?: React.ReactNode;
|
|
178
221
|
error?: boolean;
|
|
179
222
|
dataTestId?: string;
|
|
180
|
-
|
|
223
|
+
id?: string;
|
|
224
|
+
}> = ({ helperText, error, dataTestId, id }) =>
|
|
181
225
|
helperText ? (
|
|
182
226
|
<FormHelperText
|
|
227
|
+
id={id}
|
|
183
228
|
error={error}
|
|
184
229
|
sx={{ mt: 1 }}
|
|
185
230
|
data-testid={dataTestId ? `${dataTestId}-helper` : 'switch-helper'}
|
|
@@ -188,23 +233,62 @@ export const SwitchHelper: React.FC<{
|
|
|
188
233
|
</FormHelperText>
|
|
189
234
|
) : null;
|
|
190
235
|
|
|
191
|
-
|
|
236
|
+
/**
|
|
237
|
+
* The label, WIRED to the input it names (FUT-1905).
|
|
238
|
+
*
|
|
239
|
+
* It used to be a `<p>` rendered as the control's sibling, with no `for`, no
|
|
240
|
+
* `id` on the input and no `aria-labelledby` — so a labelled `Switch` announced
|
|
241
|
+
* as "checkbox, checked" with no name, and clicking the words did nothing. Every
|
|
242
|
+
* `Switch` in a consumer app was affected, not one call site, and the workaround
|
|
243
|
+
* each had to write was a hand-typed `aria-label` duplicating the text already
|
|
244
|
+
* on screen.
|
|
245
|
+
*
|
|
246
|
+
* A real `<label for>` fixes the name and the pointer in the same stroke, and it
|
|
247
|
+
* is also the answer to the TAP TARGET: no size in `SWITCH_SIZES` clears the
|
|
248
|
+
* 40px floor (`xl` is 34px tall), so the control cannot be made big enough by
|
|
249
|
+
* passing a bigger `size` — instead the label becomes the target, which is how
|
|
250
|
+
* this is normally solved. Hence `display: flex` and `TAP_TARGET_MIN`: the
|
|
251
|
+
* label fills its half of the row and is never shorter than the floor.
|
|
252
|
+
*
|
|
253
|
+
* The DESCRIPTION stays outside the label and is pointed at by
|
|
254
|
+
* `aria-describedby` instead: inside it, a two-line explanation would be read
|
|
255
|
+
* out as part of the control's name.
|
|
256
|
+
*/
|
|
257
|
+
const SwitchLabel: React.FC<{
|
|
192
258
|
label: React.ReactNode;
|
|
193
259
|
description?: React.ReactNode;
|
|
194
260
|
error?: boolean;
|
|
195
261
|
dataTestId?: string;
|
|
196
|
-
|
|
197
|
-
|
|
262
|
+
/** The input's id. Omitted only where there is no input to point at. */
|
|
263
|
+
htmlFor?: string;
|
|
264
|
+
descriptionId?: string;
|
|
265
|
+
disabled?: boolean;
|
|
266
|
+
}> = ({ label, description, error, dataTestId, htmlFor, descriptionId, disabled }) => (
|
|
267
|
+
<Box sx={{ flex: 1, minWidth: 0 }}>
|
|
198
268
|
<Typography
|
|
269
|
+
component="label"
|
|
270
|
+
htmlFor={htmlFor}
|
|
199
271
|
variant="body2"
|
|
200
272
|
fontWeight={500}
|
|
201
273
|
color={error ? 'error.main' : 'text.primary'}
|
|
274
|
+
sx={{
|
|
275
|
+
display: 'flex',
|
|
276
|
+
alignItems: 'center',
|
|
277
|
+
// The floor applies to the row the label shares with the control. A
|
|
278
|
+
// description already makes the row taller than 40px, so forcing it
|
|
279
|
+
// there would only add blank space.
|
|
280
|
+
...(description ? {} : { minHeight: TAP_TARGET_MIN }),
|
|
281
|
+
// A disabled control's label toggles nothing, so it must not wear the
|
|
282
|
+
// cursor that says it does.
|
|
283
|
+
...(htmlFor && !disabled ? { cursor: 'pointer' } : {}),
|
|
284
|
+
}}
|
|
202
285
|
data-testid={dataTestId ? `${dataTestId}-label` : 'switch-label'}
|
|
203
286
|
>
|
|
204
287
|
{label}
|
|
205
288
|
</Typography>
|
|
206
289
|
{description && (
|
|
207
290
|
<Typography
|
|
291
|
+
id={descriptionId}
|
|
208
292
|
variant="caption"
|
|
209
293
|
color={error ? 'error.main' : 'text.secondary'}
|
|
210
294
|
sx={{ display: 'block', mt: 0.5 }}
|
|
@@ -214,3 +298,52 @@ export const SwitchLabel: React.FC<{
|
|
|
214
298
|
)}
|
|
215
299
|
</Box>
|
|
216
300
|
);
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* The control and its label in one row, or the control alone.
|
|
304
|
+
*
|
|
305
|
+
* Lives here rather than inline in `Switch.tsx` because the two branches only
|
|
306
|
+
* differ in what surrounds the control — and the component that assembles them
|
|
307
|
+
* was long enough that the wiring got hard to see between them.
|
|
308
|
+
*/
|
|
309
|
+
export const SwitchRow: React.FC<{
|
|
310
|
+
label?: React.ReactNode;
|
|
311
|
+
description?: React.ReactNode;
|
|
312
|
+
labelPosition?: string;
|
|
313
|
+
error?: boolean;
|
|
314
|
+
dataTestId?: string;
|
|
315
|
+
htmlFor: string;
|
|
316
|
+
descriptionId?: string;
|
|
317
|
+
disabled?: boolean;
|
|
318
|
+
control: React.ReactNode;
|
|
319
|
+
}> = ({
|
|
320
|
+
label,
|
|
321
|
+
description,
|
|
322
|
+
labelPosition,
|
|
323
|
+
error,
|
|
324
|
+
dataTestId,
|
|
325
|
+
htmlFor,
|
|
326
|
+
descriptionId,
|
|
327
|
+
disabled,
|
|
328
|
+
control,
|
|
329
|
+
}) => {
|
|
330
|
+
if (!label) return <>{control}</>;
|
|
331
|
+
|
|
332
|
+
return (
|
|
333
|
+
<LabelContainer labelPosition={labelPosition} error={error}>
|
|
334
|
+
{labelPosition === 'start' && control}
|
|
335
|
+
|
|
336
|
+
<SwitchLabel
|
|
337
|
+
label={label}
|
|
338
|
+
description={description}
|
|
339
|
+
error={error}
|
|
340
|
+
dataTestId={dataTestId}
|
|
341
|
+
htmlFor={htmlFor}
|
|
342
|
+
descriptionId={descriptionId}
|
|
343
|
+
disabled={disabled}
|
|
344
|
+
/>
|
|
345
|
+
|
|
346
|
+
{labelPosition !== 'start' && control}
|
|
347
|
+
</LabelContainer>
|
|
348
|
+
);
|
|
349
|
+
};
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
SWITCH_RIPPLE,
|
|
27
27
|
SWITCH_SPINNER,
|
|
28
28
|
SWITCH_TRANSITION,
|
|
29
|
+
RESTING_THUMB,
|
|
29
30
|
THUMB_ELEVATION,
|
|
30
31
|
THUMB_RADIUS,
|
|
31
32
|
TRACK_LABEL,
|
|
@@ -41,7 +42,7 @@ import {
|
|
|
41
42
|
} from './Switch.metrics';
|
|
42
43
|
import type { SwitchVariant } from './Switch.base';
|
|
43
44
|
|
|
44
|
-
import { px } from '../../../tokens/theme';
|
|
45
|
+
import { inkOver, px } from '../../../tokens/theme';
|
|
45
46
|
import type { ColorValue, SizeValue } from '../../../tokens/vocabulary';
|
|
46
47
|
|
|
47
48
|
// Every number below comes from `./Switch.metrics`, which the native renderer
|
|
@@ -125,6 +126,32 @@ const rippleOverlay = (palette: ColorPalette): CSSObject => ({
|
|
|
125
126
|
pointerEvents: 'none',
|
|
126
127
|
});
|
|
127
128
|
|
|
129
|
+
/**
|
|
130
|
+
* The ink on the CHECKED track — the thumb, the `on` wording and any on-icon
|
|
131
|
+
* (FUT-1924).
|
|
132
|
+
*
|
|
133
|
+
* All three stated `#fff`, and the checked track is `palette.main`: the one
|
|
134
|
+
* surface in this component the TENANT picks. A store with a pale brand got a
|
|
135
|
+
* white thumb on a pale green bar, which does not read as a knob at all — the
|
|
136
|
+
* switch looks OFF while it is on, so this is a state a user misreads rather
|
|
137
|
+
* than a colour they dislike.
|
|
138
|
+
*
|
|
139
|
+
* The `gradient` flag paints the track `light → main → dark`, so the fills the
|
|
140
|
+
* thumb travels over are handed over together and {@link inkOver} takes the
|
|
141
|
+
* worst of them.
|
|
142
|
+
*
|
|
143
|
+
* The RESTING track is not here on purpose: it is `theme.palette.action.disabled`
|
|
144
|
+
* washed over the page, which no tenant chooses, and a white thumb on it is the
|
|
145
|
+
* conventional look in both modes.
|
|
146
|
+
*/
|
|
147
|
+
const checkedInk = (flags: SwitchFlags, palette: ColorPalette): string => {
|
|
148
|
+
const fills = flags.gradient
|
|
149
|
+
? [palette.light || palette.main, palette.main, palette.dark || palette.main]
|
|
150
|
+
: [palette.main];
|
|
151
|
+
|
|
152
|
+
return inkOver(fills, palette.contrastText || NEUTRAL_CONTRAST);
|
|
153
|
+
};
|
|
154
|
+
|
|
128
155
|
/** The checked track: the filled bar behind the thumb once the switch is on. */
|
|
129
156
|
const checkedTrack = (flags: SwitchFlags, palette: ColorPalette): CSSObject => ({
|
|
130
157
|
backgroundColor: palette.main,
|
|
@@ -170,9 +197,12 @@ const switchBaseSx = (
|
|
|
170
197
|
// The thumb travels the track minus its own width and both paddings; the
|
|
171
198
|
// iOS look insets differently, so it gets its own distance.
|
|
172
199
|
transform: `translateX(${width - thumbSize - padding * 2}px)`,
|
|
173
|
-
color:
|
|
200
|
+
color: checkedInk(flags, palette),
|
|
174
201
|
'& .MuiSwitch-thumb': {
|
|
175
202
|
animation: flags.loading ? 'none' : `${bounceAnimation} ${seconds(SWITCH_TRANSITION.ms)} ease-out`,
|
|
203
|
+
// `glass` draws its own translucent thumb and means to show the track
|
|
204
|
+
// through it, so it keeps the fill it chose.
|
|
205
|
+
...(flags.glass ? {} : { backgroundColor: checkedInk(flags, palette) }),
|
|
176
206
|
},
|
|
177
207
|
'& + .MuiSwitch-track': checkedTrack(flags, palette),
|
|
178
208
|
'&.Mui-disabled + .MuiSwitch-track': { opacity: DISABLED.checkedTrackOpacity },
|
|
@@ -197,7 +227,9 @@ const thumbSx = (
|
|
|
197
227
|
width: thumbSize,
|
|
198
228
|
height: thumbSize,
|
|
199
229
|
borderRadius: THUMB_RADIUS[look](thumbSize),
|
|
200
|
-
|
|
230
|
+
// `.Mui-checked` above replaces this for the brand-filled track; see
|
|
231
|
+
// {@link RESTING_THUMB} for why the resting one stays white.
|
|
232
|
+
backgroundColor: RESTING_THUMB,
|
|
201
233
|
boxShadow: thumbShadow(theme, look),
|
|
202
234
|
transition: `all ${seconds(SWITCH_TRANSITION.ms)} ${SWITCH_TRANSITION.easing}`,
|
|
203
235
|
position: 'relative',
|
|
@@ -239,7 +271,13 @@ const thumbSx = (
|
|
|
239
271
|
});
|
|
240
272
|
|
|
241
273
|
/** The on/off wording the `label` variant prints inside the track. */
|
|
242
|
-
const trackLabels = (
|
|
274
|
+
const trackLabels = (
|
|
275
|
+
theme: Theme,
|
|
276
|
+
flags: SwitchFlags,
|
|
277
|
+
palette: ColorPalette,
|
|
278
|
+
onText?: string,
|
|
279
|
+
offText?: string,
|
|
280
|
+
): CSSObject => ({
|
|
243
281
|
display: 'flex',
|
|
244
282
|
alignItems: 'center',
|
|
245
283
|
justifyContent: 'space-between',
|
|
@@ -258,7 +296,13 @@ const trackLabels = (theme: Theme, onText?: string, offText?: string): CSSObject
|
|
|
258
296
|
zIndex: 1,
|
|
259
297
|
},
|
|
260
298
|
...(onText && {
|
|
261
|
-
'&::before': {
|
|
299
|
+
'&::before': {
|
|
300
|
+
content: `"${onText}"`,
|
|
301
|
+
left: theme.spacing(TRACK_LABEL.insetUnits),
|
|
302
|
+
// The `on` word sits at the end the thumb travels TO, which is the
|
|
303
|
+
// filled half of the track once checked.
|
|
304
|
+
color: checkedInk(flags, palette),
|
|
305
|
+
},
|
|
262
306
|
}),
|
|
263
307
|
...(offText && {
|
|
264
308
|
'&::after': {
|
|
@@ -297,10 +341,19 @@ const trackSx = (
|
|
|
297
341
|
!glass && {
|
|
298
342
|
background: `linear-gradient(${SWITCH_GRADIENT.resting.angleDeg}deg, ${alpha(palette.light || palette.main, SWITCH_GRADIENT.resting.lightAlpha)}, ${alpha(palette.main, SWITCH_GRADIENT.resting.mainAlpha)})`,
|
|
299
343
|
}),
|
|
300
|
-
...(showsTrackLabels(customVariant, onText, offText) &&
|
|
344
|
+
...(showsTrackLabels(customVariant, onText, offText) &&
|
|
345
|
+
trackLabels(theme, flags, palette, onText, offText)),
|
|
301
346
|
};
|
|
302
347
|
};
|
|
303
348
|
|
|
349
|
+
/**
|
|
350
|
+
* The same checked-track ink, for the two ICONS the control overlays on the
|
|
351
|
+
* track — which are drawn as components rather than styles, so they cannot
|
|
352
|
+
* reach {@link checkedInk} directly.
|
|
353
|
+
*/
|
|
354
|
+
export const onTrackInk = (theme: Theme, flags: SwitchFlags): string =>
|
|
355
|
+
checkedInk(flags, getColorFromTheme(theme, flags.customColor ?? 'primary'));
|
|
356
|
+
|
|
304
357
|
export const switchSx = (theme: Theme, flags: SwitchFlags): CSSObject => {
|
|
305
358
|
const palette = getColorFromTheme(theme, flags.customColor ?? 'primary');
|
|
306
359
|
const geometry = geometryOf(flags.customSize, flags.trackWidth, flags.trackHeight);
|