From dd0695d7f52992d4160e58d0c4b4ffe41eef94fb Mon Sep 17 00:00:00 2001 From: Anurag Hazra Date: Tue, 27 Jun 2023 15:09:23 +0530 Subject: [PATCH] feat(blade): added bottomsheet body zero padding option (#1346) * feat: web implementation * chore: add native padding * chore: update snapshot * fix: react native bottomsheet fix * chore: update snapshot and test * chore: update * chore: review updates * Create many-parrots-guess.md * Update .changeset/many-parrots-guess.md Co-authored-by: Saurabh Daware --------- Co-authored-by: Saurabh Daware --- .changeset/many-parrots-guess.md | 5 + .../BottomSheet/BottomSheet.native.tsx | 14 +- .../BottomSheet/BottomSheet.stories.tsx | 81 +++ .../BottomSheet/BottomSheet.web.tsx | 13 +- .../BottomSheet/BottomSheetBody.native.tsx | 31 +- .../BottomSheet/BottomSheetBody.web.tsx | 23 +- .../BottomSheet/BottomSheetCommon.tsx | 16 +- .../BottomSheet/BottomSheetContext.ts | 6 + .../BottomSheet/BottomSheetGrabHandle.web.tsx | 8 +- .../BottomSheet/BottomSheetHeader.native.tsx | 9 +- .../BottomSheet/BottomSheetHeader.web.tsx | 14 +- .../__tests__/BottomSheet.native.test.tsx | 18 + .../__tests__/BottomSheet.web.test.tsx | 15 + .../BottomSheet.native.test.tsx.snap | 597 +++++++++++++++++- .../BottomSheet.web.test.tsx.snap | 294 +++++++++ .../getBottomSheetGrabHandleStyles.ts | 10 +- .../blade/src/components/BottomSheet/types.ts | 15 +- 17 files changed, 1139 insertions(+), 30 deletions(-) create mode 100644 .changeset/many-parrots-guess.md diff --git a/.changeset/many-parrots-guess.md b/.changeset/many-parrots-guess.md new file mode 100644 index 00000000000..483c0c963cf --- /dev/null +++ b/.changeset/many-parrots-guess.md @@ -0,0 +1,5 @@ +--- +"@razorpay/blade": minor +--- + +feat(blade): added bottomsheet body zero padding option diff --git a/packages/blade/src/components/BottomSheet/BottomSheet.native.tsx b/packages/blade/src/components/BottomSheet/BottomSheet.native.tsx index bcc7c3fe0ee..c464f764174 100644 --- a/packages/blade/src/components/BottomSheet/BottomSheet.native.tsx +++ b/packages/blade/src/components/BottomSheet/BottomSheet.native.tsx @@ -62,6 +62,8 @@ const _BottomSheet = ({ const [headerHeight, setHeaderHeight] = React.useState(0); const [footerHeight, setFooterHeight] = React.useState(0); const [contentHeight, setContentHeight] = React.useState(0); + const [hasBodyPadding, setHasBodyPadding] = React.useState(true); + const [isHeaderEmpty, setIsHeaderEmpty] = React.useState(false); const initialSnapPoint = React.useRef(0); const totalHeight = React.useMemo(() => { return headerHeight + footerHeight + contentHeight; @@ -168,6 +170,10 @@ const _BottomSheet = ({ const renderHandle = React.useCallback((): React.ReactElement => { return ( { setHeaderHeight(nativeEvent.layout.height); }} @@ -178,8 +184,9 @@ const _BottomSheet = ({ {header.current} ); - }, [zIndex]); + }, [isHeaderEmpty, zIndex]); + const isHeaderFloating = !hasBodyPadding && isHeaderEmpty; const contextValue = React.useMemo( () => ({ isInBottomSheet: true, @@ -195,8 +202,11 @@ const _BottomSheet = ({ scrollRef: () => {}, bind: {} as never, defaultInitialFocusRef, + isHeaderFloating, + setHasBodyPadding, + setIsHeaderEmpty, }), - [_isOpen, contentHeight, footerHeight, handleOnClose, headerHeight], + [_isOpen, contentHeight, footerHeight, handleOnClose, headerHeight, isHeaderFloating], ); // Hack: We need to the GorhomBottomSheet to the root of the react-native app diff --git a/packages/blade/src/components/BottomSheet/BottomSheet.stories.tsx b/packages/blade/src/components/BottomSheet/BottomSheet.stories.tsx index 8180f8f1638..86da01a75aa 100644 --- a/packages/blade/src/components/BottomSheet/BottomSheet.stories.tsx +++ b/packages/blade/src/components/BottomSheet/BottomSheet.stories.tsx @@ -1,3 +1,4 @@ +/* eslint-disable jsx-a11y/media-has-caption */ /* eslint-disable jsx-a11y/no-autofocus */ /* eslint-disable react/no-unescaped-entities */ /* eslint-disable @typescript-eslint/no-explicit-any */ @@ -42,6 +43,7 @@ import { OTPInput } from '~components/Input/OTPInput'; import { Link } from '~components/Link'; import { Sandbox } from '~src/_helpers/storybook/Sandbox'; import StoryPageWrapper from '~src/_helpers/storybook/StoryPageWrapper'; +import { isReactNative } from '~utils'; const Page = (): React.ReactElement => { return ( @@ -671,6 +673,85 @@ const InitialFocusTemplate: ComponentStory = () => export const InitialFocus = InitialFocusTemplate.bind({}); +const HeadingBanner = (): React.ReactElement => { + if (isReactNative()) { + return ( + + + + + All-in-one Escrow management platform + + + + ); + } + + return ( + + + + + + All-in-one Escrow management platform + + + + ); +}; + +const ZeroPaddingTemplate: ComponentStory = () => { + const [isOpen, setIsOpen] = React.useState(false); + + return ( + + + { + setIsOpen(false); + }} + > + + + + + + + We bring together Escrow account, Banks, Trusteeship services & Automation - all in + ONE place to deliver a seamless user experience for you. Work with our experts to + ensure your escrow money transfers are always compliant, safe & effortless. + + + 100% secure | Instant payouts | Unbeatable pricing + + + + + + + + + + ); +}; + +export const ZeroPadding = ZeroPaddingTemplate.bind({}); + const SnapPointsTemplate: ComponentStory = () => { const fruites = [ 'Apple', diff --git a/packages/blade/src/components/BottomSheet/BottomSheet.web.tsx b/packages/blade/src/components/BottomSheet/BottomSheet.web.tsx index 082d8c32608..102e5fe71e8 100644 --- a/packages/blade/src/components/BottomSheet/BottomSheet.web.tsx +++ b/packages/blade/src/components/BottomSheet/BottomSheet.web.tsx @@ -13,6 +13,7 @@ import { BottomSheetBody } from './BottomSheetBody'; import type { SnapPoints } from './utils'; import { computeMaxContent, computeSnapPointBounds } from './utils'; import { BottomSheetBackdrop } from './BottomSheetBackdrop'; +import type { BottomSheetContextProps } from './BottomSheetContext'; import { BottomSheetContext, useBottomSheetAndDropdownGlue } from './BottomSheetContext'; import { ComponentIds } from './componentIds'; import type { BottomSheetProps } from './types'; @@ -82,6 +83,8 @@ const _BottomSheet = ({ const [headerHeight, setHeaderHeight] = React.useState(0); const [footerHeight, setFooterHeight] = React.useState(0); const [grabHandleHeight, setGrabHandleHeight] = React.useState(0); + const [hasBodyPadding, setHasBodyPadding] = React.useState(true); + const [isHeaderEmpty, setIsHeaderEmpty] = React.useState(false); const bottomSheetAndDropdownGlue = useBottomSheetAndDropdownGlue(); const [positionY, _setPositionY] = React.useState(0); @@ -362,7 +365,8 @@ const _BottomSheet = ({ transitionDuration: theme.motion.duration.moderate, }); - const contextValue = React.useMemo( + const isHeaderFloating = !hasBodyPadding && isHeaderEmpty; + const contextValue: BottomSheetContextProps = React.useMemo( () => ({ isInBottomSheet: true, isOpen: Boolean(isVisible), @@ -374,9 +378,12 @@ const _BottomSheet = ({ setContentHeight, setFooterHeight, setHeaderHeight, + setHasBodyPadding, + setIsHeaderEmpty, scrollRef, bind, defaultInitialFocusRef, + isHeaderFloating, }), [ isVisible, @@ -388,9 +395,12 @@ const _BottomSheet = ({ setContentHeight, setFooterHeight, setHeaderHeight, + setHasBodyPadding, + setIsHeaderEmpty, scrollRef, bind, defaultInitialFocusRef, + isHeaderFloating, ], ); @@ -445,6 +455,7 @@ const _BottomSheet = ({ diff --git a/packages/blade/src/components/BottomSheet/BottomSheetBody.native.tsx b/packages/blade/src/components/BottomSheet/BottomSheetBody.native.tsx index 2c4ce275d74..2369c1cd697 100644 --- a/packages/blade/src/components/BottomSheet/BottomSheetBody.native.tsx +++ b/packages/blade/src/components/BottomSheet/BottomSheetBody.native.tsx @@ -4,13 +4,23 @@ import React from 'react'; import { BottomSheetScrollView } from '@gorhom/bottom-sheet'; import { ComponentIds } from './componentIds'; import { useBottomSheetContext } from './BottomSheetContext'; +import type { BottomSheetBodyProps } from './types'; import BaseBox from '~components/Box/BaseBox'; import { assignWithoutSideEffects } from '~src/utils/assignWithoutSideEffects'; import { isValidAllowedChildren } from '~utils'; import { componentIds } from '~components/ActionList/componentIds'; +import { size } from '~tokens/global'; -const _BottomSheetBody = ({ children }: { children: React.ReactNode }): React.ReactElement => { - const { footerHeight, setContentHeight } = useBottomSheetContext(); +const _BottomSheetBody = ({ + children, + padding = 'spacing.5', +}: BottomSheetBodyProps): React.ReactElement => { + const { + footerHeight, + setContentHeight, + setHasBodyPadding, + isHeaderFloating, + } = useBottomSheetContext(); const [bottomSheetHasActionList, setBottomSheetHasActionList] = React.useState< boolean | undefined >(undefined); @@ -24,6 +34,13 @@ const _BottomSheetBody = ({ children }: { children: React.ReactNode }): React.Re }); }, [children]); + React.useEffect(() => { + if (padding === 'spacing.0') { + setHasBodyPadding(false); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [padding]); + if (bottomSheetHasActionList === undefined) return <>; // If we are rendering ActionList, then we don't wrap the ActionList with extra wrappers // This is to ensure that GorhomBottomSheetSectionList work as expected, adding extra wrappers breaks gorhom's rendering @@ -36,14 +53,14 @@ const _BottomSheetBody = ({ children }: { children: React.ReactNode }): React.Re onContentSizeChange={(_width, height) => { setContentHeight(height); }} - style={{ marginBottom: footerHeight }} + style={{ marginBottom: footerHeight, borderRadius: isHeaderFloating ? size[16] : 0 }} > {children} diff --git a/packages/blade/src/components/BottomSheet/BottomSheetBody.web.tsx b/packages/blade/src/components/BottomSheet/BottomSheetBody.web.tsx index 16ac511ba6c..936f68e184f 100644 --- a/packages/blade/src/components/BottomSheet/BottomSheetBody.web.tsx +++ b/packages/blade/src/components/BottomSheet/BottomSheetBody.web.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { ComponentIds } from './componentIds'; import { useBottomSheetContext } from './BottomSheetContext'; +import type { BottomSheetBodyProps } from './types'; import { useIsomorphicLayoutEffect } from '~src/hooks/useIsomorphicLayoutEffect'; import BaseBox from '~components/Box/BaseBox'; import { assignWithoutSideEffects } from '~src/utils/assignWithoutSideEffects'; @@ -19,8 +20,11 @@ const bodyStyles: React.CSSProperties = { touchAction: 'none', }; -const _BottomSheetBody = ({ children }: { children: React.ReactNode }): React.ReactElement => { - const { scrollRef, setContentHeight, isOpen, bind } = useBottomSheetContext(); +const _BottomSheetBody = ({ + children, + padding = 'spacing.5', +}: BottomSheetBodyProps): React.ReactElement => { + const { scrollRef, setContentHeight, setHasBodyPadding, isOpen, bind } = useBottomSheetContext(); const contentRef = React.useRef(null); const [bottomSheetHasActionList, setBottomSheetHasActionList] = React.useState(false); @@ -38,6 +42,13 @@ const _BottomSheetBody = ({ children }: { children: React.ReactNode }): React.Re }); }, [children]); + React.useEffect(() => { + if (padding === 'spacing.0') { + setHasBodyPadding(false); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [padding]); + return ( diff --git a/packages/blade/src/components/BottomSheet/BottomSheetCommon.tsx b/packages/blade/src/components/BottomSheet/BottomSheetCommon.tsx index af256ab4e37..cb37000da85 100644 --- a/packages/blade/src/components/BottomSheet/BottomSheetCommon.tsx +++ b/packages/blade/src/components/BottomSheet/BottomSheetCommon.tsx @@ -37,7 +37,7 @@ const BottomSheetEmptyHeader = React.forwardRef { - const { close } = useBottomSheetContext(); + const { close, isHeaderFloating } = useBottomSheetContext(); const { theme } = useTheme(); const webOnlyEventHandlers: Record = isReactNative() ? {} @@ -52,14 +52,23 @@ const BottomSheetEmptyHeader = React.forwardRef >; setHeaderHeight: React.Dispatch>; setFooterHeight: React.Dispatch>; + setHasBodyPadding: React.Dispatch>; + setIsHeaderEmpty: React.Dispatch>; /** * Closes the bottomsheet */ @@ -52,9 +55,12 @@ const BottomSheetContext = React.createContext({ headerHeight: 0, contentHeight: 0, footerHeight: 0, + isHeaderFloating: false, setContentHeight: () => {}, setHeaderHeight: () => {}, setFooterHeight: () => {}, + setHasBodyPadding: () => {}, + setIsHeaderEmpty: () => {}, close: () => {}, scrollRef: null, bind: null, diff --git a/packages/blade/src/components/BottomSheet/BottomSheetGrabHandle.web.tsx b/packages/blade/src/components/BottomSheet/BottomSheetGrabHandle.web.tsx index b765a5fcbf7..41e6d1c266b 100644 --- a/packages/blade/src/components/BottomSheet/BottomSheetGrabHandle.web.tsx +++ b/packages/blade/src/components/BottomSheet/BottomSheetGrabHandle.web.tsx @@ -1,8 +1,10 @@ import styled from 'styled-components'; import { getBottomSheetGrabHandleStyles } from './getBottomSheetGrabHandleStyles'; -const BottomSheetGrabHandle = styled.div(({ theme }) => { - return getBottomSheetGrabHandleStyles({ theme }); -}); +const BottomSheetGrabHandle = styled.div<{ isHeaderFloating?: boolean }>( + ({ theme, isHeaderFloating }) => { + return getBottomSheetGrabHandleStyles({ theme, isHeaderFloating }); + }, +); export { BottomSheetGrabHandle }; diff --git a/packages/blade/src/components/BottomSheet/BottomSheetHeader.native.tsx b/packages/blade/src/components/BottomSheet/BottomSheetHeader.native.tsx index f59ee122336..b90cf3a9d00 100644 --- a/packages/blade/src/components/BottomSheet/BottomSheetHeader.native.tsx +++ b/packages/blade/src/components/BottomSheet/BottomSheetHeader.native.tsx @@ -17,11 +17,16 @@ const _BottomSheetHeader = ({ showBackButton = false, onBackButtonClick, }: BottomSheetHeaderProps): React.ReactElement => { - const { close, defaultInitialFocusRef } = useBottomSheetContext(); + const { close, setIsHeaderEmpty, defaultInitialFocusRef } = useBottomSheetContext(); const isHeaderEmpty = !(title || subtitle || leading || trailing || showBackButton); + React.useEffect(() => { + setIsHeaderEmpty(isHeaderEmpty); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isHeaderEmpty]); + return ( - + {isHeaderEmpty ? ( ) : ( diff --git a/packages/blade/src/components/BottomSheet/BottomSheetHeader.web.tsx b/packages/blade/src/components/BottomSheet/BottomSheetHeader.web.tsx index 4aaf1814d30..d2dd8199df7 100644 --- a/packages/blade/src/components/BottomSheet/BottomSheetHeader.web.tsx +++ b/packages/blade/src/components/BottomSheet/BottomSheetHeader.web.tsx @@ -18,7 +18,14 @@ const _BottomSheetHeader = ({ showBackButton = false, onBackButtonClick, }: BottomSheetHeaderProps): React.ReactElement => { - const { setHeaderHeight, isOpen, close, bind, defaultInitialFocusRef } = useBottomSheetContext(); + const { + setHeaderHeight, + isOpen, + close, + bind, + setIsHeaderEmpty, + defaultInitialFocusRef, + } = useBottomSheetContext(); const ref = React.useRef(null); useIsomorphicLayoutEffect(() => { @@ -28,6 +35,11 @@ const _BottomSheetHeader = ({ const isHeaderEmpty = !(title || subtitle || leading || trailing || showBackButton); + React.useEffect(() => { + setIsHeaderEmpty(isHeaderEmpty); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isHeaderEmpty]); + return ( ', () => { expect(toJSON()).toMatchSnapshot(); }); + test('should render empty header', () => { + const Example = (): React.ReactElement => { + // Can't render BottomSheetBody because https://github.com/gorhom/react-native-bottom-sheet/issues/11#issuecomment-1283588472 + return ( + + + + + + + ); + }; + const { toJSON } = renderWithTheme(); + expect(toJSON()).toMatchSnapshot(); + }); + test('BottomSheetHeader trailing should not allow any random component', () => { const mockConsoleError = jest.spyOn(console, 'error').mockImplementation(); diff --git a/packages/blade/src/components/BottomSheet/__tests__/BottomSheet.web.test.tsx b/packages/blade/src/components/BottomSheet/__tests__/BottomSheet.web.test.tsx index cc04170b642..6a58847a1fc 100644 --- a/packages/blade/src/components/BottomSheet/__tests__/BottomSheet.web.test.tsx +++ b/packages/blade/src/components/BottomSheet/__tests__/BottomSheet.web.test.tsx @@ -85,6 +85,21 @@ describe('', () => { mockConsoleError.mockRestore(); }); + it('should render empty header with padding 0', () => { + const Example = (): React.ReactElement => { + return ( + + + + BottomSheet body + + + ); + }; + const { container } = renderWithTheme(); + expect(container).toMatchSnapshot(); + }); + it('should open/close BottomSheet', async () => { const mockConsoleError = jest.spyOn(console, 'error').mockImplementation(); const user = userEvents.setup(); diff --git a/packages/blade/src/components/BottomSheet/__tests__/__snapshots__/BottomSheet.native.test.tsx.snap b/packages/blade/src/components/BottomSheet/__tests__/__snapshots__/BottomSheet.native.test.tsx.snap index eab4ec189a3..bb8f8070f5b 100644 --- a/packages/blade/src/components/BottomSheet/__tests__/__snapshots__/BottomSheet.native.test.tsx.snap +++ b/packages/blade/src/components/BottomSheet/__tests__/__snapshots__/BottomSheet.native.test.tsx.snap @@ -370,12 +370,21 @@ exports[` should render Header/Footer/Body properly 1`] = ` onLayout={[Function]} > should render Header/Footer/Body properly 1`] = ` "justifyContent": "center", "marginBottom": 4, "paddingTop": 12, + "position": "relative", "touchAction": "none", "width": "100%", + "zIndex": 100, }, ] } @@ -424,13 +435,11 @@ exports[` should render Header/Footer/Body properly 1`] = ` should render Header/Footer/Body properly 1`] = ` `; + +exports[` should render empty header 1`] = ` + + + + + + + + + + + + + + + + Remove address + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; diff --git a/packages/blade/src/components/BottomSheet/__tests__/__snapshots__/BottomSheet.web.test.tsx.snap b/packages/blade/src/components/BottomSheet/__tests__/__snapshots__/BottomSheet.web.test.tsx.snap index 77d1752e276..dc0b10d3b9e 100644 --- a/packages/blade/src/components/BottomSheet/__tests__/__snapshots__/BottomSheet.web.test.tsx.snap +++ b/packages/blade/src/components/BottomSheet/__tests__/__snapshots__/BottomSheet.web.test.tsx.snap @@ -337,6 +337,7 @@ exports[` should render Header/Footer/Body properly 1`] = ` } .c4 { + position: relative; -webkit-flex-shrink: 0; -ms-flex-negative: 0; flex-shrink: 0; @@ -359,6 +360,7 @@ exports[` should render Header/Footer/Body properly 1`] = ` -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; + z-index: 100; } .c4:after { @@ -673,3 +675,295 @@ exports[` should render Header/Footer/Body properly 1`] = ` `; + +exports[` should render empty header with padding 0 1`] = ` +.c3 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + height: 100%; +} + +.c5 { + overflow: visible; + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; +} + +.c9 { + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; + -webkit-flex-shrink: 1; + -ms-flex-negative: 1; + flex-shrink: 1; +} + +.c10 { + overflow: auto; + padding-top: 0px; + padding-bottom: 0px; + padding-right: 0px; + padding-left: 0px; +} + +.c0 { + position: fixed; + z-index: 100; + top: 0px; + right: 0px; + bottom: 0px; + left: 0px; + background-color: hsla(214,15%,18%,0.64); + opacity: 1; +} + +.c6 { + position: absolute; + height: 8px; + top: 16px; + right: 0px; + touch-action: none; +} + +.c7 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + position: absolute; + z-index: 100; + height: 28px; + width: 28px; + top: 0px; + right: 16px; + background-color: hsla(0,0%,100%,1); + border-radius: 9999px; +} + +.c8 { + border: none; + cursor: pointer; + padding: 0; + border-radius: 2px; + background: transparent; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + color: hsla(214,18%,69%,1); + -webkit-transition-property: color,box-shadow; + transition-property: color,box-shadow; + -webkit-transition-duration: 150ms; + transition-duration: 150ms; + -webkit-transition-timing-function: cubic-bezier(0.3,0,0.2,1); + transition-timing-function: cubic-bezier(0.3,0,0.2,1); +} + +.c8:hover { + color: hsla(217,18%,45%,1); +} + +.c8:focus { + outline: none; + box-shadow: 0px 0px 0px 4px hsla(218,89%,51%,0.18); + color: hsla(217,18%,45%,1); +} + +.c8:active { + color: hsla(217,18%,45%,1); +} + +.c11 { + color: hsla(217,56%,17%,1); + font-family: Lato,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"; + font-size: 0.875rem; + font-weight: 400; + font-style: normal; + -webkit-text-decoration-line: none; + text-decoration-line: none; + line-height: 1.25rem; + margin: 0; + padding: 0; +} + +.c1 { + -webkit-transition-duration: 250ms; + transition-duration: 250ms; + -webkit-transition-timing-function: cubic-bezier(0,0,0,1); + transition-timing-function: cubic-bezier(0,0,0,1); + pointer-events: all; + -webkit-transition-property: opacity; + transition-property: opacity; +} + +.c4 { + position: absolute; + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + padding-top: 12px; + margin-bottom: 4px; + touch-action: none; + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + z-index: 100; +} + +.c4:after { + margin: auto; + content: ''; + width: 56px; + height: 4px; + background-color: hsla(216,15%,54%,0.18); + border-radius: 16px; +} + +.c2 { + background: hsla(0,0%,100%,1); + border-top-left-radius: 16px; + border-top-right-radius: 16px; + border-color: hsla(216,15%,54%,0.18); + box-shadow: 0px -24px 48px -12px hsla(217,56%,17%,0.18); + opacity: 0; + pointer-events: none; + -webkit-transition-duration: 250ms; + transition-duration: 250ms; + -webkit-transition-timing-function: cubic-bezier(.15,0,.24,.97); + transition-timing-function: cubic-bezier(.15,0,.24,.97); + will-change: transform,opacity,height; + -webkit-transition-property: -webkit-transform,opacity,height; + -webkit-transition-property: transform,opacity,height; + transition-property: transform,opacity,height; + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 768px; + background-color: hsla(0,0%,100%,1); + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + touch-action: none; + overflow: hidden; +} + +
+
+ +`; diff --git a/packages/blade/src/components/BottomSheet/getBottomSheetGrabHandleStyles.ts b/packages/blade/src/components/BottomSheet/getBottomSheetGrabHandleStyles.ts index 2f12125b480..edba2dd47b6 100644 --- a/packages/blade/src/components/BottomSheet/getBottomSheetGrabHandleStyles.ts +++ b/packages/blade/src/components/BottomSheet/getBottomSheetGrabHandleStyles.ts @@ -14,8 +14,15 @@ const getHandlePartStyles = ({ theme }: { theme: Theme }): CSSObject => { borderRadius: makeSpace(theme.spacing[5]), }; }; -const getBottomSheetGrabHandleStyles = ({ theme }: { theme: Theme }): CSSObject => { +const getBottomSheetGrabHandleStyles = ({ + theme, + isHeaderFloating, +}: { + theme: Theme; + isHeaderFloating?: boolean; +}): CSSObject => { return { + position: isHeaderFloating ? 'absolute' : 'relative', flexShrink: 0, paddingTop: makeSpace(theme.spacing[4]), marginBottom: makeSpace(theme.spacing[2]), @@ -25,6 +32,7 @@ const getBottomSheetGrabHandleStyles = ({ theme }: { theme: Theme }): CSSObject flexDirection: 'column', alignItems: 'center', justifyContent: 'center', + zIndex: 100, ...(isReactNative() ? undefined : { ':after': getHandlePartStyles({ theme }) }), }; }; diff --git a/packages/blade/src/components/BottomSheet/types.ts b/packages/blade/src/components/BottomSheet/types.ts index 5e6bb93180f..ea8678c2f44 100644 --- a/packages/blade/src/components/BottomSheet/types.ts +++ b/packages/blade/src/components/BottomSheet/types.ts @@ -2,6 +2,7 @@ import type { BaseHeaderProps } from '../BaseHeaderFooter/BaseHeader'; import type { BaseFooterProps } from '../BaseHeaderFooter/BaseFooter'; import type { SnapPoints } from './utils'; +import type { SpacingValueType } from '~components/Box/BaseBox'; type BottomSheetProps = { /** @@ -52,4 +53,16 @@ type BottomSheetHeaderProps = Pick< type BottomSheetFooterProps = Pick; -export { BottomSheetProps, BottomSheetHeaderProps, BottomSheetFooterProps }; +type BottomSheetBodyProps = { + children: React.ReactNode; + /** + * Sets the padding equally on all sides. Only few `spacing` tokens are allowed deliberately + * @default `spacing.5` + * + * **Links:** + * - Docs: https://blade.razorpay.com/?path=/docs/tokens-spacing--page + */ + padding?: Extract; +}; + +export { BottomSheetProps, BottomSheetHeaderProps, BottomSheetFooterProps, BottomSheetBodyProps };