diff --git a/app/soapbox/components/radio-button.tsx b/app/soapbox/components/radio-button.tsx deleted file mode 100644 index 2d350b953..000000000 --- a/app/soapbox/components/radio-button.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import classNames from 'clsx'; -import React from 'react'; - -interface IRadioButton { - value: string, - checked?: boolean, - name: string, - onChange: React.ChangeEventHandler, - label: React.ReactNode, -} - -const RadioButton: React.FC = ({ name, value, checked, onChange, label }) => ( - -); - -export default RadioButton; diff --git a/app/soapbox/components/ui/index.ts b/app/soapbox/components/ui/index.ts index c7d4c7e4f..90f5933ed 100644 --- a/app/soapbox/components/ui/index.ts +++ b/app/soapbox/components/ui/index.ts @@ -31,6 +31,7 @@ export { export { default as Modal } from './modal/modal'; export { default as PhoneInput } from './phone-input/phone-input'; export { default as ProgressBar } from './progress-bar/progress-bar'; +export { default as RadioButton } from './radio-button/radio-button'; export { default as Select } from './select/select'; export { default as Spinner } from './spinner/spinner'; export { default as Stack } from './stack/stack'; diff --git a/app/soapbox/components/ui/radio-button/radio-button.tsx b/app/soapbox/components/ui/radio-button/radio-button.tsx new file mode 100644 index 000000000..322cbd7e7 --- /dev/null +++ b/app/soapbox/components/ui/radio-button/radio-button.tsx @@ -0,0 +1,37 @@ +import React, { useMemo } from 'react'; +import { v4 as uuidv4 } from 'uuid'; + +interface IRadioButton { + value: string + checked?: boolean + name: string + onChange: React.ChangeEventHandler + label: React.ReactNode +} + +/** + * A group for radio input with label. + */ +const RadioButton: React.FC = ({ name, value, checked, onChange, label }) => { + const formFieldId: string = useMemo(() => `radio-${uuidv4()}`, []); + + return ( +
+ + + +
+ ); +}; + +export default RadioButton; diff --git a/app/soapbox/features/directory/components/account-card.tsx b/app/soapbox/features/directory/components/account-card.tsx index f405c95fa..6c6d0a697 100644 --- a/app/soapbox/features/directory/components/account-card.tsx +++ b/app/soapbox/features/directory/components/account-card.tsx @@ -1,13 +1,12 @@ import classNames from 'clsx'; import React from 'react'; import { FormattedMessage } from 'react-intl'; -import { Link } from 'react-router-dom'; import { getSettings } from 'soapbox/actions/settings'; -import Avatar from 'soapbox/components/avatar'; -import DisplayName from 'soapbox/components/display-name'; +import Badge from 'soapbox/components/badge'; import RelativeTimestamp from 'soapbox/components/relative-timestamp'; -import { Text } from 'soapbox/components/ui'; +import { Stack, Text } from 'soapbox/components/ui'; +import AccountContainer from 'soapbox/containers/account-container'; import ActionButton from 'soapbox/features/ui/components/action-button'; import { useAppSelector } from 'soapbox/hooks'; import { makeGetAccount } from 'soapbox/selectors'; @@ -29,51 +28,76 @@ const AccountCard: React.FC = ({ id }) => { const followedBy = me !== account.id && account.relationship?.followed_by; return ( -
- {followedBy && -
- - - -
} -
- -
-
- -
+
+
+ {followedBy && ( +
+ } + /> +
+ )} -
- - - - -
+
+ +
-
-

') && 'empty')} - dangerouslySetInnerHTML={{ __html: account.note_emojified }} +
-
-
- + + + + + + +
+ + {shortNumberFormat(account.statuses_count)} - -
-
- + + + + + + + + + {shortNumberFormat(account.followers_count)} - - -
-
- {account.last_status_at === null - ? - : } -
+
+ + + + + + + + + {account.last_status_at === null ? ( + + ) : ( + + )} + + + + + +
); diff --git a/app/soapbox/features/directory/index.tsx b/app/soapbox/features/directory/index.tsx index 218df836f..1266ed0ab 100644 --- a/app/soapbox/features/directory/index.tsx +++ b/app/soapbox/features/directory/index.tsx @@ -6,8 +6,7 @@ import { useLocation } from 'react-router-dom'; import { fetchDirectory, expandDirectory } from 'soapbox/actions/directory'; import LoadMore from 'soapbox/components/load-more'; -import RadioButton from 'soapbox/components/radio-button'; -import Column from 'soapbox/features/ui/components/column'; +import { Column, RadioButton, Stack, Text } from 'soapbox/components/ui'; import { useAppSelector } from 'soapbox/hooks'; import { getFeatures } from 'soapbox/utils/features'; @@ -52,26 +51,49 @@ const Directory = () => { }; return ( - -
-
- - + + +
+
+ Display filter +
+ Display filter +
+ + +
+
+
+ + {features.federating && ( +
+ Fediverse filter +
+ Fediverse filter +
+ + +
+
+
+ )}
- {features.federating && ( -
- - -
- )} -
+
+ {accountIds.map((accountId) => ( + ), + )} +
-
- {accountIds.map((accountId) => )} -
- - + + ); }; diff --git a/app/soapbox/reducers/user-lists.ts b/app/soapbox/reducers/user-lists.ts index 721af9b73..7f5ce6716 100644 --- a/app/soapbox/reducers/user-lists.ts +++ b/app/soapbox/reducers/user-lists.ts @@ -97,7 +97,10 @@ const normalizeList = (state: State, path: NestedListPath | ListPath, accounts: const appendToList = (state: State, path: NestedListPath | ListPath, accounts: APIEntity[], next: string | null) => { return state.updateIn(path, map => { - return (map as List).set('next', next).update('items', list => (list as Items).concat(accounts.map(item => item.id))); + return (map as List) + .set('next', next) + .set('isLoading', false) + .update('items', list => (list as Items).concat(accounts.map(item => item.id))); }); }; diff --git a/app/styles/application.scss b/app/styles/application.scss index 3b3bd527c..ed74ec3aa 100644 --- a/app/styles/application.scss +++ b/app/styles/application.scss @@ -59,8 +59,6 @@ @import 'components/crypto-donate'; @import 'components/aliases'; @import 'components/icon'; -@import 'components/radio-button'; -@import 'components/directory'; @tailwind base; @tailwind components; diff --git a/app/styles/components/directory.scss b/app/styles/components/directory.scss deleted file mode 100644 index 7dc8e48cd..000000000 --- a/app/styles/components/directory.scss +++ /dev/null @@ -1,179 +0,0 @@ -.directory { - &__filter-form { - display: flex; - gap: 30px; - background: var(--foreground-color); - - &__column { - padding-bottom: 10px; - } - - .radio-button { - display: block; - } - } - - &__list { - display: grid; - grid-gap: 10px; - grid-template-columns: minmax(0, 50%) minmax(0, 50%); - width: 100%; - transition: opacity 100ms ease-in; - box-sizing: border-box; - - &.loading { - opacity: 0.7; - } - - @media screen and (max-width: 630px) { - grid-template-columns: minmax(0, 100%); - } - } - - &__card { - @apply rounded-lg bg-gray-100 dark:bg-primary-800; - box-sizing: border-box; - margin-bottom: 0; - box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.1); - overflow: hidden; - position: relative; - - &__info { - z-index: 1; - position: absolute; - top: 10px; - left: 10px; - } - - &__action-button { - z-index: 1; - position: absolute; - top: 78px; - right: 12px; - } - - &__img { - @apply bg-primary-200 dark:bg-gray-600; - height: 125px; - position: relative; - - img { - display: block; - width: 100%; - height: 100%; - margin: 0; - object-fit: cover; - } - } - - &__bar { - @apply bg-primary-200 dark:bg-primary-700; - display: flex; - align-items: center; - padding: 10px; - - &__name { - flex: 1 1 auto; - display: flex; - align-items: center; - text-decoration: none; - overflow: hidden; - } - - .account__avatar { - flex: 0 0 auto; - width: 48px; - min-width: 48px; - height: 48px; - padding-top: 2px; - - img { - width: 100%; - height: 100%; - display: block; - margin: 0; - border-radius: 4px; - background: var(--brand-color--faint); - object-fit: cover; - } - } - - .display-name { - margin-left: 15px; - text-align: left; - - strong { - @apply text-black dark:text-white; - font-size: 15px; - font-weight: 500; - overflow: hidden; - text-overflow: ellipsis; - } - - span:not(.verified-icon) { - @apply text-gray-500 dark:text-gray-400; - display: block; - font-size: 14px; - font-weight: 400; - overflow: hidden; - text-overflow: ellipsis; - } - - .verified-icon div, - .verified-icon svg { - @apply inline; - } - } - } - - &__extra { - background: var(--foreground-color); - display: flex; - align-items: center; - justify-content: center; - - .accounts-table__count { - padding: 15px 0; - text-align: center; - font-size: 15px; - font-weight: 500; - width: 33.33%; - flex: 0 0 auto; - - small { - display: block; - color: var(--primary-text-color--faint); - font-weight: 400; - font-size: 14px; - } - } - - .account__header__content { - @apply border-b border-solid border-gray-200 dark:border-primary-500; - box-sizing: border-box; - padding: 15px 10px; - width: 100%; - min-height: 50px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - - &.empty { - border-color: transparent; - } - - p { - display: none; - - &:first-child { - display: inline; - } - } - - br { - display: none; - } - } - } - } -} diff --git a/app/styles/components/radio-button.scss b/app/styles/components/radio-button.scss deleted file mode 100644 index 77fb82846..000000000 --- a/app/styles/components/radio-button.scss +++ /dev/null @@ -1,38 +0,0 @@ -.radio-button { - @apply text-black dark:text-white; - font-size: 14px; - position: relative; - display: inline-block; - padding: 6px 0; - line-height: 18px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - cursor: pointer; - - input[type=radio], - input[type=checkbox] { - display: none; - } - - &__input { - @apply inline-block relative box-border border border-solid border-primary-600; - width: 18px; - height: 18px; - flex: 0 0 auto; - margin-right: 10px; - top: -1px; - border-radius: 50%; - vertical-align: middle; - - &.checked { - @apply bg-primary-600; - } - - &:active, - &:focus, - &:hover { - @apply border-4; - } - } -}