-
Notifications
You must be signed in to change notification settings - Fork 49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DRAFT] feat: navigation bar private - add split d/m #1475
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
'@alfalab/core-components-navigation-bar-private': minor | ||
--- | ||
|
||
- Добавлен сплит д/м | ||
- Добавлено sideEffects: false |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,15 +6,46 @@ import cn from 'classnames'; | |
import { getDataTestId } from '@alfalab/core-components-shared'; | ||
import { useLayoutEffect_SAFE_FOR_SSR } from '@alfalab/hooks'; | ||
|
||
import { BackArrowAddon } from './components/back-arrow-addon'; | ||
import { Closer } from './components/closer'; | ||
import type { ContentParams, NavigationBarPrivateProps } from './types'; | ||
|
||
import styles from './index.module.css'; | ||
import { | ||
type BackArrowAddon, | ||
type BackArrowAddonDesktop, | ||
type BackArrowAddonMobile, | ||
} from './components/back-arrow-addon'; | ||
import { type Closer, type CloserDesktop, type CloserMobile } from './components/closer'; | ||
import type styles from './index.module.css'; | ||
import type { ContentParams, NavigationBarBasePrivateProps } from './types'; | ||
|
||
type NavigationBarBaseHiddenProps = { | ||
/** | ||
* Вид шапки - мобильный или десктоп | ||
*/ | ||
view: 'desktop' | 'mobile'; | ||
|
||
/** | ||
* Вид шапки - мобильный или десктоп | ||
*/ | ||
styles: typeof styles; | ||
|
||
/** | ||
* Компонент BackArrowAddon | ||
*/ | ||
BackArrowAddon: | ||
| typeof BackArrowAddonDesktop | ||
| typeof BackArrowAddonMobile | ||
| typeof BackArrowAddon; | ||
|
||
/** | ||
* Компонент Closer | ||
*/ | ||
Closer: typeof CloserDesktop | typeof CloserMobile | typeof Closer; | ||
}; | ||
|
||
const ADDONS_HEIGHT = 48; | ||
|
||
export const NavigationBarPrivate = forwardRef<HTMLDivElement, NavigationBarPrivateProps>( | ||
export const NavigationBarPrivateBase = forwardRef< | ||
HTMLDivElement, | ||
NavigationBarBasePrivateProps & NavigationBarBaseHiddenProps | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. не хватает еще SecretProps для полной картины ) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. private уже был, что мне было делать? ) |
||
>( | ||
( | ||
{ | ||
addonClassName, | ||
|
@@ -43,6 +74,9 @@ export const NavigationBarPrivate = forwardRef<HTMLDivElement, NavigationBarPriv | |
scrollableParentRef, | ||
sticky, | ||
onBack, | ||
styles, | ||
BackArrowAddon, | ||
Closer, | ||
}, | ||
ref, | ||
) => { | ||
|
@@ -54,18 +88,28 @@ export const NavigationBarPrivate = forwardRef<HTMLDivElement, NavigationBarPriv | |
const leftAddonsRef = useRef<HTMLDivElement>(null); | ||
const rightAddonsRef = useRef<HTMLDivElement>(null); | ||
|
||
// MOBILE | ||
const compactTitle = view === 'mobile' && titleSize === 'compact'; | ||
|
||
const hasLeftPart = Boolean(leftAddons || hasBackButton); | ||
const hasRightPart = Boolean(rightAddons || hasCloser); | ||
const hasContent = Boolean(title || children); | ||
|
||
// MOBILE | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. возможно стоит эти пропсы сгруппировать как-то? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. если так делать, то точно не в этом пр-е ) |
||
const withAnimation = Boolean(view === 'mobile' && hasLeftPart && sticky && !compactTitle); | ||
|
||
const showContentOnTop = hasContent && (compactTitle || !hasLeftPart); | ||
const showContentOnBot = hasContent && !compactTitle && hasLeftPart; | ||
const showStaticContentOnTop = !withAnimation && showContentOnTop; | ||
const showStaticContentOnBot = !withAnimation && showContentOnBot; | ||
|
||
// MOBILE | ||
const showAnimatedContentOnTop = | ||
withAnimation && showContentOnBot && scrollTop > ADDONS_HEIGHT; | ||
|
||
// MOBILE | ||
const showAnimatedContentOnBot = withAnimation && showContentOnBot; | ||
|
||
const headerPaddingTop = mainLinePaddingTopRef.current; | ||
|
||
useLayoutEffect_SAFE_FOR_SSR(() => { | ||
|
@@ -106,10 +150,12 @@ export const NavigationBarPrivate = forwardRef<HTMLDivElement, NavigationBarPriv | |
setScrollTop(divElement.scrollTop); | ||
}; | ||
|
||
// MOBILE | ||
if (withAnimation && headerRef.current) { | ||
mainLinePaddingTopRef.current = getComputedStyle(headerRef.current).paddingTop; | ||
} | ||
|
||
// MOBILE | ||
if (withAnimation && parent) { | ||
parent.addEventListener('scroll', handleScroll); | ||
} | ||
|
@@ -120,11 +166,14 @@ export const NavigationBarPrivate = forwardRef<HTMLDivElement, NavigationBarPriv | |
const renderBackButton = () => { | ||
let textOpacity = 1; | ||
|
||
// MOBILE | ||
if (withAnimation) { | ||
const height = hasContent ? ADDONS_HEIGHT : ADDONS_HEIGHT / 2; | ||
|
||
textOpacity = Math.max(0, 1 - scrollTop / height); | ||
} else if (compactTitle) { | ||
} | ||
// MOBILE | ||
else if (compactTitle) { | ||
textOpacity = 0; | ||
} | ||
|
||
|
@@ -150,6 +199,7 @@ export const NavigationBarPrivate = forwardRef<HTMLDivElement, NavigationBarPriv | |
ref={wrapperRef} | ||
className={cn(styles.content, extraClassName, contentClassName, styles[align], { | ||
[styles.trim]: trim, | ||
// MOBILE | ||
[styles.withCompactTitle]: view === 'mobile' && compactTitle && hasContent, | ||
})} | ||
aria-hidden={hidden} | ||
|
@@ -163,7 +213,12 @@ export const NavigationBarPrivate = forwardRef<HTMLDivElement, NavigationBarPriv | |
{title} | ||
</div> | ||
)} | ||
{compactTitle && subtitle && <div className={styles.subtitle}>{subtitle}</div>} | ||
{ | ||
// MOBILE | ||
compactTitle && subtitle && ( | ||
<div className={styles.subtitle}>{subtitle}</div> | ||
) | ||
} | ||
</div> | ||
); | ||
}; | ||
|
@@ -186,6 +241,7 @@ export const NavigationBarPrivate = forwardRef<HTMLDivElement, NavigationBarPriv | |
data-test-id={getDataTestId(dataTestId)} | ||
style={{ | ||
...(imageUrl && { backgroundImage: `url(${imageUrl})` }), | ||
// MOBILE | ||
...(withAnimation && | ||
bottomContentRef.current && { | ||
top: -bottomContentRef.current.scrollHeight, | ||
|
@@ -194,10 +250,12 @@ export const NavigationBarPrivate = forwardRef<HTMLDivElement, NavigationBarPriv | |
> | ||
<div | ||
className={cn(styles.mainLine, { | ||
// MOBILE | ||
[styles.mainLineSticky]: withAnimation, | ||
[styles.mainLineWithImageBg]: imageUrl, | ||
})} | ||
style={{ | ||
// MOBILE | ||
...(withAnimation | ||
? { | ||
marginTop: `-${headerPaddingTop}`, | ||
|
@@ -227,19 +285,25 @@ export const NavigationBarPrivate = forwardRef<HTMLDivElement, NavigationBarPriv | |
: null), | ||
})} | ||
|
||
{showAnimatedContentOnTop && | ||
renderContent({ | ||
extraClassName: styles.withBothAddons, | ||
style: { | ||
opacity: Math.min(1, (scrollTop - ADDONS_HEIGHT) / ADDONS_HEIGHT), | ||
...(align === 'center' | ||
? { | ||
marginLeft: titleMargin.left, | ||
marginRight: titleMargin.right, | ||
} | ||
: null), | ||
}, | ||
})} | ||
{ | ||
// MOBILE | ||
showAnimatedContentOnTop && | ||
renderContent({ | ||
extraClassName: styles.withBothAddons, | ||
style: { | ||
opacity: Math.min( | ||
1, | ||
(scrollTop - ADDONS_HEIGHT) / ADDONS_HEIGHT, | ||
), | ||
...(align === 'center' | ||
? { | ||
marginLeft: titleMargin.left, | ||
marginRight: titleMargin.right, | ||
} | ||
: null), | ||
}, | ||
}) | ||
} | ||
|
||
{hasRightPart && ( | ||
<div | ||
|
@@ -256,22 +320,17 @@ export const NavigationBarPrivate = forwardRef<HTMLDivElement, NavigationBarPriv | |
</div> | ||
)} | ||
</div> | ||
{ | ||
// MOBILE | ||
showAnimatedContentOnBot && | ||
renderContent({ | ||
wrapperRef: bottomContentRef, | ||
style: { opacity: Math.max(0, 1 - scrollTop / ADDONS_HEIGHT) }, | ||
hidden: scrollTop / ADDONS_HEIGHT > 1, | ||
}) | ||
} | ||
|
||
{showAnimatedContentOnBot && | ||
renderContent({ | ||
wrapperRef: bottomContentRef, | ||
extraClassName: styles.underAddons, | ||
style: { opacity: Math.max(0, 1 - scrollTop / ADDONS_HEIGHT) }, | ||
hidden: scrollTop / ADDONS_HEIGHT > 1, | ||
})} | ||
|
||
{showStaticContentOnBot && | ||
renderContent({ | ||
extraClassName: cn({ | ||
[styles.contentOnBotDesktop]: view === 'desktop', | ||
[styles.contentOnBotMobile]: view === 'mobile', | ||
}), | ||
})} | ||
{showStaticContentOnBot && renderContent({ extraClassName: styles.contentOnBot })} | ||
|
||
{bottomAddons && ( | ||
<div className={cn(styles.bottomAddons, bottomAddonsClassName)}> | ||
|
@@ -283,4 +342,4 @@ export const NavigationBarPrivate = forwardRef<HTMLDivElement, NavigationBarPriv | |
}, | ||
); | ||
|
||
NavigationBarPrivate.displayName = 'NavigationBarPrivate'; | ||
NavigationBarPrivateBase.displayName = 'NavigationBarPrivate'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
не экономь буквы плиз)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
прнято