Add popover component

This commit is contained in:
Valtteri Karesto
2022-05-03 14:02:43 +03:00
parent abb7c2bb28
commit 5defd12a11

139
components/Popover.tsx Normal file
View File

@@ -0,0 +1,139 @@
import React, { ReactNode } from "react";
import * as PopoverPrimitive from "@radix-ui/react-popover";
import { styled, keyframes } from "../stitches.config";
const slideUpAndFade = keyframes({
"0%": { opacity: 0, transform: "translateY(2px)" },
"100%": { opacity: 1, transform: "translateY(0)" },
});
const slideRightAndFade = keyframes({
"0%": { opacity: 0, transform: "translateX(-2px)" },
"100%": { opacity: 1, transform: "translateX(0)" },
});
const slideDownAndFade = keyframes({
"0%": { opacity: 0, transform: "translateY(-2px)" },
"100%": { opacity: 1, transform: "translateY(0)" },
});
const slideLeftAndFade = keyframes({
"0%": { opacity: 0, transform: "translateX(2px)" },
"100%": { opacity: 1, transform: "translateX(0)" },
});
const StyledContent = styled(PopoverPrimitive.Content, {
borderRadius: 4,
padding: "$3 $3",
fontSize: 12,
lineHeight: 1,
color: "$text",
boxShadow:
"0px 10px 38px -10px rgba(22, 23, 24, 0.35), 0px 10px 20px -15px rgba(22, 23, 24, 0.2)",
"@media (prefers-reduced-motion: no-preference)": {
animationDuration: "400ms",
animationTimingFunction: "cubic-bezier(0.16, 1, 0.3, 1)",
willChange: "transform, opacity",
'&[data-state="open"]': {
'&[data-side="top"]': { animationName: slideDownAndFade },
'&[data-side="right"]': { animationName: slideLeftAndFade },
'&[data-side="bottom"]': { animationName: slideUpAndFade },
'&[data-side="left"]': { animationName: slideRightAndFade },
},
},
".dark &": {
backgroundColor: "$mauve5",
boxShadow:
"0px 10px 38px -10px rgba(22, 23, 24, 0.85), 0px 10px 20px -15px rgba(22, 23, 24, 0.6)",
},
});
const StyledArrow = styled(PopoverPrimitive.Arrow, {
fill: "$colors$mauve2",
".dark &": {
fill: "$mauve5",
},
});
const StyledClose = styled(PopoverPrimitive.Close, {
all: "unset",
fontFamily: "inherit",
borderRadius: "100%",
height: 25,
width: 25,
display: "inline-flex",
alignItems: "center",
justifyContent: "center",
color: "$text",
position: "absolute",
top: 5,
right: 5,
});
// Exports
export const PopoverRoot = PopoverPrimitive.Root;
export const PopoverTrigger = PopoverPrimitive.Trigger;
export const PopoverContent = StyledContent;
export const PopoverArrow = StyledArrow;
export const PopoverClose = StyledClose;
// const PopoverDemo = () => (
// <Popover>
// <PopoverContent sideOffset={5}>
// <Flex css={{ flexDirection: "column", gap: 10 }}>
// <Text bold css={{ marginBottom: 10 }}>
// Dimensions
// </Text>
// <Fieldset>
// <Label htmlFor="width">Width</Label>
// <Input id="width" defaultValue="100%" />
// </Fieldset>
// <Fieldset>
// <Label htmlFor="maxWidth">Max. width</Label>
// <Input id="maxWidth" defaultValue="300px" />
// </Fieldset>
// <Fieldset>
// <Label htmlFor="height">Height</Label>
// <Input id="height" defaultValue="25px" />
// </Fieldset>
// <Fieldset>
// <Label htmlFor="maxHeight">Max. height</Label>
// <Input id="maxHeight" defaultValue="none" />
// </Fieldset>
// </Flex>
// <PopoverArrow />
// <PopoverClose aria-label="Close">
// <Cross2Icon />
// </PopoverClose>
// </PopoverContent>
// </Popover>
// );
// export default PopoverDemo;
interface IPopover {
content: string | ReactNode;
open?: boolean;
defaultOpen?: boolean;
onOpenChange?: (open: boolean) => void;
}
const Popover: React.FC<IPopover> = ({
children,
content,
open,
defaultOpen = false,
onOpenChange,
}) => (
<PopoverRoot
open={open}
defaultOpen={defaultOpen}
onOpenChange={onOpenChange}
>
<PopoverTrigger asChild>{children}</PopoverTrigger>
<PopoverContent sideOffset={5}>
{content} <PopoverArrow />
</PopoverContent>
</PopoverRoot>
);
export default Popover;