Skip to content

Commit

Permalink
#797 - Enhancing the card menu and type
Browse files Browse the repository at this point in the history
  • Loading branch information
estruyf committed Apr 25, 2024
1 parent 3fedaf7 commit 18b7708
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 10 deletions.
2 changes: 2 additions & 0 deletions l10n/bundle.l10n.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
39 changes: 29 additions & 10 deletions src/dashboardWebView/components/SnippetsView/Item.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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;
Expand Down Expand Up @@ -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>

Expand Down
97 changes: 97 additions & 0 deletions src/dashboardWebView/components/SnippetsView/ItemMenu.tsx
Original file line number Diff line number Diff line change
@@ -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>
);
};
8 changes: 8 additions & 0 deletions src/localization/localization.enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down

0 comments on commit 18b7708

Please # to comment.