Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions packages/blade/src/components/Popover/Popover.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,7 @@ const Popover = ({
context={context}
width={ARROW_WIDTH}
height={ARROW_HEIGHT}
fillColor={theme.colors.popup.background.subtle}
strokeColor={theme.colors.popup.border.subtle}
fillColor={theme.colors.popup.background.gray.moderate}
/>
}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const PopoverCloseButton = (): React.ReactElement => {
return (
<IconButton
ref={defaultInitialFocusRef as never}
size="large"
size="medium"
icon={CloseIcon}
accessibilityLabel="Close"
onClick={close}
Expand Down
12 changes: 7 additions & 5 deletions packages/blade/src/components/Popover/PopoverContent.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
import React from 'react';
import { isReactNative } from '~utils';

Check failure on line 3 in packages/blade/src/components/Popover/PopoverContent.tsx

View workflow job for this annotation

GitHub Actions / Validate Source Code

`~utils` import should occur after import of `./PopoverContext`
import { PopoverContentWrapper } from './PopoverContentWrapper';
import type { PopoverContentProps } from './types';
import { PopoverCloseButton } from './PopoverCloseButton';
import { usePopoverContext } from './PopoverContext';
import BaseBox from '~components/Box/BaseBox';
import { Text } from '~components/Typography';
import { isReactNative } from '~utils';
import { useIsMobile } from '~utils/useIsMobile';

type PopoverHeaderProps = {
Expand Down Expand Up @@ -47,7 +47,7 @@
gap="spacing.3"
>
{titleLeading
? React.cloneElement(titleLeading as React.ReactElement, { size: 'large' })
? React.cloneElement(titleLeading as React.ReactElement, { size: 'medium' })
: null}
{title ? (
<BaseBox id={titleId} paddingRight="spacing.4">
Expand Down Expand Up @@ -76,9 +76,11 @@
isVisible={isVisible}
isMobile={isMobile}
>
<BaseBox padding="spacing.4" display="flex" flexDirection="column" gap="spacing.4">
<PopoverHeader title={title} titleLeading={titleLeading} />
<BaseBox>{children}</BaseBox>
<BaseBox padding="spacing.5" display="flex" flexDirection="column" gap="spacing.5">
<BaseBox display="flex" flexDirection="column" gap="spacing.2">
<PopoverHeader title={title} titleLeading={titleLeading} />
<BaseBox>{children}</BaseBox>
</BaseBox>
{footer ? <BaseBox>{footer}</BaseBox> : null}
</BaseBox>
{arrow}
Expand Down
4 changes: 2 additions & 2 deletions packages/blade/src/components/Popover/constants.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export const ARROW_WIDTH = 14;
export const ARROW_HEIGHT = 7;
export const ARROW_WIDTH = 22;
export const ARROW_HEIGHT = 12;
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/* eslint-disable react-hooks/rules-of-hooks */
import type React from 'react';
import type { CSSObject } from 'styled-components';
import { isReactNative, makeSpace, makeBorderSize } from '~utils';
import { getPopoverBoxShadow } from './popoverTokens';

Check failure on line 5 in packages/blade/src/components/Popover/getPopoverContentWrapperStyles.ts

View workflow job for this annotation

GitHub Actions / Validate Source Code

`./popoverTokens` import should occur before import of `~utils`
import type { Theme } from '~components/BladeProvider';
import { makeBorderSize, castWebType, isReactNative, makeSpace } from '~utils';

const getPopoverContentWrapperStyles = ({
theme,
Expand All @@ -17,12 +18,10 @@
width: '100%',
maxWidth: makeSpace(isMobile ? 288 : 328),
position: isReactNative() ? 'absolute' : 'relative',
backgroundColor: theme.colors.popup.background.subtle,
borderWidth: makeBorderSize(theme.border.width.thin),
backgroundColor: theme.colors.popup.background.gray.moderate,
borderRadius: makeBorderSize(theme.border.radius.large),
borderColor: theme.colors.popup.border.subtle,
borderStyle: 'solid',
boxShadow: isReactNative() ? undefined : castWebType(theme.elevation.midRaised),
boxShadow: isReactNative() ? undefined : getPopoverBoxShadow(theme),
backdropFilter: isReactNative() ? undefined : `blur(${theme.backdropBlur.high}px)`,
...styles,
};
};
Expand Down
30 changes: 30 additions & 0 deletions packages/blade/src/components/Popover/popoverTokens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import { makePopupBoxShadow } from '~utils';
import type { ShadowLayer } from '~utils';
import type { Theme } from '~components/BladeProvider';

/**
* Popover shadow layers as per Figma design: _components/Popup shadow
*
* Consists of 2 layers:
* 1. Drop shadow: elevation.midRaised (for elevation)
* 2. Top highlight: inset 0px -1.5px 0px 1px (for depth)
*/
const getPopoverBoxShadow = (theme: Theme): string => {
const shadowLayers: ShadowLayer[] = [
// Layer 1: Top highlight for depth
{
x: 0,
y: -1.5,
blur: 0,
spread: 1,
color: theme.colors.surface.background.gray.intense,
inset: true,
},
];

// Combine elevation.midRaised with additional shadow layers
return `${theme.elevation.midRaised}, ${makePopupBoxShadow(shadowLayers)}`;
};

export { getPopoverBoxShadow };
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ const TourPopover = ({
width={ARROW_WIDTH}
height={ARROW_HEIGHT}
fillColor={theme.colors.popup.background.subtle}
strokeColor={theme.colors.popup.border.subtle}
/>
}
>
Expand Down
1 change: 1 addition & 0 deletions packages/blade/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export * from './makeMotionTime';
export * from './makeSpace';
export * from './makeTypographySize';
export * from './makeSize';
export * from './makePopupBoxShadow';

// https://github.com/razorpay/blade/pull/1193#issuecomment-1609122359
export * from './toTitleCase';
Expand Down
1 change: 1 addition & 0 deletions packages/blade/src/utils/makePopupBoxShadow/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './makePopupBoxShadow';
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */

/**
* Represents a single shadow layer configuration
* Used to create complex multi-layer shadows for popup components
*/
export type ShadowLayer = {
/** Horizontal offset in pixels */
x: number;
/** Vertical offset in pixels */
y: number;
/** Blur radius in pixels */
blur: number;
/** Spread radius in pixels */
spread: number;
/** Color value (hex, rgb, rgba, hsla, etc.) */
color: string;
/** Whether this is an inset shadow */
inset: boolean;
};

/**
* Converts an array of shadow layer objects into a CSS box-shadow string
*
* @param shadowLayers - Array of shadow layer configurations
* @returns CSS box-shadow string with multiple layers joined by commas
*
* @example
* ```ts
* const layers = [
* { x: 0, y: 2, blur: 4, spread: 0, color: 'rgba(0,0,0,0.1)', inset: false },
* { x: 0, y: 0, blur: 0, spread: 1, color: 'rgba(255,255,255,0.5)', inset: true }
* ];
* const boxShadow = makePopupBoxShadow(layers);
* // Result: "0px 2px 4px 0px rgba(0,0,0,0.1), inset 0px 0px 0px 1px rgba(255,255,255,0.5)"
* ```
*/
export const makePopupBoxShadow = (shadowLayers: ShadowLayer[]): string => {
return shadowLayers
.map((layer) => {
const inset = layer.inset ? 'inset ' : '';
return `${inset}${layer.x}px ${layer.y}px ${layer.blur}px ${layer.spread}px ${layer.color}`;
})
.join(', ');
};
Loading