mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-08-12 03:43:01 +02:00
#797 - Enhancing the card menu and type
This commit is contained in:
@@ -274,6 +274,8 @@
|
||||
"dashboard.preview.button.refresh.title": "Refresh",
|
||||
"dashboard.preview.button.open.title": "Open",
|
||||
|
||||
"dashboard.snippetsView.item.type.content": "Content snippet",
|
||||
"dashboard.snippetsView.item.type.media": "Media snippet",
|
||||
"dashboard.snippetsView.item.quickAction.editSnippet": "Edit snippet",
|
||||
"dashboard.snippetsView.item.quickAction.deleteSnippet": "Delete snippet",
|
||||
"dashboard.snippetsView.item.quickAction.viewSnippet": "View snippet file",
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import * as l10n from '@vscode/l10n';
|
||||
import { Messenger } from '@estruyf/vscode/dist/client';
|
||||
import {
|
||||
CodeBracketIcon,
|
||||
DocumentTextIcon,
|
||||
PhotoIcon,
|
||||
} from '@heroicons/react/24/solid';
|
||||
import * as React from 'react';
|
||||
import { useCallback, useMemo, useRef, useState } from 'react';
|
||||
@@ -17,9 +16,9 @@ import { Alert } from '../Modals/Alert';
|
||||
import { FormDialog } from '../Modals/FormDialog';
|
||||
import { NewForm } from './NewForm';
|
||||
import SnippetForm, { SnippetFormHandle } from './SnippetForm';
|
||||
import * as l10n from '@vscode/l10n';
|
||||
import { LocalizationKey } from '../../../localization';
|
||||
import { FooterActions } from './FooterActions';
|
||||
import { ItemMenu } from './ItemMenu';
|
||||
|
||||
export interface IItemProps {
|
||||
snippetKey: string;
|
||||
@@ -153,20 +152,40 @@ export const Item: React.FunctionComponent<IItemProps> = ({
|
||||
return (
|
||||
<>
|
||||
<li className={`group flex flex-col relative overflow-hidden shadow-md hover:shadow-xl dark:shadow-none border space-y-2 rounded bg-[var(--vscode-sideBar-background)] hover:bg-[var(--vscode-list-hoverBackground)] border-[var(--frontmatter-border)]`}>
|
||||
<div className='p-4 grow'>
|
||||
<div className='p-4 grow space-y-2'>
|
||||
<h2
|
||||
className="mt-2 mb-2 font-bold flex items-center"
|
||||
className="font-bold flex items-center"
|
||||
title={snippet.isMediaSnippet ? 'Media snippet' : 'Content snippet'}
|
||||
>
|
||||
{snippet.isMediaSnippet ? (
|
||||
<PhotoIcon className="w-5 h-5 mr-1" aria-hidden={true} />
|
||||
) : (
|
||||
<DocumentTextIcon className="w-5 h-5 mr-1" aria-hidden={true} />
|
||||
)}
|
||||
<CodeBracketIcon className="w-5 h-5 mr-2" aria-hidden={true} />
|
||||
|
||||
{snippet.title || snippetKey}
|
||||
</h2>
|
||||
|
||||
<FeatureFlag
|
||||
features={mode?.features || []}
|
||||
flag={FEATURE_FLAG.dashboard.snippets.manage}
|
||||
alternative={
|
||||
<ItemMenu
|
||||
insertEnabled={!!(insertToContent && !snippet.isMediaSnippet)}
|
||||
sourcePath={snippet.sourcePath}
|
||||
onInsert={() => setShowInsertDialog(true)} />
|
||||
}
|
||||
>
|
||||
<ItemMenu
|
||||
insertEnabled={!!(insertToContent && !snippet.isMediaSnippet)}
|
||||
sourcePath={snippet.sourcePath}
|
||||
onEdit={onOpenEdit}
|
||||
onInsert={() => setShowInsertDialog(true)}
|
||||
onDelete={() => setShowAlert(true)} />
|
||||
</FeatureFlag>
|
||||
|
||||
<div className='inline-block mr-1 mt-1 text-xs text-[var(--vscode-button-secondaryForeground)] bg-[var(--vscode-button-secondaryBackground)] border border-[var(--frontmatter-border)] rounded px-1 py-0.5'>
|
||||
{
|
||||
snippet.isMediaSnippet ? l10n.t(LocalizationKey.dashboardSnippetsViewItemTypeContent) : l10n.t(LocalizationKey.dashboardSnippetsViewItemTypeMedia)
|
||||
}
|
||||
</div>
|
||||
|
||||
<p className={`text-xs text-[var(--frontmatter-text)]`}>{snippet.description}</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
import * as React from 'react';
|
||||
import * as l10n from '@vscode/l10n';
|
||||
import { useCallback } from 'react';
|
||||
import { LocalizationKey } from '../../../localization';
|
||||
import { openFile } from '../../utils/MessageHandlers';
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '../../../components/shadcn/Dropdown';
|
||||
import { EllipsisHorizontalIcon } from '@heroicons/react/24/solid';
|
||||
import { EyeIcon, PencilIcon, PlusIcon, TrashIcon } from '@heroicons/react/24/outline';
|
||||
|
||||
export interface IItemMenuProps {
|
||||
insertEnabled: boolean;
|
||||
sourcePath?: string;
|
||||
onEdit?: () => void;
|
||||
onInsert: () => void;
|
||||
onDelete?: () => void;
|
||||
}
|
||||
|
||||
export const ItemMenu: React.FunctionComponent<IItemMenuProps> = ({
|
||||
insertEnabled,
|
||||
sourcePath,
|
||||
onEdit,
|
||||
onInsert,
|
||||
onDelete,
|
||||
}: React.PropsWithChildren<IItemMenuProps>) => {
|
||||
|
||||
const showFile = useCallback(() => {
|
||||
openFile(sourcePath);
|
||||
}, [sourcePath]);
|
||||
|
||||
if (!onEdit && !onDelete && !sourcePath && !insertEnabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`group/actions absolute top-4 right-4 flex flex-col space-y-4`}>
|
||||
<div className={`flex items-center border border-transparent rounded-full p-1 -mr-2 -mt-3 group-hover/actions:bg-[var(--vscode-sideBar-background)] group-hover/actions:border-[var(--frontmatter-border)]`}>
|
||||
<div className="relative z-10 flex text-left">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger className='text-[var(--vscode-tab-inactiveForeground)] hover:text-[var(--vscode-tab-activeForeground)]'>
|
||||
<span className="sr-only">{l10n.t(LocalizationKey.commonMenu)}</span>
|
||||
<EllipsisHorizontalIcon className="w-4 h-4" aria-hidden="true" />
|
||||
</DropdownMenuTrigger>
|
||||
|
||||
<DropdownMenuContent align="end">
|
||||
{
|
||||
insertEnabled && (
|
||||
<DropdownMenuItem
|
||||
title={l10n.t(LocalizationKey.commonInsertSnippet)}
|
||||
onClick={onInsert}>
|
||||
<PlusIcon className="mr-2 h-4 w-4" aria-hidden={true} />
|
||||
<span>{l10n.t(LocalizationKey.commonInsertSnippet)}</span>
|
||||
</DropdownMenuItem>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
!sourcePath ? (
|
||||
<>
|
||||
{
|
||||
onEdit && (
|
||||
<DropdownMenuItem
|
||||
title={l10n.t(LocalizationKey.dashboardSnippetsViewItemQuickActionEditSnippet)}
|
||||
onClick={onEdit}>
|
||||
<PencilIcon className="mr-2 h-4 w-4" aria-hidden={true} />
|
||||
<span>{l10n.t(LocalizationKey.dashboardSnippetsViewItemQuickActionEditSnippet)}</span>
|
||||
</DropdownMenuItem>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
onDelete && (
|
||||
<DropdownMenuItem
|
||||
title={l10n.t(LocalizationKey.dashboardSnippetsViewItemQuickActionDeleteSnippet)}
|
||||
onClick={onDelete}
|
||||
className={`focus:bg-[var(--vscode-statusBarItem-errorBackground)] focus:text-[var(--vscode-statusBarItem-errorForeground)]`}>
|
||||
<TrashIcon className="mr-2 h-4 w-4" aria-hidden={true} />
|
||||
<span>{l10n.t(LocalizationKey.dashboardSnippetsViewItemQuickActionDeleteSnippet)}</span>
|
||||
</DropdownMenuItem>
|
||||
)
|
||||
}
|
||||
</>
|
||||
) : (
|
||||
<DropdownMenuItem
|
||||
title={l10n.t(LocalizationKey.dashboardSnippetsViewItemQuickActionViewSnippet)}
|
||||
onClick={showFile}>
|
||||
<EyeIcon className="mr-2 h-4 w-4" aria-hidden={true} />
|
||||
<span>{l10n.t(LocalizationKey.dashboardSnippetsViewItemQuickActionViewSnippet)}</span>
|
||||
</DropdownMenuItem>
|
||||
)
|
||||
}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -887,6 +887,14 @@ export enum LocalizationKey {
|
||||
* Open
|
||||
*/
|
||||
dashboardPreviewButtonOpenTitle = 'dashboard.preview.button.open.title',
|
||||
/**
|
||||
* Content snippet
|
||||
*/
|
||||
dashboardSnippetsViewItemTypeContent = 'dashboard.snippetsView.item.type.content',
|
||||
/**
|
||||
* Media snippet
|
||||
*/
|
||||
dashboardSnippetsViewItemTypeMedia = 'dashboard.snippetsView.item.type.media',
|
||||
/**
|
||||
* Edit snippet
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user