From 6dd634abc33b008d1b409d2c068c4fa950b0e5b4 Mon Sep 17 00:00:00 2001
From: Richard Dinh <1038306+flacoman91@users.noreply.github.com>
Date: Tue, 19 May 2026 13:47:04 -0700
Subject: [PATCH 1/8] adding logo in spanish
---
src/assets/images/cfpb_logo_es.svg | 1 +
1 file changed, 1 insertion(+)
create mode 100644 src/assets/images/cfpb_logo_es.svg
diff --git a/src/assets/images/cfpb_logo_es.svg b/src/assets/images/cfpb_logo_es.svg
new file mode 100644
index 0000000000..e0fea752b5
--- /dev/null
+++ b/src/assets/images/cfpb_logo_es.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
From 1175f82aa917b01831b6f3f7804edeeb202dd768 Mon Sep 17 00:00:00 2001
From: Richard Dinh <1038306+flacoman91@users.noreply.github.com>
Date: Tue, 19 May 2026 14:02:25 -0700
Subject: [PATCH 2/8] adding spanish logo
---
src/components/Header/header.stories.tsx | 9 ++++-
src/components/Header/header.test.tsx | 14 ++++++++
src/components/Header/header.tsx | 5 ++-
src/components/Header/logo.test.tsx | 33 +++++++++++++++++++
src/components/Header/logo.tsx | 33 +++++++++++++++++++
.../Header/responsive-menu.test.tsx | 10 ++++++
src/components/Header/responsive-menu.tsx | 12 ++++---
7 files changed, 110 insertions(+), 6 deletions(-)
create mode 100644 src/components/Header/logo.test.tsx
create mode 100644 src/components/Header/logo.tsx
diff --git a/src/components/Header/header.stories.tsx b/src/components/Header/header.stories.tsx
index cf9c24e030..94668e2b90 100644
--- a/src/components/Header/header.stories.tsx
+++ b/src/components/Header/header.stories.tsx
@@ -6,7 +6,13 @@ const meta: Meta = {
title: 'Components (Draft)/Header',
tags: ['autodocs'],
component: Header,
- argTypes: {},
+ argTypes: {
+ lang: {
+ control: 'select',
+ options: ['en', 'es'],
+ description: 'Logo language (English or Spanish)',
+ },
+ },
parameters: {
sbNestedCanvasPadding: 'flush',
},
@@ -21,5 +27,6 @@ export const Default: Story = {
render: (properties) => ,
args: {
links: ExampleLinks,
+ lang: 'en',
},
};
diff --git a/src/components/Header/header.test.tsx b/src/components/Header/header.test.tsx
index 9da275a4bc..5fae5da29e 100644
--- a/src/components/Header/header.test.tsx
+++ b/src/components/Header/header.test.tsx
@@ -32,4 +32,18 @@ describe('Header', () => {
expect(container.firstChild.className).toBe('o-header-scope');
expect(container.firstChild.firstChild?.className).toBe('o-header');
});
+
+ it('renders the English logo by default', () => {
+ render();
+ expect(screen.getByAltText('CFPB Logo')).toBeInTheDocument();
+ });
+
+ it('renders the Spanish logo when lang is es', () => {
+ render();
+ expect(
+ screen.getByAltText(
+ 'Oficina para la Protección Financiera del Consumidor',
+ ),
+ ).toBeInTheDocument();
+ });
});
diff --git a/src/components/Header/header.tsx b/src/components/Header/header.tsx
index 9d12f64d07..d2551b29b5 100644
--- a/src/components/Header/header.tsx
+++ b/src/components/Header/header.tsx
@@ -1,6 +1,7 @@
import classnames from 'classnames';
import { JSX } from 'react';
import { Banner } from '../Banner/banner';
+import type { LogoLanguage } from './logo';
import ResponsiveMenu from './responsive-menu';
import './header.scss';
@@ -8,6 +9,7 @@ export interface HeaderProperties {
links?: JSX.Element[];
href?: string;
withBottomBorder?: boolean;
+ lang?: LogoLanguage;
}
/**
@@ -18,6 +20,7 @@ export const Header = ({
links,
href,
withBottomBorder = true,
+ lang = 'en',
}: HeaderProperties): JSX.Element => {
const headerClasses = ['o-header'];
if (withBottomBorder) headerClasses.push('bottom-border');
@@ -26,7 +29,7 @@ export const Header = ({
);
diff --git a/src/components/Header/logo.test.tsx b/src/components/Header/logo.test.tsx
new file mode 100644
index 0000000000..346a75c77c
--- /dev/null
+++ b/src/components/Header/logo.test.tsx
@@ -0,0 +1,33 @@
+import '@testing-library/jest-dom';
+import { render, screen } from '@testing-library/react';
+import CfpbLogoEn from '../../assets/images/cfpb_logo.svg?url';
+import CfpbLogoEs from '../../assets/images/cfpb_logo_es.svg?url';
+import { Logo } from './logo';
+
+describe('Logo', () => {
+ it('renders the English logo by default', () => {
+ render();
+
+ const image = screen.getByRole('img', { name: 'CFPB Logo' });
+ expect(image).toHaveAttribute('src', CfpbLogoEn);
+ expect(image).toHaveClass('o-header__logo-img');
+ });
+
+ it('renders the English logo when language is en', () => {
+ render();
+
+ expect(screen.getByRole('img', { name: 'CFPB Logo' })).toHaveAttribute(
+ 'src',
+ CfpbLogoEn,
+ );
+ });
+
+ it('renders the Spanish logo when language is es', () => {
+ render();
+
+ const image = screen.getByRole('img', {
+ name: 'Oficina para la Protección Financiera del Consumidor',
+ });
+ expect(image).toHaveAttribute('src', CfpbLogoEs);
+ });
+});
diff --git a/src/components/Header/logo.tsx b/src/components/Header/logo.tsx
new file mode 100644
index 0000000000..97acb852b9
--- /dev/null
+++ b/src/components/Header/logo.tsx
@@ -0,0 +1,33 @@
+import type { JSX } from 'react';
+import CfpbLogoEn from '../../assets/images/cfpb_logo.svg?url';
+import CfpbLogoEs from '../../assets/images/cfpb_logo_es.svg?url';
+
+export type LogoLanguage = 'en' | 'es';
+
+const logoSources: Record = {
+ en: CfpbLogoEn,
+ es: CfpbLogoEs,
+};
+
+const logoAltText: Record = {
+ en: 'CFPB Logo',
+ es: 'Oficina para la Protección Financiera del Consumidor',
+};
+
+export interface LogoProperties {
+ language?: LogoLanguage;
+ className?: string;
+}
+
+export function Logo({
+ language = 'en',
+ className = 'o-header__logo-img',
+}: LogoProperties): JSX.Element {
+ return (
+
+ );
+}
diff --git a/src/components/Header/responsive-menu.test.tsx b/src/components/Header/responsive-menu.test.tsx
index a00cf58326..b7cc639bee 100644
--- a/src/components/Header/responsive-menu.test.tsx
+++ b/src/components/Header/responsive-menu.test.tsx
@@ -112,4 +112,14 @@ describe('ResponsiveMenu', () => {
const logoLink = screen.getByTestId('CfpbLogoLink');
expect(logoLink).toHaveAttribute('href', customHref);
});
+
+ it('renders the Spanish logo when lang is es', () => {
+ renderWithScope();
+
+ expect(
+ screen.getByAltText(
+ 'Oficina para la Protección Financiera del Consumidor',
+ ),
+ ).toBeInTheDocument();
+ });
});
diff --git a/src/components/Header/responsive-menu.tsx b/src/components/Header/responsive-menu.tsx
index 31b24e84ac..fb459bdaf6 100644
--- a/src/components/Header/responsive-menu.tsx
+++ b/src/components/Header/responsive-menu.tsx
@@ -1,18 +1,20 @@
import React, { JSX, useCallback, useState } from 'react';
import type { KeyboardEvent, MouseEvent, ReactNode } from 'react';
-import CFPBLogo from '../../assets/images/cfpb_logo.svg?url';
import { Button } from '../Buttons/button';
import { Icon } from '../Icon/icon';
import Link from '../Link/link';
import type { JSXElement } from '../../types/jsx-element';
+import { Logo, type LogoLanguage } from './logo';
import './responsive-menu.scss';
interface CfpbLogoProperties {
href?: string;
+ language?: LogoLanguage;
}
export function CfpbLogo({
href = 'https://www.consumerfinance.gov',
+ language = 'en',
}: CfpbLogoProperties): JSX.Element {
return (
-
+
);
}
@@ -64,11 +66,13 @@ const Links = ({
interface ResponsiveMenuProperties {
links?: ReactNode[];
href?: string;
+ lang?: LogoLanguage;
}
export default function ResponsiveMenu({
links,
href,
+ lang = 'en',
}: ResponsiveMenuProperties): JSX.Element {
const [isMenuOpen, setIsMenuOpen] = useState(false);
@@ -94,7 +98,7 @@ export default function ResponsiveMenu({
return (
);
@@ -127,7 +131,7 @@ export default function ResponsiveMenu({
{isMenuOpen ? 'Close menu' : 'Open menu'}
-
+