const SelectableButton = ({ selected, ...props }) => {
  const [colorMode] = useColorMode();
  const { colors } = useTheme();
  const focusColor = colors['blue:60'];
  let _selectedColor = {
    dark: 'blue:60',
    light: 'blue:60',
  }[colorMode];
  _selectedColor = colors[_selectedColor];
  const getSelectedProps = {
    bg: _selectedColor,
    borderColor: _selectedColor,
    color: 'white:emphasis',
    cursor: 'default',
    pointerEvents: 'none',
    zIndex: 1,
    css: {
      '&::before': {
        backgroundColor: _selectedColor,
      },
      '&:focus': {
        ':not(:active)': {
          borderColor: focusColor,
          boxShadow: `inset 0 0 0 1px ${focusColor}`,
        },
        '&::before': {
          backgroundColor: focusColor,
        },
      }
    },
    _hover: {
      bg: _selectedColor,
    },
    _active: {
      bg: _selectedColor,
    },
  };
  return (
    <Button
      {...(selected && getSelectedProps)}
      {...props}
    />
  );
};
const useSelection = (defaultValue) => {
  const [value, setValue] = React.useState(defaultValue);
  const changeBy = (value) => () => setValue(value);
  return [value, changeBy];
};
const useToggle = (defaultValue) => {
  const [value, setValue] = React.useState(defaultValue);
  const toggle = () => setValue(value => !value);
  return [value, toggle, setValue];
};
const Divider = (props) => {
  const [colorMode] = useColorMode();
  const dividerColor = {
    dark: 'white:secondary',
    light: 'black:secondary',
  }[colorMode];
  return (
    <Box mb="4x" pb="4x" borderBottom={1} borderBottomColor={dividerColor} {...props} />
  );
};
const FormGroup = (props) => (
  <Box mb="4x">
    <Flex display="inline-flex" {...props} />
  </Box>
);
function Example() {
  const initialFocusRef = React.useRef();
  const [colorMode] = useColorMode();
  const iconColor = {
    dark: 'white:tertiary',
    light: 'black:tertiary',
  }[colorMode];
  const { isOpen, onOpen, onClose } = useDisclosure();
  const [placement, changePlacementBy] = useSelection('right');
  const [ensureFocus, toggleEnsureFocus] = useToggle(true);
  const [autoFocus, toggleAutoFocus] = useToggle(true);
  const [backdrop, toggleBackdrop] = useToggle(true);
  const [closeOnEsc, toggleCloseOnEsc] = useToggle(true);
  const [closeOnOutsideClick, toggleCloseOnOutsideClick, setCloseOnOutsideClick] = useToggle(true);
  const [isClosable, toggleIsClosable] = useToggle(true);
  const [isOverlayVisible, toggleIsOverlayVisible, setIsOverlayVisible] = useToggle(true);
  const [isHeaderVisible, toggleIsHeaderVisible] = useToggle(true);
  const [isBodyVisible, toggleIsBodyVisible] = useToggle(true);
  const [isFooterVisible, toggleIsFooterVisible] = useToggle(true);
  const [isAlertVisible, toggleIsAlertVisible] = useToggle(true);
  const [size, changeSizeBy] = useSelection('sm');
  return (
    <>
      <Box>
        <Button onClick={onOpen}>
          Launch drawer
        </Button>
      </Box>
      <Divider />
      <FormGroup>
        <ButtonGroup
          variant="secondary"
          css={{
            '> *:not(:first-of-type)': {
              marginLeft: -1
            }
          }}
        >
          {['left', 'right'].map(value => (
            <SelectableButton
              key={value}
              selected={value === placement} 
              onClick={changePlacementBy(value)}
              minWidth="15x"
            >
              {value}
            </SelectableButton>
          ))}
        </ButtonGroup>
      </FormGroup>
      <FormGroup>
        <ButtonGroup
          variant="secondary"
          css={{
            '> *:not(:first-of-type)': {
              marginLeft: -1
            }
          }}
        >
          {['auto', 'sm', 'md', 'lg', 'full'].map(value => (
            <SelectableButton
              key={value}
              selected={value === size}
              onClick={changeSizeBy(value)}
              minWidth="15x"
            >
              {value}
            </SelectableButton>
          ))}
        </ButtonGroup>
      </FormGroup>
      <FormGroup>
        <TextLabel display="flex" alignItems="center">
          <Checkbox
            checked={ensureFocus}
            onChange={toggleEnsureFocus}
          />
          <Space width="2x" />
          <Text fontFamily="mono" whiteSpace="nowrap">ensureFocus</Text>
        </TextLabel>
      </FormGroup>
      <FormGroup>
        <TextLabel display="flex" alignItems="center">
          <Checkbox
            checked={autoFocus}
            disabled={!ensureFocus}
            onChange={toggleAutoFocus}
          />
          <Space width="2x" />
          <Text fontFamily="mono" whiteSpace="nowrap">autoFocus</Text>
        </TextLabel>
      </FormGroup>
      <FormGroup>
        <TextLabel display="flex" alignItems="center">
          <Checkbox
            checked={backdrop}
            onChange={(e) => {
              const nextBackdrop = !backdrop;
              if (!nextBackdrop) {
                setCloseOnOutsideClick(false);
                setIsOverlayVisible(false);
              }
              toggleBackdrop(e);
            }}
          />
          <Space width="2x" />
          <Text fontFamily="mono" whiteSpace="nowrap">backdrop</Text>
        </TextLabel>
      </FormGroup>
      <FormGroup>
        <TextLabel display="flex" alignItems="center">
          <Checkbox
            checked={isClosable}
            disabled={!closeOnEsc && !closeOnOutsideClick}
            onChange={toggleIsClosable}
          />
          <Space width="2x" />
          <Text fontFamily="mono" whiteSpace="nowrap">isClosable</Text>
        </TextLabel>
      </FormGroup>
      <FormGroup>
        <TextLabel display="flex" alignItems="center">
          <Checkbox
            checked={closeOnEsc}
            disabled={!isClosable && !closeOnOutsideClick}
            onChange={toggleCloseOnEsc}
          />
          <Space width="2x" />
          <Text fontFamily="mono" whiteSpace="nowrap">closeOnEsc</Text>
        </TextLabel>
      </FormGroup>
      <FormGroup>
        <TextLabel display="flex" alignItems="center">
          <Checkbox
            checked={closeOnOutsideClick}
            disabled={(!isClosable && !closeOnEsc) || !backdrop}
            onChange={toggleCloseOnOutsideClick}
          />
          <Space width="2x" />
          <Text fontFamily="mono" whiteSpace="nowrap">closeOnOutsideClick</Text>
        </TextLabel>
      </FormGroup>
      <FormGroup>
        <TextLabel display="flex" alignItems="center">
          <Checkbox
            checked={isOverlayVisible}
            disabled={!backdrop}
            onChange={toggleIsOverlayVisible}
          />
          <Space width="2x" />
          <Text fontFamily="mono" whiteSpace="nowrap">DrawerOverlay</Text>
        </TextLabel>
      </FormGroup>
      <FormGroup>
        <TextLabel display="flex" alignItems="center">
          <Checkbox checked={isHeaderVisible} onChange={toggleIsHeaderVisible} />
          <Space width="2x" />
          <Text fontFamily="mono" whiteSpace="nowrap">DrawerHeader</Text>
        </TextLabel>
      </FormGroup>
      <FormGroup>
        <TextLabel display="flex" alignItems="center">
          <Checkbox checked={isBodyVisible} onChange={toggleIsBodyVisible} />
          <Space width="2x" />
          <Text fontFamily="mono" whiteSpace="nowrap">DrawerBody</Text>
        </TextLabel>
      </FormGroup>
      <FormGroup>
        <TextLabel display="flex" alignItems="center">
          <Checkbox checked={isFooterVisible} onChange={toggleIsFooterVisible} />
          <Space width="2x" />
          <Text fontFamily="mono" whiteSpace="nowrap">DrawerFooter</Text>
        </TextLabel>
      </FormGroup>
      <FormGroup>
        <TextLabel display="flex" alignItems="center">
          <Checkbox checked={isAlertVisible} onChange={toggleIsAlertVisible} />
          <Space width="2x" />
          <Text fontFamily="mono" whiteSpace="nowrap">Alert</Text>
        </TextLabel>
      </FormGroup>
      <Slide
        in={isOpen}
        duration={250}
        from={placement}
        finalHeight="100vh"
      >
        {styles => (
          <Drawer
            ensureFocus={ensureFocus}
            autoFocus={autoFocus}
            backdrop={backdrop}
            initialFocusRef={initialFocusRef}
            isClosable={isClosable}
            isOpen={true} 
            closeOnEsc={closeOnEsc}
            closeOnOutsideClick={closeOnOutsideClick}
            onClose={onClose}
            placement={placement}
            size={size}
          >
            {isOverlayVisible && (
              <DrawerOverlay opacity={styles.opacity} />
            )}
            <DrawerContent {...styles}>
              {isHeaderVisible && (
                <DrawerHeader>
                  Drawer Title
                </DrawerHeader>
              )}
              {isBodyVisible && (
                <DrawerBody>
                  {isAlertVisible && (
                    <Alert variant="outline" severity="info" mb="4x" isClosable onClose={() => toggleIsAlertVisible()}>
                      <Text>This is an info alert</Text>
                    </Alert>
                  )}
                  <Text mb="4x">
                    You can put any elements you want here.
                  </Text>
                  <Grid
                    templateColumns="auto 1fr"
                    rowGap="2x"
                    columnGap="3x"
                    alignItems="center"
                  >
                    <Icon icon="user" color={iconColor} />
                    <Input ref={initialFocusRef} placeholder="User name" />
                    <Icon icon="email" color={iconColor} />
                    <Input placeholder="Email address" />
                  </Grid>
                </DrawerBody>
              )}
              {isFooterVisible && (
                <DrawerFooter>
                  <Button variant="primary" onClick={onClose} minWidth="20x">
                    OK
                  </Button>
                  <Space width="2x" />
                  <Button onClick={onClose} minWidth="20x">
                    Cancel
                  </Button>
                </DrawerFooter>
              )}
            </DrawerContent>
          </Drawer>
        )}
      </Slide>
    </>
  );
}
render(<Example />);