Unverified 提交 2f73912b authored 作者: Mohamed Aziz Mejri's avatar Mohamed Aziz Mejri 提交者: GitHub

Add search query highlighting to version panel (#3117)

## Summary This PR adds visual highlighting of search query matches in the VersionPane component, making it easier for users to identify which versions match their search criteria. ## Key Changes - **New `HighlightMatch` component**: Created a reusable component that highlights matching text segments with a yellow background (with dark mode support). The matching is case-insensitive. - **Version number highlighting**: Applied highlighting to version numbers in the version list header - **Version hash highlighting**: Applied highlighting to the short commit hash (OID) displayed next to version numbers - **Message highlighting**: Applied highlighting to version messages, including those with reverted version information ## Implementation Details - The `HighlightMatch` component performs case-insensitive substring matching and wraps matched text in a `<mark>` element with Tailwind classes (`bg-yellow-200 dark:bg-yellow-800 rounded-sm`) - Search query is trimmed before being passed to the highlighting function to avoid unnecessary whitespace - The highlighting is applied consistently across all searchable text fields in the version pane (version numbers, hashes, and messages) - The implementation preserves existing message transformation logic for "Reverted" messages while adding highlighting on top <!-- devin-review-badge-begin --> --- <a href="https://app.devin.ai/review/dyad-sh/dyad/pull/3117" target="_blank"> <picture> <source media="(prefers-color-scheme: dark)" srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1"> <img src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1" alt="Open with Devin"> </picture> </a> <!-- devin-review-badge-end -->
上级 8ac4a2d6
...@@ -16,6 +16,27 @@ import { ...@@ -16,6 +16,27 @@ import {
import { useRunApp } from "@/hooks/useRunApp"; import { useRunApp } from "@/hooks/useRunApp";
function HighlightMatch({
text,
query,
}: {
text: string;
query: string;
}): React.ReactNode {
if (!query) return text;
const index = text.toLowerCase().indexOf(query.toLowerCase());
if (index === -1) return text;
return (
<>
{text.slice(0, index)}
<mark className="bg-yellow-200 dark:bg-yellow-800 rounded-sm">
{text.slice(index, index + query.length)}
</mark>
{text.slice(index + query.length)}
</>
);
}
interface VersionPaneProps { interface VersionPaneProps {
isVisible: boolean; isVisible: boolean;
onClose: () => void; onClose: () => void;
...@@ -186,8 +207,19 @@ export function VersionPane({ isVisible, onClose }: VersionPaneProps) { ...@@ -186,8 +207,19 @@ export function VersionPane({ isVisible, onClose }: VersionPaneProps) {
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span className="font-medium text-xs"> <span className="font-medium text-xs">
Version {versions.length - versions.indexOf(version)} ( Version{" "}
{version.oid.slice(0, 7)}) <HighlightMatch
text={String(
versions.length - versions.indexOf(version),
)}
query={searchQuery.trim()}
/>{" "}
(
<HighlightMatch
text={version.oid.slice(0, 7)}
query={searchQuery.trim()}
/>
)
</span> </span>
{/* example format: '2025-07-25T21:52:01Z' */} {/* example format: '2025-07-25T21:52:01Z' */}
{version.dbTimestamp && {version.dbTimestamp &&
...@@ -244,7 +276,9 @@ export function VersionPane({ isVisible, onClose }: VersionPaneProps) { ...@@ -244,7 +276,9 @@ export function VersionPane({ isVisible, onClose }: VersionPaneProps) {
<div className="flex items-center justify-between gap-2"> <div className="flex items-center justify-between gap-2">
{version.message && ( {version.message && (
<p className="mt-1 text-sm"> <p className="mt-1 text-sm">
{version.message.startsWith( <HighlightMatch
text={
version.message.startsWith(
"Reverted all changes back to version ", "Reverted all changes back to version ",
) )
? version.message.replace( ? version.message.replace(
...@@ -260,7 +294,10 @@ export function VersionPane({ isVisible, onClose }: VersionPaneProps) { ...@@ -260,7 +294,10 @@ export function VersionPane({ isVisible, onClose }: VersionPaneProps) {
: version.message; : version.message;
}, },
) )
: version.message} : version.message
}
query={searchQuery.trim()}
/>
</p> </p>
)} )}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论