From e2c712033f9c7e29077c05f32367c4ea9c96065a Mon Sep 17 00:00:00 2001 From: Gigi Date: Wed, 15 Oct 2025 17:43:31 +0200 Subject: [PATCH] feat: add paragraph alignment setting - Add paragraphAlignment setting (left/justify) to UserSettings interface - Add UI control with icon buttons in ReadingDisplaySettings - Apply alignment via CSS variable to reader content and preview - Default to left-aligned to maintain current behavior - Keep headings always left-aligned for better readability --- src/components/Settings.tsx | 1 + .../Settings/ReadingDisplaySettings.tsx | 25 +++++++++++++++++-- src/hooks/useSettings.ts | 3 +++ src/services/settingsService.ts | 2 ++ src/styles/components/forms.css | 1 + src/styles/components/reader.css | 19 +++++++++++--- 6 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/components/Settings.tsx b/src/components/Settings.tsx index c157d57f..659ca960 100644 --- a/src/components/Settings.tsx +++ b/src/components/Settings.tsx @@ -35,6 +35,7 @@ const DEFAULT_SETTINGS: UserSettings = { zapSplitAuthorWeight: 50, useLocalRelayAsCache: true, rebroadcastToAllRelays: false, + paragraphAlignment: 'left', } interface SettingsProps { diff --git a/src/components/Settings/ReadingDisplaySettings.tsx b/src/components/Settings/ReadingDisplaySettings.tsx index e844ec60..d748fd47 100644 --- a/src/components/Settings/ReadingDisplaySettings.tsx +++ b/src/components/Settings/ReadingDisplaySettings.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { faHighlighter, faUnderline, faNetworkWired, faUserGroup, faUser } from '@fortawesome/free-solid-svg-icons' +import { faHighlighter, faUnderline, faNetworkWired, faUserGroup, faUser, faAlignLeft, faAlignJustify } from '@fortawesome/free-solid-svg-icons' import { UserSettings } from '../../services/settingsService' import IconButton from '../IconButton' import ColorPicker from '../ColorPicker' @@ -48,6 +48,26 @@ const ReadingDisplaySettings: React.FC = ({ setting +
+ +
+ onUpdate({ paragraphAlignment: 'left' })} + title="Left aligned" + ariaLabel="Left aligned" + variant={(settings.paragraphAlignment || 'left') === 'left' ? 'primary' : 'ghost'} + /> + onUpdate({ paragraphAlignment: 'justify' })} + title="Justified" + ariaLabel="Justified" + variant={settings.paragraphAlignment === 'justify' ? 'primary' : 'ghost'} + /> +
+
+
@@ -157,7 +177,8 @@ const ReadingDisplaySettings: React.FC = ({ setting style={{ fontFamily: previewFontFamily, fontSize: `${settings.fontSize || 21}px`, - '--highlight-rgb': hexToRgb(settings.highlightColor || '#ffff00') + '--highlight-rgb': hexToRgb(settings.highlightColor || '#ffff00'), + '--paragraph-alignment': settings.paragraphAlignment || 'left' } as React.CSSProperties} >

The Quick Brown Fox

diff --git a/src/hooks/useSettings.ts b/src/hooks/useSettings.ts index fd210500..cb8f5f9f 100644 --- a/src/hooks/useSettings.ts +++ b/src/hooks/useSettings.ts @@ -73,6 +73,9 @@ export function useSettings({ relayPool, eventStore, pubkey, accountManager }: U root.setProperty('--highlight-color-friends', settings.highlightColorFriends || '#f97316') root.setProperty('--highlight-color-nostrverse', settings.highlightColorNostrverse || '#9333ea') + // Set paragraph alignment + root.setProperty('--paragraph-alignment', settings.paragraphAlignment || 'left') + console.log('✅ All styles applied') } diff --git a/src/services/settingsService.ts b/src/services/settingsService.ts index 16458601..2505ed6b 100644 --- a/src/services/settingsService.ts +++ b/src/services/settingsService.ts @@ -52,6 +52,8 @@ export interface UserSettings { theme?: 'dark' | 'light' | 'system' // default: system darkColorTheme?: 'black' | 'midnight' | 'charcoal' // default: midnight lightColorTheme?: 'paper-white' | 'sepia' | 'ivory' // default: sepia + // Reading settings + paragraphAlignment?: 'left' | 'justify' // default: left } export async function loadSettings( diff --git a/src/styles/components/forms.css b/src/styles/components/forms.css index acd972fd..4648956d 100644 --- a/src/styles/components/forms.css +++ b/src/styles/components/forms.css @@ -41,6 +41,7 @@ .preview-content p { margin: 0.75rem 0; word-wrap: break-word; + text-align: var(--paragraph-alignment, left); } .setting-select { width: 100%; padding: 0.5rem; background: var(--color-bg-elevated); border: 1px solid var(--color-border-subtle); border-radius: 4px; color: var(--color-text); font-size: 1rem; } .setting-inline .setting-select { width: auto; min-width: 200px; flex: 1; } diff --git a/src/styles/components/reader.css b/src/styles/components/reader.css index 149fd2ca..a58671fe 100644 --- a/src/styles/components/reader.css +++ b/src/styles/components/reader.css @@ -37,9 +37,22 @@ .highlight-indicator svg { font-size: 0.875rem; } .reader-html { color: var(--color-text); line-height: 1.6; word-wrap: break-word; overflow-wrap: break-word; word-break: break-word; font-family: var(--reading-font); font-size: var(--reading-font-size); } .reader-markdown { color: var(--color-text); line-height: 1.7; font-family: var(--reading-font); font-size: var(--reading-font-size); } -/* Ensure content is left-aligned even if source markup uses center */ -.reader .reader-html *, .reader .reader-markdown * { text-align: left !important; font-family: inherit !important; } -.reader center, .reader [align="center"] { text-align: left !important; } +/* Ensure font inheritance */ +.reader .reader-html *, .reader .reader-markdown * { font-family: inherit !important; } +/* Apply paragraph alignment from settings */ +.reader .reader-html p, +.reader .reader-markdown p, +.reader .reader-html div, +.reader .reader-markdown div, +.reader .reader-html li, +.reader .reader-markdown li, +.reader .reader-html blockquote, +.reader .reader-markdown blockquote { text-align: var(--paragraph-alignment, left); } +/* Override centered content with user preference */ +.reader center, .reader [align="center"] { text-align: var(--paragraph-alignment, left) !important; } +/* Keep headings left-aligned */ +.reader .reader-html h1, .reader .reader-html h2, .reader .reader-html h3, .reader .reader-html h4, .reader .reader-html h5, .reader .reader-html h6, +.reader .reader-markdown h1, .reader .reader-markdown h2, .reader .reader-markdown h3, .reader .reader-markdown h4, .reader .reader-markdown h5, .reader .reader-markdown h6 { text-align: left !important; } /* Tame images from external content */ .reader .reader-html img, .reader .reader-markdown img { max-width: 100%; max-height: 70vh; height: auto; width: auto; display: block; margin: 0.75rem 0; border-radius: 6px; } /* Headlines with Tailwind typography */