* adding showcase page * adding CardStatsList * clean up, tighter code * code review and code clean up * update import, clean up env for error message * tweak some css code * less css, rebuilt * re-adding bem, modifier for bds variants
LogoRectangleGrid Component
A responsive grid pattern for displaying company/partner logos with rectangle tiles and dynamic alignment based on tile count. Built on top of the TileLogo component, featuring 9:5 aspect ratio rectangle tiles with 2 color variants and full dark mode support.
Features
- 2 Color Variants: Gray and Green backgrounds
- Dynamic Alignment: Grid alignment changes based on logo count (1-3: right, 4: left, 5-9: right, 9+: left)
- Responsive Grid: Automatically adapts from 2 columns (mobile) to 3 columns (tablet) to 4 columns (desktop)
- Required Header: Heading is required, description is optional
- Clickable Logos: Support for optional links on individual logos
- Dark Mode Support: Full light and dark mode compatibility
- Rectangle Tiles: Maintains 9:5 aspect ratio at all breakpoints
- Grid Integration: Built-in PageGrid wrapper with standard container support
Responsive Behavior
The component automatically adapts its grid layout based on viewport width:
| Breakpoint | Columns | Gap | Tile Aspect Ratio |
|---|---|---|---|
| Mobile (< 768px) | 2 | 8px | 9:5 |
| Tablet (768px - 1023px) | 3 | 8px | 9:5 |
| Desktop (≥ 1024px) | 4 | 8px | 9:5 |
Dynamic Alignment
The grid alignment changes based on the number of logos:
| Logo Count | Alignment | Offset |
|---|---|---|
| 1-3 | Right | 4 columns |
| 4 | Left | 0 columns |
| 5-9 | Right | 4 columns |
| 9+ | Left | 0 columns |
This creates a visually balanced layout that adapts to different content volumes.
Color Variants
The LogoRectangleGrid pattern uses two color variants that map directly to TileLogo component variants:
| LogoRectangleGrid Variant | TileLogo Variant | Description |
|---|---|---|
gray |
neutral |
Subtle, professional appearance for general partner showcases |
green |
green |
Highlights featured or primary partners |
Colors are managed by the TileLogo component and automatically adapt between light and dark modes with proper hover states and animations.
Props API
interface LogoItem {
/** Logo image source URL */
logo: string;
/** Alt text for the logo image */
alt: string;
/** Optional link URL - makes the logo clickable */
href?: string;
/** Optional click handler - makes the logo a button */
onClick?: () => void;
/** Disabled state */
disabled?: boolean;
}
interface LogoRectangleGridProps {
/** Color variant - determines background color */
variant?: 'gray' | 'green';
/** Heading text (required) */
heading: string;
/** Optional description text */
description?: string;
/** Array of logo items to display in the grid */
logos: LogoItem[];
/** Additional CSS classes */
className?: string;
}
Note: LogoItem extends TileLogoProps from the TileLogo component. The variant property is NOT included in individual logo items - it's controlled at the component level via the LogoRectangleGridProps.variant prop, which applies to all tiles in the grid.
Default Values
variant:'gray'description:undefinedclassName:''
Required Props
heading: Heading text (required)logos: Array of logo items (required)
Usage Examples
Basic Usage with Gray Variant
import { LogoRectangleGrid } from 'shared/sections/LogoRectangleGrid';
<LogoRectangleGrid
variant="gray"
heading="Developer tools & APIs"
logos={[
{ logo: "/img/logos/company1.svg", alt: "Company 1" },
{ logo: "/img/logos/company2.svg", alt: "Company 2" },
{ logo: "/img/logos/company3.svg", alt: "Company 3" },
{ logo: "/img/logos/company4.svg", alt: "Company 4" }
]}
/>
With Description
<LogoRectangleGrid
variant="green"
heading="Developer tools & APIs"
description="Streamline development and build powerful RWA tokenization solutions with XRP Ledger's comprehensive developer toolset."
logos={[
{ logo: "/img/logos/tool1.svg", alt: "Tool 1" },
{ logo: "/img/logos/tool2.svg", alt: "Tool 2" },
{ logo: "/img/logos/tool3.svg", alt: "Tool 3" },
{ logo: "/img/logos/tool4.svg", alt: "Tool 4" },
{ logo: "/img/logos/tool5.svg", alt: "Tool 5" },
{ logo: "/img/logos/tool6.svg", alt: "Tool 6" },
{ logo: "/img/logos/tool7.svg", alt: "Tool 7" },
{ logo: "/img/logos/tool8.svg", alt: "Tool 8" }
]}
/>
With Clickable Logos
<LogoRectangleGrid
variant="gray"
heading="Our Partners"
description="Leading companies building on XRPL."
logos={[
{
logo: "/img/logos/partner1.svg",
alt: "Partner 1",
href: "https://partner1.com"
},
{
logo: "/img/logos/partner2.svg",
alt: "Partner 2",
href: "https://partner2.com"
}
]}
/>
With Button Handlers
<LogoRectangleGrid
variant="green"
heading="Interactive Partners"
description="Click any logo to learn more."
logos={[
{
logo: "/img/logos/partner1.svg",
alt: "Partner 1",
onClick: () => openModal('partner1')
},
{
logo: "/img/logos/partner2.svg",
alt: "Partner 2",
onClick: () => openModal('partner2')
}
]}
/>
With Disabled State
<LogoRectangleGrid
variant="gray"
heading="Coming Soon"
description="New partners joining the ecosystem."
logos={[
{
logo: "/img/logos/partner1.svg",
alt: "Partner 1",
href: "/partners/partner1"
},
{
logo: "/img/logos/coming-soon.svg",
alt: "Coming Soon",
disabled: true
}
]}
/>
Heading Only (No Description)
<LogoRectangleGrid
variant="gray"
heading="Ecosystem Members"
logos={[
{ logo: "/img/logos/sponsor1.svg", alt: "Sponsor 1" },
{ logo: "/img/logos/sponsor2.svg", alt: "Sponsor 2" },
{ logo: "/img/logos/sponsor3.svg", alt: "Sponsor 3" },
{ logo: "/img/logos/sponsor4.svg", alt: "Sponsor 4" }
]}
/>
Demonstrating Alignment Logic
// 1-3 logos: Right-aligned
<LogoRectangleGrid
variant="green"
heading="Featured Partners"
logos={[
{ logo: "/img/logos/partner1.svg", alt: "Partner 1" },
{ logo: "/img/logos/partner2.svg", alt: "Partner 2" }
]}
/>
// 4 logos: Left-aligned
<LogoRectangleGrid
variant="gray"
heading="Core Technologies"
logos={[
{ logo: "/img/logos/tech1.svg", alt: "Tech 1" },
{ logo: "/img/logos/tech2.svg", alt: "Tech 2" },
{ logo: "/img/logos/tech3.svg", alt: "Tech 3" },
{ logo: "/img/logos/tech4.svg", alt: "Tech 4" }
]}
/>
// 5-9 logos: Right-aligned
<LogoRectangleGrid
variant="green"
heading="Developer Tools"
logos={[
{ logo: "/img/logos/tool1.svg", alt: "Tool 1" },
{ logo: "/img/logos/tool2.svg", alt: "Tool 2" },
{ logo: "/img/logos/tool3.svg", alt: "Tool 3" },
{ logo: "/img/logos/tool4.svg", alt: "Tool 4" },
{ logo: "/img/logos/tool5.svg", alt: "Tool 5" },
{ logo: "/img/logos/tool6.svg", alt: "Tool 6" }
]}
/>
// 9+ logos: Left-aligned
<LogoRectangleGrid
variant="gray"
heading="Partner Ecosystem"
logos={[
// ... 12 logos
]}
/>
Important Implementation Details
Logo Image Requirements
For best results, logo images should:
- Be SVG format for crisp scaling
- Have transparent backgrounds
- Be reasonably sized (width: 150-250px recommended for 9:5 aspect ratio)
- Use monochrome or simple color schemes
- Have consistent visual weight across all logos
Grid Behavior
- The grid uses PageGridCol components for responsive layout
- Each tile uses
span={{ base: 2, md: 2, lg: 3 }}(2 cols on mobile out of 4, 2 cols on tablet out of 6, 3 cols on desktop out of 12) - This creates 2 columns on mobile, 3 columns on tablet, and 4 columns on desktop
- Tiles maintain a 9:5 aspect ratio using the TileLogo rectangle shape
- Gaps between tiles are handled by PageGrid's built-in gutter system
- Grid automatically wraps to new rows as needed
- Grid alignment changes dynamically based on logo count
Alignment Logic Implementation
The alignment is controlled by the alignRight variable:
const logoCount = logos.length;
const alignRight =
(logoCount >= 1 && logoCount <= 3) ||
(logoCount >= 5 && logoCount <= 9);
When alignRight is true:
- Grid container spans 8 columns on desktop (lg breakpoint)
- Grid container has 4-column offset on desktop (pushes content right)
When alignRight is false:
- Grid container spans full width
- Grid container has 0 offset (content aligns left)
Clickable Logo Behavior
Logo tiles leverage the TileLogo component's interactive capabilities:
- With
hrefproperty: Renders as a link (<a>tag) with window shade hover animation - With
onClickproperty: Renders as a button with the same interactive states - With
disabledproperty: Prevents interaction and applies disabled styling - Interactive states: Default, Hover, Focused, Pressed, and Disabled
- Animation: Window shade effect that wipes from bottom to top on hover
- All tiles automatically maintain focus states for keyboard accessibility
Styling
BEM Class Structure
.bds-logo-rectangle-grid // Base component
.bds-logo-rectangle-grid--gray // Gray variant (maps to TileLogo 'neutral')
.bds-logo-rectangle-grid--green // Green variant (maps to TileLogo 'green')
.bds-logo-rectangle-grid__header // Header section container
.bds-logo-rectangle-grid__text // Text content container
Note: Individual logo tiles are rendered using the TileLogo component with its own BEM structure (bds-tile-logo) and shape="rectangle". Grid layout is handled by PageGridRow and PageGridCol components.
Typography Tokens
-
Heading: Uses
heading-mdtype token (Tobias Light font)- Desktop: 40px / 46px line-height / -1px letter-spacing
- Tablet: 36px / 45px line-height / -0.5px letter-spacing
- Mobile: 32px / 40px line-height / 0px letter-spacing
-
Description: Uses
body-ltype token (Booton Light font)- Desktop: 18px / 26.1px line-height / -0.5px letter-spacing
- Tablet: 18px / 26.1px line-height / -0.5px letter-spacing
- Mobile: 18px / 26.1px line-height / -0.5px letter-spacing
Color Tokens
All colors are sourced from styles/_colors.scss:
// Tile backgrounds
$gray-200 // Gray variant (light mode)
$gray-700 // Gray variant (dark mode)
$green-200 // Green variant (light mode)
$green-300 // Green variant (dark mode)
Accessibility
- Semantic HTML structure with proper heading hierarchy
- All logos include descriptive alt text
- Clickable logos have proper link semantics
- Keyboard navigation support with visible focus states
- Color contrast meets WCAG AA standards in all variants
Best Practices
When to Use Each Variant
- Gray: General-purpose logo grids, subtle integration
- Green: Featured partnerships, brand-focused sections
Content Guidelines
- Heading: Required, keep concise (1-2 lines preferred), use sentence case
- Description: Optional, provide context (2-3 lines max), complete sentences
- Logo Count: Consider the alignment logic when choosing how many logos to display
- Alt Text: Use company/product names, not generic "logo"
Logo Preparation
- Consistent Sizing: Ensure all logos have similar visual weight
- Format: Use SVG for scalability and crisp rendering
- Background: Transparent backgrounds work best
- Aspect Ratio: Rectangle tiles work well with horizontal logos
- Padding: Include minimal internal padding in the SVG itself
Performance
- Use optimized SVG files (run through SVGO or similar)
- Consider lazy loading for grids with many logos
- Provide appropriate alt text for all images
- Use
widthandheightattributes on img tags when possible
Technical Implementation
- Grid System: Uses PageGridCol with
span={{ base: 2, md: 2, lg: 3 }}for responsive layout - Tile Rendering: Leverages TileLogo component with
shape="rectangle"for all logo tiles - Variant Mapping: LogoRectangleGrid 'gray' → TileLogo 'neutral', LogoRectangleGrid 'green' → TileLogo 'green'
- Interactive States: TileLogo handles href (links), onClick (buttons), and disabled states
- Aspect Ratio: Rectangle tiles maintained by TileLogo with CSS
aspect-ratio: 9/5 - Animations: Window shade hover effect managed by TileLogo component
- Dynamic Alignment: Grid alignment controlled by conditional offset based on logo count
Files
LogoRectangleGrid.tsx- Component implementationLogoRectangleGrid.scss- Styles with color variants and responsive breakpointsindex.ts- Barrel exportsREADME.md- This documentation
Related Components
- TileLogo: Core component used to render individual logo tiles with interactive states and rectangle shape
- LogoSquareGrid: Similar pattern but with square tiles instead of rectangle tiles
- PageGrid: Used internally for responsive grid structure and standard container support
Design References
- Figma Design: Section Logo - Rectangle Grid
- Showcase Page:
/about/logo-rectangle-grid-showcase.page.tsx - Component Location:
shared/sections/LogoRectangleGrid/
Version History
- January 2026: Initial implementation
- Figma design alignment with 2 color variants
- Responsive grid with 2/3/4 column layout
- Dynamic alignment based on logo count
- Required header section with optional description
- Clickable logo support
- Rectangle tiles with 9:5 aspect ratio