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 @@ +Oficina para la ProtecciónFinanciera del Consumidor \ 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 ( + {logoAltText[language]} + ); +} 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 ( - CFPB Logo + ); } @@ -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'} - +