Refactor widget library UI code

This commit is contained in:
2026-08-20 12:51:58 -07:00
parent 2b0300b075
commit 9b1ddf6dcc
2 changed files with 94 additions and 77 deletions
@@ -28,9 +28,10 @@ export function SettingsButton() {
const recipe = useRecipe({key: "glassTab"}); const recipe = useRecipe({key: "glassTab"});
const tabStyles = recipe(); const tabStyles = recipe();
// Pull the glass container styles for the dropdown // Pull the glass container styles for the dropdown and modal
const panelRecipe = useSlotRecipe({key: "glassPanel"}); const panelRecipe = useSlotRecipe({key: "glassPanel"});
const panelStyles = panelRecipe({layout: "dropdown"}); const panelStyles = panelRecipe({layout: "dropdown"});
const modalStyles = panelRecipe({layout: "popover"});
const [isLibraryOpen, setIsLibraryOpen] = useState(false); const [isLibraryOpen, setIsLibraryOpen] = useState(false);
@@ -123,88 +124,104 @@ export function SettingsButton() {
<Move size={16} style={{ marginRight: '8px' }} /> Edit Layout <Move size={16} style={{ marginRight: '8px' }} /> Edit Layout
</Menu.Item> </Menu.Item>
<Menu.Separator my={1} borderColor="glassSeperator" /> <Menu.Separator my={1} borderColor={{base: "gray.200", _dark: "whiteAlpha.200"}}/>
<Menu.Item <Menu.Item
onClick={() => setIsLibraryOpen(true)} onClick={() => setIsLibraryOpen(true)}
cursor="pointer" cursor="pointer"
_hover={{ WebkitTextStroke: "0.5px currentColor" }} _hover={{
bg: {base: "rgba(0, 0, 0, 0.05)", _dark: "rgba(255, 255, 255, 0.1)"},
WebkitTextStroke: "0.5px currentColor"
}}
>
<LayoutGrid size={16} style={{marginRight: '8px'}}/> Widget Library
</Menu.Item>
</Menu.Content>
</Menu.Positioner>
</Menu.Root>
)}
{/* THE WIDGET LIBRARY MODAL (Controlled by isLibraryOpen) */}
<Dialog.Root
open={isLibraryOpen}
onOpenChange={(e) => setIsLibraryOpen(e.open)}
size="xl"
placement="center"
closeOnInteractOutside={true}
closeOnEscapeKeyDown={true}
> >
<LayoutGrid size={16} style={{ marginRight: '8px' }} /> Widget Library {/* Soft blur can be added to the background behind the modal */}
</Menu.Item> {/*<Dialog.Backdrop bg="blackAlpha.100" backdropFilter="blur(2px)"/>*/}
</Menu.Content> <Dialog.Positioner>
</Menu.Positioner>
</Menu.Root>
)}
{/* THE WIDGET LIBRARY MODAL (Controlled by isLibraryOpen) */} <Dialog.Content css={modalStyles.root} overflow="hidden" maxW="800px" minH="800px" p={0}>
<Dialog.Root
open={isLibraryOpen}
onOpenChange={(e) => setIsLibraryOpen(e.open)}
size="xl"
placement="center"
closeOnInteractOutside={true}
closeOnEscapeKeyDown={true}
>
<Dialog.Backdrop bg="blackAlpha.600"/>
<Dialog.Positioner>
<Dialog.Content bg="gray.50" borderRadius="xl" overflow="hidden" boxShadow="xl" maxW="800px">
<Dialog.Header bg="gray.800" color="white" py={4}>
<Dialog.Title fontSize="xl" fontWeight="bold">Add Dashboard Widgets</Dialog.Title>
</Dialog.Header>
<Dialog.Body p={0}> <Dialog.Header bg="transparent" color={{base: "gray.800", _dark: "white"}} py={4}
<Tabs.Root defaultValue={categories[0]} variant="enclosed" colorScheme="blue"> borderColor={{base: "gray.200", _dark: "whiteAlpha.200"}}>
<Tabs.List bg="white" px={4} pt={4} borderBottom="1px solid" borderColor="gray.200"> <Dialog.Title fontSize="xl" fontWeight="bold">Widgets Shop</Dialog.Title>
{categories.map(cat => ( </Dialog.Header>
<Tabs.Trigger key={cat} value={cat} pb={2}>{cat}</Tabs.Trigger>
))}
</Tabs.List>
{categories.map(cat => ( <Dialog.Body p={0}>
<Tabs.Content key={cat} value={cat} p={6}> <Tabs.Root defaultValue={categories[0]} variant="enclosed" colorScheme="blue">
<Grid templateColumns="repeat(auto-fill, minmax(300px, 1fr))" gap={4}> <Tabs.List bg="transparent" px={4} pt={4}
{categorizedWidgets[cat].map(widget => ( borderColor={{base: "gray.200", _dark: "whiteAlpha.200"}}>
<Flex key={widget.id} direction="column" bg="white" p={4} borderRadius="md" border="1px solid" {categories.map(cat => (
borderColor="gray.200" boxShadow="sm"> <Tabs.Trigger key={cat} value={cat} pb={2}
<Text fontWeight="bold" fontSize="md" mb={1}>{widget.name}</Text> _selected={{color: "blue.500", borderColor: "blue.500"}}>{cat}</Tabs.Trigger>
<Text fontSize="sm" color="gray.500" mb={4} flex="1">{widget.description}</Text> ))}
</Tabs.List>
<Box borderTop="1px solid" borderColor="gray.100" pt={3}> {categories.map(cat => (
<Text fontSize="xs" fontWeight="bold" color="gray.400" textTransform="uppercase" mb={2}>Add <Tabs.Content key={cat} value={cat} p={6}>
to Grid:</Text> <Grid templateColumns="repeat(auto-fill, minmax(300px, 1fr))" gap={4}>
<HStack gap={2} flexWrap="wrap"> {categorizedWidgets[cat].map(widget => (
{Object.keys(widget.allowedSizes).map(sizeKey => ( <Flex
<Badge key={widget.id}
key={sizeKey} direction="column"
as="button" bg={{base: "rgba(255, 255, 255, 0.6)", _dark: "rgba(0, 0, 0, 0.2)"}}
onClick={() => handleAddWidget(widget.id, sizeKey)} p={4}
colorScheme="gray" borderRadius="xl"
variant="subtle" border="1px solid"
px={3} borderColor={{base: "rgba(255, 255, 255, 0.9)", _dark: "whiteAlpha.200"}}
py={1} boxShadow="sm"
borderRadius="full"
cursor="pointer"
_hover={{bg: "blue.50", color: "blue.600", transform: "scale(1.05)"}}
transition="all 0.2s"
> >
<Plus size={12} style={{display: 'inline', marginRight: '4px'}}/> <Text fontWeight="bold" fontSize="md" mb={1}>{widget.name}</Text>
{sizeKey.charAt(0).toUpperCase() + sizeKey.slice(1)} <Text fontSize="sm" color="gray.500" mb={4} flex="1">{widget.description}</Text>
</Badge>
<Box borderTop="1px solid" borderColor={{base: "gray.200", _dark: "whiteAlpha.200"}}
pt={3}>
<Text fontSize="xs" fontWeight="bold" color="gray.400" textTransform="uppercase"
mb={2}>
Add to Grid:
</Text>
<HStack gap={2} flexWrap="wrap">
{Object.keys(widget.allowedSizes).map(sizeKey => (
<Box
key={sizeKey}
as="button"
css={tabStyles}
onClick={() => handleAddWidget(widget.id, sizeKey)}
color={{base: "blue.600", _dark: "blue.300"}}
>
<Plus size={16} style={{flexShrink: 0}}/>
<Box as="span">{sizeKey.charAt(0).toUpperCase() + sizeKey.slice(1)}</Box>
</Box>
))}
</HStack>
</Box>
</Flex>
))} ))}
</HStack> </Grid>
</Box> </Tabs.Content>
</Flex> ))}
))} </Tabs.Root>
</Grid> </Dialog.Body>
</Tabs.Content> <Dialog.CloseTrigger position="absolute" top={3} right={3}
))} color={{base: "gray.500", _dark: "whiteAlpha.800"}}
</Tabs.Root> _hover={{color: "red.400"}}/>
</Dialog.Body> </Dialog.Content>
<Dialog.CloseTrigger position="absolute" top={3} right={3} color="white"/> </Dialog.Positioner>
</Dialog.Content> </Dialog.Root>
</Dialog.Positioner>
</Dialog.Root>
</> </>
); );
} }
+2 -2
View File
@@ -220,8 +220,8 @@ const glassPanelRecipe = defineSlotRecipe({
bg: { base: "rgba(255, 255, 255, 0.75)", _dark: "rgba(20, 22, 25, 0.8)" }, bg: { base: "rgba(255, 255, 255, 0.75)", _dark: "rgba(20, 22, 25, 0.8)" },
// OVERRIDES: Increase the blur just to smooth out any stubborn gridlines // OVERRIDES: Increase the blur just to smooth out any stubborn gridlines
backdropFilter: "blur(20px)", backdropFilter: "blur(15px)",
WebkitBackdropFilter: "blur(20px)", WebkitBackdropFilter: "blur(15px)",
} }
} }
} }