for context I am building a day view calendar and I have mapped each hour in the day out while filtering my events to see if they should be rendered in that hourblock
my issue is that long events which span multiple hours are positioned behind other events and i would like to find a way for the overflow content to push the next events div over to the right as if it was flexed in the same container.
Ideally the pink "event" should sit to the right of the blue one
currently the future event divs just ignore the previous events overflow
no Jquery and if this one thing can be solved with css that is ideal. doing math with JS is probably possible but could be less reliable / buggy
Thanks in advance guys :)
CalendarHour.tsx
hourBlock: {
display: 'flex',
width: '100%',
height: '64px',
position: 'relative',
},
time: {
fontSize: FONT_SIZE_SMALL,
color: PLAIN_GREY,
marginRight: '30px',
lineHeight: '0',
},
content: {
display: 'flex',
width: '100%',
borderTop: `1px solid ${PLAIN_GREY}`,
},
line: {
height: '1px',
width: '100%',
backgroundColor: LIGHT_GREY,
margin: 'auto',
},
{[...Array(hoursInDay)].map((e, index) => (
<div className={classes.hourBlock} key={e}>
<div className={classes.time}>{renderTime(index)}</div>
<div className={classes.content}>
{events
?.filter((e) => format(new Date(e.start.toString()), 'HH') == renderHour(index))
.map((e) => (
<CalendarEventItem key={e.id} event={e} />
))}
<div className={classes.line} />
</div>
</div>
))}
CalendarEventItem.tsx
eventItemWrapper: {
display: 'flex',
width: '100%',
borderLeft: `2px solid ${color}`,
backgroundColor: WHITE,
fontSize: '12px',
marginRight: '5px',
height,
position: 'relative',
},
title: {
fontWeight: 'bold',
marginRight: '5px',
},
detailsWrapper: {
backgroundColor: fadedColor,
width: '100%',
paddingLeft: '4px',
},
details: {},
<div className={classes.eventItemWrapper}>
<div className={classes.detailsWrapper}>
<div className={classes.title}>{event.name}</div>
<div className={classes.details}>{eventDetails}</div>
</div>
</div>
I hope this snippet might help you, I included two examples, the one on the left uses a fixed size container, so when the child grows, it overflows, and the only way to make the child interact with other elements is through JS.
The second example on the right on the contrary uses containers with non fixed size, so they are free to grow/shrink when the children change their size, so the child can interact with other elements through its own parent.
let height = 50;
btn.onclick = e => {
height += 1
child1.style.height = height + "px"
}
let height2 = 50;
btn2.onclick = e => {
height2 += 1
child3.style.height = height2 + "px"
}
// OBSERVER
const targetNode = child1
// Options for the observer (which mutations to observe)
const config = {
attributes: true,
childList: true,
subtree: true
};
// Callback function to execute when mutations are observed
const callback = function(mutationList, observer) {
for (const mutation of mutationList) {
if (mutation.type === 'attributes' && mutation.attributeName === "style") {
const child2Y = child2.getBoundingClientRect().y
const child1Y = child1.getBoundingClientRect().y
const child1Height = child1.getBoundingClientRect().height
if (child1Y + child1Height >= child2Y) child2.style.transform = `translateY(${child1Y+child1Height - child2Y}px)`
}
}
};
// Create an observer instance linked to the callback function
const observer = new MutationObserver(callback);
// Start observing the target node for configured mutations
observer.observe(targetNode, config);
body {
display: flex;
}
.parent1 {
height: 50px;
}
#child1 {
width: 50px;
height: 50px;
background: red;
position: relative;
}
#child2 {
width: 50px;
height: 50px;
background: blue;
}
#child3 {
width: 50px;
height: 50px;
background: red;
position: relative;
}
#child4 {
width: 50px;
height: 50px;
background: blue;
}
<div>
<div class="parent1">
<div id="child1">Child1</div>
</div>
<div class="parent2">
<div id="child2">Child2</div>
</div>
</div>
<button id="btn">Enlarge Child 1</button>
<div>
<div class="parent3">
<div id="child3">Child3</div>
</div>
<div class="parent4">
<div id="child4">Child4</div>
</div>
</div>
<button id="btn2">Enlarge Child 3</button>