diff --git a/app/soapbox/components/status-content.css b/app/soapbox/components/status-content.css new file mode 100644 index 000000000..7c1317d16 --- /dev/null +++ b/app/soapbox/components/status-content.css @@ -0,0 +1,77 @@ +.status-content p { + @apply mb-5 whitespace-pre-wrap; +} + +.status-content p:last-child { + @apply mb-0.5; +} + +.status-content a { + @apply text-primary-600 dark:text-accent-blue hover:underline; +} + +.status-content strong { + @apply font-bold; +} + +.status-content em { + @apply italic; +} + +.status-content ul, +.status-content ol { + @apply pl-10 mb-5; +} + +.status-content ul { + @apply list-disc list-outside; +} + +.status-content ol { + @apply list-decimal list-outside; +} + +.status-content blockquote { + @apply py-1 pl-4 mb-5 border-l-4 border-solid border-gray-400 text-gray-500 dark:text-gray-400; +} + +.status-content code { + @apply cursor-text font-mono; +} + +.status-content p > code, +.status-content pre { + @apply bg-gray-100 dark:bg-primary-800; +} + +/* Inline code */ +.status-content p > code { + @apply py-0.5 px-1 rounded-sm; +} + +/* Code block */ +.status-content pre { + @apply py-2 px-3 mb-5 leading-6 overflow-x-auto rounded-md break-all; +} + +.status-content pre:last-child { + @apply mb-0; +} + +/* Markdown images */ +.status-content img:not(.emojione):not([width][height]) { + @apply w-full h-72 object-contain rounded-lg overflow-hidden my-5 block; +} + +/* User setting to underline links */ +body.underline-links .status-content a { + @apply underline; +} + +.status-content .big-emoji img.emojione { + @apply inline w-9 h-9 p-1; +} + +.status-content .status-link { + @apply hover:underline text-primary-600 dark:text-accent-blue hover:text-primary-800 dark:hover:text-accent-blue; +} diff --git a/app/soapbox/components/status_content.tsx b/app/soapbox/components/status_content.tsx index 2a8972315..7d771ec37 100644 --- a/app/soapbox/components/status_content.tsx +++ b/app/soapbox/components/status_content.tsx @@ -11,6 +11,7 @@ import { onlyEmoji as isOnlyEmoji } from 'soapbox/utils/rich_content'; import { isRtl } from '../rtl'; import Poll from './polls/poll'; +import './status-content.css'; import type { Status, Mention } from 'soapbox/types/entities'; @@ -28,7 +29,7 @@ interface IReadMoreButton { /** Button to expand a truncated status (due to too much content) */ const ReadMoreButton: React.FC = ({ onClick }) => ( - @@ -48,7 +49,7 @@ const SpoilerButton: React.FC = ({ onClick, hidden, tabIndex }) 'inline-block rounded-md px-1.5 py-0.5 ml-[0.5em]', 'text-gray-900 dark:text-gray-100', 'font-bold text-[11px] uppercase', - 'bg-primary-100 dark:bg-primary-900', + 'bg-primary-100 dark:bg-primary-800', 'hover:bg-primary-300 dark:hover:bg-primary-600', 'focus:bg-primary-200 dark:focus:bg-primary-600', 'hover:no-underline', @@ -212,15 +213,18 @@ const StatusContent: React.FC = ({ status, expanded = false, onE } const isHidden = onExpandedToggle ? !expanded : hidden; + const withSpoiler = status.spoiler_text.length > 0; + + const baseClassName = 'text-gray-900 dark:text-gray-100 break-words text-ellipsis overflow-hidden relative focus:outline-none'; const content = { __html: parsedHtml }; const spoilerContent = { __html: status.spoilerHtml }; const directionStyle: React.CSSProperties = { direction: 'ltr' }; - const className = classNames('status__content', { - 'status__content--with-action': onClick, - 'status__content--with-spoiler': status.spoiler_text.length > 0, - 'status__content--collapsed': collapsed, - 'status__content--big': onlyEmoji, + const className = classNames(baseClassName, 'status-content', { + 'cursor-pointer': onClick, + 'whitespace-normal': withSpoiler, + 'max-h-[300px]': collapsed, + 'leading-normal big-emoji': onlyEmoji, }); if (isRtl(status.search_index)) { @@ -242,8 +246,10 @@ const StatusContent: React.FC = ({ status, expanded = false, onE
= ({ status, expanded = false, onE ref={node} tabIndex={0} key='content' - className={classNames('status__content', { - 'status__content--big': onlyEmoji, + className={classNames(baseClassName, 'status-content', { + 'leading-normal big-emoji': onlyEmoji, })} style={directionStyle} dangerouslySetInnerHTML={content} diff --git a/app/soapbox/features/landing_page/index.tsx b/app/soapbox/features/landing_page/index.tsx index 76e77bcfa..937e599c8 100644 --- a/app/soapbox/features/landing_page/index.tsx +++ b/app/soapbox/features/landing_page/index.tsx @@ -8,6 +8,8 @@ import RegistrationForm from 'soapbox/features/auth_login/components/registratio import { useAppDispatch, useAppSelector, useFeatures, useSoapboxConfig } from 'soapbox/hooks'; import { capitalize } from 'soapbox/utils/strings'; +import './instance-description.css'; + const LandingPage = () => { const dispatch = useAppDispatch(); const features = useFeatures(); diff --git a/app/soapbox/features/landing_page/instance-description.css b/app/soapbox/features/landing_page/instance-description.css new file mode 100644 index 000000000..f67097de0 --- /dev/null +++ b/app/soapbox/features/landing_page/instance-description.css @@ -0,0 +1,14 @@ +/* Instance HTML from the API. */ +.instance-description a { + @apply underline; +} + +.instance-description b, +.instance-description strong { + @apply font-bold; +} + +.instance-description i, +.instance-description em { + @apply italic; +} diff --git a/app/soapbox/normalizers/soapbox/soapbox_config.ts b/app/soapbox/normalizers/soapbox/soapbox_config.ts index 0e6b5c280..75426e6c0 100644 --- a/app/soapbox/normalizers/soapbox/soapbox_config.ts +++ b/app/soapbox/normalizers/soapbox/soapbox_config.ts @@ -44,6 +44,7 @@ const DEFAULT_COLORS = ImmutableMap({ 900: '#7f1d1d', }), 'sea-blue': '#2feecc', + 'greentext': '#789922', }); export const PromoPanelItemRecord = ImmutableRecord({ diff --git a/app/soapbox/utils/greentext.ts b/app/soapbox/utils/greentext.ts index 52a25e2be..eab93b22a 100644 --- a/app/soapbox/utils/greentext.ts +++ b/app/soapbox/utils/greentext.ts @@ -11,7 +11,7 @@ export const addGreentext = (html: string): string => { .replace(/@\w+/gi, '') // remove mentions (even failed ones) .trim() .startsWith('>')) { - return `${string}`; + return `${string}`; } else { return string; } diff --git a/app/styles/basics.scss b/app/styles/basics.scss index 9384c94f2..9a9eac717 100644 --- a/app/styles/basics.scss +++ b/app/styles/basics.scss @@ -99,12 +99,8 @@ noscript { } } -.floating-link { - @apply w-full h-full inset-0 absolute z-10; -} - -.greentext { - color: #789922; +.emojione { + @apply w-5 h-5 -mt-[3px] inline; } // Virtuoso empty placeholder fix. @@ -112,20 +108,3 @@ noscript { div[data-viewport-type="window"] { position: static !important; } - -// Instance HTML from the API. -.instance-description { - a { - @apply underline; - } - - b, - strong { - @apply font-bold; - } - - i, - em { - @apply italic; - } -} diff --git a/app/styles/chats.scss b/app/styles/chats.scss index 5bfb5362c..fe3d2182a 100644 --- a/app/styles/chats.scss +++ b/app/styles/chats.scss @@ -400,3 +400,7 @@ font-size: 13px; opacity: 0.8; } + +.floating-link { + @apply w-full h-full inset-0 absolute z-10; +} diff --git a/app/styles/components/status.scss b/app/styles/components/status.scss index 83670fc38..a8c8e4561 100644 --- a/app/styles/components/status.scss +++ b/app/styles/components/status.scss @@ -1,125 +1,3 @@ -.status__content { - p, - li { - strong { - font-weight: bold; - } - } - - p, - li { - em { - font-style: italic; - } - } - - ul, - ol { - @apply pl-10; - } - - ul { - list-style: disc outside none; - } - - ol { - list-style: decimal outside none; - } - - blockquote { - @apply py-1 pl-4 border-l-4 border-solid border-gray-400 text-gray-500 dark:text-gray-400; - } - - code { - font-family: 'Roboto Mono', monospace; - cursor: text; - } - - p > code, - pre { - @apply bg-gray-100 dark:bg-primary-800; - } - - /* Inline code */ - p > code { - padding: 2px 4px; - border-radius: 4px; - } - - /* Code block */ - pre { - line-height: 1.6em; - overflow-x: auto; - border-radius: 6px; - padding: 8px 12px; - margin-bottom: 20px; - word-break: break-all; - - &:last-child { - margin-bottom: 0; - } - } - - /* Markdown images */ - img:not(.emojione):not([width][height]) { - width: 100%; - height: 285.188px; - object-fit: contain; - background: var(--background-color); - border-radius: 4px; - overflow: hidden; - margin: 20px 0; - display: block; - } - - &--big { - line-height: normal !important; - - img.emojione { - display: inline; - width: 36px; - height: 36px; - padding: 5px; - } - } - - &--quote { - ul, - ol { - @apply pl-4; - } - - blockquote { - @apply pl-2; - } - } -} - -.status__content > ul, -.status__content > ol { - margin-bottom: 20px; -} - -.status__content > blockquote { - margin-bottom: 20px; -} - -.status__content--with-action { - cursor: pointer; -} - -.status__content.status__content--collapsed { - max-height: 20px * 15; // 15 lines is roughly above 500 characters -} - -.status__content__read-more-button { - @apply flex items-center text-gray-900 dark:text-gray-300 border-0 bg-transparent p-0 pt-2 hover:underline active:underline; -} - -.status-link { - @apply hover:underline text-primary-600 dark:text-accent-blue hover:text-primary-800 dark:hover:text-accent-blue; -} - .status { @apply min-h-[54px] cursor-default; @@ -216,63 +94,6 @@ padding: 10px; } -.status__content { - @apply text-gray-900 dark:text-gray-100 break-words text-ellipsis overflow-hidden relative; - - &:focus { - @apply outline-none; - } - - &.status__content--with-spoiler { - @apply whitespace-normal; - - .status__content__text { - @apply whitespace-pre-wrap; - } - } - - .emojione { - width: 20px; - height: 20px; - margin: -3px 0 0; - display: inline; - } - - p { - margin-bottom: 20px; - white-space: pre-wrap; - - &:last-child { - margin-bottom: 2px; - } - } - - a { - @apply text-primary-600 dark:text-accent-blue hover:underline; - - .fa { - color: var(--primary-text-color); - } - } - - .status__content__text { - display: none; - - &.status__content__text--visible { - display: block; - } - } -} - -.underline-links { - .status__content, - .reply-indicator__content { - a { - text-decoration: underline; - } - } -} - .focusable:focus, .focusable-within:focus-within { outline: 0; /* Required b/c HotKeys lib sets this outline */ diff --git a/tailwind.config.js b/tailwind.config.js index 091f7f823..d635c19e7 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -35,6 +35,11 @@ module.exports = { 'Segoe UI Symbol', 'Noto Color Emoji', ], + 'mono': [ + 'Roboto Mono', + 'ui-monospace', + 'mono', + ], }, colors: parseColorMatrix({ // Define color matrix (of available colors) @@ -49,6 +54,7 @@ module.exports = { 'gradient-start': true, 'gradient-end': true, 'sea-blue': true, + 'greentext': true, }), animation: { 'sonar-scale-4': 'sonar-scale-4 3s linear infinite',