diff options
author | Paul Frazee <pfrazee@gmail.com> | 2023-02-22 23:37:14 -0600 |
---|---|---|
committer | Paul Frazee <pfrazee@gmail.com> | 2023-02-22 23:37:14 -0600 |
commit | c5f28376c86478b4c55d9f0910d8d0cb4a1feb06 (patch) | |
tree | 515ba2f63955c484a0aa3ba3238187e52d76d94e | |
parent | 9bfffadd88df5ce524f0516c23b2426f463106ae (diff) | |
download | voidsky-c5f28376c86478b4c55d9f0910d8d0cb4a1feb06.tar.zst |
Rework web shell ui
-rw-r--r-- | src/lib/hooks/useColorSchemeStyle.ts | 6 | ||||
-rw-r--r-- | src/lib/icons.tsx | 26 | ||||
-rw-r--r-- | src/view/com/discover/LiteSuggestedFollows.tsx | 21 | ||||
-rw-r--r-- | src/view/shell/web/DesktopLeftColumn.tsx | 201 | ||||
-rw-r--r-- | src/view/shell/web/DesktopRightColumn.tsx | 43 |
5 files changed, 191 insertions, 106 deletions
diff --git a/src/lib/hooks/useColorSchemeStyle.ts b/src/lib/hooks/useColorSchemeStyle.ts new file mode 100644 index 000000000..61e3d7cc9 --- /dev/null +++ b/src/lib/hooks/useColorSchemeStyle.ts @@ -0,0 +1,6 @@ +import {useColorScheme} from 'react-native' + +export function useColorSchemeStyle(lightStyle: any, darkStyle: any) { + const colorScheme = useColorScheme() + return colorScheme === 'dark' ? darkStyle : lightStyle +} diff --git a/src/lib/icons.tsx b/src/lib/icons.tsx index f400c3f72..931e3c721 100644 --- a/src/lib/icons.tsx +++ b/src/lib/icons.tsx @@ -527,3 +527,29 @@ export function RectTallIcon({ </Svg> ) } +export function ComposeIcon({ + style, + size, + strokeWidth = 1.5, +}: { + style?: StyleProp<TextStyle> + size?: string | number + strokeWidth?: number +}) { + return ( + <Svg + fill="none" + viewBox="0 0 24 24" + strokeWidth={strokeWidth} + stroke="currentColor" + width={size || 24} + height={size || 24} + style={style}> + <Path + strokeLinecap="round" + strokeLinejoin="round" + d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10" + /> + </Svg> + ) +} diff --git a/src/view/com/discover/LiteSuggestedFollows.tsx b/src/view/com/discover/LiteSuggestedFollows.tsx index 5314e691c..d9620f387 100644 --- a/src/view/com/discover/LiteSuggestedFollows.tsx +++ b/src/view/com/discover/LiteSuggestedFollows.tsx @@ -5,7 +5,6 @@ import { TouchableOpacity, View, } from 'react-native' -import LinearGradient from 'react-native-linear-gradient' import {observer} from 'mobx-react-lite' import _omit from 'lodash.omit' import {Link} from '../util/Link' @@ -99,6 +98,7 @@ const User = ({ onPressUnfollow: (item: SuggestedActor) => void }) => { const pal = usePalette('default') + const palInverted = usePalette('inverted') return ( <View style={[styles.actor]}> <View style={styles.actorMeta}> @@ -121,23 +121,19 @@ const User = ({ <View style={styles.actorBtn}> {follow ? ( <TouchableOpacity onPress={() => onPressUnfollow(item)}> - <View style={[styles.btn, styles.secondaryBtn, pal.btn]}> + <View style={[styles.btn, pal.btn]}> <Text type="button" style={pal.text}> Unfollow </Text> </View> </TouchableOpacity> ) : ( - <TouchableOpacity onPress={() => onPressFollow(item)}> - <LinearGradient - colors={[gradients.blueLight.start, gradients.blueLight.end]} - start={{x: 0, y: 0}} - end={{x: 1, y: 1}} - style={[styles.btn, styles.gradientBtn]}> - <Text type="sm-medium" style={s.white}> - Follow - </Text> - </LinearGradient> + <TouchableOpacity + onPress={() => onPressFollow(item)} + style={[styles.btn, palInverted.view]}> + <Text type="sm-medium" style={palInverted.text}> + Follow + </Text> </TouchableOpacity> )} </View> @@ -187,6 +183,7 @@ const styles = StyleSheet.create({ alignItems: 'center', justifyContent: 'center', paddingVertical: 7, + paddingHorizontal: 14, borderRadius: 50, marginLeft: 6, }, diff --git a/src/view/shell/web/DesktopLeftColumn.tsx b/src/view/shell/web/DesktopLeftColumn.tsx index d5fe45e80..819bcba6d 100644 --- a/src/view/shell/web/DesktopLeftColumn.tsx +++ b/src/view/shell/web/DesktopLeftColumn.tsx @@ -1,13 +1,13 @@ import React from 'react' import {Pressable, StyleSheet, TouchableOpacity, View} from 'react-native' import {observer} from 'mobx-react-lite' -import LinearGradient from 'react-native-linear-gradient' import {Link} from '../../com/util/Link' import {Text} from '../../com/util/text/Text' import {UserAvatar} from '../../com/util/UserAvatar' -import {s, colors, gradients} from 'lib/styles' +import {colors} from 'lib/styles' import {useStores} from 'state/index' import {usePalette} from 'lib/hooks/usePalette' +import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle' import { HomeIcon, HomeIconSolid, @@ -15,6 +15,7 @@ import { BellIconSolid, MagnifyingGlassIcon, CogIcon, + ComposeIcon, } from 'lib/icons' interface NavItemProps { @@ -28,15 +29,18 @@ interface NavItemProps { export const NavItem = observer( ({label, count, href, icon, iconFilled, isProfile}: NavItemProps) => { const store = useStores() - const pal = usePalette('default') + const hoverBg = useColorSchemeStyle( + styles.navItemHoverBgLight, + styles.navItemHoverBgDark, + ) const isCurrent = store.nav.tab.current.url === href return ( <Pressable style={state => [ // @ts-ignore Pressable state differs for RNW -prf - state.hovered && {backgroundColor: pal.colors.backgroundLight}, + state.hovered && hoverBg, ]}> - <Link style={styles.navItem} href={href}> + <Link style={[styles.navItem, isCurrent && hoverBg]} href={href}> <View style={[ styles.navItemIconWrapper, @@ -50,8 +54,7 @@ export const NavItem = observer( )} </View> <Text - type={isCurrent ? 'xl-bold' : 'xl'} - style={styles.navItemLabel} + type={isCurrent || isProfile ? 'xl' : 'xl-thin'} numberOfLines={1}> {label} </Text> @@ -63,6 +66,14 @@ export const NavItem = observer( export const DesktopLeftColumn = observer(() => { const store = useStores() + const containerBg = useColorSchemeStyle( + styles.containerBgLight, + styles.containerBgDark, + ) + const hoverBg = useColorSchemeStyle( + styles.navItemHoverBgLight, + styles.navItemHoverBgDark, + ) const pal = usePalette('default') const onPressCompose = () => store.shell.openComposer({}) const avi = ( @@ -70,81 +81,152 @@ export const DesktopLeftColumn = observer(() => { handle={store.me.handle} displayName={store.me.displayName} avatar={store.me.avatar} - size={40} + size={30} /> ) return ( - <View style={[styles.container, pal.border]}> - <NavItem - isProfile - href={`/profile/${store.me.handle}`} - label={store.me.displayName || store.me.handle} - icon={avi} - iconFilled={avi} - /> - <NavItem - href="/" - label="Home" - icon={<HomeIcon />} - iconFilled={<HomeIconSolid />} - /> - <NavItem - href="/search" - label="Search" - icon={<MagnifyingGlassIcon />} - iconFilled={<MagnifyingGlassIcon strokeWidth={4} />} - /> - <NavItem - href="/notifications" - label="Notifications" - count={store.me.notifications.unreadCount} - icon={<BellIcon />} - iconFilled={<BellIconSolid />} - /> - <NavItem - href="/settings" - label="Settings" - icon={<CogIcon strokeWidth={1.5} />} - iconFilled={<CogIcon strokeWidth={2} />} - /> - <TouchableOpacity onPress={onPressCompose}> - <LinearGradient - colors={[gradients.blueLight.start, gradients.blueLight.end]} - start={{x: 0, y: 0}} - end={{x: 1, y: 1}} - style={styles.composeBtn}> - <Text type="xl-medium" style={[s.white, s.textCenter]}> - New Post + <View style={[styles.container, containerBg, pal.border]}> + <View style={styles.main}> + <Link style={styles.logo} href="/"> + <Text type="title-xl">Bluesky</Text> + </Link> + <Link href="/search" style={[pal.view, pal.borderDark, styles.search]}> + <MagnifyingGlassIcon + size={18} + style={[pal.textLight, styles.searchIconWrapper]} + /> + <Text type="md-thin" style={pal.textLight}> + Search </Text> - </LinearGradient> - </TouchableOpacity> + </Link> + <NavItem + href="/" + label="Home" + icon={<HomeIcon size={21} />} + iconFilled={<HomeIconSolid size={21} />} + /> + <NavItem + href="/search" + label="Explore" + icon={<MagnifyingGlassIcon size={21} />} + iconFilled={<MagnifyingGlassIcon strokeWidth={3} size={21} />} + /> + <NavItem + href="/notifications" + label="Notifications" + count={store.me.notifications.unreadCount} + icon={<BellIcon size={21} />} + iconFilled={<BellIconSolid size={21} />} + /> + <NavItem + href="/settings" + label="Settings" + icon={<CogIcon strokeWidth={2} size={21} />} + iconFilled={<CogIcon strokeWidth={2.5} size={21} />} + /> + <View style={[pal.border, styles.separator]} /> + <Pressable + style={state => [ + // @ts-ignore Pressable state differs for RNW -prf + state.hovered && hoverBg, + ]}> + <TouchableOpacity style={styles.navItem} onPress={onPressCompose}> + <View style={styles.navItemIconWrapper}> + <ComposeIcon size={21} /> + </View> + <Text type="xl-thin">New Post</Text> + </TouchableOpacity> + </Pressable> + </View> + <View style={[styles.footer, pal.borderDark]}> + <NavItem + isProfile + href={`/profile/${store.me.handle}`} + label={store.me.displayName || store.me.handle} + icon={avi} + iconFilled={avi} + /> + </View> </View> ) }) const styles = StyleSheet.create({ + containerBgLight: { + backgroundColor: '#f9f9fd', + }, + containerBgDark: { + backgroundColor: '#f9f9fd', // TODO + }, + container: { position: 'absolute', - left: 'calc(50vw - 530px)', - width: '230px', - height: '100%', + left: 0, + width: '300px', + height: '100vh', borderRightWidth: 1, paddingTop: 5, }, + main: { + flex: 1, + paddingHorizontal: 16, + }, + footer: { + borderTopWidth: 1, + paddingHorizontal: 16, + paddingVertical: 8, + }, + separator: { + borderTopWidth: 1, + marginVertical: 12, + marginHorizontal: 8, + }, + + logo: { + paddingTop: 6, + paddingBottom: 12, + }, + + search: { + flexDirection: 'row', + alignItems: 'center', + borderRadius: 8, + paddingVertical: 8, + paddingHorizontal: 6, + marginBottom: 10, + borderWidth: 1, + }, + searchIconWrapper: { + flexDirection: 'row', + width: 30, + justifyContent: 'center', + marginRight: 6, + }, + navItem: { - paddingVertical: 10, - paddingHorizontal: 10, + paddingVertical: 8, + paddingHorizontal: 6, + marginBottom: 2, flexDirection: 'row', alignItems: 'center', + borderRadius: 6, + }, + navItemHoverBgLight: { + backgroundColor: '#ebebf0', + borderRadius: 6, + }, + navItemHoverBgDark: { + backgroundColor: colors.gray2, // TODO + borderRadius: 6, }, navItemIconWrapper: { flexDirection: 'row', width: 30, justifyContent: 'center', - marginRight: 5, + marginRight: 8, }, navItemProfile: { - width: 40, + width: 30, marginRight: 10, }, navItemCount: { @@ -158,9 +240,6 @@ const styles = StyleSheet.create({ paddingHorizontal: 4, borderRadius: 6, }, - navItemLabel: { - fontSize: 19, - }, composeBtn: { marginTop: 20, marginBottom: 10, diff --git a/src/view/shell/web/DesktopRightColumn.tsx b/src/view/shell/web/DesktopRightColumn.tsx index 22acac382..b051e6094 100644 --- a/src/view/shell/web/DesktopRightColumn.tsx +++ b/src/view/shell/web/DesktopRightColumn.tsx @@ -1,25 +1,15 @@ import React from 'react' -import {View, StyleSheet} from 'react-native' -import {Link} from '../../com/util/Link' +import {StyleSheet, View} from 'react-native' import {Text} from '../../com/util/text/Text' -import {usePalette} from 'lib/hooks/usePalette' -import {MagnifyingGlassIcon} from 'lib/icons' import {LiteSuggestedFollows} from '../../com/discover/LiteSuggestedFollows' import {s} from 'lib/styles' +import {useStores} from 'state/index' export const DesktopRightColumn: React.FC = () => { - const pal = usePalette('default') + const store = useStores() return ( - <View style={[styles.container, pal.border]}> - <Link href="/search" style={[pal.btn, styles.searchContainer]}> - <View style={styles.searchIcon}> - <MagnifyingGlassIcon style={pal.textLight} /> - </View> - <Text type="lg" style={pal.textLight}> - Search - </Text> - </Link> - <Text type="xl-bold" style={s.mb10}> + <View style={styles.container}> + <Text type="lg-bold" style={s.mb10}> Suggested Follows </Text> <LiteSuggestedFollows /> @@ -30,23 +20,10 @@ export const DesktopRightColumn: React.FC = () => { const styles = StyleSheet.create({ container: { position: 'absolute', - right: 'calc(50vw - 650px)', - width: '350px', - height: '100%', - borderLeftWidth: 1, - overscrollBehavior: 'auto', - paddingLeft: 30, - paddingTop: 10, - }, - searchContainer: { - flexDirection: 'row', - alignItems: 'center', - paddingHorizontal: 14, - paddingVertical: 10, - borderRadius: 20, - marginBottom: 20, - }, - searchIcon: { - marginRight: 5, + right: 0, + width: '400px', + paddingHorizontal: 16, + paddingRight: 32, + paddingTop: 20, }, }) |