<div class="container"></div>
console.clear();
//ES6 const, let
//ES6 Destructuring
const { Component, useEffect, useCallback, useState, useSyncExternalStore, memo, useRef } = React;
const { css } = styled
const CIRCLE_GAP = 8
const CIRCLE_RADIUS = 10
const PADDING_Y = 17.5
const BORDER_WIDTH = 1.5
const MenuStyleBorder = styled.div`
position: relative;
width: 50%;
height: 50px;
border: ${BORDER_WIDTH}px solid orange;
border-radius: 7px;
padding: 25px;
`
const CircleCSS = css`
width: ${CIRCLE_RADIUS * 2}px;
height: ${CIRCLE_RADIUS}px;
border-bottom-left-radius: ${CIRCLE_RADIUS}px;
border-bottom-right-radius: ${CIRCLE_RADIUS}px;
border: ${BORDER_WIDTH}px solid orange;
border-top: ${BORDER_WIDTH}px solid #fff;
box-sizing: border-box;
background: #fff;
`
const HalfCircle = styled.div`
${CircleCSS}
position: absolute;
bottom: 0px;
border-top: 2px solid white;
`
const TopCircleWrapper = styled.div`
position: absolute;
top: 8px;
left: 0px;
`
const CircleWrapper = styled.div`
position: relative;
display: flex;
padding: 0 ${PADDING_Y}px;
`
const DynamicHalfCircle = ({ parentRef }) => {
const circleData = useSyncExternalStore(
(callback) => {
window.addEventListener('resize', callback)
return () => window.removeEventListener('resize', callback)
},
() => {
const { width } = parentRef.current?.getBoundingClientRect() || { width: 0 }
const count = Math.ceil((width - 7 * 2 - PADDING_Y - CIRCLE_GAP) / (CIRCLE_RADIUS * 2 + CIRCLE_GAP))
const initLeft = Math.max((width - count * CIRCLE_RADIUS * 2 - (count - 1) * CIRCLE_GAP) / 2, 0)
return JSON.stringify({
count: Math.max(count, 0),
width,
initLeft,
})
},
() =>
JSON.stringify({
count: 0,
width: 0,
initLeft: 0,
}),
)
const circleInfo = JSON.parse(circleData || '{}')
return (
<CircleWrapper>
{Array.from({ length: circleInfo?.count || 0 }, (_, i) => i).map((i) => (
<HalfCircle key={i} style={{ left: (CIRCLE_GAP + CIRCLE_RADIUS * 2) * i + (circleInfo.initLeft ?? 0) }} />
))}
</CircleWrapper>
)
}
const MenuCard = memo(
({ className, children }) => {
const MenuElemRef = useRef()
return (
<MenuStyleBorder ref={MenuElemRef}>
<TopCircleWrapper>
<DynamicHalfCircle parentRef={MenuElemRef} />
</TopCircleWrapper>
{children}
</MenuStyleBorder>
)
},
)
const App = () => {
return <MenuCard> Menu </MenuCard>;
}
ReactDOM.render(<App />, document.querySelector(".container"));
View Compiled
This Pen doesn't use any external CSS resources.