feat: WCAG AA accessibility, code splitting, responsive ads layout

- Add React.lazy code splitting for all 15 tool pages
- Fix WCAG AA contrast issues (304 text color fixes)
- Add ARIA labels and aria-expanded to navigation buttons
- Add aria-live for error announcements in tools
- Implement responsive ad layout:
  - Desktop (≥1280px): Right sidebar with 3 ad units
  - Tablet (1024-1279px): Bottom section with 3 horizontal units
  - Mobile (<1024px): Fixed bottom banner
- Add TabletAdSection component for tablet ad placement
- Integrate Onidel affiliate partnership
- Update all Adsterra domains to solutionbiologyisle.com
- Add release notes for 2026-02-18 updates
This commit is contained in:
dwindown
2026-02-18 18:57:31 +07:00
parent 9dc3285adb
commit 3a475e9df2
41 changed files with 391 additions and 318 deletions

View File

@@ -1517,7 +1517,7 @@ ${html}
className={`flex items-center gap-1 sm:gap-2 px-3 sm:px-4 py-3 text-sm font-medium transition-colors whitespace-nowrap ${
activeTab === 'create'
? 'bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-300 border-b-2 border-blue-500'
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200'
: 'text-gray-600 dark:text-gray-600 hover:text-gray-900 dark:hover:text-gray-200'
}`}
>
<Plus className="h-4 w-4 flex-shrink-0" />
@@ -1528,7 +1528,7 @@ ${html}
className={`flex items-center gap-1 sm:gap-2 px-3 sm:px-4 py-3 text-sm font-medium transition-colors whitespace-nowrap ${
activeTab === 'url'
? 'bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-300 border-b-2 border-blue-500'
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200'
: 'text-gray-600 dark:text-gray-600 hover:text-gray-900 dark:hover:text-gray-200'
}`}
>
<Globe className="h-4 w-4 flex-shrink-0" />
@@ -1539,7 +1539,7 @@ ${html}
className={`flex items-center gap-1 sm:gap-2 px-3 sm:px-4 py-3 text-sm font-medium transition-colors whitespace-nowrap ${
activeTab === 'paste'
? 'bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-300 border-b-2 border-blue-500'
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200'
: 'text-gray-600 dark:text-gray-600 hover:text-gray-900 dark:hover:text-gray-200'
}`}
>
<FileText className="h-4 w-4 flex-shrink-0" />
@@ -1550,7 +1550,7 @@ ${html}
className={`flex items-center gap-1 sm:gap-2 px-3 sm:px-4 py-3 text-sm font-medium transition-colors whitespace-nowrap ${
activeTab === 'open'
? 'bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-300 border-b-2 border-blue-500'
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200'
: 'text-gray-600 dark:text-gray-600 hover:text-gray-900 dark:hover:text-gray-200'
}`}
>
<Upload className="h-4 w-4 flex-shrink-0" />
@@ -1571,7 +1571,7 @@ ${html}
<h3 className="text-lg font-medium text-gray-900 dark:text-gray-100 mb-2">
Create New Markdown Document
</h3>
<p className="text-sm text-gray-600 dark:text-gray-400 mb-4">
<p className="text-sm text-gray-600 dark:text-gray-600 mb-4">
Choose how you'd like to begin writing
</p>
</div>
@@ -1590,11 +1590,11 @@ ${html}
}}
className="flex flex-col items-center p-6 border-2 border-dashed border-gray-300 dark:border-gray-600 rounded-lg hover:border-blue-500 dark:hover:border-blue-400 hover:bg-blue-50 dark:hover:bg-blue-900/20 transition-colors group"
>
<Plus className="h-8 w-8 text-gray-400 group-hover:text-blue-500 dark:group-hover:text-blue-400 mb-2" />
<Plus className="h-8 w-8 text-gray-600 group-hover:text-blue-500 dark:group-hover:text-blue-400 mb-2" />
<span className="font-medium text-gray-900 dark:text-gray-100 group-hover:text-blue-600 dark:group-hover:text-blue-400">
Start Empty
</span>
<span className="text-xs text-gray-500 dark:text-gray-400 text-center mt-1">
<span className="text-xs text-gray-600 dark:text-gray-600 text-center mt-1">
Begin with a blank markdown document
</span>
</button>
@@ -1628,11 +1628,11 @@ ${html}
}}
className="flex flex-col items-center p-6 border-2 border-dashed border-gray-300 dark:border-gray-600 rounded-lg hover:border-green-500 dark:hover:border-green-400 hover:bg-green-50 dark:hover:bg-green-900/20 transition-colors group"
>
<FileText className="h-8 w-8 text-gray-400 group-hover:text-green-500 dark:group-hover:text-green-400 mb-2" />
<FileText className="h-8 w-8 text-gray-600 group-hover:text-green-500 dark:group-hover:text-green-400 mb-2" />
<span className="font-medium text-gray-900 dark:text-gray-100 group-hover:text-green-600 dark:group-hover:text-green-400">
Load Template
</span>
<span className="text-xs text-gray-500 dark:text-gray-400 text-center mt-1">
<span className="text-xs text-gray-600 dark:text-gray-600 text-center mt-1">
Start with a pre-made template
</span>
</button>
@@ -1704,7 +1704,7 @@ ${html}
{fetching ? 'Fetching...' : 'Fetch Data'}
</button>
</div>
<p className="text-xs text-gray-500 dark:text-gray-400">
<p className="text-xs text-gray-600 dark:text-gray-600">
Enter a URL to a markdown file (GitHub raw, Gist, Pastebin, etc.)
</p>
</div>
@@ -1749,7 +1749,7 @@ ${html}
</div>
)}
<div className="flex items-center justify-between flex-shrink-0">
<div className="text-sm text-gray-600 dark:text-gray-400">
<div className="text-sm text-gray-600 dark:text-gray-600">
Paste markdown text
</div>
<button
@@ -1826,7 +1826,7 @@ ${html}
</h3>
{/* Statistics */}
<div className="hidden sm:flex items-center gap-3 text-xs text-gray-600 dark:text-gray-400">
<div className="hidden sm:flex items-center gap-3 text-xs text-gray-600 dark:text-gray-600">
<span>{stats.words} words</span>
<span></span>
<span>{stats.characters} chars</span>
@@ -1845,7 +1845,7 @@ ${html}
className={`flex items-center gap-2 px-3 py-2 text-sm font-medium transition-colors ${
viewMode === 'editor'
? 'bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-300'
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700'
: 'text-gray-600 dark:text-gray-600 hover:text-gray-900 dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700'
}`}
title="Editor Only"
>
@@ -1858,7 +1858,7 @@ ${html}
className={`hidden lg:flex items-center gap-2 px-3 py-2 text-sm font-medium transition-colors border-l border-gray-200 dark:border-gray-700 ${
viewMode === 'split'
? 'bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-300'
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700'
: 'text-gray-600 dark:text-gray-600 hover:text-gray-900 dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700'
}`}
title="Split View"
>
@@ -1870,7 +1870,7 @@ ${html}
className={`flex items-center gap-2 px-3 py-2 text-sm font-medium transition-colors border-l border-gray-200 dark:border-gray-700 ${
viewMode === 'preview'
? 'bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-300'
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700'
: 'text-gray-600 dark:text-gray-600 hover:text-gray-900 dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700'
}`}
title="Preview Only"
>
@@ -1881,7 +1881,7 @@ ${html}
<button
onClick={() => setIsFullscreen(!isFullscreen)}
className="p-2 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors"
className="p-2 text-gray-600 dark:text-gray-600 hover:text-gray-900 dark:hover:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors"
title={isFullscreen ? 'Exit Fullscreen' : 'Fullscreen'}
>
{isFullscreen ? <Minimize2 className="h-4 w-4" /> : <Maximize2 className="h-4 w-4" />}
@@ -1909,7 +1909,7 @@ ${html}
<div className="relative group">
<button
onClick={btn.action}
className="p-2 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-700 rounded transition-colors"
className="p-2 text-gray-600 dark:text-gray-600 hover:text-gray-900 dark:hover:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-700 rounded transition-colors"
aria-label={btn.label}
>
<Icon className="h-4 w-4" />
@@ -1977,7 +1977,7 @@ You can use:
dangerouslySetInnerHTML={{ __html: parseMarkdown(markdownText) }}
/>
) : (
<div className="flex items-center justify-center h-full text-gray-400 dark:text-gray-500">
<div className="flex items-center justify-center h-full text-gray-600 dark:text-gray-600">
<div className="text-center">
<EyeOff className="h-12 w-12 mx-auto mb-2 opacity-50" />
<p className="text-sm">Preview will appear here</p>
@@ -1999,7 +1999,7 @@ You can use:
<Download className="h-5 w-5 text-blue-600 dark:text-blue-400" />
Export Options
</h3>
<p className="text-sm text-gray-600 dark:text-gray-400 mt-1">
<p className="text-sm text-gray-600 dark:text-gray-600 mt-1">
Download your markdown in different formats
</p>
</div>
@@ -2011,9 +2011,9 @@ You can use:
onClick={handleExportMarkdown}
className="flex flex-col items-center justify-center p-4 md:p-6 border-2 border-gray-200 dark:border-gray-700 rounded-lg hover:border-blue-500 dark:hover:border-blue-400 hover:bg-blue-50 dark:hover:bg-blue-900/20 transition-all group relative"
>
<FileText className="h-8 w-8 absolute left-4 top-5 md:static md:left-0 md:top-0 text-gray-600 dark:text-gray-400 group-hover:text-blue-600 dark:group-hover:text-blue-400 mb-3" />
<FileText className="h-8 w-8 absolute left-4 top-5 md:static md:left-0 md:top-0 text-gray-600 dark:text-gray-600 group-hover:text-blue-600 dark:group-hover:text-blue-400 mb-3" />
<span className="font-medium text-gray-900 dark:text-white mb-1">Markdown</span>
<span className="text-xs text-gray-500 dark:text-gray-400">.md file</span>
<span className="text-xs text-gray-600 dark:text-gray-600">.md file</span>
</button>
{/* Export as PDF */}
@@ -2021,9 +2021,9 @@ You can use:
onClick={handleExportPDF}
className="flex flex-col items-center justify-center p-4 md:p-6 border-2 border-gray-200 dark:border-gray-700 rounded-lg hover:border-red-500 dark:hover:border-red-400 hover:bg-red-50 dark:hover:bg-red-900/20 transition-all group relative"
>
<FileDown className="h-8 w-8 absolute left-4 top-5 md:static md:left-0 md:top-0 text-gray-600 dark:text-gray-400 group-hover:text-red-600 dark:group-hover:text-red-400 mb-3" />
<FileDown className="h-8 w-8 absolute left-4 top-5 md:static md:left-0 md:top-0 text-gray-600 dark:text-gray-600 group-hover:text-red-600 dark:group-hover:text-red-400 mb-3" />
<span className="font-medium text-gray-900 dark:text-white mb-1">PDF</span>
<span className="text-xs text-gray-500 dark:text-gray-400">.pdf file</span>
<span className="text-xs text-gray-600 dark:text-gray-600">.pdf file</span>
</button>
{/* Export as Full HTML */}
@@ -2031,9 +2031,9 @@ You can use:
onClick={handleExportHTML}
className="flex flex-col items-center justify-center p-4 md:p-6 border-2 border-gray-200 dark:border-gray-700 rounded-lg hover:border-green-500 dark:hover:border-green-400 hover:bg-green-50 dark:hover:bg-green-900/20 transition-all group relative"
>
<Globe className="h-8 w-8 absolute left-4 top-5 md:static md:left-0 md:top-0 text-gray-600 dark:text-gray-400 group-hover:text-green-600 dark:group-hover:text-green-400 mb-3" />
<Globe className="h-8 w-8 absolute left-4 top-5 md:static md:left-0 md:top-0 text-gray-600 dark:text-gray-600 group-hover:text-green-600 dark:group-hover:text-green-400 mb-3" />
<span className="font-medium text-gray-900 dark:text-white mb-1">Full HTML</span>
<span className="text-xs text-gray-500 dark:text-gray-400">.html page</span>
<span className="text-xs text-gray-600 dark:text-gray-600">.html page</span>
</button>
{/* Export as HTML Content Only */}
@@ -2041,9 +2041,9 @@ You can use:
onClick={handleExportHTMLContent}
className="flex flex-col items-center justify-center p-4 md:p-6 border-2 border-gray-200 dark:border-gray-700 rounded-lg hover:border-teal-500 dark:hover:border-teal-400 hover:bg-teal-50 dark:hover:bg-teal-900/20 transition-all group relative"
>
<Code className="h-8 w-8 absolute left-4 top-5 md:static md:left-0 md:top-0 text-gray-600 dark:text-gray-400 group-hover:text-teal-600 dark:group-hover:text-teal-400 mb-3" />
<Code className="h-8 w-8 absolute left-4 top-5 md:static md:left-0 md:top-0 text-gray-600 dark:text-gray-600 group-hover:text-teal-600 dark:group-hover:text-teal-400 mb-3" />
<span className="font-medium text-gray-900 dark:text-white mb-1">HTML Content</span>
<span className="text-xs text-gray-500 dark:text-gray-400">Body only</span>
<span className="text-xs text-gray-600 dark:text-gray-600">Body only</span>
</button>
{/* Export as Plain Text */}
@@ -2051,9 +2051,9 @@ You can use:
onClick={handleExportPlainText}
className="flex flex-col items-center justify-center p-4 md:p-6 border-2 border-gray-200 dark:border-gray-700 rounded-lg hover:border-purple-500 dark:hover:border-purple-400 hover:bg-purple-50 dark:hover:bg-purple-900/20 transition-all group relative"
>
<Type className="h-8 w-8 absolute left-4 top-5 md:static md:left-0 md:top-0 text-gray-600 dark:text-gray-400 group-hover:text-purple-600 dark:group-hover:text-purple-400 mb-3" />
<Type className="h-8 w-8 absolute left-4 top-5 md:static md:left-0 md:top-0 text-gray-600 dark:text-gray-600 group-hover:text-purple-600 dark:group-hover:text-purple-400 mb-3" />
<span className="font-medium text-gray-900 dark:text-white mb-1">Plain Text</span>
<span className="text-xs text-gray-500 dark:text-gray-400">.txt file</span>
<span className="text-xs text-gray-600 dark:text-gray-600">.txt file</span>
</button>
{/* Copy to Clipboard */}
@@ -2061,9 +2061,9 @@ You can use:
onClick={handleCopyToClipboard}
className="flex flex-col items-center justify-center p-4 md:p-6 border-2 border-gray-200 dark:border-gray-700 rounded-lg hover:border-orange-500 dark:hover:border-orange-400 hover:bg-orange-50 dark:hover:bg-orange-900/20 transition-all group relative"
>
<Download className="h-8 w-8 absolute left-4 top-5 md:static md:left-0 md:top-0 text-gray-600 dark:text-gray-400 group-hover:text-orange-600 dark:group-hover:text-orange-400 mb-3" />
<Download className="h-8 w-8 absolute left-4 top-5 md:static md:left-0 md:top-0 text-gray-600 dark:text-gray-600 group-hover:text-orange-600 dark:group-hover:text-orange-400 mb-3" />
<span className="font-medium text-gray-900 dark:text-white mb-1">Copy</span>
<span className="text-xs text-gray-500 dark:text-gray-400">To clipboard</span>
<span className="text-xs text-gray-600 dark:text-gray-600">To clipboard</span>
</button>
</div>
@@ -2224,7 +2224,7 @@ const InputChangeConfirmationModal = ({ markdownText, stats, currentMethod, newM
<h4 className="text-sm font-medium text-gray-900 dark:text-gray-100 mb-2">
This will permanently delete:
</h4>
<ul className="text-sm text-gray-600 dark:text-gray-400 space-y-1">
<ul className="text-sm text-gray-600 dark:text-gray-600 space-y-1">
<li> {stats.words} words of markdown content</li>
<li> {stats.characters} characters</li>
<li> {stats.lines} lines</li>