Add author links on the explore page in web UI (#30521)
This commit is contained in:
		
					parent
					
						
							
								37f53542fe
							
						
					
				
			
			
				commit
				
					
						ed6d24330b
					
				
			
		
					 11 changed files with 185 additions and 80 deletions
				
			
		|  | @ -68,13 +68,17 @@ export function importFetchedStatuses(statuses) { | ||||||
|         status.filtered.forEach(result => pushUnique(filters, result.filter)); |         status.filtered.forEach(result => pushUnique(filters, result.filter)); | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       if (status.reblog && status.reblog.id) { |       if (status.reblog?.id) { | ||||||
|         processStatus(status.reblog); |         processStatus(status.reblog); | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       if (status.poll && status.poll.id) { |       if (status.poll?.id) { | ||||||
|         pushUnique(polls, normalizePoll(status.poll, getState().getIn(['polls', status.poll.id]))); |         pushUnique(polls, normalizePoll(status.poll, getState().getIn(['polls', status.poll.id]))); | ||||||
|       } |       } | ||||||
|  | 
 | ||||||
|  |       if (status.card?.author_account) { | ||||||
|  |         pushUnique(accounts, status.card.author_account); | ||||||
|  |       } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     statuses.forEach(processStatus); |     statuses.forEach(processStatus); | ||||||
|  |  | ||||||
|  | @ -36,6 +36,10 @@ export function normalizeStatus(status, normalOldStatus) { | ||||||
|     normalStatus.poll = status.poll.id; |     normalStatus.poll = status.poll.id; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   if (status.card?.author_account) { | ||||||
|  |     normalStatus.card = { ...status.card, author_account: status.card.author_account.id }; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   if (status.filtered) { |   if (status.filtered) { | ||||||
|     normalStatus.filtered = status.filtered.map(normalizeFilterResult); |     normalStatus.filtered = status.filtered.map(normalizeFilterResult); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| import api, { getLinks } from '../api'; | import api, { getLinks } from '../api'; | ||||||
| 
 | 
 | ||||||
| import { importFetchedStatuses } from './importer'; | import { importFetchedStatuses, importFetchedAccounts } from './importer'; | ||||||
| 
 | 
 | ||||||
| export const TRENDS_TAGS_FETCH_REQUEST = 'TRENDS_TAGS_FETCH_REQUEST'; | export const TRENDS_TAGS_FETCH_REQUEST = 'TRENDS_TAGS_FETCH_REQUEST'; | ||||||
| export const TRENDS_TAGS_FETCH_SUCCESS = 'TRENDS_TAGS_FETCH_SUCCESS'; | export const TRENDS_TAGS_FETCH_SUCCESS = 'TRENDS_TAGS_FETCH_SUCCESS'; | ||||||
|  | @ -49,8 +49,11 @@ export const fetchTrendingLinks = () => (dispatch) => { | ||||||
|   dispatch(fetchTrendingLinksRequest()); |   dispatch(fetchTrendingLinksRequest()); | ||||||
| 
 | 
 | ||||||
|   api() |   api() | ||||||
|     .get('/api/v1/trends/links') |     .get('/api/v1/trends/links', { params: { limit: 20 } }) | ||||||
|     .then(({ data }) => dispatch(fetchTrendingLinksSuccess(data))) |     .then(({ data }) => { | ||||||
|  |       dispatch(importFetchedAccounts(data.map(link => link.author_account).filter(account => !!account))); | ||||||
|  |       dispatch(fetchTrendingLinksSuccess(data)); | ||||||
|  |     }) | ||||||
|     .catch(err => dispatch(fetchTrendingLinksFail(err))); |     .catch(err => dispatch(fetchTrendingLinksFail(err))); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										19
									
								
								app/javascript/mastodon/components/more_from_author.jsx
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								app/javascript/mastodon/components/more_from_author.jsx
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | ||||||
|  | import PropTypes from 'prop-types'; | ||||||
|  | 
 | ||||||
|  | import { FormattedMessage } from 'react-intl'; | ||||||
|  | 
 | ||||||
|  | import { AuthorLink } from 'mastodon/features/explore/components/author_link'; | ||||||
|  | 
 | ||||||
|  | export const MoreFromAuthor = ({ accountId }) => ( | ||||||
|  |   <div className='more-from-author'> | ||||||
|  |     <svg viewBox='0 0 79 79' className='logo logo--icon' role='img'> | ||||||
|  |       <use xlinkHref='#logo-symbol-icon' /> | ||||||
|  |     </svg> | ||||||
|  | 
 | ||||||
|  |     <FormattedMessage id='link_preview.more_from_author' defaultMessage='More from {name}' values={{ name: <AuthorLink accountId={accountId} /> }} /> | ||||||
|  |   </div> | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | MoreFromAuthor.propTypes = { | ||||||
|  |   accountId: PropTypes.string.isRequired, | ||||||
|  | }; | ||||||
|  | @ -0,0 +1,21 @@ | ||||||
|  | import PropTypes from 'prop-types'; | ||||||
|  | 
 | ||||||
|  | import { Link } from 'react-router-dom'; | ||||||
|  | 
 | ||||||
|  | import { Avatar } from 'mastodon/components/avatar'; | ||||||
|  | import { useAppSelector } from 'mastodon/store'; | ||||||
|  | 
 | ||||||
|  | export const AuthorLink = ({ accountId }) => { | ||||||
|  |   const account = useAppSelector(state => state.getIn(['accounts', accountId])); | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <Link to={`/@${account.get('acct')}`} className='story__details__shared__author-link'> | ||||||
|  |       <Avatar account={account} size={16} /> | ||||||
|  |       <bdi dangerouslySetInnerHTML={{ __html: account.get('display_name_html') }} /> | ||||||
|  |     </Link> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | AuthorLink.propTypes = { | ||||||
|  |   accountId: PropTypes.string.isRequired, | ||||||
|  | }; | ||||||
|  | @ -1,61 +1,89 @@ | ||||||
| import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||||
| import { PureComponent } from 'react'; | import { useState, useCallback } from 'react'; | ||||||
| 
 | 
 | ||||||
| import { FormattedMessage } from 'react-intl'; | import { FormattedMessage } from 'react-intl'; | ||||||
| 
 | 
 | ||||||
| import classNames from 'classnames'; | import classNames from 'classnames'; | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| import { Blurhash } from 'mastodon/components/blurhash'; | import { Blurhash } from 'mastodon/components/blurhash'; | ||||||
| import { accountsCountRenderer } from 'mastodon/components/hashtag'; |  | ||||||
| import { RelativeTimestamp } from 'mastodon/components/relative_timestamp'; | import { RelativeTimestamp } from 'mastodon/components/relative_timestamp'; | ||||||
| import { ShortNumber } from 'mastodon/components/short_number'; | import { ShortNumber } from 'mastodon/components/short_number'; | ||||||
| import { Skeleton } from 'mastodon/components/skeleton'; | import { Skeleton } from 'mastodon/components/skeleton'; | ||||||
| 
 | 
 | ||||||
| export default class Story extends PureComponent { | import { AuthorLink } from './author_link'; | ||||||
| 
 | 
 | ||||||
|   static propTypes = { | const sharesCountRenderer = (displayNumber, pluralReady) => ( | ||||||
|     url: PropTypes.string, |   <FormattedMessage | ||||||
|     title: PropTypes.string, |     id='link_preview.shares' | ||||||
|     lang: PropTypes.string, |     defaultMessage='{count, plural, one {{counter} post} other {{counter} posts}}' | ||||||
|     publisher: PropTypes.string, |     values={{ | ||||||
|     publishedAt: PropTypes.string, |       count: pluralReady, | ||||||
|     author: PropTypes.string, |       counter: <strong>{displayNumber}</strong>, | ||||||
|     sharedTimes: PropTypes.number, |     }} | ||||||
|     thumbnail: PropTypes.string, |   /> | ||||||
|     thumbnailDescription: PropTypes.string, | ); | ||||||
|     blurhash: PropTypes.string, |  | ||||||
|     expanded: PropTypes.bool, |  | ||||||
|   }; |  | ||||||
| 
 | 
 | ||||||
|   state = { | export const Story = ({ | ||||||
|     thumbnailLoaded: false, |   url, | ||||||
|   }; |   title, | ||||||
|  |   lang, | ||||||
|  |   publisher, | ||||||
|  |   publishedAt, | ||||||
|  |   author, | ||||||
|  |   authorAccount, | ||||||
|  |   sharedTimes, | ||||||
|  |   thumbnail, | ||||||
|  |   thumbnailDescription, | ||||||
|  |   blurhash, | ||||||
|  |   expanded | ||||||
|  | }) => { | ||||||
|  |   const [thumbnailLoaded, setThumbnailLoaded] = useState(false); | ||||||
| 
 | 
 | ||||||
|   handleImageLoad = () => this.setState({ thumbnailLoaded: true }); |   const handleImageLoad = useCallback(() => { | ||||||
|  |     setThumbnailLoaded(true); | ||||||
|  |   }, [setThumbnailLoaded]); | ||||||
| 
 | 
 | ||||||
|   render () { |   return ( | ||||||
|     const { expanded, url, title, lang, publisher, author, publishedAt, sharedTimes, thumbnail, thumbnailDescription, blurhash } = this.props; |     <div className={classNames('story', { expanded })}> | ||||||
| 
 |       <div className='story__details'> | ||||||
|     const { thumbnailLoaded } = this.state; |         <div className='story__details__publisher'> | ||||||
| 
 |           {publisher ? <span lang={lang}>{publisher}</span> : <Skeleton width={50} />}{publishedAt && <> · <RelativeTimestamp timestamp={publishedAt} /></>} | ||||||
|     return ( |  | ||||||
|       <a className={classNames('story', { expanded })} href={url} target='blank' rel='noopener'> |  | ||||||
|         <div className='story__details'> |  | ||||||
|           <div className='story__details__publisher'>{publisher ? <span lang={lang}>{publisher}</span> : <Skeleton width={50} />}{publishedAt && <> · <RelativeTimestamp timestamp={publishedAt} /></>}</div> |  | ||||||
|           <div className='story__details__title' lang={lang}>{title ? title : <Skeleton />}</div> |  | ||||||
|           <div className='story__details__shared'>{author && <><FormattedMessage id='link_preview.author' defaultMessage='By {name}' values={{ name: <strong>{author}</strong> }} /> · </>}{typeof sharedTimes === 'number' ? <ShortNumber value={sharedTimes} renderer={accountsCountRenderer} /> : <Skeleton width={100} />}</div> |  | ||||||
|         </div> |         </div> | ||||||
| 
 | 
 | ||||||
|         <div className='story__thumbnail'> |         <a className='story__details__title' lang={lang} href={url} target='blank' rel='noopener'> | ||||||
|           {thumbnail ? ( |           {title ? title : <Skeleton />} | ||||||
|             <> |         </a> | ||||||
|               <div className={classNames('story__thumbnail__preview', { 'story__thumbnail__preview--hidden': thumbnailLoaded })}><Blurhash hash={blurhash} /></div> | 
 | ||||||
|               <img src={thumbnail} onLoad={this.handleImageLoad} alt={thumbnailDescription} title={thumbnailDescription} lang={lang} /> |         <div className='story__details__shared'> | ||||||
|             </> |           {author ? <FormattedMessage id='link_preview.author' className='story__details__shared__author' defaultMessage='By {name}' values={{ name: authorAccount ? <AuthorLink accountId={authorAccount} /> : <strong>{author}</strong> }} /> : <span />} | ||||||
|           ) : <Skeleton />} |           {typeof sharedTimes === 'number' ? <span className='story__details__shared__pill'><ShortNumber value={sharedTimes} renderer={sharesCountRenderer} /></span> : <Skeleton width='10ch' />} | ||||||
|         </div> |         </div> | ||||||
|  |       </div> | ||||||
|  | 
 | ||||||
|  |       <a className='story__thumbnail' href={url} target='blank' rel='noopener'> | ||||||
|  |         {thumbnail ? ( | ||||||
|  |           <> | ||||||
|  |             <div className={classNames('story__thumbnail__preview', { 'story__thumbnail__preview--hidden': thumbnailLoaded })}><Blurhash hash={blurhash} /></div> | ||||||
|  |             <img src={thumbnail} onLoad={handleImageLoad} alt={thumbnailDescription} title={thumbnailDescription} lang={lang} /> | ||||||
|  |           </> | ||||||
|  |         ) : <Skeleton />} | ||||||
|       </a> |       </a> | ||||||
|     ); |     </div> | ||||||
|   } |   ); | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| } | Story.propTypes = { | ||||||
|  |   url: PropTypes.string, | ||||||
|  |   title: PropTypes.string, | ||||||
|  |   lang: PropTypes.string, | ||||||
|  |   publisher: PropTypes.string, | ||||||
|  |   publishedAt: PropTypes.string, | ||||||
|  |   author: PropTypes.string, | ||||||
|  |   authorAccount: PropTypes.string, | ||||||
|  |   sharedTimes: PropTypes.number, | ||||||
|  |   thumbnail: PropTypes.string, | ||||||
|  |   thumbnailDescription: PropTypes.string, | ||||||
|  |   blurhash: PropTypes.string, | ||||||
|  |   expanded: PropTypes.bool, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ import { DismissableBanner } from 'mastodon/components/dismissable_banner'; | ||||||
| import { LoadingIndicator } from 'mastodon/components/loading_indicator'; | import { LoadingIndicator } from 'mastodon/components/loading_indicator'; | ||||||
| import { WithRouterPropTypes } from 'mastodon/utils/react_router'; | import { WithRouterPropTypes } from 'mastodon/utils/react_router'; | ||||||
| 
 | 
 | ||||||
| import Story from './components/story'; | import { Story } from './components/story'; | ||||||
| 
 | 
 | ||||||
| const mapStateToProps = state => ({ | const mapStateToProps = state => ({ | ||||||
|   links: state.getIn(['trends', 'links', 'items']), |   links: state.getIn(['trends', 'links', 'items']), | ||||||
|  | @ -75,6 +75,7 @@ class Links extends PureComponent { | ||||||
|             publisher={link.get('provider_name')} |             publisher={link.get('provider_name')} | ||||||
|             publishedAt={link.get('published_at')} |             publishedAt={link.get('published_at')} | ||||||
|             author={link.get('author_name')} |             author={link.get('author_name')} | ||||||
|  |             authorAccount={link.getIn(['author_account', 'id'])} | ||||||
|             sharedTimes={link.getIn(['history', 0, 'accounts']) * 1 + link.getIn(['history', 1, 'accounts']) * 1} |             sharedTimes={link.getIn(['history', 0, 'accounts']) * 1 + link.getIn(['history', 1, 'accounts']) * 1} | ||||||
|             thumbnail={link.get('image')} |             thumbnail={link.get('image')} | ||||||
|             thumbnailDescription={link.get('image_description')} |             thumbnailDescription={link.get('image_description')} | ||||||
|  |  | ||||||
|  | @ -6,7 +6,6 @@ import { PureComponent } from 'react'; | ||||||
| import { FormattedMessage } from 'react-intl'; | import { FormattedMessage } from 'react-intl'; | ||||||
| 
 | 
 | ||||||
| import classNames from 'classnames'; | import classNames from 'classnames'; | ||||||
| import { Link } from 'react-router-dom'; |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| import Immutable from 'immutable'; | import Immutable from 'immutable'; | ||||||
|  | @ -15,9 +14,9 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; | ||||||
| import DescriptionIcon from '@/material-icons/400-24px/description-fill.svg?react'; | import DescriptionIcon from '@/material-icons/400-24px/description-fill.svg?react'; | ||||||
| import OpenInNewIcon from '@/material-icons/400-24px/open_in_new.svg?react'; | import OpenInNewIcon from '@/material-icons/400-24px/open_in_new.svg?react'; | ||||||
| import PlayArrowIcon from '@/material-icons/400-24px/play_arrow-fill.svg?react'; | import PlayArrowIcon from '@/material-icons/400-24px/play_arrow-fill.svg?react'; | ||||||
| import { Avatar } from 'mastodon/components/avatar'; |  | ||||||
| import { Blurhash } from 'mastodon/components/blurhash'; | import { Blurhash } from 'mastodon/components/blurhash'; | ||||||
| import { Icon }  from 'mastodon/components/icon'; | import { Icon }  from 'mastodon/components/icon'; | ||||||
|  | import { MoreFromAuthor } from 'mastodon/components/more_from_author'; | ||||||
| import { RelativeTimestamp } from 'mastodon/components/relative_timestamp'; | import { RelativeTimestamp } from 'mastodon/components/relative_timestamp'; | ||||||
| import { useBlurhash } from 'mastodon/initial_state'; | import { useBlurhash } from 'mastodon/initial_state'; | ||||||
| 
 | 
 | ||||||
|  | @ -59,20 +58,6 @@ const addAutoPlay = html => { | ||||||
|   return html; |   return html; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const MoreFromAuthor = ({ author }) => ( |  | ||||||
|   <div className='more-from-author'> |  | ||||||
|     <svg viewBox='0 0 79 79' className='logo logo--icon' role='img'> |  | ||||||
|       <use xlinkHref='#logo-symbol-icon' /> |  | ||||||
|     </svg> |  | ||||||
| 
 |  | ||||||
|     <FormattedMessage id='link_preview.more_from_author' defaultMessage='More from {name}' values={{ name: <Link to={`/@${author.get('acct')}`}><Avatar account={author} size={16} /> {author.get('display_name')}</Link> }} /> |  | ||||||
|   </div> |  | ||||||
| ); |  | ||||||
| 
 |  | ||||||
| MoreFromAuthor.propTypes = { |  | ||||||
|   author: ImmutablePropTypes.map, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| export default class Card extends PureComponent { | export default class Card extends PureComponent { | ||||||
| 
 | 
 | ||||||
|   static propTypes = { |   static propTypes = { | ||||||
|  | @ -259,7 +244,7 @@ export default class Card extends PureComponent { | ||||||
|           {description} |           {description} | ||||||
|         </a> |         </a> | ||||||
| 
 | 
 | ||||||
|         {showAuthor && <MoreFromAuthor author={card.get('author_account')} />} |         {showAuthor && <MoreFromAuthor accountId={card.get('author_account')} />} | ||||||
|       </> |       </> | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | @ -415,6 +415,7 @@ | ||||||
|   "limited_account_hint.title": "This profile has been hidden by the moderators of {domain}.", |   "limited_account_hint.title": "This profile has been hidden by the moderators of {domain}.", | ||||||
|   "link_preview.author": "By {name}", |   "link_preview.author": "By {name}", | ||||||
|   "link_preview.more_from_author": "More from {name}", |   "link_preview.more_from_author": "More from {name}", | ||||||
|  |   "link_preview.shares": "{count, plural, one {{counter} post} other {{counter} posts}}", | ||||||
|   "lists.account.add": "Add to list", |   "lists.account.add": "Add to list", | ||||||
|   "lists.account.remove": "Remove from list", |   "lists.account.remove": "Remove from list", | ||||||
|   "lists.delete": "Delete list", |   "lists.delete": "Delete list", | ||||||
|  |  | ||||||
|  | @ -8796,43 +8796,80 @@ noscript { | ||||||
|   display: flex; |   display: flex; | ||||||
|   align-items: center; |   align-items: center; | ||||||
|   color: $primary-text-color; |   color: $primary-text-color; | ||||||
|   text-decoration: none; |   padding: 16px; | ||||||
|   padding: 15px; |  | ||||||
|   border-bottom: 1px solid var(--background-border-color); |   border-bottom: 1px solid var(--background-border-color); | ||||||
|   gap: 15px; |   gap: 16px; | ||||||
| 
 | 
 | ||||||
|   &:last-child { |   &:last-child { | ||||||
|     border-bottom: 0; |     border-bottom: 0; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   &:hover, |  | ||||||
|   &:active, |  | ||||||
|   &:focus { |  | ||||||
|     color: $highlight-text-color; |  | ||||||
| 
 |  | ||||||
|     .story__details__publisher, |  | ||||||
|     .story__details__shared { |  | ||||||
|       color: $highlight-text-color; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   &__details { |   &__details { | ||||||
|     flex: 1 1 auto; |     flex: 1 1 auto; | ||||||
| 
 | 
 | ||||||
|     &__publisher { |     &__publisher { | ||||||
|       color: $darker-text-color; |       color: $darker-text-color; | ||||||
|       margin-bottom: 8px; |       margin-bottom: 8px; | ||||||
|  |       font-size: 14px; | ||||||
|  |       line-height: 20px; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     &__title { |     &__title { | ||||||
|  |       display: block; | ||||||
|       font-size: 19px; |       font-size: 19px; | ||||||
|       line-height: 24px; |       line-height: 24px; | ||||||
|       font-weight: 500; |       font-weight: 500; | ||||||
|       margin-bottom: 8px; |       margin-bottom: 8px; | ||||||
|  |       text-decoration: none; | ||||||
|  |       color: $primary-text-color; | ||||||
|  | 
 | ||||||
|  |       &:hover, | ||||||
|  |       &:active, | ||||||
|  |       &:focus { | ||||||
|  |         color: $highlight-text-color; | ||||||
|  |       } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     &__shared { |     &__shared { | ||||||
|  |       display: flex; | ||||||
|  |       align-items: center; | ||||||
|       color: $darker-text-color; |       color: $darker-text-color; | ||||||
|  |       gap: 8px; | ||||||
|  |       justify-content: space-between; | ||||||
|  |       font-size: 14px; | ||||||
|  |       line-height: 20px; | ||||||
|  | 
 | ||||||
|  |       & > span { | ||||||
|  |         display: flex; | ||||||
|  |         align-items: center; | ||||||
|  |         gap: 4px; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       &__pill { | ||||||
|  |         background: var(--surface-variant-background-color); | ||||||
|  |         border-radius: 4px; | ||||||
|  |         color: inherit; | ||||||
|  |         text-decoration: none; | ||||||
|  |         padding: 4px 12px; | ||||||
|  |         font-size: 12px; | ||||||
|  |         font-weight: 500; | ||||||
|  |         line-height: 16px; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       &__author-link { | ||||||
|  |         display: inline-flex; | ||||||
|  |         align-items: center; | ||||||
|  |         gap: 4px; | ||||||
|  |         color: $primary-text-color; | ||||||
|  |         font-weight: 500; | ||||||
|  |         text-decoration: none; | ||||||
|  | 
 | ||||||
|  |         &:hover, | ||||||
|  |         &:active, | ||||||
|  |         &:focus { | ||||||
|  |           color: $highlight-text-color; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     strong { |     strong { | ||||||
|  | @ -9903,14 +9940,14 @@ noscript { | ||||||
|     color: inherit; |     color: inherit; | ||||||
|     text-decoration: none; |     text-decoration: none; | ||||||
|     padding: 4px 12px; |     padding: 4px 12px; | ||||||
|     background: $ui-base-color; |     background: var(--surface-variant-background-color); | ||||||
|     border-radius: 4px; |     border-radius: 4px; | ||||||
|     font-weight: 500; |     font-weight: 500; | ||||||
| 
 | 
 | ||||||
|     &:hover, |     &:hover, | ||||||
|     &:focus, |     &:focus, | ||||||
|     &:active { |     &:active { | ||||||
|       background: lighten($ui-base-color, 4%); |       background: var(--surface-variant-active-background-color); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -106,4 +106,6 @@ $font-monospace: 'mastodon-font-monospace' !default; | ||||||
|   --background-color: #{darken($ui-base-color, 8%)}; |   --background-color: #{darken($ui-base-color, 8%)}; | ||||||
|   --background-color-tint: #{rgba(darken($ui-base-color, 8%), 0.9)}; |   --background-color-tint: #{rgba(darken($ui-base-color, 8%), 0.9)}; | ||||||
|   --surface-background-color: #{darken($ui-base-color, 4%)}; |   --surface-background-color: #{darken($ui-base-color, 4%)}; | ||||||
|  |   --surface-variant-background-color: #{$ui-base-color}; | ||||||
|  |   --surface-variant-active-background-color: #{lighten($ui-base-color, 4%)}; | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue