G
Tokens
TypographySpacingColorRadiusShadowMotion
Foundational
FieldMenuTextbox

Modal

Content


    () => {
      const [isOpen, setIsOpen] = useState(false);
      return (
        <>
          <Button onClick={() => setIsOpen(true)}>Open Modal</Button>
          <Modal
            isOpen={isOpen}
            onClose={() => setIsOpen(false)}
          >
            Content
          </Modal>
        </>
      )
    }
  

Title and description


    () => {
      const [isOpen, setIsOpen] = useState(false);
      return (
        <>
          <Button onClick={() => setIsOpen(true)}>Open Modal</Button>
          <Modal
            isOpen={isOpen}
            onClose={() => setIsOpen(false)}
            title={demoText.s}
            description={demoText.m}
          >
            <Box marginTop="m">
              <Button onClick={() => setIsOpen(false)}>Close</Button>
            </Box>
          </Modal>
        </>
      )
    }
  

Card padding and radius

For padding and radius use the card patterns.

It's recomemded to use var(--grn-card-padding) and var(--grn-card-radius), these variables will dynamically adjust based on the card width and apply the corresponding values from card patterns.


    () => {
      const [isOpen, setIsOpen] = useState(false);
      return (
        <>
          <Button onClick={() => setIsOpen(true)}>Open Modal</Button>
          <Modal
            isOpen={isOpen}
            onClose={() => setIsOpen(false)}
            cardPadding="var(--grn-card-padding)"
            cardRadius="var(--grn-card-radius)"
            cardMaxWidth="wide"
            title="Resize the window and check the padding and radius"
            description={demoText.xl}
          />
        </>
      )
    }
  

Card max width


    () => {
      const [isOpen, setIsOpen] = useState(false);
      const [activeWidth, setActiveWidth] = useState('narrow');
      return (
        <>
          <Arrange gap="s">
            {['narrow', 'medium', 'wide'].map((width) => (
              <Button
                key={width}
                onClick={() => {
                  setActiveWidth(width)
                  setIsOpen(true)
                }}
              >
                {width}
              </Button>
            ))}
          </Arrange>
          <Modal
            isOpen={isOpen}
            onClose={() => setIsOpen(false)}
            cardPadding="var(--grn-card-padding)"
            cardRadius="var(--grn-card-radius)"
            cardMaxWidth={activeWidth}
            title={activeWidth}
            description={demoText.xl}
          />
        </>
      )
    }


Examples

Large content


    () => {
      const [isOpen, setIsOpen] = useState(false);
      return (
        <>
          <Button onClick={() => setIsOpen(true)}>Open Modal</Button>
          <Modal
            isOpen={isOpen}
            onClose={() => setIsOpen(false)}
          >
            {[...demoFilms, ...demoFilms].map((film, index) => (
              <Text size="l" key={index}>{film}</Text>
            ))}
          </Modal>
        </>
      )
    }
  

Content with scrollable sections


    () => {
      const [isOpen, setIsOpen] = useState(false);
      return (
        <>
          <Button onClick={() => setIsOpen(true)}>Open Modal</Button>
          <Modal
            isOpen={isOpen}
            onClose={() => setIsOpen(false)}
            cardMaxWidth="wide"
            cardPadding="0"
          >
            <Arrange autoFlow="row" rows="auto auto" justifyContent="stretch" height="80vh">
              <Box padding="xl" overflow="auto" maxHeight="100%">
                {[...demoFilms, ...demoFilms].map((film, index) => (
                  <Text size="l" key={index}>{film}</Text>
                ))}
              </Box>
              <Arrange justifyContent="space-between" padding="xl" borderSide="top">
                <Button>Action</Button>
                <Button variant="accent">Action</Button>
              </Arrange>
            </Arrange>
          </Modal>
        </>
      )
    }
  

Sticky title


    () => {
      const [isOpen, setIsOpen] = useState(false);
      return (
        <>
          <Button onClick={() => setIsOpen(true)}>Open Modal</Button>
          <Modal
            isOpen={isOpen}
            onClose={() => setIsOpen(false)}
            cardPadding="0" 
          >
            <Box
              position="sticky"
              top="0"
              backgroundColor="floatingBackground"
              paddingX="xl"
              paddingTop="xl"
              paddingBottom="m"
            >
              <Modal.Title>
                Sticky title
              </Modal.Title>
            </Box>
            <Box paddingX="xl" paddingBottom="xl">
              {[...demoFilms, ...demoFilms].map((film, index) => (
                <Text size="l" key={index}>{film}</Text>
              ))}
            </Box>
          </Modal>
        </>
      )
    }
  

Full screen


    () => {
      const [isOpen, setIsOpen] = useState(false);
      return (
        <>
          <Button onClick={() => setIsOpen(true)}>Open Modal</Button>
          <Modal
            isOpen={isOpen}
            onClose={() => setIsOpen(false)}
            paddingX="0"
            cardPadding="xl"
            cardRadius="0"
            cardMaxWidth="100%"
            cardHeight="100vh"
            cardMaxHeight="unset"
          >
            <Stack gap="m">
              <Text>
                {demoText.xl}
              </Text>
              <Button
                onClick={() => setIsOpen(false)}
                variant="accent"
              >
                Close
              </Button>
            </Stack>
          </Modal>
        </>
      )
    }
  

Props

Name
Type
Default
paddingX
oneOfType
number
string
'l'
cardPadding
oneOfType
number
string
'xl'
cardRadius
oneOfType
oneOf
"xs" "s" "m" "l"
string
number
'l'
cardMaxWidth
oneOfType
number
string
oneOf
'narrow' 'medium' 'wide'
68
cardMaxHeight
oneOfType
number
string
'90vh'
zIndex
oneOfType
number
string
1099
hasCloseButton
bool
true
disableCloseHandler
bool
false
isOpen
bool
children
node
onClose
func
title
oneOfType
string
node
description
oneOfType
string
node
cardHeight
oneOfType
number
string
cardTop
oneOfType
oneOf
"xs" "s" "s2" "m" "l" "l2" "xl" "xl2" "xxl"
number
string
initialFocus
node
returnFocus
node
closeButtonProps
object