-
Notifications
You must be signed in to change notification settings - Fork 8
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
feat: aside header top alert #118
Changes from 13 commits
3fef146
fccba6b
e5c7363
d4a3e76
6e9e767
a1929bd
fec3a00
e15a016
3d4f002
0a1ce0c
2a94579
18b751e
a0c63d2
48daab3
d041c19
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 |
---|---|---|
|
@@ -80,7 +80,7 @@ body { | |
&__settings-panel, | ||
&__search-panel { | ||
width: 300px; | ||
height: 100%; | ||
height: calc(100% - 40px); | ||
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. fix drawer padding at 20px for remove unexpected scroll |
||
padding: 20px; | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
import React, {FC, useState} from 'react'; | ||
import React, {FC} from 'react'; | ||
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. Maybe then we’ll remove 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. fixed |
||
|
||
import { | ||
Button, | ||
|
@@ -11,7 +11,7 @@ | |
} from '@gravity-ui/uikit'; | ||
import {Bug, Gear, Magnifier} from '@gravity-ui/icons'; | ||
|
||
import {AsideHeader, FooterItem} from '../..'; | ||
import {AsideHeader, FooterItem, AsideHeaderTopAlertProps} from '../..'; | ||
import {cn} from '../../utils/cn'; | ||
import {menuItemsShowcase, text as placeholderText} from './moc'; | ||
import {MenuItem, OpenModalSubscriber} from '../../types'; | ||
|
@@ -38,11 +38,13 @@ | |
interface AsideHeaderShowcaseProps { | ||
multipleTooltip?: boolean; | ||
initialCompact?: boolean; | ||
topAlert?: AsideHeaderTopAlertProps; | ||
} | ||
|
||
export const AsideHeaderShowcase: FC<AsideHeaderShowcaseProps> = ({ | ||
multipleTooltip = false, | ||
initialCompact = false, | ||
topAlert, | ||
}) => { | ||
const ref = React.useRef<HTMLDivElement>(null); | ||
const [popupVisible, setPopupVisible] = React.useState(false); | ||
|
@@ -59,12 +61,12 @@ | |
const openModalCount = data?.meta?.layers?.filter( | ||
({type}) => type === 'modal', | ||
).length; | ||
callback(openModalCount !== 0); | ||
} | ||
}); | ||
}; | ||
|
||
const [menuItems, setMenuItems] = useState<MenuItem[]>([ | ||
const [menuItems, setMenuItems] = React.useState<MenuItem[]>([ | ||
...menuItemsShowcase, | ||
{ | ||
id: 'components', | ||
|
@@ -138,7 +140,8 @@ | |
compact={compact} | ||
multipleTooltip={multipleTooltip} | ||
openModalSubscriber={openModalSubscriber} | ||
topAlert={topAlert} | ||
renderFooter={({compact, asideRef}) => ( | ||
<React.Fragment> | ||
<FooterItem | ||
compact={compact} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import React from 'react'; | ||
import {Alert} from '@gravity-ui/uikit'; | ||
|
||
import {b} from '../utils'; | ||
import {AsideHeaderTopAlertProps} from '../../types'; | ||
import {useAsideHeaderTopPanel} from '../useAsideHeaderTopPanel'; | ||
|
||
type Props = { | ||
topAlert?: AsideHeaderTopAlertProps; | ||
}; | ||
|
||
export const TopPanel = ({topAlert}: Props) => { | ||
const {topRef, updateTopSize} = useAsideHeaderTopPanel({topAlert}); | ||
|
||
const [opened, setOpened] = React.useState(true); | ||
|
||
const handleClose = React.useCallback(() => { | ||
setOpened(false); | ||
topAlert?.onCloseTopAlert?.(); | ||
}, [topAlert]); | ||
|
||
React.useEffect(() => { | ||
if (!opened) { | ||
updateTopSize(); | ||
} | ||
}, [opened, updateTopSize]); | ||
|
||
if (!topAlert || !topAlert.message) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<div ref={topRef} className={b('pane-top', {opened})}> | ||
{opened && ( | ||
<React.Fragment> | ||
<Alert | ||
className={b('pane-top-alert', { | ||
centered: topAlert.centered, | ||
dense: topAlert.dense, | ||
})} | ||
corners="square" | ||
layout="horizontal" | ||
theme={topAlert.theme || 'warning'} | ||
icon={topAlert.icon} | ||
title={topAlert.title} | ||
message={topAlert.message} | ||
actions={topAlert.actions} | ||
onClose={topAlert.closable ? handleClose : undefined} | ||
/> | ||
<div className={b('pane-top-divider')}></div> | ||
</React.Fragment> | ||
)} | ||
</div> | ||
); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export {FirstPanel} from './FirstPanel'; | ||
export {TopPanel} from './TopPanel'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import React from 'react'; | ||
|
||
import debounceFn from 'lodash/debounce'; | ||
import {AsideHeaderTopAlertProps} from '../types'; | ||
|
||
type AsideHeaderTopPanel = { | ||
topRef: React.RefObject<HTMLDivElement>; | ||
updateTopSize: () => void; | ||
}; | ||
|
||
const useRefHeight = (ref: React.RefObject<HTMLDivElement>) => { | ||
const [topHeight, setTopHeight] = React.useState(0); | ||
React.useEffect(() => { | ||
if (ref.current) { | ||
const {current} = ref; | ||
setTopHeight(current.clientHeight); | ||
} | ||
}, [ref]); | ||
return topHeight; | ||
}; | ||
|
||
export const useAsideHeaderTopPanel = ({ | ||
topAlert, | ||
}: { | ||
topAlert?: AsideHeaderTopAlertProps; | ||
}): AsideHeaderTopPanel => { | ||
const topRef = React.useRef<HTMLDivElement>(null); | ||
const topHeight = useRefHeight(topRef); | ||
|
||
const setAsideTopPanelHeight = React.useCallback((clientHeight: number) => { | ||
document.documentElement.style.setProperty( | ||
'--gn-aside-top-panel-height', | ||
clientHeight + 'px', | ||
); | ||
}, []); | ||
|
||
const updateTopSize = React.useCallback(() => { | ||
if (topRef.current) { | ||
setAsideTopPanelHeight(topRef.current?.clientHeight || 0); | ||
} | ||
}, [topRef, setAsideTopPanelHeight]); | ||
|
||
React.useLayoutEffect(() => { | ||
const updateTopSizeDebounce = debounceFn(updateTopSize, 200, {leading: true}); | ||
|
||
if (topAlert) { | ||
window.addEventListener('resize', updateTopSizeDebounce); | ||
updateTopSizeDebounce(); | ||
} | ||
return () => { | ||
window.removeEventListener('resize', updateTopSizeDebounce); | ||
setAsideTopPanelHeight(0); | ||
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. set top panel size to zero for correct destroy component behaviour with iframe switching at storybook |
||
}; | ||
}, [topAlert, topHeight, topRef, updateTopSize]); | ||
|
||
return { | ||
topRef, | ||
updateTopSize, | ||
}; | ||
}; |
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.
Why is it not in the
.g-root
?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.
Then we can not change this value from document object
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.
We can use the correct selector
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.
Ok, changed to
getElementsByClassName
selector