Skip to content

Commit

Permalink
Add heading entrance animations
Browse files Browse the repository at this point in the history
REDMINE-20488
  • Loading branch information
tf committed Nov 2, 2023
1 parent 9725158 commit 3c09c86
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 3 deletions.
12 changes: 12 additions & 0 deletions entry_types/scrolled/config/locales/new/heading_subtitles.de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,15 @@ de:
inline_editing:
type_subtitle: "Untertitel eingeben"
type_tagline: "Tagline eingeben"
editor:
content_elements:
heading:
attributes:
entranceAnimation:
inline_help: Lege die Animation fest, mit der die Überschrift eingeblendet werden soll, wenn sie die Mitte des Viewports erreicht.
label: Eingangsanimation
values:
none: "(Keine)"
fadeIn: Einblenden
fadeInFast: Einblenden (Schnell)
fadeInSlow: Einblenden (Langsam)
12 changes: 12 additions & 0 deletions entry_types/scrolled/config/locales/new/heading_subtitles.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,15 @@ en:
inline_editing:
type_subtitle: "Type subtitle"
type_tagline: "Type tagline"
editor:
content_elements:
heading:
attributes:
entranceAnimation:
inline_help: Determine how the heading becomes visible once it reaches the center of the viewport
label: Entrance Animation
values:
fadeIn: Fade in
fadeInFast: Fade in (Fast)
fadeInSlow: Fade in (Slow)
none: "(None)"
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, {useEffect, useState, useRef} from 'react';
import classNames from 'classnames';
import {
withShadowClassName,
Expand All @@ -7,7 +7,9 @@ import {
EditableInlineText,
useContentElementConfigurationUpdate,
useContentElementEditorState,
useContentElementLifecycle,
useDarkBackground,
useIsStaticPreview,
useI18n,
contentElementWidths,
utils
Expand All @@ -21,13 +23,48 @@ export function Heading({configuration, sectionProps, contentElementWidth}) {
const updateConfiguration = useContentElementConfigurationUpdate();
const {t} = useI18n({locale: 'ui'});
const darkBackground = useDarkBackground();
const {isSelected} = useContentElementEditorState();
const {isSelected, isEditable} = useContentElementEditorState();

const legacyValue = configuration.children;
const Tag = firstSectionInEntry ? 'h1' : 'h2';

const forcePaddingTop = firstSectionInEntry && !('marginTop' in configuration);

const entranceAnimation = (!useIsStaticPreview() && configuration.entranceAnimation) || 'none';
const [animating, setAnimating] = useState(false);

useContentElementLifecycle({
onActivate() {
setAnimating(entranceAnimation !== 'none');
},

onInvisible() {
if (isEditable) {
setAnimating(false);
}
}
});

const previousAnimation = useRef(entranceAnimation);
const previouslySelected = useRef(isSelected);

useEffect(() => {
if (isEditable && previousAnimation.current !== entranceAnimation) {
previousAnimation.current = entranceAnimation;

setAnimating(false)
setTimeout(() => setAnimating(true), 100);
}
}, [entranceAnimation, isEditable]);

useEffect(() => {
if (!previouslySelected.current && isSelected) {
setAnimating(true)
}

previouslySelected.current = isSelected;
}, [isSelected]);

function renderSubtitle(name) {
const value = configuration[name];

Expand All @@ -50,6 +87,11 @@ export function Heading({configuration, sectionProps, contentElementWidth}) {

return (
<header className={classNames(styles.root,
styles[`animation-${entranceAnimation}`],
{[styles.animating]: animating},
{[styles.hasTagline]: !utils.isBlankEditableTextValue(
configuration.tagline
) || isSelected},
{[styles.forcePaddingTop]: forcePaddingTop},
{[styles[sectionProps.layout]]:
contentElementWidth > contentElementWidths.md ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,48 @@
padding-top: 0.45em;
}

.animation-fadeIn {
--fade-in-duration: 2s;
--fade-in-delay: 0.4s;
}

.animation-fadeInFast {
composes: animation-fadeIn;
--fade-in-duration: 1s;
--fade-in-delay: 0.4s;
}

.animation-fadeInSlow {
composes: animation-fadeIn;
--fade-in-duration: 3s;
--fade-in-delay: 0.8s;
}

.animation-fadeIn .main,
.animation-fadeIn .tagline,
.animation-fadeIn .subtitle {
opacity: 0;
}

.animation-fadeIn.animating .main,
.animation-fadeIn.animating .tagline,
.animation-fadeIn.animating .subtitle {
transition: opacity var(--fade-in-duration) ease;
opacity: 1;
}

.animation-fadeIn.animating .subtitle {
transition-delay: var(--fade-in-delay);
}

.animation-fadeIn.hasTagline.animating .main {
transition-delay: var(--fade-in-delay);
}

.animation-fadeIn.hasTagline.animating .subtitle {
transition-delay: calc(var(--fade-in-delay) * 2);
}

.main {
margin: 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ editor.contentElementTypes.register('heading', {
model: modelDelegator,
propertyName: 'color'
});
this.input('entranceAnimation', SelectInputView, {
values: ['none', 'fadeInSlow', 'fadeIn', 'fadeInFast'],
});

this.input('hyphens', SelectInputView, {
values: ['auto', 'manual']
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ import {frontend} from 'pageflow-scrolled/frontend';
import {Heading} from './Heading';

frontend.contentElementTypes.register('heading', {
component: Heading
component: Heading,
lifecycle: true
});

0 comments on commit 3c09c86

Please sign in to comment.