Replace the cabinet's hand-written heroicons-style SVG icon components with
the Remnawave panel's own icon family — Phosphor via react-icons/pi (Duotone).
All icons now live in a single central barrel (src/components/icons:
index + extended-icons + editor-icons, 144 icons); every feature file imports
from it instead of redefining inline SVGs (~440 icon defs removed).
- Add react-icons dependency
- Desktop nav (AppShell) now uses the central Phosphor icons, removing a
stroke-vs-duotone inconsistency the partial migration introduced
- Icons with custom props (SortIcon's direction, expandable chevrons) kept as
thin Phosphor wrappers; the RemnawaveIcon brand logo and animated SVGs
(checkmarks, spinners) are intentionally left as-is
- Restore the original per-call-site icon sizes wherever the centralized
default differed (211 call sites)
After re-audit/critique cycle the deterministic detector (npx impeccable)
flagged 34 design-spec violations. Knock out 33 of them.
• 25 × pure-black-white: sed-sweep bg-black/X → bg-dark-950/X across
18+ files (modal scrims, photo viewer backdrop, code blocks). The
base resolves to rgba(10,15,26,X) — visually identical to true
black, satisfies the 'no #000' impeccable rule.
• 3 × bounce-easing: SuccessNotificationModal celebration icon and
SyncTab loading arrows used animate-bounce; replaced with
animate-pulse. Bounce easing reads dated; pulse conveys 'in
progress' without the cartoon feel.
• 3 × border-accent-on-rounded: TelegramCallback + VerifyEmail
spinners used 'border-b-2 border-accent-500' on rounded-full —
detector reads it as a side-stripe even though it's a ring loader.
Switch to canonical 'border-2 border-accent-500 border-t-transparent'
(3/4 ring colored). Same visual, no spec violation.
• 1 × ai-color-palette: AdminLandingStats had text-purple-400 on a
gift-stats heading; purple is not in the brand palette. Swap to
text-accent-400.
• 1 × layout-transition: TrafficProgressBar.tsx fill bar still used
transition: width 1.2s (slipped past the earlier optimize pass).
Convert to transform: scaleX with origin-left. Same gradient, same
duration, runs on the compositor.
Remaining: 1 finding in third-party Aceternity background-beams-collision
component (indigo-500 gradient on decorative WebGL background) — left
as-is, it's lifted decorative third-party code.
Detector: 34 → 1.
Four image sites that render thumbnails/previews inside lists or tab
panels now hint loading=lazy so the browser defers the network fetch
until the element is near the viewport:
- Support.tsx attachment preview grid
- AdminTickets.tsx reply attachment grid
- BroadcastPreview.tsx photo preview
- BrandingTab.tsx logo preview in admin settings
Top-of-page logos (AppHeader/AppShell/DesktopSidebar/Login/Telegram
redirect/DeepLink) intentionally stay eager — they're above the fold
and should paint on first frame. Payment-method icons (6x6 px) are
already negligible. Compose attachment previews use blob: URLs where
loading=lazy is a no-op.
Sweep 30 files: text/bg/border/ring/from/to/via/fill/stroke/shadow/divide/decoration/
outline/placeholder-red-N → -error-N. All red usages were semantically error/danger
(no brand red), so tokens now flow through the design-system CSS variables and respond
to palette overrides.
Add htmlFor/id pairs for the create-ticket subject and message fields so screen
readers announce the label and clicking the label focuses the control (WCAG 1.3.1).
- Add media_items array support to ticket messages (types, API clients)
- Create shared MessageMediaGrid component with photo grid, fullscreen
viewer, keyboard nav, video/document rendering
- Replace per-page AdminMessageMedia/MessageMedia with MessageMediaGrid
- Add linkifyText util (DOMPurify-sanitized) for auto-linking URLs
- Support multi-file upload (up to 10) in AdminTickets and Support pages
- Remove unused ticketsApi import from AdminUserDetail
- Add URL.revokeObjectURL on unmount and media removal in
AdminBroadcastCreate, AdminPinnedMessageCreate, Support
- Track blob URLs via refs to revoke before creating new ones
- Add clearCreateAttachment/clearReplyAttachment helpers in Support
to properly revoke blob URLs when clearing attachments
- Cap adminTraffic cache at 20 entries with FIFO eviction to prevent
unbounded memory growth from different filter combinations
Major changes:
- Redesign cabinet with Linear-style components and top navigation
- Replace detail modals with dedicated pages (users, broadcasts, email templates)
- Add email channel support for broadcasts
- Remove pull-to-refresh, improve drag-and-drop on touch devices
- Fix Telegram Mini App: fullscreen, back button, scroll restoration
- Unify admin pages color scheme to design system
- Mobile-first improvements: horizontal tabs for settings, better touch targets
- Removed VITE_APP_VERSION from Dockerfile and GitHub workflows.
- Simplified Vite configuration by eliminating the Git version retrieval function and global constant for app version.
- Updated ColorPicker and other components to enhance accessibility with aria-labels.
- Introduced unique identifiers for buttons in the AppEditorModal for better React key management.
- Improved error handling in the Login component to provide user-friendly messages without exposing sensitive data.