aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2022-02-24 12:32:02 +0100
committerLibravatar Kristóf Marussy <kristof@marussy.com>2022-03-06 18:56:46 +0100
commitac1b8fbf529ee2d95b4c9aecb47b07d77400bd0b (patch)
tree0e0059b44916c08b10f3a27f1de6dad39a6fb3ad
parentfix: Stop spinner after in-page navigation (diff)
downloadsophie-ac1b8fbf529ee2d95b4c9aecb47b07d77400bd0b.tar.gz
sophie-ac1b8fbf529ee2d95b4c9aecb47b07d77400bd0b.tar.zst
sophie-ac1b8fbf529ee2d95b4c9aecb47b07d77400bd0b.zip
design: Simpler message count indicators
Signed-off-by: Kristóf Marussy <kristof@marussy.com>
-rw-r--r--packages/renderer/src/components/sidebar/ServiceIcon.tsx78
1 files changed, 30 insertions, 48 deletions
diff --git a/packages/renderer/src/components/sidebar/ServiceIcon.tsx b/packages/renderer/src/components/sidebar/ServiceIcon.tsx
index 83b2a5f..144f860 100644
--- a/packages/renderer/src/components/sidebar/ServiceIcon.tsx
+++ b/packages/renderer/src/components/sidebar/ServiceIcon.tsx
@@ -22,7 +22,7 @@ import Badge from '@mui/material/Badge';
22import { styled, useTheme } from '@mui/material/styles'; 22import { styled, useTheme } from '@mui/material/styles';
23import { Service } from '@sophie/shared'; 23import { Service } from '@sophie/shared';
24import { observer } from 'mobx-react-lite'; 24import { observer } from 'mobx-react-lite';
25import React from 'react'; 25import React, { useEffect, useState } from 'react';
26 26
27const ServiceIconRoot = styled('div', { 27const ServiceIconRoot = styled('div', {
28 name: 'ServiceIcon', 28 name: 'ServiceIcon',
@@ -47,39 +47,15 @@ const ServiceIconText = styled('div', {
47 color: theme.palette.primary.contrastText, 47 color: theme.palette.primary.contrastText,
48})); 48}));
49 49
50const IndirectMessageBadge = styled(Badge)(({ theme }) => ({ 50const ServiceIconBadge = styled(Badge, {
51 '& .MuiBadge-dot': { 51 name: 'ServiceIcon',
52 // The indirect message badge floats ouside the icon in the middle. 52 slot: 'Badge',
53 top: '50%', 53})(({ theme }) => ({
54 ...(theme.direction === 'ltr' 54 '.MuiBadge-dot': {
55 ? {
56 left: theme.spacing(-1),
57 }
58 : {
59 right: theme.spacing(-1),
60 }),
61 background: 55 background:
62 theme.palette.mode === 'dark' 56 theme.palette.mode === 'dark'
63 ? theme.palette.text.primary 57 ? theme.palette.text.primary
64 : 'currentColor', 58 : theme.palette.primary.light,
65 },
66}));
67
68const DirectMessageBadge = styled(Badge)(({ theme }) => ({
69 '& .MuiBadge-badge': {
70 // Move the badge closer to the icon so that even "99+" messages can fit in the sidebar.
71 ...(theme.direction === 'ltr'
72 ? {
73 right: theme.spacing(0.25),
74 }
75 : {
76 left: theme.spacing(0.25),
77 }),
78 top: theme.spacing(0.25),
79 // Set the badge apart from the icon with a shadow (a border would be too heavy).
80 boxShadow: theme.shadows[1],
81 // Add a bit more emphasis to the badge.
82 fontWeight: 700,
83 }, 59 },
84})); 60}));
85 61
@@ -91,28 +67,34 @@ function ServiceIcon({ service }: { service: Service }): JSX.Element {
91 indirectMessageCount, 67 indirectMessageCount,
92 } = service; 68 } = service;
93 69
70 // Hadge color histeresis for smooth appear / disappear animation.
71 // If we compute hasDirectMessage = directMessageCount >= 1 directly (without any histeresis),
72 // the badge momentarily turns light during the disappear animation.
73 const [hasDirectMessage, setHasDirectMessage] = useState(false);
74 useEffect(() => {
75 if (directMessageCount >= 1) {
76 setHasDirectMessage(true);
77 } else if (indirectMessageCount >= 1) {
78 setHasDirectMessage(false);
79 }
80 }, [directMessageCount, indirectMessageCount, setHasDirectMessage]);
81
94 return ( 82 return (
95 <IndirectMessageBadge 83 <ServiceIconBadge
96 badgeContent={indirectMessageCount} 84 badgeContent={
97 variant="dot" 85 hasDirectMessage ? directMessageCount : indirectMessageCount
86 }
87 variant={hasDirectMessage ? 'standard' : 'dot'}
88 color="error"
98 anchorOrigin={{ 89 anchorOrigin={{
99 vertical: 'top', 90 vertical: 'top',
100 horizontal: direction === 'ltr' ? 'left' : 'right', 91 horizontal: direction === 'ltr' ? 'right' : 'left',
101 }} 92 }}
102 > 93 >
103 <DirectMessageBadge 94 <ServiceIconRoot>
104 badgeContent={directMessageCount} 95 <ServiceIconText>{name.length > 0 ? name[0] : '?'}</ServiceIconText>
105 color="error" 96 </ServiceIconRoot>
106 anchorOrigin={{ 97 </ServiceIconBadge>
107 vertical: 'top',
108 horizontal: direction === 'ltr' ? 'right' : 'left',
109 }}
110 >
111 <ServiceIconRoot>
112 <ServiceIconText>{name.length > 0 ? name[0] : '?'}</ServiceIconText>
113 </ServiceIconRoot>
114 </DirectMessageBadge>
115 </IndirectMessageBadge>
116 ); 98 );
117} 99}
118 100