mirror of
https://github.com/antebudimir/feishin.git
synced 2026-01-02 10:53:33 +00:00
Migrate to Mantine v8 and Design Changes (#961)
* mantine v8 migration * various design changes and improvements
This commit is contained in:
parent
bea55d48a8
commit
c1330d92b2
473 changed files with 12469 additions and 11607 deletions
|
|
@ -1,12 +1,8 @@
|
|||
import { ActionIcon, Group, Kbd, ScrollArea } from '@mantine/core';
|
||||
import { useDebouncedValue, useDisclosure } from '@mantine/hooks';
|
||||
import { Fragment, useCallback, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { RiCloseFill, RiSearchLine } from 'react-icons/ri';
|
||||
import { generatePath, useNavigate } from 'react-router';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { Button, Modal, Paper, Spinner, TextInput } from '/@/renderer/components';
|
||||
import { usePlayQueueAdd } from '/@/renderer/features/player';
|
||||
import { Command, CommandPalettePages } from '/@/renderer/features/search/components/command';
|
||||
import { GoToCommands } from '/@/renderer/features/search/components/go-to-commands';
|
||||
|
|
@ -16,18 +12,21 @@ import { ServerCommands } from '/@/renderer/features/search/components/server-co
|
|||
import { useSearch } from '/@/renderer/features/search/queries/search-query';
|
||||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
import { useCurrentServer } from '/@/renderer/store';
|
||||
import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
|
||||
import { Box } from '/@/shared/components/box/box';
|
||||
import { Button } from '/@/shared/components/button/button';
|
||||
import { Group } from '/@/shared/components/group/group';
|
||||
import { Icon } from '/@/shared/components/icon/icon';
|
||||
import { Kbd } from '/@/shared/components/kbd/kbd';
|
||||
import { Modal } from '/@/shared/components/modal/modal';
|
||||
import { Spinner } from '/@/shared/components/spinner/spinner';
|
||||
import { TextInput } from '/@/shared/components/text-input/text-input';
|
||||
import { LibraryItem } from '/@/shared/types/domain-types';
|
||||
|
||||
interface CommandPaletteProps {
|
||||
modalProps: (typeof useDisclosure)['arguments'];
|
||||
}
|
||||
|
||||
const CustomModal = styled(Modal)`
|
||||
& .mantine-Modal-header {
|
||||
display: none;
|
||||
}
|
||||
`;
|
||||
|
||||
export const CommandPalette = ({ modalProps }: CommandPaletteProps) => {
|
||||
const navigate = useNavigate();
|
||||
const server = useCurrentServer();
|
||||
|
|
@ -69,7 +68,7 @@ export const CommandPalette = ({ modalProps }: CommandPaletteProps) => {
|
|||
const handlePlayQueueAdd = usePlayQueueAdd();
|
||||
|
||||
return (
|
||||
<CustomModal
|
||||
<Modal
|
||||
{...modalProps}
|
||||
centered
|
||||
handlers={{
|
||||
|
|
@ -91,19 +90,21 @@ export const CommandPalette = ({ modalProps }: CommandPaletteProps) => {
|
|||
}
|
||||
},
|
||||
}}
|
||||
scrollAreaComponent={ScrollArea.Autosize}
|
||||
size="lg"
|
||||
styles={{
|
||||
header: { display: 'none' },
|
||||
}}
|
||||
>
|
||||
<Group
|
||||
gap="sm"
|
||||
mb="1rem"
|
||||
spacing="sm"
|
||||
>
|
||||
{pages.map((page, index) => (
|
||||
<Fragment key={page}>
|
||||
{index > 0 && ' > '}
|
||||
<Button
|
||||
compact
|
||||
disabled
|
||||
size="compact-md"
|
||||
variant="default"
|
||||
>
|
||||
{page?.toLocaleUpperCase()}
|
||||
|
|
@ -123,20 +124,23 @@ export const CommandPalette = ({ modalProps }: CommandPaletteProps) => {
|
|||
>
|
||||
<TextInput
|
||||
data-autofocus
|
||||
icon={<RiSearchLine />}
|
||||
leftSection={<Icon icon="search" />}
|
||||
onChange={(e) => setQuery(e.currentTarget.value)}
|
||||
ref={searchInputRef}
|
||||
rightSection={
|
||||
<ActionIcon
|
||||
onClick={() => {
|
||||
setQuery('');
|
||||
searchInputRef.current?.focus();
|
||||
}}
|
||||
>
|
||||
<RiCloseFill />
|
||||
</ActionIcon>
|
||||
query && (
|
||||
<ActionIcon
|
||||
onClick={() => {
|
||||
setQuery('');
|
||||
searchInputRef.current?.focus();
|
||||
}}
|
||||
variant="transparent"
|
||||
>
|
||||
<Icon icon="x" />
|
||||
</ActionIcon>
|
||||
)
|
||||
}
|
||||
size="lg"
|
||||
size="sm"
|
||||
value={query}
|
||||
/>
|
||||
<Command.Separator />
|
||||
|
|
@ -263,22 +267,22 @@ export const CommandPalette = ({ modalProps }: CommandPaletteProps) => {
|
|||
)}
|
||||
</Command.List>
|
||||
</Command>
|
||||
<Paper
|
||||
<Box
|
||||
mt="0.5rem"
|
||||
p="0.5rem"
|
||||
>
|
||||
<Group position="apart">
|
||||
<Group justify="space-between">
|
||||
<Command.Loading>
|
||||
{isHome && isLoading && query !== '' && <Spinner />}
|
||||
</Command.Loading>
|
||||
<Group spacing="sm">
|
||||
<Group gap="sm">
|
||||
<Kbd size="md">ESC</Kbd>
|
||||
<Kbd size="md">↑</Kbd>
|
||||
<Kbd size="md">↓</Kbd>
|
||||
<Kbd size="md">⏎</Kbd>
|
||||
</Group>
|
||||
</Group>
|
||||
</Paper>
|
||||
</CustomModal>
|
||||
</Box>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
44
src/renderer/features/search/components/command.css
Normal file
44
src/renderer/features/search/components/command.css
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
input[cmdk-input] {
|
||||
width: 100%;
|
||||
font-size: var(--theme-font-size-md);
|
||||
border: none;
|
||||
border-radius: var(--theme-radius-sm);
|
||||
}
|
||||
|
||||
[cmdk-group-heading] {
|
||||
margin: var(--theme-spacing-md) 0;
|
||||
font-size: var(--theme-font-size-sm);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
[cmdk-group-items] {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--theme-spacing-xs);
|
||||
}
|
||||
|
||||
[cmdk-item] {
|
||||
display: flex;
|
||||
gap: var(--theme-spacing-sm);
|
||||
align-items: center;
|
||||
padding: var(--theme-spacing-sm);
|
||||
font-size: var(--theme-font-size-md);
|
||||
color: var(--theme-colors-foreground);
|
||||
cursor: pointer;
|
||||
border-radius: var(--theme-radius-sm);
|
||||
|
||||
svg {
|
||||
width: 1.2rem;
|
||||
height: 1.2rem;
|
||||
}
|
||||
|
||||
&[data-selected] {
|
||||
background: var(--theme-colors-surface);
|
||||
}
|
||||
}
|
||||
|
||||
[cmdk-separator] {
|
||||
height: 1px;
|
||||
margin: 0 0 var(--theme-spacing-sm);
|
||||
background: var(--theme-colors-border);
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
import { Command as Cmdk } from 'cmdk';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import './command.css';
|
||||
|
||||
export enum CommandPalettePages {
|
||||
GO_TO = 'go',
|
||||
|
|
@ -7,64 +8,4 @@ export enum CommandPalettePages {
|
|||
MANAGE_SERVERS = 'servers',
|
||||
}
|
||||
|
||||
export const Command = styled(Cmdk)`
|
||||
[cmdk-root] {
|
||||
background-color: var(--background-color);
|
||||
}
|
||||
|
||||
input[cmdk-input] {
|
||||
width: 100%;
|
||||
height: 1.5rem;
|
||||
padding: 1.3rem 0.5rem;
|
||||
margin-bottom: 1rem;
|
||||
font-family: var(--content-font-family);
|
||||
color: var(--input-fg);
|
||||
background: var(--input-bg);
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
|
||||
&::placeholder {
|
||||
color: var(--input-placeholder-fg);
|
||||
}
|
||||
}
|
||||
|
||||
[cmdk-group-heading] {
|
||||
margin: 1rem 0;
|
||||
font-size: 0.9rem;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
[cmdk-group-items] {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
[cmdk-item] {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
align-items: center;
|
||||
padding: 0.5rem;
|
||||
font-family: var(--content-font-family);
|
||||
color: var(--btn-default-fg);
|
||||
cursor: pointer;
|
||||
background: var(--btn-default-bg);
|
||||
border-radius: 5px;
|
||||
|
||||
svg {
|
||||
width: 1.2rem;
|
||||
height: 1.2rem;
|
||||
}
|
||||
|
||||
&[data-selected] {
|
||||
color: var(--btn-default-fg-hover);
|
||||
background: var(--btn-default-bg-hover);
|
||||
}
|
||||
}
|
||||
|
||||
[cmdk-separator] {
|
||||
height: 1px;
|
||||
margin: 0 0 0.5rem;
|
||||
background: var(--generic-border-color);
|
||||
}
|
||||
`;
|
||||
export const Command = Cmdk as typeof Cmdk;
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ export const HomeCommands = ({
|
|||
|
||||
openModal({
|
||||
children: <CreatePlaylistForm onCancel={() => closeAllModals()} />,
|
||||
size: server?.type === ServerType?.NAVIDROME ? 'xl' : 'sm',
|
||||
size: server?.type === ServerType?.NAVIDROME ? 'lg' : 'sm',
|
||||
title: t('form.createPlaylist.title', { postProcess: 'sentenceCase' }),
|
||||
});
|
||||
}, [handleClose, server?.type, t]);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
.item-grid {
|
||||
display: grid;
|
||||
grid-template-areas: 'image info';
|
||||
grid-template-rows: 1fr;
|
||||
grid-template-columns: var(--item-height) minmax(0, 1fr);
|
||||
grid-auto-columns: 1fr;
|
||||
gap: 0.5rem;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: 100%;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.image-wrapper {
|
||||
display: flex;
|
||||
grid-area: image;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.metadata-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
grid-area: info;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.image {
|
||||
object-fit: var(--theme-image-fit);
|
||||
background: alpha(var(--theme-colors-foreground-muted), 0.3);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
|
@ -1,59 +1,16 @@
|
|||
import { Center, Flex } from '@mantine/core';
|
||||
import { MouseEvent, useCallback } from 'react';
|
||||
import { CSSProperties, MouseEvent, useCallback, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
RiAddBoxFill,
|
||||
RiAddCircleFill,
|
||||
RiAlbumFill,
|
||||
RiPlayFill,
|
||||
RiPlayListFill,
|
||||
RiShuffleFill,
|
||||
RiUserVoiceFill,
|
||||
} from 'react-icons/ri';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { Button, Text } from '/@/renderer/components';
|
||||
import styles from './library-command-item.module.css';
|
||||
|
||||
import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
|
||||
import { Flex } from '/@/shared/components/flex/flex';
|
||||
import { Group } from '/@/shared/components/group/group';
|
||||
import { Image } from '/@/shared/components/image/image';
|
||||
import { Text } from '/@/shared/components/text/text';
|
||||
import { LibraryItem } from '/@/shared/types/domain-types';
|
||||
import { Play, PlayQueueAddOptions } from '/@/shared/types/types';
|
||||
|
||||
const Item = styled(Flex)``;
|
||||
|
||||
const ItemGrid = styled.div<{ height: number }>`
|
||||
display: grid;
|
||||
grid-template-areas: 'image info';
|
||||
grid-template-rows: 1fr;
|
||||
grid-template-columns: ${(props) => props.height}px minmax(0, 1fr);
|
||||
grid-auto-columns: 1fr;
|
||||
gap: 0.5rem;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: 100%;
|
||||
letter-spacing: 0.5px;
|
||||
`;
|
||||
|
||||
const ImageWrapper = styled.div`
|
||||
display: flex;
|
||||
grid-area: image;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
`;
|
||||
|
||||
const MetadataWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
grid-area: info;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const StyledImage = styled.img<{ placeholder?: string }>`
|
||||
object-fit: var(--image-fit);
|
||||
border-radius: 4px;
|
||||
`;
|
||||
|
||||
const ActionsContainer = styled(Flex)``;
|
||||
|
||||
interface LibraryCommandItemProps {
|
||||
disabled?: boolean;
|
||||
handlePlayQueueAdd?: (options: PlayQueueAddOptions) => void;
|
||||
|
|
@ -74,25 +31,6 @@ export const LibraryCommandItem = ({
|
|||
title,
|
||||
}: LibraryCommandItemProps) => {
|
||||
const { t } = useTranslation();
|
||||
let Placeholder = RiAlbumFill;
|
||||
|
||||
switch (itemType) {
|
||||
case LibraryItem.ALBUM:
|
||||
Placeholder = RiAlbumFill;
|
||||
break;
|
||||
case LibraryItem.ALBUM_ARTIST:
|
||||
Placeholder = RiUserVoiceFill;
|
||||
break;
|
||||
case LibraryItem.ARTIST:
|
||||
Placeholder = RiUserVoiceFill;
|
||||
break;
|
||||
case LibraryItem.PLAYLIST:
|
||||
Placeholder = RiPlayListFill;
|
||||
break;
|
||||
default:
|
||||
Placeholder = RiAlbumFill;
|
||||
break;
|
||||
}
|
||||
|
||||
const handlePlay = useCallback(
|
||||
(e: MouseEvent, id: string, playType: Play) => {
|
||||
|
|
@ -108,110 +46,95 @@ export const LibraryCommandItem = ({
|
|||
[handlePlayQueueAdd, itemType],
|
||||
);
|
||||
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
|
||||
return (
|
||||
<Item
|
||||
<Flex
|
||||
gap="xl"
|
||||
justify="space-between"
|
||||
onMouseEnter={() => setIsHovered(true)}
|
||||
onMouseLeave={() => setIsHovered(false)}
|
||||
style={{ height: '40px', width: '100%' }}
|
||||
>
|
||||
<ItemGrid height={40}>
|
||||
<ImageWrapper>
|
||||
{imageUrl ? (
|
||||
<StyledImage
|
||||
alt="cover"
|
||||
height={40}
|
||||
placeholder="var(--placeholder-bg)"
|
||||
src={imageUrl}
|
||||
style={{}}
|
||||
width={40}
|
||||
/>
|
||||
) : (
|
||||
<Center
|
||||
style={{
|
||||
background: 'var(--placeholder-bg)',
|
||||
borderRadius: 'var(--card-default-radius)',
|
||||
height: `${40}px`,
|
||||
width: `${40}px`,
|
||||
}}
|
||||
>
|
||||
<Placeholder
|
||||
color="var(--placeholder-fg)"
|
||||
size={35}
|
||||
/>
|
||||
</Center>
|
||||
)}
|
||||
</ImageWrapper>
|
||||
<MetadataWrapper>
|
||||
<div
|
||||
className={styles.itemGrid}
|
||||
style={{ '--item-height': '40px' } as CSSProperties}
|
||||
>
|
||||
<div className={styles.imageWrapper}>
|
||||
<Image
|
||||
alt="cover"
|
||||
className={styles.image}
|
||||
height={40}
|
||||
src={imageUrl || ''}
|
||||
width={40}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.metadataWrapper}>
|
||||
<Text overflow="hidden">{title}</Text>
|
||||
<Text
|
||||
$secondary
|
||||
isMuted
|
||||
overflow="hidden"
|
||||
>
|
||||
{subtitle}
|
||||
</Text>
|
||||
</MetadataWrapper>
|
||||
</ItemGrid>
|
||||
<ActionsContainer
|
||||
align="center"
|
||||
gap="sm"
|
||||
justify="flex-end"
|
||||
>
|
||||
<Button
|
||||
compact
|
||||
disabled={disabled}
|
||||
onClick={(e) => handlePlay(e, id, Play.NOW)}
|
||||
size="md"
|
||||
tooltip={{
|
||||
label: t('player.play', { postProcess: 'sentenceCase' }),
|
||||
openDelay: 500,
|
||||
}}
|
||||
variant="default"
|
||||
</div>
|
||||
</div>
|
||||
{isHovered && (
|
||||
<Group
|
||||
align="center"
|
||||
gap="sm"
|
||||
justify="flex-end"
|
||||
wrap="nowrap"
|
||||
>
|
||||
<RiPlayFill />
|
||||
</Button>
|
||||
{itemType !== LibraryItem.SONG && (
|
||||
<Button
|
||||
compact
|
||||
<ActionIcon
|
||||
disabled={disabled}
|
||||
onClick={(e) => handlePlay(e, id, Play.SHUFFLE)}
|
||||
size="md"
|
||||
icon="mediaPlay"
|
||||
onClick={(e) => handlePlay(e, id, Play.NOW)}
|
||||
size="xs"
|
||||
tooltip={{
|
||||
label: t('player.shuffle', { postProcess: 'sentenceCase' }),
|
||||
label: t('player.play', { postProcess: 'sentenceCase' }),
|
||||
openDelay: 500,
|
||||
}}
|
||||
variant="default"
|
||||
>
|
||||
<RiShuffleFill />
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
compact
|
||||
disabled={disabled}
|
||||
onClick={(e) => handlePlay(e, id, Play.LAST)}
|
||||
size="md"
|
||||
tooltip={{
|
||||
label: t('player.addLast', { postProcess: 'sentenceCase' }),
|
||||
variant="subtle"
|
||||
/>
|
||||
{itemType !== LibraryItem.SONG && (
|
||||
<ActionIcon
|
||||
disabled={disabled}
|
||||
icon="mediaShuffle"
|
||||
onClick={(e) => handlePlay(e, id, Play.SHUFFLE)}
|
||||
size="xs"
|
||||
tooltip={{
|
||||
label: t('player.shuffle', { postProcess: 'sentenceCase' }),
|
||||
openDelay: 500,
|
||||
}}
|
||||
variant="subtle"
|
||||
/>
|
||||
)}
|
||||
<ActionIcon
|
||||
disabled={disabled}
|
||||
icon="mediaPlayLast"
|
||||
onClick={(e) => handlePlay(e, id, Play.LAST)}
|
||||
size="xs"
|
||||
tooltip={{
|
||||
label: t('player.addLast', { postProcess: 'sentenceCase' }),
|
||||
|
||||
openDelay: 500,
|
||||
}}
|
||||
variant="default"
|
||||
>
|
||||
<RiAddBoxFill />
|
||||
</Button>
|
||||
<Button
|
||||
compact
|
||||
disabled={disabled}
|
||||
onClick={(e) => handlePlay(e, id, Play.NEXT)}
|
||||
size="md"
|
||||
tooltip={{
|
||||
label: t('player.addNext', { postProcess: 'sentenceCase' }),
|
||||
openDelay: 500,
|
||||
}}
|
||||
variant="default"
|
||||
>
|
||||
<RiAddCircleFill />
|
||||
</Button>
|
||||
</ActionsContainer>
|
||||
</Item>
|
||||
openDelay: 500,
|
||||
}}
|
||||
variant="subtle"
|
||||
/>
|
||||
<ActionIcon
|
||||
disabled={disabled}
|
||||
icon="mediaPlayNext"
|
||||
onClick={(e) => handlePlay(e, id, Play.NEXT)}
|
||||
size="xs"
|
||||
tooltip={{
|
||||
label: t('player.addNext', { postProcess: 'sentenceCase' }),
|
||||
openDelay: 500,
|
||||
}}
|
||||
variant="subtle"
|
||||
/>
|
||||
</Group>
|
||||
)}
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,17 +1,21 @@
|
|||
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
|
||||
|
||||
import { Flex, Group, Stack } from '@mantine/core';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { ChangeEvent, MutableRefObject } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { generatePath, Link, useParams, useSearchParams } from 'react-router-dom';
|
||||
|
||||
import { Button, PageHeader, SearchInput } from '/@/renderer/components';
|
||||
import { PageHeader } from '/@/renderer/components/page-header/page-header';
|
||||
import { FilterBar, LibraryHeaderBar } from '/@/renderer/features/shared';
|
||||
import { SearchInput } from '/@/renderer/features/shared/components/search-input';
|
||||
import { useContainerQuery } from '/@/renderer/hooks';
|
||||
import { useListFilterRefresh } from '/@/renderer/hooks/use-list-filter-refresh';
|
||||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
import { useCurrentServer, useListStoreByKey } from '/@/renderer/store';
|
||||
import { Button } from '/@/shared/components/button/button';
|
||||
import { Flex } from '/@/shared/components/flex/flex';
|
||||
import { Group } from '/@/shared/components/group/group';
|
||||
import { Stack } from '/@/shared/components/stack/stack';
|
||||
import {
|
||||
AlbumArtistListQuery,
|
||||
AlbumListQuery,
|
||||
|
|
@ -46,8 +50,8 @@ export const SearchHeader = ({ navigationId, tableRef }: SearchHeaderProps) => {
|
|||
|
||||
return (
|
||||
<Stack
|
||||
gap={0}
|
||||
ref={cq.ref}
|
||||
spacing={0}
|
||||
>
|
||||
<PageHeader>
|
||||
<Flex
|
||||
|
|
@ -61,7 +65,6 @@ export const SearchHeader = ({ navigationId, tableRef }: SearchHeaderProps) => {
|
|||
<SearchInput
|
||||
defaultValue={searchParams.get('query') || ''}
|
||||
onChange={handleSearch}
|
||||
openedWidth={cq.isMd ? 250 : cq.isSm ? 200 : 150}
|
||||
/>
|
||||
</Group>
|
||||
</Flex>
|
||||
|
|
@ -69,11 +72,10 @@ export const SearchHeader = ({ navigationId, tableRef }: SearchHeaderProps) => {
|
|||
<FilterBar>
|
||||
<Group>
|
||||
<Button
|
||||
compact
|
||||
component={Link}
|
||||
fw={600}
|
||||
replace
|
||||
size="md"
|
||||
size="compact-md"
|
||||
state={{ navigationId }}
|
||||
to={{
|
||||
pathname: generatePath(AppRoute.SEARCH, { itemType: LibraryItem.SONG }),
|
||||
|
|
@ -84,11 +86,10 @@ export const SearchHeader = ({ navigationId, tableRef }: SearchHeaderProps) => {
|
|||
{t('entity.track_other', { postProcess: 'sentenceCase' })}
|
||||
</Button>
|
||||
<Button
|
||||
compact
|
||||
component={Link}
|
||||
fw={600}
|
||||
replace
|
||||
size="md"
|
||||
size="compact-md"
|
||||
state={{ navigationId }}
|
||||
to={{
|
||||
pathname: generatePath(AppRoute.SEARCH, {
|
||||
|
|
@ -101,11 +102,10 @@ export const SearchHeader = ({ navigationId, tableRef }: SearchHeaderProps) => {
|
|||
{t('entity.album_other', { postProcess: 'sentenceCase' })}
|
||||
</Button>
|
||||
<Button
|
||||
compact
|
||||
component={Link}
|
||||
fw={600}
|
||||
replace
|
||||
size="md"
|
||||
size="compact-md"
|
||||
state={{ navigationId }}
|
||||
to={{
|
||||
pathname: generatePath(AppRoute.SEARCH, {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue