Skip to content

Commit

Permalink
Merge pull request #1949 from adevinta/1948-component-dialog-apply-pa…
Browse files Browse the repository at this point in the history
…dding-right-to-dialogtitle-when-dialogclosebutton-is-present

feat(dialog): apply padding right to dialog title when closebutton is present
  • Loading branch information
acd02 authored Mar 15, 2024
2 parents 017b58f + 0c4976b commit 0557130
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 11 deletions.
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/components/dialog/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"@spark-ui/icon": "^2.1.2",
"@spark-ui/icon-button": "^2.2.3",
"@spark-ui/icons": "^1.21.6",
"@spark-ui/internal-utils": "^2.3.0",
"class-variance-authority": "0.7.0"
}
}
27 changes: 27 additions & 0 deletions packages/components/dialog/src/Dialog.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -188,4 +188,31 @@ describe('Dialog', () => {

expect(screen.getByText(/dialog contents/i).parentElement).not.toHaveClass('px-xl py-lg')
})

it('should apply padding-right to the Dialog.Title if Dialog.CloseButton is present', async () => {
render(
<Dialog defaultOpen>
<Dialog.Portal>
<Dialog.Overlay />
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Edit profile</Dialog.Title>
</Dialog.Header>

<Dialog.Body>
<p>Dialog contents</p>
</Dialog.Body>

<Dialog.Footer>
<Button>Close</Button>
</Dialog.Footer>

<Dialog.CloseButton aria-label="Close" />
</Dialog.Content>
</Dialog.Portal>
</Dialog>
)

expect(screen.getByText(/Edit profile/i)).toHaveClass('pr-3xl')
})
})
6 changes: 5 additions & 1 deletion packages/components/dialog/src/DialogCloseButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type CloseButtonElement = ElementRef<typeof Close>
export type CloseButtonProps = CloseProps &
Pick<IconButtonProps, 'size' | 'intent' | 'design' | 'aria-label'>

export const CloseButton = forwardRef<CloseButtonElement, CloseButtonProps>(
const Root = forwardRef<CloseButtonElement, CloseButtonProps>(
(
{
'aria-label': ariaLabel,
Expand All @@ -36,4 +36,8 @@ export const CloseButton = forwardRef<CloseButtonElement, CloseButtonProps>(
)
)

export const CloseButton = Object.assign(Root, {
id: 'CloseButton',
})

CloseButton.displayName = 'Dialog.CloseButton'
27 changes: 24 additions & 3 deletions packages/components/dialog/src/DialogContext.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,44 @@
import { createContext, type ReactNode, useContext, useState } from 'react'
import { deepFind } from '@spark-ui/internal-utils'
import {
createContext,
type ReactElement,
type ReactNode,
useContext,
useEffect,
useState,
} from 'react'

export interface DialogContextState {
isFullScreen: boolean
setIsFullScreen: (value: boolean) => void
hasCloseButton: boolean
}

const DialogContext = createContext<DialogContextState | null>(null)

export const DialogProvider = ({ children }: { children: ReactNode }) => {
export const DialogProvider = ({ children: childrenProp }: { children: ReactNode }) => {
const [isFullScreen, setIsFullScreen] = useState(false)
const [hasCloseButton, setHasCloseButton] = useState(false)

const closeButton = deepFind(childrenProp, node => {
const reactElementId = ((node as ReactElement)?.type as { id?: string }).id

return reactElementId === 'CloseButton'
})

useEffect(() => {
setHasCloseButton(!!closeButton)
}, [closeButton])

return (
<DialogContext.Provider
value={{
isFullScreen,
setIsFullScreen,
hasCloseButton,
}}
>
{children}
{childrenProp}
</DialogContext.Provider>
)
}
Expand Down
20 changes: 13 additions & 7 deletions packages/components/dialog/src/DialogTitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,21 @@ import * as RadixDialog from '@radix-ui/react-dialog'
import { cx } from 'class-variance-authority'
import { ElementRef, forwardRef } from 'react'

import { useDialog } from './DialogContext'

export type TitleElement = ElementRef<typeof RadixDialog.Title>
export type TitleProps = RadixDialog.DialogTitleProps

export const Title = forwardRef<TitleElement, TitleProps>(({ className, ...others }, ref) => (
<RadixDialog.Title
ref={ref}
className={cx('text-headline-1 text-on-surface', className)}
{...others}
/>
))
export const Title = forwardRef<TitleElement, TitleProps>(({ className, ...others }, ref) => {
const { hasCloseButton } = useDialog()

return (
<RadixDialog.Title
ref={ref}
className={cx('text-headline-1 text-on-surface', hasCloseButton && 'pr-3xl', className)}
{...others}
/>
)
})

Title.displayName = 'Dialog.Title'

0 comments on commit 0557130

Please sign in to comment.