-
Notifications
You must be signed in to change notification settings - Fork 93
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
updated lib/KListWithOverflow.vue and lib/KBreadcrumbs.vue #857
base: develop
Are you sure you want to change the base?
Conversation
Converting to draft #693 (comment) |
@shruti862 Also referencing @AlexVelezLl's comments that touches on some areas you mentioned, perhaps it helps #693 (comment) |
@AlexVelezLl Hi Alex, @shruti862 continues this work and already followed some of your guidance. @shruti862 experienced some blockers and I asked to elaborate in this PR on some specific places. Would you please be available for giving a direction? |
Thanks @shruti862! I will take a look later today :) |
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.
Thank you @shruti862!! This is a great start! I have left some instructions to solve the issues you were experiencing, along with some other things I noticed. Thank you!!
lib/KListWithOverflow.vue
Outdated
@@ -274,7 +284,15 @@ | |||
} | |||
|
|||
.more-button-wrapper { | |||
visibility: hidden; | |||
visibility: visible; | |||
order: 0; /* Ensure it remains in its original position for keyboard navigation */ |
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 cant have this solution for the position of the button, because Keyboard navigation would not be the same. We need to keep the current behaviour in KBreadcrumbs that if the more button appears at the beginning, the keyboard navigation should focus it first, before the rest items.
@@ -274,7 +284,15 @@ | |||
} | |||
|
|||
.more-button-wrapper { | |||
visibility: hidden; | |||
visibility: visible; |
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.
Hmm interested to know why is this change needed? The more button starts as hidden because we measure its width first, before doing the next computations, so to avoid it being visible for that first render we initialize its visibility as hidden.
lib/KListWithOverflow.vue
Outdated
@@ -129,6 +137,8 @@ | |||
*/ | |||
setOverflowItems() { | |||
const { list, listWrapper, moreButtonWrapper } = this.$refs; | |||
|
|||
// Exit early if necessary refs are not available |
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.
Lets remove these comments, as the code itself is descriptive
const itemWidth = itemsSizes[i].width; | ||
|
||
// If the item dont fit in the available space or if we have already |
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.
Lets get back these comments that describes a behaviour a little bit more complex
lib/KBreadcrumbs.vue
Outdated
appearance="raised-button" | ||
> | ||
<template #menu> | ||
<!-- issue :: dropdown menu shows only text of the overflowItems but not the link , I don't know whether i am doing the right way to reference link or not --> |
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.
For this you can add these lines in KDropdownMenu:
<UiMenu
ref="menu"
:options="options"
:hasIcons="hasIcons"
@select="handleSelection"
>
<template #option="{ option }">
<slot name="option" :option="option"/>
</template>
</UiMenu>
And then you will be able to customize these dropdown options using this option slot in KDropdownMenu. There we can handle the link behaviour
lib/KBreadcrumbs.vue
Outdated
} | ||
// Add separators between items | ||
return crumbs.flatMap((item, index) => | ||
index > 0 ? [{ type: 'separator' }, item] : [item] |
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.
The reason the dividers are not being visible is because we are passing this as type: "separator"
while the correct name is type: "divider"
lib/KBreadcrumbs.vue
Outdated
<style scoped> | ||
.breadcrumbs-divider { | ||
margin: 0 10px; | ||
color: black; /* Adjust color for the ">" separator */ |
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.
Lets standarize the name, and lets call it always "divider" instead of "separator"
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.
Also, lets not use burned colors. Instead we can use our color tokens, we cant reference these in css, so we will need to set this color in the vue template
lib/KBreadcrumbs.vue
Outdated
<!-- issue :: dropdown menu shows only text of the overflowItems but not the link , I don't know whether i am doing the right way to reference link or not --> | ||
<KDropdownMenu | ||
:options="overflowItems | ||
.filter(item => item.type !== 'separator') // Filter out separators |
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.
idem "divider" instead of separator
lib/KListWithOverflow.vue
Outdated
.list-wrapper { | ||
display: flex; | ||
justify-content: space-between; | ||
justify-content: space-between; |
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.
Lets add a alignItems: center
instruction here, so the default behaviour is that the items are centered
77c86a0
to
6c6b208
Compare
…tem into new-change3
This reverts commit 4ada24c.
|
|
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.
Hi @shruti862! Thanks! This is looking so much better! I have made some notes that will help to solve the issues that you are experiencing :).
Apologies for the late response 😅.
lib/KListWithOverflow.vue
Outdated
</slot> | ||
<!-- @slot Slot responsible of rendering each item in the visible list --> | ||
></slot> | ||
<!-- Item Slot --> |
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.
Lets gonna revert this change, this comment is useful for KDS docs:
<!-- Item Slot --> | |
<!-- @slot Slot responsible of rendering each item in the visible list --> |
lib/KListWithOverflow.vue
Outdated
} | ||
|
||
/* When the 'start-button' class is added, position visually at the start */ | ||
.more-button-wrapper.start-button { |
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.
I dont think this change is needed anymore, is it?
@@ -153,15 +177,13 @@ | |||
const itemSize = this.getSize(item); |
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.
The issue you are facing with the list width not being calculated correctly is because this getSize
method currently doesnt support items with margins. So to fix this, lets rewrite this getSize
method to something like this:
getSize(element) {
if (!element) {
return { width: 0, height: 0 };
}
let { width, height } = element.getBoundingClientRect();
const style = element.currentStyle || window.getComputedStyle(element);
const marginX = parseFloat(style.marginLeft) + parseFloat(style.marginRight);
const marginY = parseFloat(style.marginTop) + parseFloat(style.marginBottom);
width += marginX;
height += marginY;
return { width, height };
},
After this you wont see the list item in the next line when there is still space for it..
lib/KBreadcrumbs.vue
Outdated
:to="item.link" | ||
> | ||
|
||
<template #text="{ text }"> |
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.
Be aware that KRouterLink
doesnt have a #text slot. So we just need to use the default slot here instead
@@ -153,15 +177,13 @@ | |||
const itemSize = this.getSize(item); | |||
itemsSizes.push(itemSize); | |||
} | |||
|
|||
const indexSequence = [...Array(list.children.length).keys()]; |
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 are a couple of things that needs to be changed with this reversed behaviour:
- The
fixDividersVisibility
method. The intention of this method is to avoid that a divider is placed as the first or last item in the list. And here we calculate thislastVisibleIdx
https://github.com/shruti862/kolibri-design-system/blob/01aededc7ac60f49278ebf9ff15db89d8aec0581/lib/KListWithOverflow.vue#L248 which will need to change when we are in reversed mode because the lastVisibleIdx is not the same in both cases. - We have a couple of little bugs here and here, because we change the visibility of the item, but we need to change also the position to be
position: absolute
if the item is hidden, andposition: unset
when the item is visible. So, althoguh its not a regression of your PR, fixing this will prevent some bugs that become more apparent when we work with the overflowDirection as "start".
lib/KBreadcrumbs.vue
Outdated
.breadcrumbs-divider { | ||
margin-right: 8px; | ||
margin-left: 8px; | ||
color: #000000; |
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.
Lets avoid burned color, and lets use the KDS color tokens instead https://design-system.learningequality.org/colors/#tokens-text
lib/KBreadcrumbs.vue
Outdated
padding: 16px; | ||
font-size: 16px; | ||
font-weight: bold; | ||
color: #4368f5; |
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.
idem, lets avoid burned colors
lib/KBreadcrumbs.vue
Outdated
left: -1000em; | ||
padding: 16px; | ||
font-size: 16px; | ||
color: #000000; |
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.
Idem
@AlexVelezLl Can you please review my current changes specially the fixDividersVisibility method ::Since the lastVisibleIdx in case of overflowdirection:'start' will always be last element of list.children because overflowIdx array is calculated after reversing the list.children for start direction so I didn't applied any checks on it. |
@AlexVelezLl But now i am facing issue on truncating the last visible item of the list. Could you please guide me how to approach this?? |
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.
Hey @shruti862! Apologies for the late response, this is a big change and needed to find a considerable amount of time to review it well. I have left some suggestions here to fix the problems you are facing, and also some considerations we need to take into account. Let me know if you have any question 🤗.
class="breadcrumbs" | ||
v-bind="$attrs" | ||
:aria-label="$attrs.ariaLabel" | ||
<div class="breadcrumbs"> |
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.
instead of a div, we will need to have here a <nav
instead, just as it was before.
> | ||
<ol class="breadcrumbs-dropdown-items"> |
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 also need another change here. In the past, the list container was an ol`` element, so we need to modify
KListWithOverflowto receive a prop, lets say
listElement` or so, so we can indicate to the KListWithOverflow that the list should be an ol, so we can have the semantic structure ol > li
if (this.isDivider(this.items[firstOverflowedIdx])) { | ||
overflowItemsIdx.shift(); | ||
} | ||
if (this.overflowDirection === 'start') { |
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.
To fix the divider visibility of the overflowed items, we dont need any change actually 😅, so we can just have:
const [firstOverflowedIdx] = overflowItemsIdx;
if (this.isDivider(this.items[firstOverflowedIdx])) {
overflowItemsIdx.shift();
}
const dividerNode = list.children[lastVisibleIdx]; | ||
dividerNode.style.visibility = 'hidden'; | ||
return itemsSizes[lastVisibleIdx].width; | ||
const lastVisibleIdx = firstOverflowedIdx - 1; |
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.
Here is where we need to do the change, because when we have an overflowDirection == start, then we will need to check the visibility of the first item instead. So we can do this instead:
if (this.overflowDirection === 'start') {
const firstVisibleIdx = firstOverflowedIdx + 1;
if (this.isDivider(this.items[firstVisibleIdx])) {
const dividerNode = list.children[firstVisibleIdx];
dividerNode.style.visibility = 'hidden';
dividerNode.style.position = 'absolute';
return itemsSizes[firstVisibleIdx].width;
}
} else {
const lastVisibleIdx = firstOverflowedIdx - 1;
if (this.isDivider(this.items[lastVisibleIdx])) {
const dividerNode = list.children[lastVisibleIdx];
dividerNode.style.visibility = 'hidden';
return itemsSizes[lastVisibleIdx].width;
}
}
In general this method should look like:
fixDividersVisibility(overflowItemsIdx, itemsSizes) {
if (overflowItemsIdx.length === 0) {
return;
}
const { list } = this.$refs;
const [firstOverflowedIdx] = overflowItemsIdx;
if (this.isDivider(this.items[firstOverflowedIdx])) {
overflowItemsIdx.shift();
}
if (this.overflowDirection === 'start') {
const firstVisibleIdx = firstOverflowedIdx + 1;
if (this.isDivider(this.items[firstVisibleIdx])) {
const dividerNode = list.children[firstVisibleIdx];
dividerNode.style.visibility = 'hidden';
dividerNode.style.position = 'absolute';
return itemsSizes[firstVisibleIdx].width;
}
} else {
const lastVisibleIdx = firstOverflowedIdx - 1;
if (this.isDivider(this.items[lastVisibleIdx])) {
const dividerNode = list.children[lastVisibleIdx];
dividerNode.style.visibility = 'hidden';
return itemsSizes[lastVisibleIdx].width;
}
}
},
</div> | ||
</KDropdownMenu> | ||
</template> | ||
</KIconButton> |
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.
To avoid messing with the dividers visibility after the KIconButton, we can just add the divider besides the KIconButton from the more slot, since for this case, always that we show the more slot, will need to show the divider. So we can have just something like
<template #more="{ overflowItems }">
<div style="display: flex; align-items: center;">
<KIconButton
...
>
...
</KIconButton>
<span
:style="{ color: $themeTokens.text }"
class="breadcrumbs-divider"
>›
</span>
</div>
</template>
</li> | ||
|
||
<li | ||
v-else |
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.
> | ||
<!-- Render individual breadcrumb items --> | ||
<template #item="{ item,index }"> | ||
<li> |
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 will also need to set the maxWidth that we set to the spans here to the li, for it to know what its its own max width, instead of getting it from the listOverflow container.
dir="auto" | ||
:title="item.text" | ||
> | ||
<template #default="{ text }"> |
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.
doesnt have a slot with props, and it doesnt pass the text to the slot, and this is making that we dont render the span with the breadcrumbs-crumb-text
class. We need to have the slot defined just as <template #default>
and inside render the text using item.text
Description
Updated lib/KListWithOverflow.vue and lib/KBreadcrumbs.vue files
Issue addressed
Addresses issue #693
Addresses #PR# HERE
Before/after screenshots
Changelog
Steps to test
(optional) Implementation notes
At a high level, how did you implement this?
Does this introduce any tech-debt items?
Testing checklist
Reviewer guidance
Comments