-
-
Notifications
You must be signed in to change notification settings - Fork 36
Added Feature: Information description for each tab #349 #350
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
.info-icon-wrapper { | ||
position: relative; | ||
display: inline-block; | ||
cursor: pointer; | ||
} | ||
|
||
.info-icon { | ||
color: #555; | ||
} | ||
|
||
.tooltip-text { | ||
visibility: hidden; | ||
background-color: #333; | ||
color: #fff; | ||
padding: 8px 10px; | ||
border-radius: 4px; | ||
position: absolute; | ||
left: 120%; | ||
top: 50%; | ||
transform: translateY(-50%); | ||
opacity: 0; | ||
transition: opacity 0.3s ease-in-out; | ||
white-space: nowrap; | ||
font-size: 0.85rem; | ||
z-index: 10; | ||
} | ||
|
||
.info-icon-wrapper:hover .tooltip-text { | ||
visibility: visible; | ||
opacity: 1; | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,17 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import InfoIcon from '@mui/icons-material/Info'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import './info-tool-tip.css'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const InfoTooltip = ({ text }) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<div | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
className="info-icon-wrapper" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tabIndex="0" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
aria-describedby="tooltip-text" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<InfoIcon className="info-icon" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<span className="tooltip-text">{text}</span> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+11
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tooltip lacks ARIA attributes and keyboard support; consider adding
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback
Comment on lines
+4
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using a static id 'tooltip-text' for aria-describedby can lead to duplicate IDs when multiple tooltips are rendered. Consider generating unique IDs per instance or using aria-label with a
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export default InfoTooltip; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,12 +14,15 @@ import { SearchHeaderDebounced } from '../history/search-header'; | |
import { VisibleWithDelay } from '../../common-components/visible'; | ||
import { resolveHandleOrDID } from '../../api'; | ||
import { useAccountResolver } from '../account-resolver'; | ||
import InfoTooltip from '../../common-components/info-tool-tip'; | ||
|
||
export function BlockedByLists() { | ||
const accountQuery = useAccountResolver(); | ||
const shortHandle = accountQuery.data?.shortHandle; | ||
const { data, fetchNextPage, hasNextPage, isLoading, isFetching } = useBlockedByLists(shortHandle); | ||
const { data: totalData, isLoading: isLoadingTotal } = useBlockedByListsTotal(shortHandle); | ||
const { data, fetchNextPage, hasNextPage, isLoading, isFetching } = | ||
useBlockedByLists(shortHandle); | ||
const { data: totalData, isLoading: isLoadingTotal } = | ||
useBlockedByListsTotal(shortHandle); | ||
|
||
const [searchParams, setSearchParams] = useSearchParams(); | ||
const [tick, setTick] = useState(0); | ||
|
@@ -29,54 +32,64 @@ export function BlockedByLists() { | |
const listsTotal = totalData?.count; | ||
const listPages = data?.pages || []; | ||
const allLists = listPages.flatMap((page) => page.blocklist); | ||
const filteredLists = !search ? allLists : matchSearch(allLists, search, () => setTick(tick + 1)); | ||
const filteredLists = !search | ||
? allLists | ||
: matchSearch(allLists, search, () => setTick(tick + 1)); | ||
|
||
// Show loader for initial load | ||
if (isLoading) { | ||
return ( | ||
<div style={{ padding: '1em', textAlign: 'center', opacity: '0.5' }}> | ||
<CircularProgress size="1.5em" /> | ||
<CircularProgress size="1.5em" /> | ||
<div style={{ marginTop: '0.5em' }}> | ||
{'Loading blocked by lists...'} | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
const shouldShowLoadMore = hasNextPage && (!search || filteredLists.length > 0); | ||
const shouldShowLoadMore = | ||
hasNextPage && (!search || filteredLists.length > 0); | ||
|
||
return ( | ||
<> | ||
<div> | ||
<div style={showSearch ? undefined : { display: 'none' }}> | ||
<SearchHeaderDebounced | ||
label='Search' | ||
setQ /> | ||
<SearchHeaderDebounced label="Search" setQ /> | ||
</div> | ||
</div> | ||
|
||
<h3 className='lists-header'> | ||
{(isLoadingTotal && !listsTotal) && <span style={{ opacity: 0.5 }}>{"Counting block lists..."}</span>} | ||
{listsTotal ? | ||
<h3 className="lists-header"> | ||
<div style={{ fontWeight: '400', paddingBottom: '0.2em' }}> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree with copilot: if this same div and style is repeated everywhere we use the tooltip component, then just include it inside the tooltip directly |
||
<InfoTooltip text="this page shows panel members that blocked you via lists" /> | ||
</div> | ||
{isLoadingTotal && !listsTotal && ( | ||
<span style={{ opacity: 0.5 }}>{'Counting block lists...'}</span> | ||
)} | ||
{listsTotal ? ( | ||
<> | ||
{`Blocked by ${Intl.NumberFormat().format(listsTotal)} users via lists`} | ||
<span className='panel-toggles'> | ||
{!showSearch && | ||
{`Blocked by ${Intl.NumberFormat().format( | ||
listsTotal | ||
)} users via lists`} | ||
<span className="panel-toggles"> | ||
{!showSearch && ( | ||
<Button | ||
size='small' | ||
className='panel-show-search' | ||
title='Search' | ||
onClick={() => setShowSearch(true)}><SearchIcon /></Button> | ||
} | ||
size="small" | ||
className="panel-show-search" | ||
title="Search" | ||
onClick={() => setShowSearch(true)} | ||
> | ||
<SearchIcon /> | ||
</Button> | ||
)} | ||
</span> | ||
</> : | ||
isLoadingTotal ? null : 'Not blocked by any users via lists' | ||
} | ||
</> | ||
) : isLoadingTotal ? null : ( | ||
'Not blocked by any users via lists' | ||
)} | ||
</h3> | ||
|
||
<BlockListsView | ||
list={filteredLists} | ||
handle={shortHandle} /> | ||
<BlockListsView list={filteredLists} handle={shortHandle} /> | ||
|
||
{shouldShowLoadMore && ( | ||
<VisibleWithDelay | ||
|
@@ -99,11 +112,12 @@ export function BlockedByLists() { | |
*/ | ||
function matchSearch(blocklist, search, redraw) { | ||
const searchLowercase = search.toLowerCase(); | ||
const filtered = blocklist.filter(entry => { | ||
if ((entry.list_name || '').toLowerCase().includes(searchLowercase)) return true; | ||
const filtered = blocklist.filter((entry) => { | ||
if ((entry.list_name || '').toLowerCase().includes(searchLowercase)) | ||
return true; | ||
|
||
resolveHandleOrDID(entry.list_owner).then(redraw); | ||
return false; | ||
}); | ||
return filtered; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -14,12 +14,15 @@ import { SearchHeaderDebounced } from '../history/search-header'; | |||
import { VisibleWithDelay } from '../../common-components/visible'; | ||||
import { resolveHandleOrDID } from '../../api'; | ||||
import { useAccountResolver } from '../account-resolver'; | ||||
import InfoTooltip from '../../common-components/info-tool-tip'; | ||||
|
||||
export function BlockingLists() { | ||||
const accountQuery = useAccountResolver(); | ||||
const shortHandle = accountQuery.data?.shortHandle; | ||||
const { data, fetchNextPage, hasNextPage, isLoading, isFetching } = useBlockingLists(shortHandle); | ||||
const { data: totalData, isLoading: isLoadingTotal } = useBlockingListsTotal(shortHandle); | ||||
const { data, fetchNextPage, hasNextPage, isLoading, isFetching } = | ||||
useBlockingLists(shortHandle); | ||||
const { data: totalData, isLoading: isLoadingTotal } = | ||||
useBlockingListsTotal(shortHandle); | ||||
|
||||
const [searchParams, setSearchParams] = useSearchParams(); | ||||
const [tick, setTick] = useState(0); | ||||
|
@@ -29,53 +32,68 @@ export function BlockingLists() { | |||
const listTotalBlocks = totalData?.count; | ||||
const listPages = data?.pages || []; | ||||
const allLists = listPages.flatMap((page) => page.blocklist); | ||||
const filteredLists = !search ? allLists : matchSearch(allLists, search, () => setTick(tick + 1)); | ||||
const filteredLists = !search | ||||
? allLists | ||||
: matchSearch(allLists, search, () => setTick(tick + 1)); | ||||
|
||||
// Show loader for initial load | ||||
if (isLoading) { | ||||
return ( | ||||
<div style={{ padding: '1em', textAlign: 'center', opacity: '0.5' }}> | ||||
<CircularProgress size="1.5em" /> | ||||
<div style={{ marginTop: '0.5em' }}> | ||||
{'Loading blocking lists...'} | ||||
</div> | ||||
<CircularProgress size="1.5em" /> | ||||
<div style={{ marginTop: '0.5em' }}>{'Loading blocking lists...'}</div> | ||||
</div> | ||||
); | ||||
} | ||||
|
||||
const shouldShowLoadMore = hasNextPage && (!search || filteredLists.length > 0); | ||||
const shouldShowLoadMore = | ||||
hasNextPage && (!search || filteredLists.length > 0); | ||||
|
||||
return ( | ||||
<> | ||||
<div> | ||||
<div style={showSearch ? undefined : { display: 'none' }}> | ||||
<SearchHeaderDebounced | ||||
label='Search' | ||||
setQ /> | ||||
<SearchHeaderDebounced label="Search" setQ /> | ||||
</div> | ||||
</div> | ||||
|
||||
<h3 className='lists-header'> | ||||
{(isLoadingTotal && !listTotalBlocks) && <span style={{ opacity: 0.5 }}>{"Counting lists..."}</span>} | ||||
{listTotalBlocks ? | ||||
<div | ||||
style={{ | ||||
fontWeight: '400', | ||||
// paddingBottom: '0.2em', | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nitpick] Commented-out style rules can clutter the code. If this padding is no longer needed, remove the commented line to keep the code clean.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||
paddingLeft: '0.5em', | ||||
paddingTop: '0.3em', | ||||
}} | ||||
> | ||||
<InfoTooltip text="this page shows panel members you have blocked via lists" /> | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the wording on some of these are confusing to me. what is a "panel member"? these are also all worded using the 2nd person voice, assuming the reader is only viewing their own profile: "members YOU have blocked" |
||||
</div> | ||||
<h3 className="lists-header"> | ||||
{isLoadingTotal && !listTotalBlocks && ( | ||||
<span style={{ opacity: 0.5 }}>{'Counting lists...'}</span> | ||||
)} | ||||
{listTotalBlocks ? ( | ||||
<> | ||||
{`Blocking ${Intl.NumberFormat().format(listTotalBlocks)} total users via lists`} | ||||
<span className='panel-toggles'> | ||||
{!showSearch && | ||||
{`Blocking ${Intl.NumberFormat().format( | ||||
listTotalBlocks | ||||
)} total users via lists`} | ||||
<span className="panel-toggles"> | ||||
{!showSearch && ( | ||||
<Button | ||||
size='small' | ||||
className='panel-show-search' | ||||
title='Search' | ||||
onClick={() => setShowSearch(true)}><SearchIcon /></Button> | ||||
} | ||||
size="small" | ||||
className="panel-show-search" | ||||
title="Search" | ||||
onClick={() => setShowSearch(true)} | ||||
> | ||||
<SearchIcon /> | ||||
</Button> | ||||
)} | ||||
</span> | ||||
</> : | ||||
isLoadingTotal ? null : 'Not blocking any users via lists' | ||||
} | ||||
</> | ||||
) : isLoadingTotal ? null : ( | ||||
'Not blocking any users via lists' | ||||
)} | ||||
</h3> | ||||
|
||||
<BlockListsView | ||||
list={filteredLists} /> | ||||
<BlockListsView list={filteredLists} /> | ||||
|
||||
{shouldShowLoadMore && ( | ||||
<VisibleWithDelay | ||||
|
@@ -98,11 +116,12 @@ export function BlockingLists() { | |||
*/ | ||||
function matchSearch(blocklist, search, redraw) { | ||||
const searchLowercase = search.toLowerCase(); | ||||
const filtered = blocklist.filter(entry => { | ||||
if ((entry.list_name || '').toLowerCase().includes(searchLowercase)) return true; | ||||
const filtered = blocklist.filter((entry) => { | ||||
if ((entry.list_name || '').toLowerCase().includes(searchLowercase)) | ||||
return true; | ||||
|
||||
resolveHandleOrDID(entry.list_owner).then(redraw); | ||||
return false; | ||||
}); | ||||
return filtered; | ||||
} | ||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ import { Button, Tooltip, IconButton } from '@mui/material'; | |
import InfoIcon from '@mui/icons-material/Info'; | ||
import './history-panel.css'; | ||
import { useAccountResolver } from '../account-resolver'; | ||
import InfoTooltip from '../../common-components/info-tool-tip'; | ||
|
||
export default function HistoryPanel() { | ||
const accountQuery = useAccountResolver(); | ||
|
@@ -21,6 +22,15 @@ export default function HistoryPanel() { | |
|
||
return ( | ||
<> | ||
<div | ||
style={{ | ||
fontWeight: '400', | ||
paddingTop: '0.3em', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nitpick] This inline style is duplicated across panels; consider extracting into a shared CSS class or wrapper component. Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||
paddingLeft: '0.5em', | ||
}} | ||
> | ||
<InfoTooltip text="this page shows your posts" /> | ||
</div> | ||
<SearchHeaderDebounced | ||
label={localise('Search history', { uk: 'Шукати в історії' })} | ||
setQ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this here when there's no element with an id of
tooltip-text
for it to refer to?