A social knowledge tool for researchers built on ATProto

refactor: unify colour tokens for future dark mode support

Changed files
+60 -38
src
webapp
.storybook
app
(dashboard)
profile
[handle]
(withHeader)
components
navigation
bottomBarItem
header
features
feeds
components
feedActivityStatus
feedItem
profile
components
+2 -2
src/webapp/.storybook/preview.tsx
··· 1 1 import '@mantine/core/styles.css'; 2 2 3 - import React, { useEffect } from 'react'; 4 - import { MantineProvider, useMantineColorScheme } from '@mantine/core'; 3 + import React from 'react'; 4 + import { MantineProvider } from '@mantine/core'; 5 5 import { theme } from '../styles/theme'; 6 6 import { Hanken_Grotesk } from 'next/font/google'; 7 7
+1 -1
src/webapp/app/(dashboard)/profile/[handle]/(withHeader)/layout.tsx
··· 42 42 zIndex: 1, 43 43 }} 44 44 > 45 - <Container bg={'white'} px={'xs'} mt={'md'} size={'xl'}> 45 + <Container px={'xs'} mt={'md'} size={'xl'}> 46 46 <ProfileTabs handle={handle} /> 47 47 </Container> 48 48 </Box>
+1 -1
src/webapp/app/layout.tsx
··· 26 26 {...mantineHtmlProps} 27 27 > 28 28 <head> 29 - <ColorSchemeScript /> 29 + <ColorSchemeScript defaultColorScheme="light" /> 30 30 </head> 31 31 <body className={GlobalStyles.main}> 32 32 <Providers>{children}</Providers>
+8 -2
src/webapp/components/navigation/bottomBarItem/BottomBarItem.tsx
··· 3 3 import { usePathname } from 'next/navigation'; 4 4 import Link from 'next/link'; 5 5 import { ReactElement, isValidElement } from 'react'; 6 + import { useColorScheme } from '@mantine/hooks'; 6 7 7 8 interface Props { 8 9 href: string; ··· 10 11 } 11 12 12 13 export default function BottomBarItem(props: Props) { 14 + const colorScheme = useColorScheme(); 13 15 const pathname = usePathname(); 14 16 const isActive = pathname === props.href; 15 17 ··· 28 30 href={props.href} 29 31 variant={isActive ? 'light' : 'transparent'} 30 32 size={'lg'} 31 - bg={isActive ? 'gray.1' : 'transparent'} 32 - color={isActive ? 'dark' : 'gray'} 33 + bg={ 34 + isActive 35 + ? `${colorScheme === 'dark' ? 'dark.5' : 'gray.1'}` 36 + : 'transparent' 37 + } 38 + color="gray" 33 39 > 34 40 {renderIcon()} 35 41 </ActionIcon>
+3 -3
src/webapp/components/navigation/header/Header.tsx
··· 1 - import { Box, Divider, Group } from '@mantine/core'; 1 + import { Box, Divider, Group, Paper } from '@mantine/core'; 2 2 import NavbarToggle from '../NavbarToggle'; 3 3 import { ReactElement } from 'react'; 4 4 ··· 8 8 9 9 export default function Header(props: Props) { 10 10 return ( 11 - <Box pos={'sticky'} top={0} bg={'white'} style={{ zIndex: 1 }}> 11 + <Paper pos={'sticky'} top={0} style={{ zIndex: 1 }}> 12 12 <Group gap={'xs'} p={'xs'} justify="space-between"> 13 13 {props.children} 14 14 <Box ml={'auto'}> ··· 16 16 </Box> 17 17 </Group> 18 18 <Divider /> 19 - </Box> 19 + </Paper> 20 20 ); 21 21 }
+8 -4
src/webapp/features/feeds/components/feedActivityStatus/FeedActivityStatus.tsx
··· 1 - import { Anchor, Avatar, Group, Paper, Stack, Text } from '@mantine/core'; 1 + 'use client'; 2 + 3 + import { Anchor, Avatar, Card, Group, Paper, Stack, Text } from '@mantine/core'; 2 4 import { FeedItem, Collection } from '@/api-client'; 3 5 import { Fragment } from 'react'; 4 6 import Link from 'next/link'; 5 7 import { getRelativeTime } from '@/lib/utils/time'; 6 8 import { getRecordKey } from '@/lib/utils/atproto'; 7 9 import { sanitizeText } from '@/lib/utils/text'; 10 + import { useColorScheme } from '@mantine/hooks'; 8 11 9 12 interface Props { 10 13 user: FeedItem['user']; ··· 13 16 } 14 17 15 18 export default function FeedActivityStatus(props: Props) { 19 + const colorScheme = useColorScheme(); 16 20 const MAX_DISPLAYED = 2; 17 21 const time = getRelativeTime(props.createdAt.toString()); 18 22 const relativeCreatedDate = time === 'just now' ? `Now` : `${time} ago`; ··· 23 27 const remainingCount = collections.length - MAX_DISPLAYED; 24 28 25 29 return ( 26 - <Text fw={500} c={'gray.7'}> 30 + <Text fw={500} c={colorScheme === 'dark' ? 'gray' : 'gray.7'}> 27 31 <Anchor 28 32 component={Link} 29 33 href={`/profile/${props.user.handle}`} ··· 64 68 }; 65 69 66 70 return ( 67 - <Paper bg={'gray.1'} radius={'lg'}> 71 + <Card p={0} bg={colorScheme === 'dark' ? 'dark.4' : 'gray.1'} radius={'lg'}> 68 72 <Stack gap={'xs'}> 69 73 <Group gap={'xs'} wrap="nowrap" align="center" p={'xs'}> 70 74 <Avatar ··· 76 80 {renderActivityText()} 77 81 </Group> 78 82 </Stack> 79 - </Paper> 83 + </Card> 80 84 ); 81 85 }
+12 -3
src/webapp/features/feeds/components/feedItem/Skeleton.FeedItem.tsx
··· 1 + 'use client'; 2 + 1 3 import UrlCardSkeleton from '@/features/cards/components/urlCard/Skeleton.UrlCard'; 2 - import { Avatar, Group, Paper, Skeleton, Stack } from '@mantine/core'; 4 + import { Avatar, Card, Group, Paper, Skeleton, Stack } from '@mantine/core'; 5 + import { useColorScheme } from '@mantine/hooks'; 3 6 4 7 export default function FeedItemSkeleton() { 8 + const colorScheme = useColorScheme(); 9 + 5 10 return ( 6 11 <Stack gap={'xs'} align="stretch"> 7 12 {/* Feed activity status*/} 8 - <Paper bg={'gray.1'} radius={'lg'}> 13 + <Card 14 + p={0} 15 + bg={colorScheme === 'dark' ? 'dark.4' : 'gray.1'} 16 + radius={'lg'} 17 + > 9 18 <Stack gap={'xs'} align="stretch" w={'100%'}> 10 19 <Group gap={'xs'} wrap="nowrap" align="center" p={'xs'}> 11 20 <Avatar /> ··· 15 24 </Stack> 16 25 </Group> 17 26 </Stack> 18 - </Paper> 27 + </Card> 19 28 20 29 <UrlCardSkeleton /> 21 30 </Stack>
+3 -3
src/webapp/features/profile/components/profileHeader/ProfileHeader.tsx
··· 23 23 const profile = await getProfile(props.handle); 24 24 25 25 return ( 26 - <Container bg={'white'} p={0} size={'xl'}> 26 + <Container p={0} size={'xl'}> 27 27 <MinimalProfileHeaderContainer 28 28 avatarUrl={profile.avatarUrl} 29 29 name={profile.name} ··· 69 69 component="a" 70 70 href={`https://bsky.app/profile/${profile.handle}`} 71 71 target="_blank" 72 + variant="light" 72 73 radius={'xl'} 73 - bg="gray.2" 74 - c={'gray'} 74 + color={'gray'} 75 75 leftSection={<FaBluesky />} 76 76 > 77 77 {truncateText(profile.handle, 14)}
+1 -1
src/webapp/features/profile/components/profileHeader/Skeleton.ProfileHeader.tsx
··· 10 10 11 11 export default function ProfileHeaderSkeleton() { 12 12 return ( 13 - <Container bg={'white'} p={'xs'} size={'xl'}> 13 + <Container p={'xs'} size={'xl'}> 14 14 <Stack gap={'sm'}> 15 15 <Stack gap={'xl'}> 16 16 <Grid gutter={'md'} align={'center'} grow>
+3 -2
src/webapp/features/profile/components/profileMenu/ProfileMenu.tsx
··· 16 16 import { IoMdLogOut } from 'react-icons/io'; 17 17 import { useNavbarContext } from '@/providers/navbar'; 18 18 import { BiSolidUserCircle } from 'react-icons/bi'; 19 + import { useColorScheme } from '@mantine/hooks'; 19 20 20 21 export default function ProfileMenu() { 21 22 const router = useRouter(); 23 + const colorScheme = useColorScheme(); 22 24 const { toggleMobile } = useNavbarContext(); 23 25 const { data, error, isPending } = useMyProfile(); 24 26 const { logout } = useAuth(); ··· 46 48 <Menu.Target> 47 49 <Button 48 50 variant="subtle" 49 - color="gray" 50 - c={'dark'} 51 + color={colorScheme === 'dark' ? 'gray' : 'dark'} 51 52 fz={'md'} 52 53 radius={'md'} 53 54 size="lg"
+18 -16
src/webapp/features/profile/components/profileTabs/ProfileTabs.tsx
··· 1 1 'use client'; 2 2 3 - import { Group, ScrollAreaAutosize, Tabs } from '@mantine/core'; 3 + import { Group, Paper, ScrollAreaAutosize, Tabs } from '@mantine/core'; 4 4 import TabItem from './TabItem'; 5 5 import { usePathname } from 'next/navigation'; 6 6 ··· 16 16 17 17 return ( 18 18 <Tabs value={currentTab}> 19 - <ScrollAreaAutosize type="scroll"> 20 - <Tabs.List> 21 - <Group wrap="nowrap"> 22 - <TabItem value="profile" href={basePath}> 23 - Profile 24 - </TabItem> 25 - <TabItem value="cards" href={`${basePath}/cards`}> 26 - Cards 27 - </TabItem> 28 - <TabItem value="collections" href={`${basePath}/collections`}> 29 - Collections 30 - </TabItem> 31 - </Group> 32 - </Tabs.List> 33 - </ScrollAreaAutosize> 19 + <Paper radius={0}> 20 + <ScrollAreaAutosize type="scroll"> 21 + <Tabs.List> 22 + <Group wrap="nowrap"> 23 + <TabItem value="profile" href={basePath}> 24 + Profile 25 + </TabItem> 26 + <TabItem value="cards" href={`${basePath}/cards`}> 27 + Cards 28 + </TabItem> 29 + <TabItem value="collections" href={`${basePath}/collections`}> 30 + Collections 31 + </TabItem> 32 + </Group> 33 + </Tabs.List> 34 + </ScrollAreaAutosize> 35 + </Paper> 34 36 </Tabs> 35 37 ); 36 38 }