Skip to content

Commit

Permalink
Show tags in note preview
Browse files Browse the repository at this point in the history
  • Loading branch information
colebemis committed Dec 12, 2024
1 parent 3fb8466 commit 1b25e5d
Show file tree
Hide file tree
Showing 12 changed files with 238 additions and 34 deletions.
12 changes: 9 additions & 3 deletions src/components/command-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { useNavigate } from "@tanstack/react-router"
import { parseDate } from "chrono-node"
import { Command } from "cmdk"
import { useAtomValue } from "jotai"
import { selectAtom, useAtomCallback } from "jotai/utils"
import { useCallback, useMemo, useRef, useState } from "react"
import { useHotkeys } from "react-hotkeys-hook"
import { useDebounce } from "use-debounce"
import { pinnedNotesAtom, tagSearcherAtom } from "../global-state"
import { notesAtom, pinnedNotesAtom, tagSearcherAtom } from "../global-state"
import { useSaveNote } from "../hooks/note"
import { useSearchNotes } from "../hooks/search"
import { Note } from "../schema"
Expand All @@ -23,13 +24,18 @@ import {
} from "./icons"
import { NoteFavicon } from "./note-favicon"

const hasDailyNoteAtom = selectAtom(notesAtom, (notes) => notes.has(toDateString(new Date())))
const hasWeeklyNoteAtom = selectAtom(notesAtom, (notes) => notes.has(toWeekString(new Date())))

export function CommandMenu() {
const navigate = useNavigate()

const searchNotes = useSearchNotes()
const tagSearcher = useAtomValue(tagSearcherAtom)
const saveNote = useSaveNote()
const pinnedNotes = useAtomValue(pinnedNotesAtom)
const getHasDailyNote = useAtomCallback(useCallback((get) => get(hasDailyNoteAtom), []))
const getHasWeeklyNote = useAtomCallback(useCallback((get) => get(hasWeeklyNoteAtom), []))

// Refs
const prevActiveElement = useRef<HTMLElement>()
Expand Down Expand Up @@ -98,7 +104,7 @@ export function CommandMenu() {
_splat: toDateString(new Date()),
},
search: {
mode: "read",
mode: getHasDailyNote() ? "read" : "write",
query: undefined,
view: "grid",
},
Expand All @@ -115,7 +121,7 @@ export function CommandMenu() {
_splat: toWeekString(new Date()),
},
search: {
mode: "read",
mode: getHasWeeklyNote() ? "read" : "write",
query: undefined,
view: "grid",
},
Expand Down
19 changes: 15 additions & 4 deletions src/components/link-highlight-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import React from "react"
import React, { useContext, useMemo } from "react"

type LinkHighlightProviderProps = {
href: string | string[]
children?: React.ReactNode
}

export const LinkHighlightContext = React.createContext<string[]>([])

export function LinkHighlightProvider({ href, children }: LinkHighlightProviderProps) {
const inheritedHrefs = useLinkHighlight()

// Scope styles using a unique ID
const id = React.useMemo(() => `id-${Math.random().toString(36).substring(2, 15)}`, [])
const hrefs = Array.isArray(href) ? href : [href]
const id = useMemo(() => `id-${Math.random().toString(36).substring(2, 15)}`, [])
const hrefs = useMemo(() => (Array.isArray(href) ? href : [href]), [href])

const contextValue = useMemo(() => [...inheritedHrefs, ...hrefs], [inheritedHrefs, hrefs])

return (
<div id={id}>
<style>
Expand All @@ -21,7 +28,11 @@ export function LinkHighlightProvider({ href, children }: LinkHighlightProviderP
}`,
)}
</style>
{children}
<LinkHighlightContext.Provider value={contextValue}>{children}</LinkHighlightContext.Provider>
</div>
)
}

export function useLinkHighlight() {
return useContext(LinkHighlightContext)
}
6 changes: 3 additions & 3 deletions src/components/markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export const Markdown = React.memo(
<div className="flex flex-wrap items-center gap-2">
<h1 className="text-xl font-semibold leading-5">{parsedTemplate.data.name}</h1>
<PillButton variant="dashed" asChild>
<Link to="/" search={{ query: "has:template", view: "grid" }}>
<Link to="/" search={{ query: "type:template", view: "grid" }}>
Template
</Link>
</PillButton>
Expand Down Expand Up @@ -754,7 +754,7 @@ function NoteLink({ id, text }: NoteLinkProps) {
>
{isFirst && note && online ? (
<NoteFavicon
note={note}
note={note}
content={note.content}
className="mr-2 align-sub [h1>a>&]:align-baseline"
defaultFavicon={null}
Expand All @@ -771,7 +771,7 @@ function NoteLink({ id, text }: NoteLinkProps) {
className=" card-2 z-20 w-96 animate-in fade-in data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2"
>
{note ? (
<NotePreview>{note.content}</NotePreview>
<NotePreview note={note} />
) : (
<span className="flex items-center gap-2 p-4 text-text-danger">
<ErrorIcon16 />
Expand Down
2 changes: 1 addition & 1 deletion src/components/note-preview-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ const _NotePreviewCard = React.memo(function NoteCard({ id }: NoteCardProps) {
isDropdownOpen && "ring-2 ring-border",
)}
>
<NotePreview>{note?.content ?? ""}</NotePreview>
<NotePreview note={note} />
</Link>
<div
className={cx(
Expand Down
34 changes: 30 additions & 4 deletions src/components/note-preview.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,36 @@
import { Note } from "../schema"
import { cx } from "../utils/cx"
import { removeParentTags } from "../utils/remove-parent-tags"
import { useLinkHighlight } from "./link-highlight-provider"
import { Markdown } from "./markdown"

export function NotePreview({ children }: { children: string }) {
export function NotePreview({ note }: { note: Note }) {
const highlightedHrefs = useLinkHighlight()
console.log(highlightedHrefs)
return (
<div className="aspect-[5/3] w-full overflow-hidden p-3 [contain:layout_paint] [mask-image:linear-gradient(to_bottom,black_0%,black_75%,transparent_100%)] [&_*::-webkit-scrollbar]:hidden">
<div {...{ inert: "" }} className="w-[125%] origin-top-left scale-[80%]">
<Markdown hideFrontmatter>{children}</Markdown>
<div
{...{ inert: "" }}
className="grid aspect-[5/3] w-full grid-rows-[1fr_auto] gap-1.5 overflow-hidden p-3 [contain:layout_paint]"
>
<div className="overflow-hidden [mask-image:linear-gradient(to_bottom,black_0%,black_75%,transparent_100%)] [&_*::-webkit-scrollbar]:hidden">
<div className="w-[125%] origin-top-left scale-[80%]">
<Markdown hideFrontmatter>{note.content}</Markdown>
</div>
</div>
<div className="flex flex-wrap gap-1.5 pr-10 coarse:pr-12">
{removeParentTags(note.tags).map((tag) => (
<div
key={tag}
className={cx(
"flex h-5 items-center rounded-full px-1.5 text-sm",
highlightedHrefs.some((href) => `/tags/${tag}`.startsWith(href))
? "bg-bg-highlight text-text-highlight"
: "bg-bg-secondary text-text-secondary",
)}
>
{tag}
</div>
))}
</div>
</div>
)
Expand Down
1 change: 0 additions & 1 deletion src/hooks/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,6 @@ export function testQualifiers(qualifiers: Qualifier[], item: Note) {
})
break

case "is":
case "type":
value = qualifier.values.includes(item.type)
break
Expand Down
2 changes: 1 addition & 1 deletion src/routes/notes_.$.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ function NotePage() {
<span className={cx("truncate", !note ? "italic text-text-secondary" : "")}>
<PageTitle note={parsedNote} />
</span>
{isDirty ? <DotIcon8 className="text-[var(--yellow-11)]" /> : null}
{isDirty ? <DotIcon8 className="text-[var(--amber-11)]" /> : null}
</span>
}
icon={<NoteFavicon note={parsedNote} />}
Expand Down
11 changes: 9 additions & 2 deletions src/routes/settings.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createFileRoute } from "@tanstack/react-router"
import { createFileRoute, useNavigate } from "@tanstack/react-router"
import { useAtomValue } from "jotai"
import { useState } from "react"
import { useNetworkState } from "react-use"
Expand Down Expand Up @@ -45,6 +45,7 @@ function SettingsSection({ title, children }: { title: string; children: React.R
}

function GitHubSection() {
const navigate = useNavigate()
const githubUser = useAtomValue(githubUserAtom)
const githubRepo = useAtomValue(githubRepoAtom)
const isRepoNotCloned = useAtomValue(isRepoNotClonedAtom)
Expand Down Expand Up @@ -74,7 +75,13 @@ function GitHubSection() {
<span className="truncate">{githubUser.login}</span>
</span>
</div>
<Button className="flex-shrink-0" onClick={signOut}>
<Button
className="flex-shrink-0"
onClick={() => {
signOut()
navigate({ to: "/", search: { query: undefined, view: "grid" } })
}}
>
Sign out
</Button>
</div>
Expand Down
27 changes: 15 additions & 12 deletions src/routes/tags_.$.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { IconButton } from "../components/icon-button"
import { EditIcon16, MoreIcon16, TagIcon16, TrashIcon16 } from "../components/icons"
import { NoteList } from "../components/note-list"
import { useDeleteTag, useRenameTag } from "../hooks/tag"
import { LinkHighlightProvider } from "../components/link-highlight-provider"

type RouteSearch = {
query: string | undefined
Expand Down Expand Up @@ -85,18 +86,20 @@ function RouteComponent() {
}
>
<div className="p-4 pt-0">
<NoteList
key={tag}
baseQuery={`tag:${tag}`}
query={query ?? ""}
view={view}
onQueryChange={(query) =>
navigate({ search: (prev) => ({ ...prev, query }), replace: true })
}
onViewChange={(view) =>
navigate({ search: (prev) => ({ ...prev, view }), replace: true })
}
/>
<LinkHighlightProvider href={`/tags/${tag}`}>
<NoteList
key={tag}
baseQuery={`tag:${tag}`}
query={query ?? ""}
view={view}
onQueryChange={(query) =>
navigate({ search: (prev) => ({ ...prev, query }), replace: true })
}
onViewChange={(view) =>
navigate({ search: (prev) => ({ ...prev, view }), replace: true })
}
/>
</LinkHighlightProvider>
</div>
</AppLayout>
)
Expand Down
Loading

0 comments on commit 1b25e5d

Please sign in to comment.