Implement load transitions and fix resetting filters (#365)

This PR implements:
* Fade-in transitions when cells load in, making navigation and loading
appear less janky.
* When scrolling, skeleton reps show up before the actual ones load in.
* Resetting filters will also reset any set inclusions or exclusions
This commit is contained in:
Justin Edmund 2023-08-22 01:29:48 -07:00 committed by GitHub
parent 6dd2579e6e
commit 2d1af335c3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 371 additions and 69 deletions

View file

@ -1,5 +1,6 @@
import TableField from '~components/common/TableField' import TableField from '~components/common/TableField'
import MentionTypeahead from '../MentionTypeahead' import MentionTypeahead from '../MentionTypeahead'
import Typeahead from 'react-bootstrap-typeahead/types/core/Typeahead'
interface Props interface Props
extends React.DetailedHTMLProps< extends React.DetailedHTMLProps<
@ -11,6 +12,7 @@ interface Props
placeholder?: string placeholder?: string
inclusions: MentionItem[] inclusions: MentionItem[]
exclusions: MentionItem[] exclusions: MentionItem[]
typeaheadRef: React.Ref<Typeahead>
onUpdate: (content: MentionItem[]) => void onUpdate: (content: MentionItem[]) => void
} }
@ -20,6 +22,7 @@ const MentionTableField = ({
placeholder, placeholder,
inclusions, inclusions,
exclusions, exclusions,
typeaheadRef,
...props ...props
}: Props) => { }: Props) => {
return ( return (
@ -31,6 +34,7 @@ const MentionTableField = ({
label={label} label={label}
> >
<MentionTypeahead <MentionTypeahead
ref={typeaheadRef}
label={label} label={label}
description={description} description={description}
placeholder={placeholder} placeholder={placeholder}

View file

@ -1,3 +1,4 @@
import React from 'react'
import { useState } from 'react' import { useState } from 'react'
import { getCookie } from 'cookies-next' import { getCookie } from 'cookies-next'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
@ -14,6 +15,7 @@ import {
RenderMenuProps, RenderMenuProps,
Token, Token,
} from 'react-bootstrap-typeahead' } from 'react-bootstrap-typeahead'
import Typeahead from 'react-bootstrap-typeahead/types/core/Typeahead'
import api from '~utils/api' import api from '~utils/api'
import { numberToElement } from '~utils/elements' import { numberToElement } from '~utils/elements'
@ -41,14 +43,10 @@ interface RawSearchResponse {
element: number element: number
} }
const MentionTypeahead = ({ const MentionTypeahead = React.forwardRef<Typeahead, Props>(function Typeahead(
label, { label, description, placeholder, inclusions, exclusions, ...props }: Props,
description, forwardedRef
placeholder, ) {
inclusions,
exclusions,
...props
}: Props) => {
const { t } = useTranslation('common') const { t } = useTranslation('common')
const locale = getCookie('NEXT_LOCALE') const locale = getCookie('NEXT_LOCALE')
? (getCookie('NEXT_LOCALE') as string) ? (getCookie('NEXT_LOCALE') as string)
@ -159,6 +157,7 @@ const MentionTypeahead = ({
return ( return (
<AsyncTypeahead <AsyncTypeahead
multiple multiple
ref={forwardedRef}
className={styles.typeahead} className={styles.typeahead}
id={label} id={label}
align="left" align="left"
@ -166,7 +165,6 @@ const MentionTypeahead = ({
labelKey={(option) => (option as MentionItem).name[locale]} labelKey={(option) => (option as MentionItem).name[locale]}
defaultSelected={inclusions} defaultSelected={inclusions}
filterBy={() => true} filterBy={() => true}
minLength={3}
onSearch={handleSearch} onSearch={handleSearch}
options={options} options={options}
useCache={false} useCache={false}
@ -181,6 +179,6 @@ const MentionTypeahead = ({
onChange={(selected) => props.onUpdate(selected as MentionItem[])} onChange={(selected) => props.onUpdate(selected as MentionItem[])}
/> />
) )
} })
export default MentionTypeahead export default MentionTypeahead

View file

@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react' import React, { useEffect, useRef, useState } from 'react'
import { getCookie, setCookie } from 'cookies-next' import { getCookie, setCookie } from 'cookies-next'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { Trans, useTranslation } from 'react-i18next' import { Trans, useTranslation } from 'react-i18next'
@ -10,16 +10,16 @@ import DialogContent from '~components/common/DialogContent'
import Button from '~components/common/Button' import Button from '~components/common/Button'
import InputTableField from '~components/common/InputTableField' import InputTableField from '~components/common/InputTableField'
import MentionTableField from '~components/common/MentionTableField'
import SelectTableField from '~components/common/SelectTableField' import SelectTableField from '~components/common/SelectTableField'
import SliderTableField from '~components/common/SliderTableField' import SliderTableField from '~components/common/SliderTableField'
import SwitchTableField from '~components/common/SwitchTableField' import SwitchTableField from '~components/common/SwitchTableField'
import SelectItem from '~components/common/SelectItem' import SelectItem from '~components/common/SelectItem'
import type { DialogProps } from '@radix-ui/react-dialog' import type { DialogProps } from '@radix-ui/react-dialog'
import Typeahead from 'react-bootstrap-typeahead/types/core/Typeahead'
import styles from './index.module.scss' import styles from './index.module.scss'
import MentionTableField from '~components/common/MentionTableField'
import classNames from 'classnames'
interface Props extends DialogProps { interface Props extends DialogProps {
defaultFilterSet: FilterSet defaultFilterSet: FilterSet
@ -43,6 +43,8 @@ const FilterModal = (props: Props) => {
// Refs // Refs
const headerRef = React.createRef<HTMLDivElement>() const headerRef = React.createRef<HTMLDivElement>()
const footerRef = React.createRef<HTMLDivElement>() const footerRef = React.createRef<HTMLDivElement>()
const inclusionRef = useRef<Typeahead>(null)
const exclusionRef = useRef<Typeahead>(null)
// States // States
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
@ -88,7 +90,6 @@ const FilterModal = (props: Props) => {
useEffect(() => { useEffect(() => {
if (props.open !== undefined) { if (props.open !== undefined) {
setOpen(props.open) setOpen(props.open)
// When should we reset the filter state? // When should we reset the filter state?
} }
}) })
@ -160,6 +161,12 @@ const FilterModal = (props: Props) => {
setUserQuality(props.defaultFilterSet.user_quality) setUserQuality(props.defaultFilterSet.user_quality)
setNameQuality(props.defaultFilterSet.name_quality) setNameQuality(props.defaultFilterSet.name_quality)
setOriginalOnly(props.defaultFilterSet.original) setOriginalOnly(props.defaultFilterSet.original)
setInclusions([])
inclusionRef.current?.clear()
setExclusions([])
exclusionRef.current?.clear()
} }
function openChange() { function openChange() {
@ -413,6 +420,7 @@ const FilterModal = (props: Props) => {
exclusions={exclusions} exclusions={exclusions}
placeholder={t('modals.filters.placeholders.inclusion')} placeholder={t('modals.filters.placeholders.inclusion')}
label={t('modals.filters.labels.inclusion')} label={t('modals.filters.labels.inclusion')}
typeaheadRef={inclusionRef}
onUpdate={storeInclusions} onUpdate={storeInclusions}
/> />
) )
@ -424,6 +432,7 @@ const FilterModal = (props: Props) => {
exclusions={inclusions} exclusions={inclusions}
placeholder={t('modals.filters.placeholders.exclusion')} placeholder={t('modals.filters.placeholders.exclusion')}
label={t('modals.filters.labels.exclusion')} label={t('modals.filters.labels.exclusion')}
typeaheadRef={exclusionRef}
onUpdate={storeExclusions} onUpdate={storeExclusions}
/> />
) )

View file

@ -8,8 +8,8 @@ import DOMPurify from 'dompurify'
import Button from '~components/common/Button' import Button from '~components/common/Button'
import SegmentedControl from '~components/common/SegmentedControl' import SegmentedControl from '~components/common/SegmentedControl'
import Segment from '~components/common/Segment' import Segment from '~components/common/Segment'
import GridRepCollection from '~components/GridRepCollection' import GridRepCollection from '~components/reps/GridRepCollection'
import GridRep from '~components/GridRep' import GridRep from '~components/reps/GridRep'
import RemixTeamAlert from '~components/dialogs/RemixTeamAlert' import RemixTeamAlert from '~components/dialogs/RemixTeamAlert'
import RemixedToast from '~components/toasts/RemixedToast' import RemixedToast from '~components/toasts/RemixedToast'
import EditPartyModal from '../EditPartyModal' import EditPartyModal from '../EditPartyModal'

View file

@ -9,6 +9,16 @@
padding: $unit-2x; padding: $unit-2x;
min-width: 320px; min-width: 320px;
width: 100%; width: 100%;
opacity: 1;
transition: opacity 0.3s ease-in-out;
&.visible {
opacity: 1;
}
&.hidden {
opacity: 0;
}
&:hover { &:hover {
background: var(--grid-rep-hover); background: var(--grid-rep-hover);

View file

@ -40,10 +40,16 @@ const GridRep = (props: Props) => {
const locale = const locale =
router.locale && ['en', 'ja'].includes(router.locale) ? router.locale : 'en' router.locale && ['en', 'ja'].includes(router.locale) ? router.locale : 'en'
const [visible, setVisible] = useState(false)
const [mainhand, setMainhand] = useState<Weapon>() const [mainhand, setMainhand] = useState<Weapon>()
const [weapons, setWeapons] = useState<GridArray<Weapon>>({}) const [weapons, setWeapons] = useState<GridArray<Weapon>>({})
const [grid, setGrid] = useState<GridArray<GridWeapon>>({}) const [grid, setGrid] = useState<GridArray<GridWeapon>>({})
const gridRepStyles = classNames({
[styles.gridRep]: true,
[styles.visible]: visible,
[styles.hidden]: !visible,
})
const titleClass = classNames({ const titleClass = classNames({
empty: !props.name, empty: !props.name,
}) })
@ -68,6 +74,14 @@ const GridRep = (props: Props) => {
[styles.grid]: true, [styles.grid]: true,
}) })
useEffect(() => {
setVisible(false) // Trigger fade out
const timeout = setTimeout(() => {
setVisible(true) // Trigger fade in
}, 300) // You can adjust the timing based on your preference
return () => clearTimeout(timeout)
}, [])
useEffect(() => { useEffect(() => {
const newWeapons = Array(numWeapons) const newWeapons = Array(numWeapons)
const gridWeapons = Array(numWeapons) const gridWeapons = Array(numWeapons)
@ -249,7 +263,7 @@ const GridRep = (props: Props) => {
return ( return (
<Link legacyBehavior href={`/p/${props.shortcode}`}> <Link legacyBehavior href={`/p/${props.shortcode}`}>
<a className={styles.gridRep}> <a className={gridRepStyles}>
{detailsWithUsername} {detailsWithUsername}
<div className={styles.weaponGrid}> <div className={styles.weaponGrid}>
<div className={mainhandClasses}>{generateMainhandImage()}</div> <div className={mainhandClasses}>{generateMainhandImage()}</div>

View file

@ -0,0 +1,150 @@
.gridRep {
aspect-ratio: 3/2;
border: 1px solid transparent;
border-radius: $card-corner;
box-sizing: border-box;
display: grid;
grid-template-rows: 1fr 1fr;
gap: $unit;
padding: $unit-2x;
min-width: 320px;
width: 100%;
.placeholder {
// background: var(--placeholder-bg);
animation-duration: 2s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-name: placeHolderShimmer;
animation-timing-function: linear;
background-color: #f6f7f8;
background: linear-gradient(
to right,
var(--placeholder-bg) 8%,
var(--placeholder-bg-accent) 18%,
var(--placeholder-bg) 33%
);
background-size: 1200px 104px;
&.small {
border-radius: calc($font-small / 2);
height: $font-small;
}
&.regular {
border-radius: calc($font-regular / 2);
height: $font-regular;
}
}
& > .weaponGrid {
aspect-ratio: 2/0.95;
display: grid;
grid-template-columns: 1fr 3.36fr; /* left column takes up 1 fraction, right column takes up 3 fractions */
grid-gap: $unit; /* add a gap of 8px between grid items */
.weapon {
border-radius: $item-corner-small;
}
.mainhand.weapon {
aspect-ratio: 73/153;
display: grid;
grid-column: 1 / 2; /* spans one column */
height: calc(100% - $unit-fourth);
}
.weapons {
display: grid; /* make the right-images container a grid */
grid-template-columns: repeat(
3,
1fr
); /* create 3 columns, each taking up 1 fraction */
grid-template-rows: repeat(
3,
1fr
); /* create 3 rows, each taking up 1 fraction */
gap: $unit;
// column-gap: $unit;
// row-gap: $unit-2x;
}
.grid.weapon {
aspect-ratio: 280 / 160;
display: grid;
}
.mainhand.weapon img[src*='jpg'],
.grid.weapon img[src*='jpg'] {
border-radius: 4px;
width: 100%;
}
}
.details {
display: flex;
flex-direction: column;
gap: $unit-half;
.top {
display: flex;
flex-direction: row;
gap: calc($unit / 2);
align-items: center;
.info {
display: flex;
flex-direction: column;
flex-grow: 1;
gap: calc($unit / 2);
.title {
width: 100%;
}
}
}
.attributed {
display: flex;
gap: $unit-half;
align-items: center;
justify-content: space-between;
.user {
display: flex;
flex-grow: 1;
gap: calc($unit / 2);
align-items: center;
.image {
$diameter: 18px;
border-radius: calc($diameter / 2);
height: $diameter;
width: $diameter;
}
.text {
border-radius: calc($font-small / 2);
height: $font-small;
width: 40%;
}
}
.timestamp {
width: 20%;
}
}
}
}
@keyframes placeHolderShimmer {
$width: 400px;
0% {
background-position: ($width * -1) 0;
}
100% {
background-position: $width 0;
}
}

View file

@ -0,0 +1,81 @@
import classNames from 'classnames'
import styles from './index.module.scss'
interface Props {}
const LoadingRep = (props: Props) => {
const numWeapons: number = 9
const mainhandClasses = classNames({
[styles.weapon]: true,
[styles.mainhand]: true,
[styles.placeholder]: true,
})
const weaponClasses = classNames({
[styles.weapon]: true,
[styles.grid]: true,
[styles.placeholder]: true,
})
return (
<div className={styles.gridRep}>
<div className={styles.details}>
<div className={styles.top}>
<div className={styles.info}>
<div
className={classNames({
[styles.title]: true,
[styles.placeholder]: true,
[styles.regular]: true,
})}
/>
<div className={styles.properties}>
<span className={styles.raid} />
</div>
</div>
</div>
<div className={styles.attributed}>
<span className={styles.user}>
<figure
className={classNames({
[styles.image]: true,
[styles.placeholder]: true,
})}
/>
<span
className={classNames({
[styles.text]: true,
[styles.placeholder]: true,
[styles.small]: true,
})}
/>
</span>
<div
className={classNames({
[styles.timestamp]: true,
[styles.placeholder]: true,
[styles.small]: true,
})}
/>
</div>
</div>
<div className={styles.weaponGrid}>
<div className={mainhandClasses} />
<ul className={styles.weapons}>
{Array.from(Array(numWeapons)).map((x, i) => {
return (
<li
key={`placeholder-${Math.random()}`}
className={weaponClasses}
/>
)
})}
</ul>
</div>
</div>
)
}
export default LoadingRep

View file

@ -15,8 +15,9 @@ import { permissiveFilterset } from '~utils/defaultFilters'
import { elements, allElement } from '~data/elements' import { elements, allElement } from '~data/elements'
import { emptyPaginationObject } from '~utils/emptyStates' import { emptyPaginationObject } from '~utils/emptyStates'
import GridRep from '~components/GridRep' import GridRep from '~components/reps/GridRep'
import GridRepCollection from '~components/GridRepCollection' import GridRepCollection from '~components/reps/GridRepCollection'
import LoadingRep from '~components/reps/LoadingRep'
import ErrorSection from '~components/ErrorSection' import ErrorSection from '~components/ErrorSection'
import FilterBar from '~components/filters/FilterBar' import FilterBar from '~components/filters/FilterBar'
import ProfileHead from '~components/head/ProfileHead' import ProfileHead from '~components/head/ProfileHead'
@ -265,6 +266,26 @@ const ProfileRoute: React.FC<Props> = ({
) )
}) })
} }
function renderLoading(number: number) {
return (
<GridRepCollection>
{Array.from(Array(number)).map((x, i) => (
<LoadingRep key={`loading-${i}`} />
))}
</GridRepCollection>
)
}
const renderInfiniteScroll = (
<InfiniteScroll
dataLength={parties && parties.length > 0 ? parties.length : 0}
next={() => setCurrentPage(currentPage + 1)}
hasMore={totalPages > currentPage}
loader={renderLoading(3)}
>
<GridRepCollection>{renderParties()}</GridRepCollection>
</InfiniteScroll>
)
if (context) { if (context) {
return ( return (
@ -285,18 +306,7 @@ const ProfileRoute: React.FC<Props> = ({
</FilterBar> </FilterBar>
<section> <section>
<InfiniteScroll {renderInfiniteScroll}
dataLength={parties && parties.length > 0 ? parties.length : 0}
next={() => setCurrentPage(currentPage + 1)}
hasMore={totalPages > currentPage}
loader={
<div className="notFound">
<h2>{t('loading')}</h2>
</div>
}
>
<GridRepCollection>{renderParties()}</GridRepCollection>
</InfiniteScroll>
{parties.length == 0 ? ( {parties.length == 0 ? (
<div className="notFound"> <div className="notFound">

View file

@ -17,8 +17,9 @@ import { elements, allElement } from '~data/elements'
import { emptyPaginationObject } from '~utils/emptyStates' import { emptyPaginationObject } from '~utils/emptyStates'
import ErrorSection from '~components/ErrorSection' import ErrorSection from '~components/ErrorSection'
import GridRep from '~components/GridRep' import GridRep from '~components/reps/GridRep'
import GridRepCollection from '~components/GridRepCollection' import GridRepCollection from '~components/reps/GridRepCollection'
import LoadingRep from '~components/reps/LoadingRep'
import FilterBar from '~components/filters/FilterBar' import FilterBar from '~components/filters/FilterBar'
import SavedHead from '~components/head/SavedHead' import SavedHead from '~components/head/SavedHead'
@ -306,6 +307,27 @@ const SavedRoute: React.FC<Props> = ({
}) })
} }
function renderLoading(number: number) {
return (
<GridRepCollection>
{Array.from(Array(number)).map((x, i) => (
<LoadingRep key={`loading-${i}`} />
))}
</GridRepCollection>
)
}
const renderInfiniteScroll = (
<InfiniteScroll
dataLength={parties && parties.length > 0 ? parties.length : 0}
next={() => setCurrentPage(currentPage + 1)}
hasMore={totalPages > currentPage}
loader={renderLoading(3)}
>
<GridRepCollection>{renderParties()}</GridRepCollection>
</InfiniteScroll>
)
if (context) { if (context) {
return ( return (
<div className="teams"> <div className="teams">
@ -325,18 +347,7 @@ const SavedRoute: React.FC<Props> = ({
</FilterBar> </FilterBar>
<section> <section>
<InfiniteScroll {renderInfiniteScroll}
dataLength={parties && parties.length > 0 ? parties.length : 0}
next={() => setCurrentPage(currentPage + 1)}
hasMore={totalPages > currentPage}
loader={
<div className="notFound">
<h2>{t('loading')}</h2>
</div>
}
>
<GridRepCollection>{renderParties()}</GridRepCollection>
</InfiniteScroll>
{parties.length == 0 ? ( {parties.length == 0 ? (
<div className="notFound"> <div className="notFound">

View file

@ -19,8 +19,9 @@ import { emptyPaginationObject } from '~utils/emptyStates'
import { convertAdvancedFilters } from '~utils/convertAdvancedFilters' import { convertAdvancedFilters } from '~utils/convertAdvancedFilters'
import ErrorSection from '~components/ErrorSection' import ErrorSection from '~components/ErrorSection'
import GridRep from '~components/GridRep' import GridRep from '~components/reps/GridRep'
import GridRepCollection from '~components/GridRepCollection' import GridRepCollection from '~components/reps/GridRepCollection'
import LoadingRep from '~components/reps/LoadingRep'
import FilterBar from '~components/filters/FilterBar' import FilterBar from '~components/filters/FilterBar'
import TeamsHead from '~components/head/TeamsHead' import TeamsHead from '~components/head/TeamsHead'
@ -55,6 +56,7 @@ const TeamsRoute: React.FC<Props> = ({
// Set up app-specific states // Set up app-specific states
const [mounted, setMounted] = useState(false) const [mounted, setMounted] = useState(false)
const [scrolled, setScrolled] = useState(false) const [scrolled, setScrolled] = useState(false)
const [isLoading, setIsLoading] = useState(false)
// Set up page-specific states // Set up page-specific states
const [parties, setParties] = useState<Party[]>([]) const [parties, setParties] = useState<Party[]>([])
@ -122,6 +124,8 @@ const TeamsRoute: React.FC<Props> = ({
appState.version = version appState.version = version
} }
setCurrentPage(1) setCurrentPage(1)
setIsLoading(false)
}, []) }, [])
// Add scroll event listener for shadow on FilterBar on mount // Add scroll event listener for shadow on FilterBar on mount
@ -151,6 +155,8 @@ const TeamsRoute: React.FC<Props> = ({
const fetchTeams = useCallback( const fetchTeams = useCallback(
({ replace }: { replace: boolean }) => { ({ replace }: { replace: boolean }) => {
setIsLoading(true)
const filters: { const filters: {
[key: string]: any [key: string]: any
} = { } = {
@ -183,6 +189,10 @@ const TeamsRoute: React.FC<Props> = ({
if (replace) replaceResults(meta.count, results) if (replace) replaceResults(meta.count, results)
else appendResults(results) else appendResults(results)
}) })
.then(() => {
console.log('You are here')
setIsLoading(false)
})
.catch((error) => handleError(error)) .catch((error) => handleError(error))
}, },
[currentPage, parties, element, raid, recency, advancedFilters] [currentPage, parties, element, raid, recency, advancedFilters]
@ -318,6 +328,27 @@ const TeamsRoute: React.FC<Props> = ({
}) })
} }
function renderLoading(number: number) {
return (
<GridRepCollection>
{Array.from(Array(number)).map((x, i) => (
<LoadingRep key={`loading-${i}`} />
))}
</GridRepCollection>
)
}
const renderInfiniteScroll = (
<InfiniteScroll
dataLength={parties && parties.length > 0 ? parties.length : 0}
next={() => setCurrentPage(currentPage + 1)}
hasMore={totalPages > currentPage}
loader={renderLoading(3)}
>
<GridRepCollection>{renderParties()}</GridRepCollection>
</InfiniteScroll>
)
if (context) { if (context) {
return ( return (
<div className="teams"> <div className="teams">
@ -336,28 +367,7 @@ const TeamsRoute: React.FC<Props> = ({
<h1>{t('teams.title')}</h1> <h1>{t('teams.title')}</h1>
</FilterBar> </FilterBar>
<section> <section>{renderInfiniteScroll}</section>
<InfiniteScroll
dataLength={parties && parties.length > 0 ? parties.length : 0}
next={() => setCurrentPage(currentPage + 1)}
hasMore={totalPages > currentPage}
loader={
<div className="notFound">
<h2>{t('loading')}</h2>
</div>
}
>
<GridRepCollection>{renderParties()}</GridRepCollection>
</InfiniteScroll>
{parties.length == 0 ? (
<div className="notFound">
<h2>{t('teams.not_found')}</h2>
</div>
) : (
''
)}
</section>
</div> </div>
) )
} else return pageError() } else return pageError()

View file

@ -28,7 +28,9 @@
--selected-item-bg: #{$selected--item--bg--light}; --selected-item-bg: #{$selected--item--bg--light};
--selected-item-bg-hover: #{$selected--item--bg--light--hover}; --selected-item-bg-hover: #{$selected--item--bg--light--hover};
--anonymous-bg: #{$anonymous--bg--light}; --anonymous-bg: #{$anonymous--bg--light};
--placeholder-bg: #{$grey-80}; --placeholder-bg: #{$grey-80};
--placeholder-bg-accent: #{$grey-75};
--transparent-stroke: #{$transparent--stroke--light}; --transparent-stroke: #{$transparent--stroke--light};
@ -252,7 +254,9 @@
--selected-item-bg-hover: #{$selected--item--bg--dark--hover}; --selected-item-bg-hover: #{$selected--item--bg--dark--hover};
--anonymous-bg: #{$anonymous--bg--dark}; --anonymous-bg: #{$anonymous--bg--dark};
--placeholder-bg: #{$grey-40}; --placeholder-bg: #{$grey-40};
--placeholder-bg-accent: #{$grey-45};
--transparent-stroke: #{$transparent--stroke--dark}; --transparent-stroke: #{$transparent--stroke--dark};

View file

@ -45,6 +45,7 @@ $grey-20: #212121;
$grey-25: #232323; $grey-25: #232323;
$grey-30: #2f2f2f; $grey-30: #2f2f2f;
$grey-40: #444; $grey-40: #444;
$grey-45: #515151;
$grey-50: #777; $grey-50: #777;
$grey-55: #888; $grey-55: #888;
$grey-60: #a9a9a9; $grey-60: #a9a9a9;