Skip to content

Commit 2912ef9

Browse files
author
CheFu Inc
committed
feat: polish Flow mail compose and reader
1 parent c241ee8 commit 2912ef9

4 files changed

Lines changed: 674 additions & 70 deletions

File tree

src/app/icon.svg

Lines changed: 27 additions & 0 deletions
Loading

src/app/layout.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ export const metadata: Metadata = {
1717
title: "Flow",
1818
description:
1919
"CheFu Inc's email ecosystem.",
20+
icons: {
21+
icon: "/icon.svg",
22+
shortcut: "/icon.svg",
23+
},
2024
};
2125

2226
export default function RootLayout({

src/components/FlowConsole.module.css

Lines changed: 294 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
.readerIconButton,
2929
.composeIconButton,
3030
.searchAction,
31+
.accountButton,
3132
.rowStar {
33+
position: relative;
3234
display: inline-grid;
3335
place-items: center;
3436
border: 0;
@@ -47,10 +49,58 @@
4749
.readerIconButton:hover,
4850
.composeIconButton:hover,
4951
.searchAction:hover,
52+
.accountButton:hover,
5053
.rowStar:hover {
5154
background: #e8eaed;
5255
}
5356

57+
.iconButton[data-tooltip]::after,
58+
.toolbarButton[data-tooltip]::after,
59+
.readerIconButton[data-tooltip]::after,
60+
.composeIconButton[data-tooltip]::after,
61+
.searchAction[data-tooltip]::after,
62+
.accountButton[data-tooltip]::after,
63+
.rowStar[data-tooltip]::after {
64+
position: absolute;
65+
top: calc(100% + 8px);
66+
left: 50%;
67+
z-index: 70;
68+
max-width: 180px;
69+
transform: translateX(-50%) translateY(-2px);
70+
border-radius: 4px;
71+
background: rgba(32, 33, 36, 0.94);
72+
color: #ffffff;
73+
content: attr(data-tooltip);
74+
font-size: 12px;
75+
font-weight: 500;
76+
line-height: 1;
77+
opacity: 0;
78+
padding: 7px 9px;
79+
pointer-events: none;
80+
transition:
81+
opacity 0.12s ease,
82+
transform 0.12s ease;
83+
white-space: nowrap;
84+
}
85+
86+
.iconButton[data-tooltip]:hover::after,
87+
.toolbarButton[data-tooltip]:hover::after,
88+
.readerIconButton[data-tooltip]:hover::after,
89+
.composeIconButton[data-tooltip]:hover::after,
90+
.searchAction[data-tooltip]:hover::after,
91+
.accountButton[data-tooltip]:hover::after,
92+
.rowStar[data-tooltip]:hover::after,
93+
.iconButton[data-tooltip]:focus-visible::after,
94+
.toolbarButton[data-tooltip]:focus-visible::after,
95+
.readerIconButton[data-tooltip]:focus-visible::after,
96+
.composeIconButton[data-tooltip]:focus-visible::after,
97+
.searchAction[data-tooltip]:focus-visible::after,
98+
.accountButton[data-tooltip]:focus-visible::after,
99+
.rowStar[data-tooltip]:focus-visible::after {
100+
opacity: 1;
101+
transform: translateX(-50%) translateY(0);
102+
}
103+
54104
.brand {
55105
display: flex;
56106
min-width: 0;
@@ -274,6 +324,46 @@
274324
padding: 8px 8px 16px;
275325
}
276326

327+
.sidebar,
328+
.messageList,
329+
.reader,
330+
.composeBody {
331+
scrollbar-color: #7dd3c7 transparent;
332+
scrollbar-width: thin;
333+
}
334+
335+
.sidebar::-webkit-scrollbar,
336+
.messageList::-webkit-scrollbar,
337+
.reader::-webkit-scrollbar,
338+
.composeBody::-webkit-scrollbar {
339+
width: 8px;
340+
}
341+
342+
.sidebar::-webkit-scrollbar-track,
343+
.messageList::-webkit-scrollbar-track,
344+
.reader::-webkit-scrollbar-track,
345+
.composeBody::-webkit-scrollbar-track {
346+
background: transparent;
347+
}
348+
349+
.sidebar::-webkit-scrollbar-thumb,
350+
.messageList::-webkit-scrollbar-thumb,
351+
.reader::-webkit-scrollbar-thumb,
352+
.composeBody::-webkit-scrollbar-thumb {
353+
border: 2px solid transparent;
354+
border-radius: 999px;
355+
background: #7dd3c7;
356+
background-clip: content-box;
357+
}
358+
359+
.sidebar::-webkit-scrollbar-thumb:hover,
360+
.messageList::-webkit-scrollbar-thumb:hover,
361+
.reader::-webkit-scrollbar-thumb:hover,
362+
.composeBody::-webkit-scrollbar-thumb:hover {
363+
background: #14b8a6;
364+
background-clip: content-box;
365+
}
366+
277367
.composeButton {
278368
display: inline-flex;
279369
min-width: 140px;
@@ -697,6 +787,116 @@
697787
white-space: pre-line;
698788
}
699789

790+
.reactionRow {
791+
display: flex;
792+
flex-wrap: wrap;
793+
gap: 8px;
794+
margin-top: 18px;
795+
}
796+
797+
.reactionChip {
798+
display: inline-flex;
799+
min-height: 34px;
800+
align-items: center;
801+
gap: 5px;
802+
border: 1px solid #dadce0;
803+
border-radius: 999px;
804+
background: #ffffff;
805+
color: #202124;
806+
font-size: 16px;
807+
line-height: 1;
808+
padding: 5px 11px;
809+
}
810+
811+
.reactionChip strong {
812+
color: #0f766e;
813+
font-size: 13px;
814+
font-weight: 700;
815+
}
816+
817+
.confirmOverlay {
818+
position: fixed;
819+
inset: 0;
820+
z-index: 60;
821+
display: grid;
822+
place-items: center;
823+
background: rgba(32, 33, 36, 0.36);
824+
padding: 20px;
825+
}
826+
827+
.confirmDialog {
828+
display: grid;
829+
width: min(420px, 100%);
830+
gap: 12px;
831+
border: 1px solid #dadce0;
832+
border-radius: 8px;
833+
background: #ffffff;
834+
box-shadow:
835+
0 8px 10px 1px rgba(60, 64, 67, 0.14),
836+
0 3px 14px 2px rgba(60, 64, 67, 0.12);
837+
padding: 22px;
838+
}
839+
840+
.confirmDialog h2 {
841+
margin: 0;
842+
color: #202124;
843+
font-size: 18px;
844+
font-weight: 600;
845+
}
846+
847+
.confirmDialog p {
848+
margin: 0;
849+
color: #5f6368;
850+
font-size: 14px;
851+
line-height: 1.5;
852+
}
853+
854+
.confirmActions {
855+
display: flex;
856+
justify-content: flex-end;
857+
gap: 10px;
858+
margin-top: 8px;
859+
}
860+
861+
.cancelButton,
862+
.dangerConfirmButton {
863+
display: inline-flex;
864+
min-width: 92px;
865+
height: 36px;
866+
align-items: center;
867+
justify-content: center;
868+
gap: 8px;
869+
border: 0;
870+
border-radius: 18px;
871+
font-size: 14px;
872+
font-weight: 600;
873+
padding: 0 16px;
874+
}
875+
876+
.cancelButton {
877+
background: #f1f3f4;
878+
color: #3c4043;
879+
}
880+
881+
.cancelButton:hover {
882+
background: #e8eaed;
883+
}
884+
885+
.dangerConfirmButton {
886+
background: #c5221f;
887+
color: #ffffff;
888+
}
889+
890+
.dangerConfirmButton:hover {
891+
background: #a50e0e;
892+
}
893+
894+
.cancelButton:disabled,
895+
.dangerConfirmButton:disabled {
896+
cursor: not-allowed;
897+
opacity: 0.62;
898+
}
899+
700900
.composeOverlay {
701901
position: fixed;
702902
inset: 0;
@@ -747,7 +947,7 @@
747947
padding: 9px 0;
748948
}
749949

750-
.composeLine span {
950+
.composeLine > span {
751951
flex: 0 0 auto;
752952
color: #5f6368;
753953
font-size: 14px;
@@ -768,9 +968,83 @@
768968
cursor: pointer;
769969
}
770970

971+
.recipientComposer {
972+
display: grid;
973+
min-width: 0;
974+
flex: 1;
975+
gap: 8px;
976+
}
977+
978+
.recipientInputRow {
979+
display: flex;
980+
min-width: 0;
981+
align-items: center;
982+
gap: 8px;
983+
}
984+
985+
.recipientInputRow input {
986+
min-width: 0;
987+
flex: 1;
988+
}
989+
990+
.addRecipientButton {
991+
height: 30px;
992+
border: 0;
993+
border-radius: 15px;
994+
background: #e6fffb;
995+
color: #0f766e;
996+
font-size: 13px;
997+
font-weight: 700;
998+
padding: 0 14px;
999+
}
1000+
1001+
.addRecipientButton:hover {
1002+
background: #ccfbf1;
1003+
}
1004+
1005+
.addRecipientButton:disabled {
1006+
cursor: not-allowed;
1007+
opacity: 0.45;
1008+
}
1009+
1010+
.recipientChips {
1011+
display: flex;
1012+
min-width: 0;
1013+
flex-wrap: wrap;
1014+
gap: 6px;
1015+
}
1016+
1017+
.recipientChip {
1018+
display: inline-flex;
1019+
max-width: 100%;
1020+
min-width: 0;
1021+
height: 28px;
1022+
align-items: center;
1023+
gap: 6px;
1024+
border: 1px solid #b2dfdb;
1025+
border-radius: 999px;
1026+
background: #f0fdfa;
1027+
color: #0f4f4a;
1028+
font-size: 13px;
1029+
font-weight: 600;
1030+
padding: 0 9px 0 11px;
1031+
}
1032+
1033+
.recipientChip:hover {
1034+
background: #ccfbf1;
1035+
}
1036+
1037+
.recipientChip span {
1038+
min-width: 0;
1039+
overflow: hidden;
1040+
text-overflow: ellipsis;
1041+
white-space: nowrap;
1042+
}
1043+
7711044
.composeBody {
7721045
min-width: 0;
7731046
min-height: 0;
1047+
overflow-y: auto;
7741048
resize: none;
7751049
border: 0;
7761050
color: #202124;
@@ -788,8 +1062,12 @@
7881062
}
7891063

7901064
.sendButton {
1065+
display: inline-flex;
7911066
min-width: 100px;
7921067
height: 36px;
1068+
align-items: center;
1069+
justify-content: center;
1070+
gap: 8px;
7931071
border: 0;
7941072
border-radius: 18px;
7951073
background: #0f766e;
@@ -802,6 +1080,21 @@
8021080
background: #115e59;
8031081
}
8041082

1083+
.sendButton:disabled {
1084+
cursor: wait;
1085+
opacity: 0.72;
1086+
}
1087+
1088+
.spin {
1089+
animation: spin 0.9s linear infinite;
1090+
}
1091+
1092+
@keyframes spin {
1093+
to {
1094+
transform: rotate(360deg);
1095+
}
1096+
}
1097+
8051098
@media (max-width: 920px) {
8061099
.mailShell {
8071100
height: auto;

0 commit comments

Comments
 (0)