New styles for various empty states

This commit is contained in:
Fedor Indutny 2024-08-13 16:34:42 -07:00 committed by GitHub
parent 74b90a5cdd
commit d70aa55a78
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 295 additions and 95 deletions

View file

@ -5257,11 +5257,19 @@
},
"icu:emptyInboxMessage": {
"messageformat": "Click the {composeIcon} above and search for your contacts or groups to message.",
"description": "Shown in the left-pane when the inbox is empty"
"description": "(Deleted 2024/08/05) Shown in the left-pane when the inbox is empty"
},
"icu:composeIcon": {
"messageformat": "compose button",
"description": "Shown in the left-pane when the inbox is empty. Describes the button that composes a new message."
"description": "(Deleted 2024/08/05) Shown in the left-pane when the inbox is empty. Describes the button that composes a new message."
},
"icu:emptyInbox__title": {
"messageformat": "No chats",
"description": "Shown as a title in the left-pane when the inbox is empty"
},
"icu:emptyInbox__subtitle": {
"messageformat": "Recent chats will appear here.",
"description": "Shown as a subtitle in the left-pane when the inbox is empty"
},
"icu:ForwardMessageModal__title": {
"messageformat": "Forward To",
@ -6445,6 +6453,14 @@
"messageformat": "No recent stories to show right now",
"description": "Description for when there are no stories to show"
},
"icu:Stories__list__empty--title": {
"messageformat": "No stories",
"description": "Message title for when there are no stories to show"
},
"icu:Stories__list__empty--subtitle": {
"messageformat": "New updates will appear here.",
"description": "Message subtitle for when there are no stories to show"
},
"icu:Stories__list--sending": {
"messageformat": "Sending...",
"description": "Pending text for story being sent in list view"
@ -6465,6 +6481,10 @@
"messageformat": "Click to view a story",
"description": "Placeholder label for the story view"
},
"icu:Stories__placeholder-with-icon--text": {
"messageformat": "Click <newStoryIcon>Add a story</newStoryIcon> to add an update.",
"description": "Placeholder label for the story view"
},
"icu:Stories__from-to-group": {
"messageformat": "{name} to {group}",
"description": "Title for someone sending a story to a group"
@ -7183,6 +7203,10 @@
},
"icu:CallsTab__EmptyStateText": {
"messageformat": "Click to view or start a call",
"description": "(Deleted 2024/08/12) Calls Tab > When no call is selected > Empty state > Call to action text"
},
"icu:CallsTab__EmptyStateText--with-icon": {
"messageformat": "Click <newCallIcon>New Call</newCallIcon> to start a new voice or video call.",
"description": "Calls Tab > When no call is selected > Empty state > Call to action text"
},
"icu:CallsList__SearchInputPlaceholder": {
@ -7199,7 +7223,23 @@
},
"icu:CallsList__EmptyState--noQuery": {
"messageformat": "No recent calls. Get started by calling a friend.",
"description": "Calls Tab > Calls List > When no results found > With no search query"
"description": "(Deleted 2024/08/12) Calls Tab > Calls List > When no results found > With no search query"
},
"icu:CallsList__EmptyState--noQuery__title": {
"messageformat": "No calls",
"description": "Calls Tab > Calls List > When no results found > With no search query. Message title"
},
"icu:CallsList__EmptyState--noQuery__subtitle": {
"messageformat": "Recent calls will appear here.",
"description": "Calls Tab > Calls List > When no results found > With no search query. Message subtitle"
},
"icu:CallsList__EmptyState--noQuery--missed__title": {
"messageformat": "No missed calls",
"description": "Calls Tab > Calls List > When no missed calls found > With no search query. Message title"
},
"icu:CallsList__EmptyState--noQuery--missed__subtitle": {
"messageformat": "Missed calls will appear here.",
"description": "Calls Tab > Calls List > When no missed calls found > With no search query. Message subtitle"
},
"icu:CallsList__EmptyState--hasQuery": {
"messageformat": "No results for “{query}”",

View file

@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18.9998 2.5C18.9998 1.94772 18.5521 1.5 17.9998 1.5C17.4475 1.5 16.9998 1.94772 16.9998 2.5V5H14.4998C13.9475 5 13.4998 5.44772 13.4998 6C13.4998 6.55228 13.9475 7 14.4998 7H16.9998V9.5C16.9998 10.0523 17.4475 10.5 17.9998 10.5C18.5521 10.5 18.9998 10.0523 18.9998 9.5V7H21.4998C22.0521 7 22.4998 6.55228 22.4998 6C22.4998 5.44772 22.0521 5 21.4998 5H18.9998V2.5Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.32982 3.6746C7.23927 2.23966 5.13324 2.09673 3.85881 3.37116L3.435 3.79497C1.87849 5.35148 1.01247 7.6866 1.78645 9.94502C2.73212 12.7044 4.3058 15.2956 6.50503 17.4948C8.70426 19.694 11.2954 21.2677 14.0548 22.2134C16.3132 22.9874 18.6483 22.1213 20.2049 20.5648L20.6287 20.141C21.9031 18.8666 21.7602 16.7606 20.3252 15.67L17.5492 13.5602C16.365 12.6602 14.6981 12.7734 13.6464 13.8251L12.6929 14.7786C12.621 14.7484 12.5307 14.7052 12.4216 14.6446C11.9551 14.3854 11.3393 13.9167 10.7112 13.2886C10.0831 12.6606 9.61438 12.0447 9.35524 11.5783C9.29464 11.4692 9.25143 11.3788 9.22122 11.3069L10.1748 10.3534C11.2265 9.30169 11.3396 7.63481 10.4396 6.45067L8.32982 3.6746ZM5.27302 4.78538C5.69046 4.36793 6.38029 4.41475 6.7375 4.88477L8.84732 7.66084C9.14209 8.0487 9.10504 8.59469 8.76056 8.93917L7.552 10.1477C7.09678 10.6029 7.13727 11.1969 7.19765 11.5086C7.26603 11.8617 7.42416 12.2206 7.60693 12.5495C7.97934 13.2199 8.57585 13.9817 9.29696 14.7029C10.0181 15.424 10.7799 16.0205 11.4503 16.3929C11.7793 16.5757 12.1381 16.7338 12.4912 16.8022C12.8029 16.8626 13.3969 16.903 13.8521 16.4478L15.0607 15.2393C15.4051 14.8948 15.9511 14.8577 16.339 15.1525L19.1151 17.2623C19.5851 17.6195 19.6319 18.3094 19.2144 18.7268L18.7906 19.1506C17.6362 20.305 16.0715 20.7903 14.7032 20.3214C12.2258 19.4724 9.89825 18.0596 7.91924 16.0806C5.94023 14.1016 4.52745 11.774 3.67843 9.29663C3.20949 7.92828 3.69479 6.36361 4.84921 5.20918L5.27302 4.78538ZM12.8935 14.8419C12.8935 14.8419 12.8896 14.8419 12.8807 14.8403C12.8888 14.8409 12.8935 14.8419 12.8935 14.8419ZM9.15793 11.1063C9.15793 11.1063 9.15892 11.111 9.15948 11.1192C9.15797 11.1102 9.15793 11.1063 9.15793 11.1063Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.3479 2.75C17.2721 2.74999 16.3892 2.74997 15.671 2.80865C14.9267 2.86946 14.25 2.99948 13.6165 3.32222C12.6287 3.82555 11.8256 4.6287 11.3222 5.61655C10.9995 6.24996 10.8695 6.92671 10.8086 7.67102C10.75 8.38918 10.75 9.27207 10.75 10.3479V29.6521C10.75 30.7279 10.75 31.6108 10.8086 32.329C10.8695 33.0733 10.9995 33.75 11.3222 34.3835C11.8256 35.3713 12.6287 36.1744 13.6165 36.6778C14.25 37.0005 14.9267 37.1305 15.671 37.1914C16.3892 37.25 17.272 37.25 18.3479 37.25H26.6521C27.728 37.25 28.6108 37.25 29.329 37.1914C30.0733 37.1305 30.75 37.0005 31.3834 36.6778C32.3713 36.1744 33.1744 35.3713 33.6778 34.3835C34.0005 33.75 34.1305 33.0733 34.1914 32.329C34.25 31.6108 34.25 30.728 34.25 29.6522V10.3479C34.25 9.27207 34.25 8.38916 34.1914 7.67102C34.1305 6.92671 34.0005 6.24996 33.6778 5.61655C33.1744 4.6287 32.3713 3.82555 31.3834 3.32222C30.75 2.99948 30.0733 2.86946 29.329 2.80865C28.6108 2.74997 27.7279 2.74999 26.6521 2.75H18.3479ZM14.7515 5.54973C14.9738 5.4365 15.2849 5.34853 15.8746 5.30035C16.4789 5.25097 17.2593 5.25 18.4 5.25H26.6C27.7407 5.25 28.5211 5.25097 29.1254 5.30035C29.7151 5.34853 30.0262 5.4365 30.2485 5.54973C30.7659 5.81339 31.1866 6.23408 31.4503 6.75153C31.5635 6.97377 31.6515 7.28489 31.6997 7.8746C31.749 8.4789 31.75 9.25927 31.75 10.4V29.6C31.75 30.7407 31.749 31.5211 31.6997 32.1254C31.6515 32.7151 31.5635 33.0262 31.4503 33.2485C31.1866 33.7659 30.7659 34.1866 30.2485 34.4503C30.0262 34.5635 29.7151 34.6515 29.1254 34.6997C28.5211 34.749 27.7407 34.75 26.6 34.75H18.4C17.2593 34.75 16.4789 34.749 15.8746 34.6997C15.2849 34.6515 14.9738 34.5635 14.7515 34.4503C14.2341 34.1866 13.8134 33.7659 13.5497 33.2485C13.4365 33.0262 13.3485 32.7151 13.3003 32.1254C13.251 31.5211 13.25 30.7407 13.25 29.6V10.4C13.25 9.25927 13.251 8.4789 13.3003 7.8746C13.3485 7.28489 13.4365 6.97377 13.5497 6.75153C13.8134 6.23408 14.2341 5.81339 14.7515 5.54973Z" fill="black"/>
<path d="M9.23414 6.33258C9.14574 6.74195 9.09596 7.14342 9.06449 7.52852C9.02634 7.99543 9.01074 8.51644 9.00438 9.07691C8.18127 9.37776 7.58408 9.60268 7.11743 9.81702C6.57977 10.064 6.31749 10.2531 6.14739 10.4355C5.75132 10.8602 5.49988 11.3994 5.42911 11.9758C5.39871 12.2234 5.42246 12.5459 5.57888 13.1165C5.73916 13.7012 6.00515 14.4349 6.3953 15.5068L9.00003 22.6632L9.00005 29.9612C8.86759 29.6089 8.72856 29.2269 8.57857 28.8148L4.02826 16.3129C3.66028 15.3019 3.35831 14.4723 3.16782 13.7774C2.97039 13.0572 2.86111 12.3768 2.94774 11.6712C3.08286 10.5707 3.56288 9.54133 4.319 8.73049C4.80383 8.21057 5.3953 7.85693 6.07392 7.54522C6.7287 7.24446 7.55834 6.94251 8.56931 6.57456L9.23414 6.33258Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -1 +0,0 @@
<svg width="40" height="40" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M18.357 3c-1.084 0-1.958 0-2.666.058-.729.06-1.369.185-1.961.487a5 5 0 0 0-2.185 2.185c-.302.592-.428 1.233-.487 1.961C11 8.4 11 9.273 11 10.357v19.286c0 1.084 0 1.958.058 2.666.06.729.185 1.369.487 1.961a5 5 0 0 0 2.185 2.185c.592.302 1.232.428 1.961.487.708.058 1.582.058 2.666.058h8.286c1.084 0 1.958 0 2.666-.058.729-.06 1.369-.185 1.961-.487a5 5 0 0 0 2.185-2.185c.302-.592.428-1.233.487-1.961C34 31.6 34 30.727 34 29.643V10.357c0-1.084 0-1.958-.058-2.666-.06-.728-.185-1.369-.487-1.96a5 5 0 0 0-2.185-2.186c-.592-.302-1.232-.428-1.961-.487C28.6 3 27.727 3 26.643 3h-8.286Zm-3.719 2.327c.263-.134.611-.226 1.216-.276.617-.05 1.41-.051 2.546-.051h8.2c1.137 0 1.929 0 2.546.051.605.05.953.142 1.216.276a3 3 0 0 1 1.311 1.311c.134.263.226.611.276 1.216.05.617.051 1.41.051 2.546v19.2c0 1.137 0 1.929-.051 2.546-.05.605-.142.953-.276 1.216a3 3 0 0 1-1.311 1.311c-.263.134-.611.226-1.216.276-.617.05-1.41.051-2.546.051h-8.2c-1.137 0-1.929 0-2.546-.051-.605-.05-.953-.142-1.216-.276a3 3 0 0 1-1.311-1.311c-.134-.263-.226-.611-.276-1.216-.05-.617-.051-1.41-.051-2.546V10.4c0-1.137 0-1.929.051-2.546.05-.605.142-.953.276-1.216a3 3 0 0 1 1.311-1.311Z" fill="#000"/><path d="M9.727 6.42a8.657 8.657 0 0 0-.164 1.15 17.28 17.28 0 0 0-.05 1.056l-.125.045c-1.068.389-1.813.66-2.375.919-.552.253-.847.459-1.048.675a3 3 0 0 0-.784 1.68c-.036.294-.004.652.157 1.238.163.596.434 1.341.822 2.41l3.34 9.175v4.924l.001.871a64.71 64.71 0 0 1-.69-1.842L4.265 16.236c-.37-1.018-.67-1.84-.857-2.525-.193-.705-.294-1.35-.213-2.01a5 5 0 0 1 1.306-2.8c.453-.486 1.012-.823 1.676-1.129.646-.296 1.467-.595 2.486-.966l1.063-.387Z" fill="#000"/></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -58,6 +58,11 @@
width: 128px;
}
&.module-img--80 {
height: 80px;
width: 80px;
}
&.module-logo-blue {
background-color: $color-ultramarine-icon;
}
@ -5312,41 +5317,6 @@ button.module-calling-participants-list__contact {
}
}
.module-left-pane__empty {
align-items: center;
display: flex;
height: 100%;
justify-content: center;
padding-block: 0;
padding-inline: 32px;
text-align: center;
.module-left-pane--width-narrow & {
display: none;
}
&--composer_icon {
align-items: center;
background-color: $color-gray-05;
border-radius: 100%;
display: inline-flex;
height: 28px;
justify-content: center;
margin-bottom: -2px;
margin-inline-start: 4px;
vertical-align: bottom;
width: 28px;
&--icon {
$icon: '../images/icons/v3/compose/compose.svg';
@include color-svg($icon, $color-gray-90);
display: inline-block;
height: 16px;
width: 16px;
}
}
}
.module-left-pane__header {
flex-grow: 0;
flex-shrink: 0;

View file

@ -44,11 +44,12 @@
align-items: center;
justify-content: center;
flex-direction: column;
padding-block: 78px 28px;
}
.CallsTab__EmptyStateIcon {
width: 56px;
height: 56px;
width: 40px;
height: 40px;
opacity: 0.7;
@include light-theme {
@include color-svg('../images/icons/v3/phone/phone.svg', $color-gray-60);
@ -62,6 +63,7 @@
margin-block: 12px 0;
margin-inline: 0;
opacity: 0.7;
text-align: center;
@include light-theme {
color: $color-gray-60;
}
@ -70,6 +72,26 @@
}
}
.CallsTab__EmptyState__ActionIcon {
vertical-align: text-top;
display: inline-block;
width: 16px;
height: 16px;
@include light-theme {
@include color-svg(
'../images/icons/v3/phone/phone-plus-bold.svg',
$color-gray-60
);
}
@include dark-theme {
@include color-svg(
'../images/icons/v3/phone/phone-plus-bold.svg',
$color-gray-25
);
}
}
.CallsTab__ConversationCallDetails {
display: block;
overflow: auto;

View file

@ -35,6 +35,10 @@
}
}
.Inbox__no-conversation-open .module-splash-screen__logo {
margin: 0;
}
.Inbox__logo {
flex-shrink: 0;
@ -78,3 +82,20 @@
opacity: 1;
}
}
.Inbox__welcome {
margin-block: 20px 6px;
@include font-title-medium;
line-height: 24px;
}
.Inbox__whatsnew {
margin: 0;
}
// To center the content relative left pane
.Inbox__padding {
flex-grow: 1;
max-height: 28px;
}

View file

@ -222,3 +222,41 @@
margin-bottom: 8px;
gap: 12px;
}
.NavSidebarEmpty {
position: absolute;
top: 0;
inset-inline-start: 0;
pointer-events: none; // since this is going to overlap with the navbar header
// we don't want it to capture any clicks.
align-items: center;
display: flex;
width: 100%;
height: 100%;
justify-content: center;
padding-block: 0;
padding-inline: 32px;
text-align: center;
.module-left-pane--width-narrow & {
display: none;
}
}
.NavSidebarEmpty__inner {
padding-block: 100px 28px;
}
.NavSidebarEmpty__title {
margin-block: 0px 6px;
@include font-title-medium;
color: $color-gray-45;
}
.NavSidebarEmpty__subtitle {
margin-block: 0;
color: $color-gray-45;
}

View file

@ -123,6 +123,8 @@
flex: 1;
justify-content: center;
opacity: 0.7;
padding-block: 78px 28px;
@include light-theme {
color: $color-gray-60;
}
@ -130,23 +132,41 @@
color: $color-gray-25;
}
&__stories {
height: 56px;
margin-bottom: 22px;
width: 56px;
&__icon {
margin-bottom: 12px;
width: 40px;
height: 40px;
@include light-theme {
@include color-svg(
'../images/icons/v3/stories/stories-display.svg',
'../images/icons/v3/stories/stories-display-bold.svg',
$color-gray-60
);
}
@include dark-theme {
@include color-svg(
'../images/icons/v3/stories/stories-display.svg',
'../images/icons/v3/stories/stories-display-bold.svg',
$color-gray-25
);
}
}
&__text {
text-align: center;
}
&__text__action {
vertical-align: text-top;
display: inline-block;
width: 16px;
height: 16px;
@include light-theme {
@include color-svg('../images/icons/v3/plus/plus.svg', $color-gray-60);
}
@include dark-theme {
@include color-svg('../images/icons/v3/plus/plus.svg', $color-gray-25);
}
}
}
&__hidden-stories {

View file

@ -38,7 +38,7 @@ import { drop } from '../util/drop';
import { strictAssert } from '../util/assert';
import { UserText } from './UserText';
import { I18n } from './I18n';
import { NavSidebarSearchHeader } from './NavSidebar';
import { NavSidebarSearchHeader, NavSidebarEmpty } from './NavSidebar';
import { SizeObserver } from '../hooks/useSizeObserver';
import {
formatCallHistoryGroup,
@ -205,21 +205,27 @@ export function CallsList({
const searchStateQuery = searchState.options?.query ?? '';
const searchStateStatus =
searchState.options?.status ?? CallHistoryFilterStatus.All;
const hasSearchStateQuery = searchStateQuery !== '';
const searchFiltering =
searchStateQuery !== '' ||
searchStateStatus !== CallHistoryFilterStatus.All;
hasSearchStateQuery || searchStateStatus !== CallHistoryFilterStatus.All;
const searchPending = searchState.state === 'pending';
const isEmpty = !searchState.results?.items?.length;
const rows = useMemo(() => {
let results: ReadonlyArray<Row> = searchState.results?.items ?? [];
if (results.length === 0) {
if (results.length === 0 && hasSearchStateQuery) {
results = ['EmptyState'];
}
if (!searchFiltering && canCreateCallLinks) {
results = ['CreateCallLink', ...results];
}
return results;
}, [searchState.results?.items, searchFiltering, canCreateCallLinks]);
}, [
searchState.results?.items,
hasSearchStateQuery,
searchFiltering,
canCreateCallLinks,
]);
const rowCount = rows.length;
@ -698,17 +704,13 @@ export function CallsList({
if (item === 'EmptyState') {
return (
<div key={key} className="CallsList__EmptyState" style={style}>
{searchStateQuery === '' ? (
i18n('icu:CallsList__EmptyState--noQuery')
) : (
<I18n
i18n={i18n}
id="icu:CallsList__EmptyState--hasQuery"
components={{
query: <UserText text={searchStateQuery} />,
}}
/>
)}
<I18n
i18n={i18n}
id="icu:CallsList__EmptyState--hasQuery"
components={{
query: <UserText text={searchStateQuery} />,
}}
/>
</div>
);
}
@ -930,6 +932,22 @@ export function CallsList({
return (
<>
{isEmpty && !searchFiltering && (
<NavSidebarEmpty
title={i18n('icu:CallsList__EmptyState--noQuery__title')}
subtitle={i18n('icu:CallsList__EmptyState--noQuery__subtitle')}
/>
)}
{isEmpty &&
statusInput === CallHistoryFilterStatus.Missed &&
!hasSearchStateQuery && (
<NavSidebarEmpty
title={i18n('icu:CallsList__EmptyState--noQuery--missed__title')}
subtitle={i18n(
'icu:CallsList__EmptyState--noQuery--missed__subtitle'
)}
/>
)}
<NavSidebarSearchHeader>
<SearchInput
i18n={i18n}

View file

@ -24,6 +24,7 @@ import type { WidthBreakpoint } from './_util';
import type { CallLinkType } from '../types/CallLink';
import type { CallStateType } from '../state/selectors/calling';
import type { StartCallData } from './ConfirmLeaveCallModal';
import { I18n } from './I18n';
enum CallsTabSidebarView {
CallsListView,
@ -316,7 +317,26 @@ export function CallsTab({
<div className="CallsTab__EmptyState">
<div className="CallsTab__EmptyStateIcon" />
<p className="CallsTab__EmptyStateLabel">
{i18n('icu:CallsTab__EmptyStateText')}
<I18n
i18n={i18n}
id="icu:CallsTab__EmptyStateText--with-icon"
components={{
// eslint-disable-next-line react/no-unstable-nested-components
newCallIcon: children => {
let label: string | undefined;
const first = children[0];
if (typeof first === 'string') {
label = first;
}
return (
<span
className="CallsTab__EmptyState__ActionIcon"
aria-label={label}
/>
);
},
}}
/>
</p>
</div>
) : (

View file

@ -58,15 +58,16 @@ export function ChatsTab({
) : (
<div className="Inbox__no-conversation-open">
{renderMiniPlayer({ shouldFlow: false })}
<div className="module-splash-screen__logo module-img--128 module-logo-blue" />
<h3>
<div className="module-splash-screen__logo module-img--80 module-logo-blue" />
<h3 className="Inbox__welcome">
{getEnvironment() !== Environment.Staging
? i18n('icu:welcomeToSignal')
: 'THIS IS A STAGING DESKTOP'}
</h3>
<p>
<p className="Inbox__whatsnew">
<WhatsNewLink i18n={i18n} showWhatsNewModal={showWhatsNewModal} />
</p>
<div className="Inbox__padding" />
</div>
)}
</div>

View file

@ -472,6 +472,10 @@ export function LeftPane({
startSearch,
]);
const backgroundNode = helper.getBackgroundNode({
i18n,
});
const preRowsNode = helper.getPreRowsNode({
clearConversationSearch,
clearGroupCreationError,
@ -686,6 +690,7 @@ export function LeftPane({
</>
}
>
{backgroundNode}
<nav
className={classNames(
'module-left-pane',

View file

@ -239,3 +239,20 @@ export function NavSidebarSearchHeader({
}): JSX.Element {
return <div className="NavSidebarSearchHeader">{children}</div>;
}
export function NavSidebarEmpty({
title,
subtitle,
}: {
title: string;
subtitle: string;
}): JSX.Element {
return (
<div className="NavSidebarEmpty">
<div className="NavSidebarEmpty__inner">
<h3 className="NavSidebarEmpty__title">{title}</h3>
<p className="NavSidebarEmpty__subtitle">{subtitle}</p>
</div>
</div>
);
}

View file

@ -18,7 +18,7 @@ import { MyStoryButton } from './MyStoryButton';
import { SearchInput } from './SearchInput';
import { StoryListItem } from './StoryListItem';
import { isNotNil } from '../util/isNotNil';
import { NavSidebarSearchHeader } from './NavSidebar';
import { NavSidebarSearchHeader, NavSidebarEmpty } from './NavSidebar';
const FUSE_OPTIONS: Fuse.IFuseOptions<ConversationStoryType> = {
getFn: (story, path) => {
@ -104,6 +104,12 @@ export function StoriesPane({
}, [searchTerm, stories]);
return (
<>
{!stories.length && (
<NavSidebarEmpty
title={i18n('icu:Stories__list__empty--title')}
subtitle={i18n('icu:Stories__list__empty--subtitle')}
/>
)}
<NavSidebarSearchHeader>
<SearchInput
i18n={i18n}
@ -180,11 +186,6 @@ export function StoriesPane({
))}
</>
)}
{!stories.length && (
<div className="Stories__pane__list--empty">
{i18n('icu:Stories__list-empty')}
</div>
)}
</div>
</>
);

View file

@ -24,6 +24,7 @@ import { StoriesPane } from './StoriesPane';
import { NavSidebar, NavSidebarActionButton } from './NavSidebar';
import { StoriesAddStoryButton } from './StoriesAddStoryButton';
import { ContextMenu } from './ContextMenu';
import { I18n } from './I18n';
import type { WidthBreakpoint } from './_util';
import type { UnreadStats } from '../util/countUnreadStats';
@ -217,8 +218,33 @@ export function StoriesTab({
</NavSidebar>
)}
<div className="Stories__placeholder">
<div className="Stories__placeholder__stories" />
{i18n('icu:Stories__placeholder--text')}
<div className="Stories__placeholder__icon" />
<div className="Stories__placeholder__text">
{stories.length ? (
i18n('icu:Stories__placeholder--text')
) : (
<I18n
i18n={i18n}
id="icu:Stories__placeholder-with-icon--text"
components={{
// eslint-disable-next-line react/no-unstable-nested-components
newStoryIcon: children => {
let label: string | undefined;
const first = children[0];
if (typeof first === 'string') {
label = first;
}
return (
<span
className="Stories__placeholder__text__action"
aria-label={label}
/>
);
},
}}
/>
)}
</div>
</div>
</div>
);

View file

@ -66,6 +66,14 @@ export abstract class LeftPaneHelper<T> {
return undefined;
}
getBackgroundNode(
_: Readonly<{
i18n: LocalizerType;
}>
): null | ReactChild {
return null;
}
getPreRowsNode(
_: Readonly<{
clearConversationSearch: () => unknown;

View file

@ -5,7 +5,6 @@ import { last } from 'lodash';
import type { ReactChild } from 'react';
import React from 'react';
import { I18n } from '../I18n';
import type { ToFindType } from './LeftPaneHelper';
import type {
ConversationType,
@ -15,6 +14,7 @@ import { LeftPaneHelper } from './LeftPaneHelper';
import { getConversationInDirection } from './getConversationInDirection';
import type { Row } from '../ConversationList';
import { RowType } from '../ConversationList';
import { NavSidebarEmpty } from '../NavSidebar';
import type { PropsData as ConversationListItemPropsType } from '../conversationList/ConversationListItem';
import type { LocalizerType } from '../../types/Util';
import { handleKeydownForSearch } from './handleKeydownForSearch';
@ -121,31 +121,17 @@ export class LeftPaneInboxHelper extends LeftPaneHelper<LeftPaneInboxPropsType>
);
}
override getPreRowsNode({
override getBackgroundNode({
i18n,
}: Readonly<{
i18n: LocalizerType;
}>): ReactChild | null {
if (this.getRowCount() === 0) {
return (
<div className="module-left-pane__empty">
<div>
<I18n
i18n={i18n}
id="icu:emptyInboxMessage"
components={{
composeIcon: (
<span>
<strong>{i18n('icu:composeIcon')}</strong>
<span className="module-left-pane__empty--composer_icon">
<i className="module-left-pane__empty--composer_icon--icon" />
</span>
</span>
),
}}
/>
</div>
</div>
<NavSidebarEmpty
title={i18n('icu:emptyInbox__title')}
subtitle={i18n('icu:emptyInbox__subtitle')}
/>
);
}