feat(reader): open bookmark URLs in reader instead of new window

- Change URL links to buttons that open in reader
- Style URL buttons to look like links (cursor, hover, no button appearance)
- Rename 'content-panel' to 'reader' throughout codebase
- Update all CSS classes: content-panel → reader, content-title → reader-title, etc.
- Change empty state text from 'preview' to 'read' to match reader terminology
- Keep things simple and focused on in-app reading experience
This commit is contained in:
Gigi
2025-10-03 09:30:28 +02:00
parent d6756dc5a1
commit 53b54c77e7
3 changed files with 48 additions and 35 deletions

View File

@@ -99,14 +99,13 @@ export const BookmarkItem: React.FC<BookmarkItemProps> = ({ bookmark, index, onS
const classification = classifyUrl(url)
return (
<div key={urlIndex} className="url-row">
<a
href={url}
target="_blank"
rel="noopener noreferrer"
<button
className="bookmark-url"
onClick={() => onSelectUrl?.(url)}
title="Open in reader"
>
{url}
</a>
</button>
<IconButton
icon={getIconForUrlType(url)}
ariaLabel={classification.buttonText}

View File

@@ -15,15 +15,15 @@ interface ContentPanelProps {
const ContentPanel: React.FC<ContentPanelProps> = ({ loading, title, html, markdown, selectedUrl }) => {
if (!selectedUrl) {
return (
<div className="content-panel empty">
<p>Select a bookmark to preview its content.</p>
<div className="reader empty">
<p>Select a bookmark to read its content.</p>
</div>
)
}
if (loading) {
return (
<div className="content-panel loading">
<div className="reader loading">
<div className="loading-spinner">
<FontAwesomeIcon icon={faSpinner} spin />
<span>Loading content</span>
@@ -33,18 +33,18 @@ const ContentPanel: React.FC<ContentPanelProps> = ({ loading, title, html, markd
}
return (
<div className="content-panel">
{title && <h2 className="content-title">{title}</h2>}
<div className="reader">
{title && <h2 className="reader-title">{title}</h2>}
{markdown ? (
<div className="content-markdown">
<div className="reader-markdown">
<ReactMarkdown remarkPlugins={[remarkGfm]}>
{markdown}
</ReactMarkdown>
</div>
) : html ? (
<div className="content-html" dangerouslySetInnerHTML={{ __html: html }} />
<div className="reader-html" dangerouslySetInnerHTML={{ __html: html }} />
) : (
<div className="content-panel empty">
<div className="reader empty">
<p>No readable content found for this URL.</p>
</div>
)}

View File

@@ -232,6 +232,13 @@ body {
color: #007bff;
text-decoration: none;
word-break: break-all;
background: none;
border: none;
padding: 0;
font: inherit;
cursor: pointer;
text-align: left;
width: 100%;
}
.bookmark-url:hover {
@@ -414,7 +421,7 @@ body {
min-height: 60vh;
}
.content-panel {
.reader {
background: #1a1a1a;
border: 1px solid #333;
border-radius: 12px;
@@ -422,7 +429,7 @@ body {
text-align: left;
}
.content-panel.empty {
.reader.empty {
color: #888;
}
@@ -437,11 +444,11 @@ body {
font-size: 1.2rem;
}
.content-title {
.reader-title {
margin: 0 0 1rem 0;
}
.content-html {
.reader-html {
color: #ddd;
line-height: 1.6;
word-wrap: break-word;
@@ -449,25 +456,25 @@ body {
word-break: break-word;
}
.content-markdown {
.reader-markdown {
color: #ddd;
line-height: 1.7;
}
/* Ensure content is left-aligned even if source markup uses center */
.content-panel .content-html *,
.content-panel .content-markdown * {
.reader .reader-html *,
.reader .reader-markdown * {
text-align: left !important;
}
.content-panel center,
.content-panel [align="center"] {
.reader center,
.reader [align="center"] {
text-align: left !important;
}
/* Tame images from external content */
.content-panel .content-html img,
.content-panel .content-markdown img {
.reader .reader-html img,
.reader .reader-markdown img {
max-width: 100%;
max-height: 70vh;
height: auto;
@@ -477,37 +484,37 @@ body {
border-radius: 6px;
}
.content-markdown h1,
.content-markdown h2,
.content-markdown h3,
.content-markdown h4 {
.reader-markdown h1,
.reader-markdown h2,
.reader-markdown h3,
.reader-markdown h4 {
margin-top: 1.2rem;
}
.content-markdown p {
.reader-markdown p {
margin: 0.5rem 0;
}
.content-markdown a {
.reader-markdown a {
color: #8ab4f8;
text-decoration: none;
}
.content-markdown a:hover { text-decoration: underline; }
.reader-markdown a:hover { text-decoration: underline; }
.content-markdown pre,
.content-markdown code {
.reader-markdown pre,
.reader-markdown code {
background: #111;
border: 1px solid #333;
border-radius: 6px;
}
.content-markdown pre {
.reader-markdown pre {
padding: 0.75rem;
overflow: auto;
}
.content-markdown code {
.reader-markdown code {
padding: 0.1rem 0.3rem;
}
@@ -536,6 +543,13 @@ body {
display: block;
margin-bottom: 0.5rem;
word-break: break-all;
background: none;
border: none;
padding: 0;
font: inherit;
cursor: pointer;
text-align: left;
width: 100%;
}
.bookmark-url:hover {