diff --git a/packages/react/src/LogoSuite/LogoSuite.module.css b/packages/react/src/LogoSuite/LogoSuite.module.css index 12c19b2f2..5a9d28a71 100644 --- a/packages/react/src/LogoSuite/LogoSuite.module.css +++ b/packages/react/src/LogoSuite/LogoSuite.module.css @@ -100,6 +100,7 @@ } .LogoSuite__logobar--has-marquee { + position: relative; display: flex; flex-direction: column; gap: var(--base-size-40); @@ -140,7 +141,7 @@ } } -.LogoSuite__logobar--has-marquee:hover .LogoSuite__logobar-marqueeGroup, +.LogoSuite__logobar-marquee:hover .LogoSuite__logobar-marqueeGroup, .LogoSuite__logobar-marqueeGroup--speed-idle { animation-play-state: paused; } @@ -160,3 +161,56 @@ ); mask-image: linear-gradient(to right, hsl(0 0% 0% / 0), hsl(0 0% 0% / 1) 20%, hsl(0 0% 0% / 1) 80%, hsl(0 0% 0% / 0)); } + +.LogoSuite__logobar--paused * { + animation-play-state: paused !important; +} + +.LogoSuite__logobar-playPauseButton { + cursor: pointer; + position: absolute; + right: 0; + bottom: 0; + display: flex; + width: 44px; + height: 44px; + margin: 0; + padding: 0; + border: none; + border-radius: 50%; + justify-content: center; + align-items: center; + background: none; + outline-offset: 2px; +} + +.LogoSuite__logobar-playPauseButton:focus-visible { + outline: 4px solid var(--brand-color-focus); + outline-offset: 2px; +} + +.LogoSuite__logobar-playPauseButton::before { + position: absolute; + width: 100%; + height: 100%; + content: ''; + background: var(--brand-LogoSuite-color-logo-muted); + opacity: 0.6; + border-radius: 50%; + transition: opacity 0.2s ease-out; +} + +.LogoSuite__logobar-playPauseButton:hover::before { + opacity: 0.8; +} + +.LogoSuite__logobar-playPauseButton svg { + width: var(--base-size-20); + height: var(--base-size-20); + z-index: 1; + color: var(--brand-LogoSuite-color-logo-emphasis); +} + +.LogoSuite__logobar-playPauseButton path { + fill: currentColor; +} diff --git a/packages/react/src/LogoSuite/LogoSuite.module.css.d.ts b/packages/react/src/LogoSuite/LogoSuite.module.css.d.ts index 335b0b5df..46f96235e 100644 --- a/packages/react/src/LogoSuite/LogoSuite.module.css.d.ts +++ b/packages/react/src/LogoSuite/LogoSuite.module.css.d.ts @@ -15,8 +15,10 @@ declare const styles: { readonly "LogobarScrollX": string; readonly "LogoSuite__logobar-marqueeGroup--speed-default": string; readonly "LogoSuite__logobar-marqueeGroup--speed-slow": string; - readonly "LogoSuite__logobar-marqueeGroup--speed-idle": string; readonly "LogoSuite__logobar-marquee": string; + readonly "LogoSuite__logobar-marqueeGroup--speed-idle": string; + readonly "LogoSuite__logobar--paused": string; + readonly "LogoSuite__logobar-playPauseButton": string; }; export = styles; diff --git a/packages/react/src/LogoSuite/LogoSuite.tsx b/packages/react/src/LogoSuite/LogoSuite.tsx index a8c8de8db..fa76f35f4 100644 --- a/packages/react/src/LogoSuite/LogoSuite.tsx +++ b/packages/react/src/LogoSuite/LogoSuite.tsx @@ -1,5 +1,5 @@ import {default as clsx} from 'clsx' -import React, {type PropsWithChildren, type Ref, forwardRef, useEffect, useMemo, useState} from 'react' +import React, {type PropsWithChildren, type Ref, forwardRef, useCallback, useEffect, useMemo, useState} from 'react' import type {BaseProps} from '../component-helpers' import {Heading, HeadingProps, defaultHeadingTag, Text, TextProps} from '../' @@ -144,6 +144,50 @@ const _Description = forwardRef( }, ) +const PauseIcon = () => ( + +) + +const PlayIcon = () => ( + +) + +type PlayPauseButtonProps = { + initialPlaying?: boolean + onPlayPause?: (isPlaying: boolean) => void +} + +const PlayPauseButton = ({initialPlaying = true, onPlayPause}: PlayPauseButtonProps) => { + const [playing, setPlaying] = useState(initialPlaying) + + const onClick = useCallback(() => { + setPlaying(!playing) + onPlayPause?.(!playing) + }, [onPlayPause, playing]) + + return ( + + ) +} + export type LogoSuiteLogoBarProps = BaseProps & { children: React.ReactNode | React.ReactNode[] /** @@ -166,6 +210,7 @@ const _LogoBar = forwardRef( ref: Ref, ) => { const [prefersReducedMotion, setPrefersReducedMotion] = useState(false) + const [isPlaying, setIsPlaying] = useState(marquee && !prefersReducedMotion) const childrenCount = React.Children.toArray(children).length variant ??= childrenCount <= 5 ? 'emphasis' : 'muted' @@ -194,7 +239,14 @@ const _LogoBar = forwardRef( if (marquee && !prefersReducedMotion) { const {className: marqueeDefaultClassName, ...restProps} = defaultProps return ( -
+
+
) }