diff --git a/CHANGELOG.md b/CHANGELOG.md index ee32cbb92..b6bc03ee8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Posts: truncate Nostr pubkeys in reply mentions. - Posts: upgraded emoji picker component. +- Posts: improved design of threads. - UI: unified design of "approve" and "reject" buttons in follow requests and waitlist. +- UI: added sticky column header. ### Fixed - Posts: fixed emojis being cut off in reactions modal. diff --git a/app/soapbox/components/ui/card/card.tsx b/app/soapbox/components/ui/card/card.tsx index aedf3e132..512910410 100644 --- a/app/soapbox/components/ui/card/card.tsx +++ b/app/soapbox/components/ui/card/card.tsx @@ -16,11 +16,13 @@ const messages = defineMessages({ back: { id: 'card.back.label', defaultMessage: 'Back' }, }); +export type CardSizes = keyof typeof sizes + interface ICard { /** The type of card. */ variant?: 'default' | 'rounded' /** Card size preset. */ - size?: keyof typeof sizes + size?: CardSizes /** Extra classnames for the
element. */ className?: string /** Elements inside the card. */ @@ -33,7 +35,7 @@ const Card = React.forwardRef(({ children, variant = 'def ref={ref} {...filteredProps} className={clsx({ - 'bg-white dark:bg-primary-900 text-gray-900 dark:text-gray-100 shadow-lg dark:shadow-none overflow-hidden': variant === 'rounded', + 'bg-white dark:bg-primary-900 text-gray-900 dark:text-gray-100 shadow-lg dark:shadow-none': variant === 'rounded', [sizes[size]]: variant === 'rounded', }, className)} > @@ -72,7 +74,7 @@ const CardHeader: React.FC = ({ className, children, backHref, onBa }; return ( - + {renderBackButton()} {children} diff --git a/app/soapbox/components/ui/column/column.tsx b/app/soapbox/components/ui/column/column.tsx index d6cadec77..8813b107b 100644 --- a/app/soapbox/components/ui/column/column.tsx +++ b/app/soapbox/components/ui/column/column.tsx @@ -1,11 +1,12 @@ import clsx from 'clsx'; -import React from 'react'; +import throttle from 'lodash/throttle'; +import React, { useCallback, useEffect, useState } from 'react'; import { useHistory } from 'react-router-dom'; import Helmet from 'soapbox/components/helmet'; import { useSoapboxConfig } from 'soapbox/hooks'; -import { Card, CardBody, CardHeader, CardTitle } from '../card/card'; +import { Card, CardBody, CardHeader, CardTitle, type CardSizes } from '../card/card'; type IColumnHeader = Pick; @@ -54,13 +55,29 @@ export interface IColumn { ref?: React.Ref /** Children to display in the column. */ children?: React.ReactNode + /** Action for the ColumnHeader, displayed at the end. */ action?: React.ReactNode + /** Column size, inherited from Card. */ + size?: CardSizes } /** A backdrop for the main section of the UI. */ const Column: React.FC = React.forwardRef((props, ref: React.ForwardedRef): JSX.Element => { - const { backHref, children, label, transparent = false, withHeader = true, className, action } = props; + const { backHref, children, label, transparent = false, withHeader = true, className, action, size } = props; const soapboxConfig = useSoapboxConfig(); + const [isScrolled, setIsScrolled] = useState(false); + + const handleScroll = useCallback(throttle(() => { + setIsScrolled(window.pageYOffset > 32); + }, 50), []); + + useEffect(() => { + window.addEventListener('scroll', handleScroll); + + return () => { + window.removeEventListener('scroll', handleScroll); + }; + }, []); return (
@@ -76,12 +93,18 @@ const Column: React.FC = React.forwardRef((props, ref: React.ForwardedR )} - + {withHeader && ( )} diff --git a/app/soapbox/features/status/index.tsx b/app/soapbox/features/status/index.tsx index b51333883..a9743b48b 100644 --- a/app/soapbox/features/status/index.tsx +++ b/app/soapbox/features/status/index.tsx @@ -50,8 +50,9 @@ import type { } from 'soapbox/types/entities'; const messages = defineMessages({ - title: { id: 'status.title', defaultMessage: '@{username}\'s Post' }, + title: { id: 'status.title', defaultMessage: 'Post Details' }, titleDirect: { id: 'status.title_direct', defaultMessage: 'Direct message' }, + titleGroup: { id: 'status.title_group', defaultMessage: 'Group Post Details' }, deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' }, deleteHeading: { id: 'confirmations.delete.heading', defaultMessage: 'Delete post' }, deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this post?' }, @@ -462,9 +463,6 @@ const Thread: React.FC = (props) => { react: handleHotkeyReact, }; - const username = String(status.getIn(['account', 'acct'])); - const titleMessage = status.visibility === 'direct' ? messages.titleDirect : messages.title; - const focusedStatus = (
@@ -488,7 +486,7 @@ const Thread: React.FC = (props) => { {!isUnderReview ? ( <> -
+
= (props) => {
{hasDescendants && ( -
+
)}
); @@ -523,10 +521,15 @@ const Thread: React.FC = (props) => { return ; } + const titleMessage = () => { + if (status.visibility === 'direct') return messages.titleDirect; + return status.group ? messages.titleGroup : messages.title; + }; + return ( - + - +
= ({ account, username }) => - + {account.bot && } @@ -153,7 +153,7 @@ const ProfileInfoPanel: React.FC = ({ account, username }) => - + @{displayFqn ? account.fqn : account.acct} diff --git a/app/soapbox/locales/en.json b/app/soapbox/locales/en.json index fcb527c16..080a6dfc5 100644 --- a/app/soapbox/locales/en.json +++ b/app/soapbox/locales/en.json @@ -1462,8 +1462,9 @@ "status.show_less_all": "Show less for all", "status.show_more_all": "Show more for all", "status.show_original": "Show original", - "status.title": "@{username}'s post", + "status.title": "Post Details", "status.title_direct": "Direct message", + "status.title_group": "Group Post Details", "status.translate": "Translate", "status.translated_from_with": "Translated from {lang} using {provider}", "status.unbookmark": "Remove bookmark", diff --git a/app/styles/components/detailed-status.scss b/app/styles/components/detailed-status.scss index 7b5086776..d07c31814 100644 --- a/app/styles/components/detailed-status.scss +++ b/app/styles/components/detailed-status.scss @@ -1,5 +1,5 @@ .thread { - @apply bg-white dark:bg-primary-900 p-4 shadow-xl dark:shadow-none sm:p-6 sm:rounded-xl; + @apply bg-white dark:bg-primary-900 sm:rounded-xl; &__status { @apply relative pb-4; diff --git a/app/styles/components/status.scss b/app/styles/components/status.scss index 96bf3aec2..b5a0571c1 100644 --- a/app/styles/components/status.scss +++ b/app/styles/components/status.scss @@ -17,7 +17,7 @@ [column-type='filled'] .status__wrapper, [column-type='filled'] .status-placeholder { - @apply bg-transparent dark:bg-transparent rounded-none shadow-none p-4; + @apply bg-transparent dark:bg-transparent rounded-none shadow-none; } .status-check-box {