#440 - Type to search/filter in the snippets dashboard

This commit is contained in:
Elio Struyf
2022-11-04 15:25:00 +01:00
parent 5205b2d079
commit d701651a05
3 changed files with 61 additions and 1 deletions
+1
View File
@@ -12,6 +12,7 @@
- [#428](https://github.com/estruyf/vscode-front-matter/issues/428): Improved UX for inserting images to your content
- [#430](https://github.com/estruyf/vscode-front-matter/issues/430): Support for HEXO its `post_asset_folder` setting (image location)
- [#434](https://github.com/estruyf/vscode-front-matter/issues/434): Webview errors are logged in the extension output
- [#440](https://github.com/estruyf/vscode-front-matter/issues/440): Type to search/filter in the snippets dashboard
- [#447](https://github.com/estruyf/vscode-front-matter/issues/447): Allow to use placeholders on git commit messages
- [#449](https://github.com/estruyf/vscode-front-matter/issues/449): Show `filename` if the `title` is not set
- [#450](https://github.com/estruyf/vscode-front-matter/issues/450): Additional time placeholders added `{{hour12}}`, `{{hour24}}`, `{{ampm}}`, and `{{minute}}`
@@ -0,0 +1,45 @@
import { SearchIcon, XCircleIcon } from '@heroicons/react/outline';
import * as React from 'react';
export interface IFilterInputProps {
placeholder: string;
value: string;
isReady: boolean;
autoFocus: boolean;
onReset?: () => void;
onChange: (value: string) => void;
}
export const FilterInput: React.FunctionComponent<IFilterInputProps> = ({ placeholder, value, isReady, autoFocus, onReset, onChange}: React.PropsWithChildren<IFilterInputProps>) => {
return (
<div className="flex space-x-4 flex-1">
<div className="min-w-0">
<label htmlFor="search" className="sr-only">Search</label>
<div className="relative flex justify-center">
<div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<SearchIcon className="h-5 w-5 text-gray-400" aria-hidden="true" />
</div>
<input
type="text"
name="search"
className={`block w-full py-2 pl-10 pr-3 sm:text-sm bg-white dark:bg-vulcan-300 border border-gray-300 dark:border-vulcan-100 text-vulcan-500 dark:text-whisper-500 placeholder-gray-400 dark:placeholder-whisper-800 focus:outline-none appearance-none disabled:opacity-50`}
placeholder={placeholder || "Search"}
value={value}
autoFocus={autoFocus}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => onChange(event.target.value)}
disabled={!isReady}
/>
{
value && onReset && (
<button onClick={onReset} className="absolute inset-y-0 right-0 pr-3 flex items-center">
<XCircleIcon className="h-5 w-5 text-gray-400" aria-hidden="true" />
</button>
)
}
</div>
</div>
</div>
);
};
@@ -9,6 +9,7 @@ import { TelemetryEvent } from '../../../constants/TelemetryEvent';
import { SnippetParser } from '../../../helpers/SnippetParser';
import { DashboardMessage } from '../../DashboardMessage';
import { ModeAtom, SettingsSelector, ViewDataSelector } from '../../state';
import { FilterInput } from '../Header/FilterInput';
import { PageLayout } from '../Layout/PageLayout';
import { FormDialog } from '../Modals/FormDialog';
import { SponsorMsg } from '../SponsorMsg';
@@ -26,9 +27,13 @@ export const Snippets: React.FunctionComponent<ISnippetsProps> = (props: React.P
const [ snippetBody, setSnippetBody ] = useState<string>('');
const [ showCreateDialog, setShowCreateDialog ] = useState(false);
const [ mediaSnippet, setMediaSnippet ] = useState(false);
const [ snippetFilter, setSnippetFilter ] = useState<string>('');
const snippets = settings?.snippets || {};
const snippetKeys = useMemo(() => Object.keys(snippets) || [], [settings?.snippets]);
const snippetKeys = useMemo(() => {
const allSnippetKeys = Object.keys(snippets).sort((a, b) => a.localeCompare(b));
return allSnippetKeys.filter((key) => key.toLowerCase().includes(snippetFilter.toLowerCase()));
}, [settings?.snippets, snippetFilter]);
const onSnippetAdd = useCallback(() => {
if (!snippetTitle || !snippetBody) {
@@ -70,6 +75,15 @@ export const Snippets: React.FunctionComponent<ISnippetsProps> = (props: React.P
className="py-3 px-4 flex items-center justify-between border-b border-gray-300 dark:border-vulcan-100"
aria-label="snippets header"
>
<FilterInput
placeholder='Search'
isReady={true}
autoFocus={true}
value={snippetFilter}
onChange={(value: string) => setSnippetFilter(value)}
onReset={() => setSnippetFilter('')}
/>
<div className="flex flex-1 justify-end">
<button
className={`inline-flex items-center px-3 py-1 border border-transparent text-xs leading-4 font-medium text-white dark:text-vulcan-500 bg-teal-600 hover:bg-teal-700 focus:outline-none disabled:bg-gray-500`}