Centralize icon system
This commit is contained in:
parent
4849d591d3
commit
0ca8823dae
@ -11,19 +11,20 @@ import {
|
||||
PATH_GRID_INFERRED,
|
||||
} from '@/app/paths';
|
||||
import { useAppState } from '@/state/AppState';
|
||||
import { ImCheckboxUnchecked } from 'react-icons/im';
|
||||
import { IoArrowDown, IoArrowUp, IoCloseSharp } from 'react-icons/io5';
|
||||
import { IoArrowDown, IoArrowUp } from 'react-icons/io5';
|
||||
import { clsx } from 'clsx/lite';
|
||||
import { TbChecklist, TbPhoto } from 'react-icons/tb';
|
||||
import { FiTag } from 'react-icons/fi';
|
||||
import { BiLockAlt } from 'react-icons/bi';
|
||||
import AdminAppInfoIcon from './AdminAppInfoIcon';
|
||||
import { PiSignOutBold } from 'react-icons/pi';
|
||||
import { signOutAction } from '@/auth/actions';
|
||||
import { ComponentProps } from 'react';
|
||||
import { FaRegFolderOpen } from 'react-icons/fa';
|
||||
import { FiUploadCloud } from 'react-icons/fi';
|
||||
import useIsKeyBeingPressed from '@/utility/useIsKeyBeingPressed';
|
||||
import IconSelectMultiple from '@/components/icons/IconSelectMultiple';
|
||||
import IconPhoto from '@/components/icons/IconPhoto';
|
||||
import IconUpload from '@/components/icons/IconUpload';
|
||||
import IconRecipe from '@/components/icons/IconRecipe';
|
||||
import IconTag from '@/components/icons/IconTag';
|
||||
import IconFolder from '@/components/icons/IconFolder';
|
||||
import IconSignOut from '@/components/icons/IconSignOut';
|
||||
import IconLock from '@/components/icons/IconLock';
|
||||
|
||||
export default function AdminAppMenu({
|
||||
active,
|
||||
@ -54,7 +55,7 @@ export default function AdminAppMenu({
|
||||
|
||||
const items: ComponentProps<typeof MoreMenu>['items'] = [{
|
||||
label: 'Upload Photos',
|
||||
icon: <FiUploadCloud
|
||||
icon: <IconUpload
|
||||
size={15}
|
||||
className="translate-x-[0.5px] translate-y-[0.5px]"
|
||||
/>,
|
||||
@ -73,7 +74,7 @@ export default function AdminAppMenu({
|
||||
...photosCountTotal && {
|
||||
annotation: `${photosCountTotal}`,
|
||||
},
|
||||
icon: <TbPhoto
|
||||
icon: <IconPhoto
|
||||
size={15}
|
||||
className="translate-x-[-0.5px] translate-y-[0.5px]"
|
||||
/>,
|
||||
@ -85,7 +86,7 @@ export default function AdminAppMenu({
|
||||
items.push({
|
||||
label: 'Uploads',
|
||||
annotation: `${uploadsCount}`,
|
||||
icon: <FaRegFolderOpen
|
||||
icon: <IconFolder
|
||||
size={16}
|
||||
className="translate-y-[0.5px]"
|
||||
/>,
|
||||
@ -97,7 +98,7 @@ export default function AdminAppMenu({
|
||||
items.push({
|
||||
label: 'Manage Tags',
|
||||
annotation: `${tagsCount}`,
|
||||
icon: <FiTag
|
||||
icon: <IconTag
|
||||
size={15}
|
||||
className="translate-y-[0.5px]"
|
||||
/>,
|
||||
@ -109,7 +110,7 @@ export default function AdminAppMenu({
|
||||
items.push({
|
||||
label: 'Manage Recipes',
|
||||
annotation: `${recipesCount}`,
|
||||
icon: <TbChecklist
|
||||
icon: <IconRecipe
|
||||
size={17}
|
||||
className="translate-x-[-0.5px] translate-y-[0.5px]"
|
||||
/>,
|
||||
@ -122,13 +123,7 @@ export default function AdminAppMenu({
|
||||
label: isSelecting
|
||||
? 'Exit Select'
|
||||
: 'Edit Multiple',
|
||||
icon: isSelecting
|
||||
? <IoCloseSharp
|
||||
className="text-[18px] translate-x-[-1px] translate-y-[1px]"
|
||||
/>
|
||||
: <ImCheckboxUnchecked
|
||||
className="translate-x-[-0.5px] text-[0.75rem]"
|
||||
/>,
|
||||
icon: <IconSelectMultiple {...{ isSelecting }} />,
|
||||
href: PATH_GRID_INFERRED,
|
||||
action: () => {
|
||||
if (isSelecting) {
|
||||
@ -157,14 +152,17 @@ export default function AdminAppMenu({
|
||||
: PATH_ADMIN_CONFIGURATION,
|
||||
}, {
|
||||
label: 'Sign Out',
|
||||
icon: <PiSignOutBold size={15} />,
|
||||
icon: <IconSignOut size={15} />,
|
||||
action: () => signOutAction().then(clearAuthStateAndRedirect),
|
||||
});
|
||||
|
||||
return (
|
||||
<MoreMenu
|
||||
header={<div className="flex items-center select-none">
|
||||
<BiLockAlt size={17} className="inline-block w-5 mr-2" />
|
||||
<IconLock
|
||||
size={15}
|
||||
className="inline-block w-5 mr-2 translate-x-[1px]"
|
||||
/>
|
||||
<span className="grow">Admin menu</span>
|
||||
</div>}
|
||||
icon={<div className={clsx(
|
||||
|
||||
@ -15,8 +15,10 @@ import { tagMultiplePhotosAction } from '@/photo/actions';
|
||||
import { toastSuccess } from '@/toast';
|
||||
import DeletePhotosButton from './DeletePhotosButton';
|
||||
import { photoQuantityText } from '@/photo';
|
||||
import { FaArrowDown, FaCheck, FaRegStar } from 'react-icons/fa6';
|
||||
import { FaArrowDown, FaCheck } from 'react-icons/fa6';
|
||||
import ResponsiveText from '@/components/primitives/ResponsiveText';
|
||||
import IconFavs from '@/components/icons/IconFavs';
|
||||
import IconTag from '@/components/icons/IconTag';
|
||||
|
||||
export default function AdminBatchEditPanelClient({
|
||||
uniqueTags,
|
||||
@ -113,7 +115,7 @@ export default function AdminBatchEditPanelClient({
|
||||
onFinish={() => setIsPerformingSelectEdit?.(false)}
|
||||
/>
|
||||
<LoaderButton
|
||||
icon={<FaRegStar />}
|
||||
icon={<IconFavs />}
|
||||
disabled={isPerformingSelectEdit}
|
||||
confirmText={`Are you sure you want to favorite ${photosText}?`}
|
||||
onClick={() => {
|
||||
@ -132,10 +134,9 @@ export default function AdminBatchEditPanelClient({
|
||||
<LoaderButton
|
||||
onClick={() => setTags('')}
|
||||
disabled={isPerformingSelectEdit}
|
||||
icon={<IconTag size={15} className="translate-y-[1.5px]" />}
|
||||
>
|
||||
<ResponsiveText shortText="Tag">
|
||||
Tag ...
|
||||
</ResponsiveText>
|
||||
Tag ...
|
||||
</LoaderButton>
|
||||
</>}
|
||||
<LoaderButton
|
||||
|
||||
@ -21,8 +21,8 @@ import PhotoTagFieldset from './PhotoTagFieldset';
|
||||
import DeleteUploadButton from './DeleteUploadButton';
|
||||
import { useAppState } from '@/state/AppState';
|
||||
import { pluralize } from '@/utility/string';
|
||||
import { FaRegStar } from 'react-icons/fa6';
|
||||
import { AiOutlineEyeInvisible } from 'react-icons/ai';
|
||||
import IconFavs from '@/components/icons/IconFavs';
|
||||
import IconHidden from '@/components/icons/IconHidden';
|
||||
|
||||
const UPLOAD_BATCH_SIZE = 4;
|
||||
|
||||
@ -147,7 +147,7 @@ export default function AdminBatchUploadActions({
|
||||
<div className="flex gap-8">
|
||||
<FieldSetWithStatus
|
||||
label="Favorite"
|
||||
icon={<FaRegStar size={14} />}
|
||||
icon={<IconFavs size={14} />}
|
||||
type="checkbox"
|
||||
value={favorite}
|
||||
onChange={setFavorite}
|
||||
@ -155,7 +155,7 @@ export default function AdminBatchUploadActions({
|
||||
/>
|
||||
<FieldSetWithStatus
|
||||
label="Hidden"
|
||||
icon={<AiOutlineEyeInvisible size={16} />}
|
||||
icon={<IconHidden size={16} />}
|
||||
type="checkbox"
|
||||
value={hidden}
|
||||
onChange={setHidden}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
import { Photo } from '@/photo';
|
||||
import AdminPhotosTable from '@/admin/AdminPhotosTable';
|
||||
import LoaderButton from '@/components/primitives/LoaderButton';
|
||||
import IconGrSync from '@/app/IconGrSync';
|
||||
import IconGrSync from '@/components/icons/IconGrSync';
|
||||
import Note from '@/components/Note';
|
||||
import AdminChildPage from '@/components/AdminChildPage';
|
||||
import { PATH_ADMIN_PHOTOS } from '@/app/paths';
|
||||
|
||||
@ -7,7 +7,6 @@ import {
|
||||
syncPhotoAction,
|
||||
toggleFavoritePhotoAction,
|
||||
} from '@/photo/actions';
|
||||
import { FaRegEdit, FaRegStar, FaStar } from 'react-icons/fa';
|
||||
import {
|
||||
Photo,
|
||||
deleteConfirmationTextForPhoto,
|
||||
@ -21,9 +20,11 @@ import { useAppState } from '@/state/AppState';
|
||||
import { RevalidatePhoto } from '@/photo/InfinitePhotoScroll';
|
||||
import { MdOutlineFileDownload } from 'react-icons/md';
|
||||
import MoreMenuItem from '@/components/more/MoreMenuItem';
|
||||
import IconGrSync from '@/app/IconGrSync';
|
||||
import IconGrSync from '@/components/icons/IconGrSync';
|
||||
import { isPhotoOutdated } from '@/photo/outdated';
|
||||
import InsightsIndicatorDot from './insights/InsightsIndicatorDot';
|
||||
import IconFavs from '@/components/icons/IconFavs';
|
||||
import IconEdit from '@/components/icons/IconEdit';
|
||||
|
||||
export default function AdminPhotoMenuClient({
|
||||
photo,
|
||||
@ -42,12 +43,10 @@ export default function AdminPhotoMenuClient({
|
||||
const shouldRedirectFav = isPathFavs(path) && isFav;
|
||||
const shouldRedirectDelete = pathForPhoto({ photo: photo.id }) === path;
|
||||
|
||||
const favIconClass = 'translate-x-[-1px] translate-y-[0.5px]';
|
||||
|
||||
const items = useMemo(() => {
|
||||
const items: ComponentProps<typeof MoreMenuItem>[] = [{
|
||||
label: 'Edit',
|
||||
icon: <FaRegEdit
|
||||
icon: <IconEdit
|
||||
size={15}
|
||||
className="translate-x-[0.5px] translate-y-[-0.5px]"
|
||||
/>,
|
||||
@ -56,15 +55,11 @@ export default function AdminPhotoMenuClient({
|
||||
if (includeFavorite) {
|
||||
items.push({
|
||||
label: isFav ? 'Unfavorite' : 'Favorite',
|
||||
icon: isFav
|
||||
? <FaStar
|
||||
size={14}
|
||||
className={`text-amber-500 ${favIconClass}`}
|
||||
/>
|
||||
: <FaRegStar
|
||||
size={14}
|
||||
className={favIconClass}
|
||||
/>,
|
||||
icon: <IconFavs
|
||||
size={14}
|
||||
className="translate-x-[-1px]"
|
||||
highlight={isFav}
|
||||
/>,
|
||||
action: () => toggleFavoritePhotoAction(
|
||||
photo.id,
|
||||
shouldRedirectFav,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import IconEdit from '@/components/icons/IconEdit';
|
||||
import PathLoaderButton from '@/components/primitives/PathLoaderButton';
|
||||
import { FaRegEdit } from 'react-icons/fa';
|
||||
|
||||
export default function EditButton ({
|
||||
path,
|
||||
@ -9,7 +9,7 @@ export default function EditButton ({
|
||||
return (
|
||||
<PathLoaderButton
|
||||
path={path}
|
||||
icon={<FaRegEdit size={15} className="translate-y-[0.5px]" />}
|
||||
icon={<IconEdit size={15} className="translate-y-[0.5px]" />}
|
||||
>
|
||||
Edit
|
||||
</PathLoaderButton>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import LoaderButton from '@/components/primitives/LoaderButton';
|
||||
import { syncPhotoAction } from '@/photo/actions';
|
||||
import IconGrSync from '@/app/IconGrSync';
|
||||
import IconGrSync from '@/components/icons/IconGrSync';
|
||||
import { toastSuccess } from '@/toast';
|
||||
import { ComponentProps, useState } from 'react';
|
||||
import Tooltip from '@/components/Tooltip';
|
||||
|
||||
@ -1,23 +1,26 @@
|
||||
import Switcher from '@/components/Switcher';
|
||||
import SwitcherItem from '@/components/SwitcherItem';
|
||||
import IconFeed from '@/app/IconFeed';
|
||||
import IconGrid from '@/app/IconGrid';
|
||||
import IconFeed from '@/components/icons/IconFeed';
|
||||
import IconGrid from '@/components/icons/IconGrid';
|
||||
import {
|
||||
PATH_FEED_INFERRED,
|
||||
PATH_GRID_INFERRED,
|
||||
} from '@/app/paths';
|
||||
import IconSearch from './IconSearch';
|
||||
import IconSearch from '../components/icons/IconSearch';
|
||||
import { useAppState } from '@/state/AppState';
|
||||
import { GRID_HOMEPAGE_ENABLED } from './config';
|
||||
import AdminAppMenu from '@/admin/AdminAppMenu';
|
||||
import Spinner from '@/components/Spinner';
|
||||
import clsx from 'clsx/lite';
|
||||
|
||||
export type SwitcherSelection = 'feed' | 'grid' | 'admin';
|
||||
|
||||
export default function ViewSwitcher({
|
||||
currentSelection,
|
||||
className,
|
||||
}: {
|
||||
currentSelection?: SwitcherSelection
|
||||
className?: string
|
||||
}) {
|
||||
const {
|
||||
isUserSignedIn,
|
||||
@ -42,7 +45,10 @@ export default function ViewSwitcher({
|
||||
/>;
|
||||
|
||||
return (
|
||||
<div className="flex gap-1 sm:gap-2">
|
||||
<div className={clsx(
|
||||
'flex gap-1 sm:gap-2',
|
||||
className,
|
||||
)}>
|
||||
<Switcher>
|
||||
{GRID_HOMEPAGE_ENABLED ? renderItemGrid : renderItemFeed}
|
||||
{GRID_HOMEPAGE_ENABLED ? renderItemFeed : renderItemGrid}
|
||||
|
||||
@ -19,8 +19,8 @@ import {
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import { useAppState } from '@/state/AppState';
|
||||
import { clsx } from 'clsx/lite';
|
||||
import { FiLock } from 'react-icons/fi';
|
||||
import { PATH_ADMIN_PHOTOS } from '@/app/paths';
|
||||
import IconLock from '@/components/icons/IconLock';
|
||||
|
||||
export default function SignInForm({
|
||||
includeTitle = true,
|
||||
@ -71,7 +71,7 @@ export default function SignInForm({
|
||||
'flex gap-3 items-center justify-center',
|
||||
'self-start text-2xl mb-3.5',
|
||||
)}>
|
||||
<FiLock className="text-main translate-y-[0.5px]" />
|
||||
<IconLock className="text-main translate-y-[0.5px]" />
|
||||
<span className="text-main">
|
||||
Sign in
|
||||
</span>
|
||||
|
||||
@ -4,7 +4,7 @@ import { Camera, formatCameraText, isCameraApple } from '.';
|
||||
import EntityLink, {
|
||||
EntityLinkExternalProps,
|
||||
} from '@/components/primitives/EntityLink';
|
||||
import { TbCamera } from 'react-icons/tb';
|
||||
import IconCamera from '@/components/icons/IconCamera';
|
||||
|
||||
export default function PhotoCamera({
|
||||
camera,
|
||||
@ -33,7 +33,7 @@ export default function PhotoCamera({
|
||||
className="translate-x-[-1px] translate-y-[-0.5px]"
|
||||
size={15}
|
||||
/>
|
||||
: <TbCamera
|
||||
: <IconCamera
|
||||
size={15}
|
||||
className="translate-x-[-0.5px]"
|
||||
/>}
|
||||
|
||||
6
src/components/icons/IconCamera.tsx
Normal file
6
src/components/icons/IconCamera.tsx
Normal file
@ -0,0 +1,6 @@
|
||||
import { IconBaseProps } from 'react-icons';
|
||||
import { TbCamera } from 'react-icons/tb';
|
||||
|
||||
export default function IconCamera(props: IconBaseProps) {
|
||||
return <TbCamera {...props} />;
|
||||
}
|
||||
6
src/components/icons/IconEdit.tsx
Normal file
6
src/components/icons/IconEdit.tsx
Normal file
@ -0,0 +1,6 @@
|
||||
import { IconBaseProps } from 'react-icons';
|
||||
import { FaRegEdit } from 'react-icons/fa';
|
||||
|
||||
export default function IconEdit(props: IconBaseProps) {
|
||||
return <FaRegEdit {...props} />;
|
||||
}
|
||||
16
src/components/icons/IconFavs.tsx
Normal file
16
src/components/icons/IconFavs.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import { clsx } from 'clsx/lite';
|
||||
import { IconBaseProps } from 'react-icons';
|
||||
import { FaRegStar, FaStar } from 'react-icons/fa6';
|
||||
|
||||
export default function IconFavs({
|
||||
highlight,
|
||||
className,
|
||||
...props
|
||||
}: IconBaseProps & { highlight?: boolean}) {
|
||||
return highlight
|
||||
? <FaStar
|
||||
{...props}
|
||||
className={clsx('text-amber-500', className)}
|
||||
/>
|
||||
: <FaRegStar {...{ ...props, className }} />;
|
||||
}
|
||||
6
src/components/icons/IconFilmSimulation.tsx
Normal file
6
src/components/icons/IconFilmSimulation.tsx
Normal file
@ -0,0 +1,6 @@
|
||||
import { IconBaseProps } from 'react-icons';
|
||||
import { IoFilmOutline } from 'react-icons/io5';
|
||||
|
||||
export default function IconFilmSimulation(props: IconBaseProps) {
|
||||
return <IoFilmOutline {...props} />;
|
||||
}
|
||||
17
src/components/icons/IconFocalLength.tsx
Normal file
17
src/components/icons/IconFocalLength.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import { IconBaseProps } from 'react-icons';
|
||||
import { TbCone } from 'react-icons/tb';
|
||||
|
||||
export default function IconFocalLength({
|
||||
style,
|
||||
...props
|
||||
}: IconBaseProps) {
|
||||
return <TbCone {...{
|
||||
...props,
|
||||
style: {
|
||||
...style,
|
||||
transform: `rotate(270deg)${style?.transform
|
||||
? ` ${style.transform}`
|
||||
: ''}`,
|
||||
},
|
||||
}} />;
|
||||
}
|
||||
6
src/components/icons/IconFolder.tsx
Normal file
6
src/components/icons/IconFolder.tsx
Normal file
@ -0,0 +1,6 @@
|
||||
import { IconBaseProps } from 'react-icons';
|
||||
import { FaRegFolderOpen } from 'react-icons/fa';
|
||||
|
||||
export default function IconFolder(props: IconBaseProps) {
|
||||
return <FaRegFolderOpen {...props} />;
|
||||
}
|
||||
6
src/components/icons/IconHidden.tsx
Normal file
6
src/components/icons/IconHidden.tsx
Normal file
@ -0,0 +1,6 @@
|
||||
import { IconBaseProps } from 'react-icons';
|
||||
import { AiOutlineEyeInvisible } from 'react-icons/ai';
|
||||
|
||||
export default function IconHidden(props: IconBaseProps) {
|
||||
return <AiOutlineEyeInvisible {...props} />;
|
||||
}
|
||||
6
src/components/icons/IconLens.tsx
Normal file
6
src/components/icons/IconLens.tsx
Normal file
@ -0,0 +1,6 @@
|
||||
import { IconBaseProps } from 'react-icons';
|
||||
import { RiCameraLensLine } from 'react-icons/ri';
|
||||
|
||||
export default function IconLens(props: IconBaseProps) {
|
||||
return <RiCameraLensLine {...props} />;
|
||||
}
|
||||
6
src/components/icons/IconLock.tsx
Normal file
6
src/components/icons/IconLock.tsx
Normal file
@ -0,0 +1,6 @@
|
||||
import { IconBaseProps } from 'react-icons';
|
||||
import { FiLock } from 'react-icons/fi';
|
||||
|
||||
export default function IconLock(props: IconBaseProps) {
|
||||
return <FiLock {...props} />;
|
||||
}
|
||||
6
src/components/icons/IconPhoto.tsx
Normal file
6
src/components/icons/IconPhoto.tsx
Normal file
@ -0,0 +1,6 @@
|
||||
import { IconBaseProps } from 'react-icons';
|
||||
import { TbPhoto } from 'react-icons/tb';
|
||||
|
||||
export default function IconPhoto(props: IconBaseProps) {
|
||||
return <TbPhoto {...props} />;
|
||||
}
|
||||
6
src/components/icons/IconRecipe.tsx
Normal file
6
src/components/icons/IconRecipe.tsx
Normal file
@ -0,0 +1,6 @@
|
||||
import { IconBaseProps } from 'react-icons';
|
||||
import { TbChecklist } from 'react-icons/tb';
|
||||
|
||||
export default function IconRecipe(props: IconBaseProps) {
|
||||
return <TbChecklist {...props} />;
|
||||
}
|
||||
28
src/components/icons/IconSelectMultiple.tsx
Normal file
28
src/components/icons/IconSelectMultiple.tsx
Normal file
@ -0,0 +1,28 @@
|
||||
import clsx from 'clsx/lite';
|
||||
import { IconBaseProps } from 'react-icons';
|
||||
import { ImCheckboxUnchecked } from 'react-icons/im';
|
||||
import { IoCloseSharp } from 'react-icons/io5';
|
||||
|
||||
export default function IconSelectMultiple({
|
||||
isSelecting,
|
||||
className,
|
||||
...props
|
||||
}: IconBaseProps & { isSelecting: boolean }) {
|
||||
return isSelecting
|
||||
? <IoCloseSharp {...{
|
||||
...props,
|
||||
className: clsx(
|
||||
'text-[18px] translate-x-[-1px] translate-y-[0.5px]',
|
||||
className,
|
||||
),
|
||||
}} />
|
||||
: <ImCheckboxUnchecked
|
||||
{...{
|
||||
...props,
|
||||
className: clsx(
|
||||
'translate-x-[-0.5px] translate-y-[0.5px] text-[0.75rem]',
|
||||
className,
|
||||
),
|
||||
}}
|
||||
/>;
|
||||
}
|
||||
6
src/components/icons/IconSignOut.tsx
Normal file
6
src/components/icons/IconSignOut.tsx
Normal file
@ -0,0 +1,6 @@
|
||||
import { IconBaseProps } from 'react-icons';
|
||||
import { PiSignOutBold } from 'react-icons/pi';
|
||||
|
||||
export default function IconSignOut(props: IconBaseProps) {
|
||||
return <PiSignOutBold {...props} />;
|
||||
}
|
||||
6
src/components/icons/IconTag.tsx
Normal file
6
src/components/icons/IconTag.tsx
Normal file
@ -0,0 +1,6 @@
|
||||
import { IconBaseProps } from 'react-icons';
|
||||
import { FiTag } from 'react-icons/fi';
|
||||
|
||||
export default function IconTag(props: IconBaseProps) {
|
||||
return <FiTag {...props} />;
|
||||
}
|
||||
6
src/components/icons/IconUpload.tsx
Normal file
6
src/components/icons/IconUpload.tsx
Normal file
@ -0,0 +1,6 @@
|
||||
import { IconBaseProps } from 'react-icons';
|
||||
import { FiUploadCloud } from 'react-icons/fi';
|
||||
|
||||
export default function IconUpload(props: IconBaseProps) {
|
||||
return <FiUploadCloud {...props} />;
|
||||
}
|
||||
@ -2,8 +2,8 @@ import { pathForFocalLength } from '@/app/paths';
|
||||
import EntityLink, {
|
||||
EntityLinkExternalProps,
|
||||
} from '@/components/primitives/EntityLink';
|
||||
import { TbCone } from 'react-icons/tb';
|
||||
import { formatFocalLength } from '.';
|
||||
import IconFocalLength from '@/components/icons/IconFocalLength';
|
||||
|
||||
export default function PhotoFocalLength({
|
||||
focal,
|
||||
@ -21,7 +21,7 @@ export default function PhotoFocalLength({
|
||||
<EntityLink
|
||||
label={formatFocalLength(focal)}
|
||||
href={pathForFocalLength(focal)}
|
||||
icon={<TbCone className="rotate-[270deg]" />}
|
||||
icon={<IconFocalLength />}
|
||||
type={type}
|
||||
className={className}
|
||||
badged={badged}
|
||||
|
||||
@ -8,9 +8,9 @@ import {
|
||||
formatCameraText,
|
||||
isCameraApple,
|
||||
} from '@/camera';
|
||||
import { IoMdCamera } from 'react-icons/io';
|
||||
import { NextImageSize } from '@/platforms/next-image';
|
||||
import { AiFillApple } from 'react-icons/ai';
|
||||
import IconCamera from '@/components/icons/IconCamera';
|
||||
|
||||
export default function CameraImageResponse({
|
||||
camera: cameraProp,
|
||||
@ -47,10 +47,11 @@ export default function CameraImageResponse({
|
||||
transform: `translateY(${-height * .002}px)`,
|
||||
}}
|
||||
/>
|
||||
: <IoMdCamera
|
||||
size={height * .079}
|
||||
: <IconCamera
|
||||
size={height * .09}
|
||||
style={{
|
||||
marginRight: height * .015,
|
||||
transform: `translateY(${height * .001}px)`,
|
||||
}}
|
||||
/>,
|
||||
title: formatCameraText(camera).toLocaleUpperCase(),
|
||||
|
||||
@ -3,8 +3,8 @@ import ImageCaption from './components/ImageCaption';
|
||||
import ImagePhotoGrid from './components/ImagePhotoGrid';
|
||||
import ImageContainer from './components/ImageContainer';
|
||||
import type { NextImageSize } from '@/platforms/next-image';
|
||||
import { TbCone } from 'react-icons/tb';
|
||||
import { formatFocalLength } from '@/focal';
|
||||
import IconFocalLength from '@/components/icons/IconFocalLength';
|
||||
|
||||
export default function FocalLengthImageResponse({
|
||||
focal,
|
||||
@ -32,13 +32,13 @@ export default function FocalLengthImageResponse({
|
||||
width,
|
||||
height,
|
||||
fontFamily,
|
||||
icon: <TbCone
|
||||
size={height * .075}
|
||||
style={{
|
||||
transform: `translateY(${height * .002}px) rotate(270deg)`,
|
||||
marginRight: height * .01,
|
||||
}}
|
||||
/>,
|
||||
icon: <span style={{
|
||||
display: 'flex',
|
||||
transform: `translateY(${height * .002}px)`,
|
||||
marginRight: height * .01,
|
||||
}}>
|
||||
<IconFocalLength size={height * .075} />
|
||||
</span>,
|
||||
title: formatFocalLength(focal),
|
||||
}} />
|
||||
</ImageContainer>
|
||||
|
||||
@ -4,7 +4,7 @@ import ImagePhotoGrid from './components/ImagePhotoGrid';
|
||||
import ImageContainer from './components/ImageContainer';
|
||||
import { NextImageSize } from '@/platforms/next-image';
|
||||
import { formatLensText, Lens, lensFromPhoto } from '@/lens';
|
||||
import { RiCameraLensLine } from 'react-icons/ri';
|
||||
import IconLens from '@/components/icons/IconLens';
|
||||
|
||||
export default function LensImageResponse({
|
||||
lens: lensProp,
|
||||
@ -33,7 +33,7 @@ export default function LensImageResponse({
|
||||
width,
|
||||
height,
|
||||
fontFamily,
|
||||
icon: <RiCameraLensLine
|
||||
icon: <IconLens
|
||||
size={height * .079}
|
||||
style={{
|
||||
marginRight: height * .015,
|
||||
|
||||
@ -4,10 +4,10 @@ import ImagePhotoGrid from './components/ImagePhotoGrid';
|
||||
import ImageContainer from './components/ImageContainer';
|
||||
import type { NextImageSize } from '@/platforms/next-image';
|
||||
import { formatTag } from '@/tag';
|
||||
import { TbChecklist } from 'react-icons/tb';
|
||||
import { generateRecipeText, getPhotoWithRecipeFromPhotos } from '@/recipe';
|
||||
import PhotoFilmSimulationIcon from '@/simulation/PhotoFilmSimulationIcon';
|
||||
import { isStringFilmSimulation } from '@/platforms/fujifilm/simulation';
|
||||
import IconRecipe from '@/components/icons/IconRecipe';
|
||||
const MAX_RECIPE_LINES = 8;
|
||||
|
||||
export default function RecipeImageResponse({
|
||||
@ -49,7 +49,6 @@ export default function RecipeImageResponse({
|
||||
photos,
|
||||
width,
|
||||
height,
|
||||
gap: 0,
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
@ -65,10 +64,10 @@ export default function RecipeImageResponse({
|
||||
fontFamily,
|
||||
legacyBottomAlignment: false,
|
||||
gap: '0',
|
||||
icon: <TbChecklist
|
||||
icon: <IconRecipe
|
||||
size={height * .087}
|
||||
style={{
|
||||
transform: `translateY(${height * .003}px)`,
|
||||
transform: `translateY(${height * .002}px)`,
|
||||
marginRight: height * .02,
|
||||
}}
|
||||
/>,
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import type { Photo } from '../photo';
|
||||
import { FaStar, FaTag } from 'react-icons/fa';
|
||||
import ImageCaption from './components/ImageCaption';
|
||||
import ImagePhotoGrid from './components/ImagePhotoGrid';
|
||||
import ImageContainer from './components/ImageContainer';
|
||||
import type { NextImageSize } from '@/platforms/next-image';
|
||||
import { formatTag, isTagFavs } from '@/tag';
|
||||
import IconTag from '@/components/icons/IconTag';
|
||||
import IconFavs from '@/components/icons/IconFavs';
|
||||
|
||||
export default function TagImageResponse({
|
||||
tag,
|
||||
@ -33,7 +34,7 @@ export default function TagImageResponse({
|
||||
height,
|
||||
fontFamily,
|
||||
icon: isTagFavs(tag)
|
||||
? <FaStar
|
||||
? <IconFavs
|
||||
size={height * .066}
|
||||
style={{
|
||||
// Fix horizontal distortion in icon size
|
||||
@ -41,11 +42,11 @@ export default function TagImageResponse({
|
||||
marginRight: height * .015,
|
||||
}}
|
||||
/>
|
||||
: <FaTag
|
||||
size={height * .06}
|
||||
: <IconTag
|
||||
size={height * .0725}
|
||||
style={{
|
||||
transform: `translateY(${height * .006}px)`,
|
||||
marginRight: height * .02,
|
||||
transform: `translateY(${height * .007}px)`,
|
||||
marginRight: height * .01,
|
||||
}}
|
||||
/>,
|
||||
title: formatTag(tag).toLocaleUpperCase(),
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Photo } from '../photo';
|
||||
import IconFeed from '@/app/IconFeed';
|
||||
import IconGrid from '@/app/IconGrid';
|
||||
import IconFeed from '@/components/icons/IconFeed';
|
||||
import IconGrid from '@/components/icons/IconGrid';
|
||||
import ImagePhotoGrid from './components/ImagePhotoGrid';
|
||||
import { NextImageSize } from '@/platforms/next-image';
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ export default function ImagePhotoGrid({
|
||||
widthArbitrary,
|
||||
height,
|
||||
imagePosition = 'center',
|
||||
gap = 4,
|
||||
gap = 0,
|
||||
imageStyle,
|
||||
}: ({
|
||||
photos: Photo[]
|
||||
|
||||
@ -3,7 +3,7 @@ import { Lens, formatLensText } from '.';
|
||||
import EntityLink, {
|
||||
EntityLinkExternalProps,
|
||||
} from '@/components/primitives/EntityLink';
|
||||
import { RiCameraLensLine } from 'react-icons/ri';
|
||||
import IconLens from '@/components/icons/IconLens';
|
||||
|
||||
export default function PhotoLens({
|
||||
lens,
|
||||
@ -21,7 +21,7 @@ export default function PhotoLens({
|
||||
<EntityLink
|
||||
label={formatLensText(lens, 'short')}
|
||||
href={pathForLens(lens)}
|
||||
icon={<RiCameraLensLine
|
||||
icon={<IconLens
|
||||
size={14}
|
||||
className="translate-x-[-0.5px] translate-y-[-0.5px]"
|
||||
/>}
|
||||
|
||||
@ -4,12 +4,9 @@ import { Cameras, sortCamerasWithCount } from '@/camera';
|
||||
import PhotoCamera from '@/camera/PhotoCamera';
|
||||
import HeaderList from '@/components/HeaderList';
|
||||
import PhotoTag from '@/tag/PhotoTag';
|
||||
import { FaTag } from 'react-icons/fa';
|
||||
import { IoMdCamera } from 'react-icons/io';
|
||||
import { PhotoDateRange, dateRangeForPhotos, photoQuantityText } from '.';
|
||||
import { TAG_FAVS, TAG_HIDDEN, Tags, addHiddenToTags } from '@/tag';
|
||||
import PhotoFilmSimulation from '@/simulation/PhotoFilmSimulation';
|
||||
import PhotoFilmSimulationIcon from '@/simulation/PhotoFilmSimulationIcon';
|
||||
import { FilmSimulations, sortFilmSimulationsWithCount } from '@/simulation';
|
||||
import FavsTag from '../tag/FavsTag';
|
||||
import { useAppState } from '@/state/AppState';
|
||||
@ -23,7 +20,10 @@ import {
|
||||
import { clsx } from 'clsx/lite';
|
||||
import { Recipes, sortRecipesWithCount } from '@/recipe';
|
||||
import PhotoRecipe from '@/recipe/PhotoRecipe';
|
||||
import { TbChecklist } from 'react-icons/tb';
|
||||
import IconCamera from '@/components/icons/IconCamera';
|
||||
import IconRecipe from '@/components/icons/IconRecipe';
|
||||
import IconTag from '@/components/icons/IconTag';
|
||||
import IconFilmSimulation from '@/components/icons/IconFilmSimulation';
|
||||
|
||||
export default function PhotoGridSidebar({
|
||||
tags,
|
||||
@ -52,8 +52,8 @@ export default function PhotoGridSidebar({
|
||||
? <HeaderList
|
||||
key="tags"
|
||||
title='Tags'
|
||||
icon={<FaTag
|
||||
size={12}
|
||||
icon={<IconTag
|
||||
size={14}
|
||||
className="translate-y-[1px]"
|
||||
/>}
|
||||
items={tagsIncludingHidden.map(({ tag, count }) => {
|
||||
@ -95,10 +95,7 @@ export default function PhotoGridSidebar({
|
||||
? <HeaderList
|
||||
key="cameras"
|
||||
title="Cameras"
|
||||
icon={<IoMdCamera
|
||||
size={13}
|
||||
className="translate-y-[-0.25px]"
|
||||
/>}
|
||||
icon={<IconCamera size={15} />}
|
||||
items={cameras
|
||||
.sort(sortCamerasWithCount)
|
||||
.map(({ cameraKey, camera, count }) =>
|
||||
@ -119,7 +116,7 @@ export default function PhotoGridSidebar({
|
||||
? <HeaderList
|
||||
key="recipes"
|
||||
title="Recipes"
|
||||
icon={<TbChecklist
|
||||
icon={<IconRecipe
|
||||
size={16}
|
||||
className="translate-x-[-1px]"
|
||||
/>}
|
||||
@ -141,9 +138,7 @@ export default function PhotoGridSidebar({
|
||||
? <HeaderList
|
||||
key="films"
|
||||
title="Films"
|
||||
icon={<PhotoFilmSimulationIcon
|
||||
className="translate-y-[0.5px]"
|
||||
/>}
|
||||
icon={<IconFilmSimulation size={15} />}
|
||||
items={simulations
|
||||
.sort(sortFilmSimulationsWithCount)
|
||||
.map(({ simulation, count }) =>
|
||||
|
||||
@ -284,11 +284,12 @@ export default function PhotoLarge({
|
||||
<div>
|
||||
{(showCameraContent || showLensContent) &&
|
||||
<div className="flex flex-col">
|
||||
<PhotoCamera
|
||||
camera={camera}
|
||||
contrast="medium"
|
||||
prefetch={prefetchRelatedLinks}
|
||||
/>
|
||||
{showCameraContent &&
|
||||
<PhotoCamera
|
||||
camera={camera}
|
||||
contrast="medium"
|
||||
prefetch={prefetchRelatedLinks}
|
||||
/>}
|
||||
{showLensContent &&
|
||||
<PhotoLens
|
||||
lens={lens}
|
||||
|
||||
@ -42,17 +42,17 @@ import { convertRecipesForForm, Recipes } from '@/recipe';
|
||||
import deepEqual from 'fast-deep-equal/es6/react';
|
||||
import ApplyRecipeTitleGloballyCheckbox from './ApplyRecipesGloballyCheckbox';
|
||||
import { FilmSimulation } from '@/simulation';
|
||||
import { FaRegStar } from 'react-icons/fa6';
|
||||
import { AiOutlineEyeInvisible } from 'react-icons/ai';
|
||||
import IconFavs from '@/components/icons/IconFavs';
|
||||
import IconHidden from '@/components/icons/IconHidden';
|
||||
|
||||
const THUMBNAIL_SIZE = 300;
|
||||
|
||||
const iconForKey = (key: keyof PhotoFormData) => {
|
||||
switch (key) {
|
||||
case 'favorite':
|
||||
return <FaRegStar size={14} />;
|
||||
return <IconFavs size={14} />;
|
||||
case 'hidden':
|
||||
return <AiOutlineEyeInvisible size={16} />;
|
||||
return <IconHidden size={16} />;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -2,10 +2,10 @@ import { pathForRecipe } from '@/app/paths';
|
||||
import EntityLink, {
|
||||
EntityLinkExternalProps,
|
||||
} from '@/components/primitives/EntityLink';
|
||||
import { TbChecklist } from 'react-icons/tb';
|
||||
import { formatRecipe } from '.';
|
||||
import clsx from 'clsx/lite';
|
||||
import { RefObject } from 'react';
|
||||
import IconRecipe from '@/components/icons/IconRecipe';
|
||||
|
||||
export default function PhotoRecipe({
|
||||
recipe,
|
||||
@ -31,7 +31,7 @@ export default function PhotoRecipe({
|
||||
title="Recipe"
|
||||
label={formatRecipe(recipe)}
|
||||
href={pathForRecipe(recipe)}
|
||||
icon={<TbChecklist
|
||||
icon={<IconRecipe
|
||||
size={16}
|
||||
className={clsx(
|
||||
badged
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import { FaStar } from 'react-icons/fa';
|
||||
import { TAG_FAVS } from '.';
|
||||
import { pathForTag } from '@/app/paths';
|
||||
import { clsx } from 'clsx/lite';
|
||||
import EntityLink, {
|
||||
EntityLinkExternalProps,
|
||||
} from '@/components/primitives/EntityLink';
|
||||
import IconFavs from '@/components/icons/IconFavs';
|
||||
|
||||
export default function FavsTag({
|
||||
type,
|
||||
@ -21,20 +20,19 @@ export default function FavsTag({
|
||||
label={badged
|
||||
? <span className="inline-flex gap-1 items-center">
|
||||
{TAG_FAVS}
|
||||
<FaStar
|
||||
<IconFavs
|
||||
size={10}
|
||||
className="text-amber-500 translate-y-[-0.5px]"
|
||||
className="translate-y-[-0.5px]"
|
||||
highlight
|
||||
/>
|
||||
</span>
|
||||
: TAG_FAVS}
|
||||
href={pathForTag(TAG_FAVS)}
|
||||
icon={!badged &&
|
||||
<FaStar
|
||||
size={12}
|
||||
className={clsx(
|
||||
'text-amber-500',
|
||||
'translate-x-[-1px]',
|
||||
)}
|
||||
<IconFavs
|
||||
size={13}
|
||||
className="translate-x-[-0.5px] translate-y-[-0.5px]"
|
||||
highlight
|
||||
/>}
|
||||
type={type}
|
||||
className={className}
|
||||
|
||||
@ -3,7 +3,7 @@ import { formatTag } from '.';
|
||||
import EntityLink, {
|
||||
EntityLinkExternalProps,
|
||||
} from '@/components/primitives/EntityLink';
|
||||
import { FiTag } from 'react-icons/fi';
|
||||
import IconTag from '@/components/icons/IconTag';
|
||||
|
||||
export default function PhotoTag({
|
||||
tag,
|
||||
@ -21,7 +21,7 @@ export default function PhotoTag({
|
||||
<EntityLink
|
||||
label={formatTag(tag)}
|
||||
href={pathForTag(tag)}
|
||||
icon={<FiTag size={14} className="translate-x-[0.5px]" />}
|
||||
icon={<IconTag size={14} className="translate-x-[0.5px]" />}
|
||||
type={type}
|
||||
className={className}
|
||||
badged={badged}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user