mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2026-09-27 15:37:57 +00:00
* Perf pass + migrate home/payments page sections to shared
Performance work across every page plus a refactor moving home/payments
page sections into reusable shared components.
JavaScript
- Defer xrpl.js, jQuery, and Bootstrap in the global <head> (redocly.yaml)
and on the 11 interactive tool pages' inline <script> tags — removes
~1MB of render-blocking JS from first paint on every page.
- Drop moment/moment-timezone from the client: remove the dead APEX-2025
countdown in the navbar AlertBanner; format/parse dates with native
Date/Intl in the blog and events pages.
Fonts & icons
- Remove render-blocking font-awesome.min.css + webfont. CSS glyphs
(callouts, breadcrumbs, status labels, tutorials) now render as
self-contained data-URI SVG masks (styles/_fa-icons.scss); markup icons
use a shared inline-SVG <Icon> component (shared/components/Icon).
- Preconnect to Google Fonts / osano / GTM origins; preload the primary
Booton UI font so text no longer waits on the 775KB stylesheet to parse.
Images & rendering
- Re-encode/resize oversized assets: new-york.jpeg 3.86MB→60KB,
resources-icon.svg 4.2MB→150KB, event date/location SVGs ~1MB→0.5MB.
- Add loading=lazy/decoding=async to shared card components and the
Video embed iframe.
- Add content-visibility to the events page's ~126-card grid to skip
off-screen rendering.
- Earlier QA fixes: light-mode link color (#141414), events card grid
layout, close nav menu on client-side navigation.
Home / payments refactor
- Move home page sections from page-local pages/home/sections/* to reusable
shared/sections/* components (HomeHero relocated to shared/sections/HomeHero;
home page now composes CalloutMediaBanner, CardStatsList, LinkTextDirectory,
LogoSquareGrid, StandardCardGroupSection, FeatureSingleTopic, CarouselFeatured).
- Remove the now-unused pages/payments/sections/* in the same migration.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Revert FontAwesome removal (keep it for open-source flexibility)
Restore the FontAwesome webfont + font-awesome.min.css and all FA icon
usages (markup fa-* classes and CSS ::before glyphs), reverting the
consolidation in d4cf4e8581. Other performance changes from that commit
(deferred head scripts, moment removal, image optimization, lazy-loading,
content-visibility, preconnect/preload) are retained.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* cleaning up breadcrumb styling
* sticky side nav
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
163 lines
4.3 KiB
TypeScript
163 lines
4.3 KiB
TypeScript
import React, { useState } from 'react';
|
|
import clsx from 'clsx';
|
|
|
|
/** True when the logo URL is an SVG (file path or data URL) — used for dark neutral monochrome treatment. */
|
|
function isSvgLogoSource(src: string): boolean {
|
|
if (/^data:image\/svg\+xml/i.test(src)) return true;
|
|
const path = src.split(/[?#]/)[0].toLowerCase();
|
|
return path.endsWith('.svg');
|
|
}
|
|
|
|
export interface TileLogoProps {
|
|
/** Shape variant: 'square' (default) or 'rectangle' */
|
|
shape?: 'square' | 'rectangle';
|
|
/** Color variant: 'neutral' (default) or 'green' */
|
|
variant?: 'neutral' | 'green';
|
|
/** Logo image source (URL or path) */
|
|
logo: string;
|
|
/** Alt text for accessibility */
|
|
alt: string;
|
|
/** Click handler - renders as <button> */
|
|
onClick?: () => void;
|
|
/** Link destination - renders as <a> */
|
|
href?: string;
|
|
/** Disabled state - prevents interaction */
|
|
disabled?: boolean;
|
|
/** Additional CSS classes */
|
|
className?: string;
|
|
}
|
|
|
|
/**
|
|
* TileLogo Component
|
|
*
|
|
* A tile/card component designed to display brand logos with interactive states.
|
|
* Supports two shape variants (Square and Rectangle) and two color variants
|
|
* (Neutral and Green) with five interaction states (Default, Hover, Focused,
|
|
* Pressed, Disabled).
|
|
*
|
|
* Features a "window shade" hover animation where the hover color wipes from
|
|
* bottom to top on mouse enter, and top to bottom on mouse leave.
|
|
*
|
|
* Colors are defined in `TileLogo.scss` and follow `html.light` / `html.dark`.
|
|
* Green variant tokens: light mode uses green-200 (default), green-300 (hover /
|
|
* focus overlay), green-400 (pressed); dark mode uses green-300 (default),
|
|
* green-200 (hover / focus overlay), green-400 (pressed).
|
|
*
|
|
* Shape sizes are responsive and change based on breakpoints:
|
|
* - Square: 1:1 aspect ratio, width controlled by parent (use PageGridCol with span 2/2/3)
|
|
* - Rectangle: 9:5 aspect ratio, width controlled by parent (use PageGridCol with span 2/2/3)
|
|
*
|
|
* @example
|
|
* // Basic usage with link (square shape - default)
|
|
* <TileLogo
|
|
* variant="neutral"
|
|
* logo="/logos/partner-logo.svg"
|
|
* alt="Partner Name"
|
|
* href="/partners/partner-name"
|
|
* />
|
|
*
|
|
* @example
|
|
* // Rectangle shape with click handler
|
|
* <TileLogo
|
|
* shape="rectangle"
|
|
* variant="green"
|
|
* logo="/logos/featured-logo.svg"
|
|
* alt="Featured Partner"
|
|
* onClick={() => openPartnerModal('featured')}
|
|
* />
|
|
*
|
|
* @example
|
|
* // Disabled state
|
|
* <TileLogo
|
|
* variant="neutral"
|
|
* logo="/logos/coming-soon.svg"
|
|
* alt="Coming Soon"
|
|
* disabled
|
|
* />
|
|
*/
|
|
export const TileLogo: React.FC<TileLogoProps> = ({
|
|
shape = 'square',
|
|
variant = 'neutral',
|
|
logo,
|
|
alt,
|
|
onClick,
|
|
href,
|
|
disabled = false,
|
|
className = '',
|
|
}) => {
|
|
// Track hover state for animation
|
|
const [isHovered, setIsHovered] = useState(false);
|
|
|
|
// Build class names using BEM convention
|
|
const classNames = clsx(
|
|
'bds-tile-logo',
|
|
`bds-tile-logo--${shape}`,
|
|
`bds-tile-logo--${variant}`,
|
|
{
|
|
'bds-tile-logo--disabled': disabled,
|
|
'bds-tile-logo--hovered': isHovered && !disabled,
|
|
},
|
|
className
|
|
);
|
|
|
|
// Hover handlers
|
|
const handleMouseEnter = () => !disabled && setIsHovered(true);
|
|
const handleMouseLeave = () => setIsHovered(false);
|
|
|
|
const imageClassName = clsx(
|
|
'bds-tile-logo__image',
|
|
variant === 'neutral' &&
|
|
isSvgLogoSource(logo) &&
|
|
'bds-tile-logo__image--monochrome-white'
|
|
);
|
|
|
|
// Common content (overlay + logo image)
|
|
const content = (
|
|
<>
|
|
{/* Hover overlay for window shade animation */}
|
|
<div className="bds-tile-logo__overlay" aria-hidden="true" />
|
|
<img
|
|
src={logo}
|
|
alt={alt}
|
|
className={imageClassName}
|
|
aria-hidden="false"
|
|
loading="lazy"
|
|
decoding="async"
|
|
/>
|
|
</>
|
|
);
|
|
|
|
// Render as anchor tag when href is provided
|
|
if (href && !disabled) {
|
|
return (
|
|
<a
|
|
href={href}
|
|
className={classNames}
|
|
aria-label={alt}
|
|
onMouseEnter={handleMouseEnter}
|
|
onMouseLeave={handleMouseLeave}
|
|
>
|
|
{content}
|
|
</a>
|
|
);
|
|
}
|
|
|
|
// Render as button (for onClick or disabled state)
|
|
return (
|
|
<button
|
|
type="button"
|
|
className={classNames}
|
|
onClick={onClick}
|
|
disabled={disabled}
|
|
aria-disabled={disabled}
|
|
aria-label={alt}
|
|
onMouseEnter={handleMouseEnter}
|
|
onMouseLeave={handleMouseLeave}
|
|
>
|
|
{content}
|
|
</button>
|
|
);
|
|
};
|
|
|
|
export default TileLogo;
|