Skip to content
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

addition of nav-item component styles and style behavior #28

Open
wants to merge 1 commit into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/components/mf-nav-item/mf-nav-item.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export default class MfNavItem extends ShoelaceElement {
super.connectedCallback();
this.addEventListener('click', this.handleHostClick);
this.addEventListener('mouseover', this.handleMouseOver);
this.getNavItemLevel(this.hasSlotController.host?.parentElement);
}

disconnectedCallback() {
Expand Down Expand Up @@ -141,6 +142,28 @@ export default class MfNavItem extends ShoelaceElement {
return this.hasSlotController.test('subnav');
}

private getNavItemLevel(navItemParent: HTMLElement | null) {
let level = 0;

const loopingBehavior = (passedNavItemParent: HTMLElement) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I read an article that discourage this kind of lambda expressions as they can cause memory leaks.
This is just a comment to share this information, no need to update the code

For reference here you can read the article: on-js-closures-and-leaks

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i needed a behavior that can distinguish each level of the navigation items, to be able to style it

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the article it recommends to avoid closures, that's what is the comment about :)

const navElementParent = passedNavItemParent;
const isMainNav =
navElementParent?.tagName?.toLocaleLowerCase() === 'mf-navigation' &&

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you consider to rename from mf-navigation to mf-nav in a separate PR?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes it should be renamed to mf-navigation, i'll be doing it once am back from vacation.
or someone else can pick up

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You meant maf-nav right? Someone can pick up this if we are aligned with the name

navElementParent?.getAttribute('slot') !== 'subnav';
if (navElementParent?.hasAttribute('slot') && navElementParent?.getAttribute('slot') === 'subnav') {
++level;
}
if (!isMainNav && navElementParent?.parentElement) {
loopingBehavior(navElementParent?.parentElement);
}
return level;
};
if (navItemParent) {
loopingBehavior(navItemParent);
}
this.setAttribute('level', `level-${level}`);
}

render() {
const isRtl = this.localize.dir() === 'rtl';
const isSubnavExpanded = this.subnavController.isExpanded();
Expand Down
194 changes: 181 additions & 13 deletions src/components/mf-nav-item/mf-nav-item.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,95 @@ export default css`
}

.nav-item {
// position: relative;
display: flex;
align-items: stretch;
font-family: var(--sl-font-sans);
font-size: var(--sl-font-size-medium);
font-weight: var(--sl-font-weight-normal);
line-height: var(--sl-line-height-normal);
letter-spacing: var(--sl-letter-spacing-normal);
color: var(--sl-color-neutral-700);
font-family: var(--mafui-navigationItem-font-family-primary);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a good practice to include a fallback value, especially for properties like color or font-family. Check below example:

font-family: var(--mafui-navigationItem-font-family-primary, Arial, sans-serif);

font-size: var(--mafui-navigationItem-font-size-primary);
font-weight: var(--mafui-navigationItem-font-weight-primary);
line-height: var(--mafui-navigationItem-line-height-primary);
letter-spacing: var(--mafui-navigationItem-letter-spacing-primary);
color: var(--mafui-navigationItem-font-color-primary);
background-color: var(--mafui-navigationItem-color-background-primary);
border-top: var(--mafui-navigationItem-border-width-top-primary)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the borders on all sides are meant to be the same, you can simplify this to use a shorthand border property instead of defining each side separately. Like below:

border: var(--mafui-navigationItem-border-width-primary)
var(--mafui-navigationItem-border-style-primary)
var(--mafui-navigationItem-color-border-primary);

var(--mafui-navigationItem-border-style-top-primary) var(--mafui-navigationItem-color-border-top-primary);
border-right: var(--mafui-navigationItem-border-width-right-primary)
var(--mafui-navigationItem-border-style-right-primary) var(--mafui-navigationItem-color-border-right-primary);
border-bottom: var(--mafui-navigationItem-border-width-bottom-primary)
var(--mafui-navigationItem-border-style-bottom-primary) var(--mafui-navigationItem-color-border-bottom-primary);
border-left: var(--mafui-navigationItem-border-width-left-primary)
var(--mafui-navigationItem-border-style-left-primary) var(--mafui-navigationItem-color-border-left-primary);
Comment on lines +17 to +31

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would remove -primary on the first level, for example:

font-family: var(--mafui-navigationItem-font-family);

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems fair, as its the main style for all navigation items.
but also sounds a bit counter intuitive, lets decide on this.
@moalobaidat

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My point is every menu can can levels 1, 2 and 3 (we will discourage to use more than 3 levels) and we can have more than one menu.

Each menu variant should have it's own suffix like primary, secondary etc. and each menu level it's own suffix too

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation, @carlos-verdes . I get your point about using clear suffixes for consistency, but I’m not sure removing -primary from font-family is the right move. The -primary suffix helps keep things clear by showing what the default style should be, especially as we scale and maintain the code.

Maybe instead of removing it, we could look at how we’re using these suffixes and make sure they’re not confusing or redundant.

Let’s discuss further to make sure we’re keeping things both clear and easy to maintain.


padding: var(--nav-spacing-inset-stretch, --nav-spacing-inset) var(--nav-spacing-inset-squish, --nav-spacing-inset);
margin-right: var(--nav-spacing-inline);
margin-bottom: var(--nav-spacing-stack);
transition: var(--sl-transition-fast) fill;

user-select: none;
-webkit-user-select: none;
white-space: nowrap;
cursor: pointer;
text-decoration: none;
}

:host([level='level-1']) .nav-item {
font-family: var(--mafui-navigationItem-font-family-secondary);
font-size: var(--mafui-navigationItem-font-size-secondary);
font-weight: var(--mafui-navigationItem-font-weight-secondary);
line-height: var(--mafui-navigationItem-line-height-secondary);
letter-spacing: var(--mafui-navigationItem-letter-spacing-secondary);
color: var(--mafui-navigationItem-font-color-secondary);
background-color: var(--mafui-navigationItem-color-background-secondary);
border-top: var(--mafui-navigationItem-border-width-top-secondary)
var(--mafui-navigationItem-border-style-top-secondary) var(--mafui-navigationItem-color-border-top-secondary);
border-right: var(--mafui-navigationItem-border-width-right-secondary)
var(--mafui-navigationItem-border-style-right-secondary) var(--mafui-navigationItem-color-border-right-secondary);
border-bottom: var(--mafui-navigationItem-border-width-bottom-secondary)
var(--mafui-navigationItem-border-style-bottom-secondary)
var(--mafui-navigationItem-color-border-bottom-secondary);
border-left: var(--mafui-navigationItem-border-width-left-secondary)
var(--mafui-navigationItem-border-style-left-secondary) var(--mafui-navigationItem-color-border-left-secondary);
}
Comment on lines +45 to +62

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

level-1 and -secondary is confusing to me, I would use level-1 for first parent and default css variables (following previous commit) and level-2 for secondary

Also I was thinking secondary is a variant and it may be useful to use it for a secondary menu (imagine a section with settings for example), so maybe is better to be explicit and use -level-2 as suffix:

:host([level='level-2']) .nav-item {
    font-family: var(--mafui-navigationItem-font-family-level-2);

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, @moalobaidat ?


:host([level='level-2']) .nav-item {
font-family: var(--mafui-navigationItem-font-family-tertiary);
font-size: var(--mafui-navigationItem-font-size-tertiary);
font-weight: var(--mafui-navigationItem-font-weight-tertiary);
line-height: var(--mafui-navigationItem-line-height-tertiary);
letter-spacing: var(--mafui-navigationItem-letter-spacing-tertiary);
color: var(--mafui-navigationItem-font-color-tertiary);
background-color: var(--mafui-navigationItem-color-background-tertiary);
border-top: var(--mafui-navigationItem-border-width-top-tertiary)
var(--mafui-navigationItem-border-style-top-tertiary) var(--mafui-navigationItem-color-border-top-tertiary);
border-right: var(--mafui-navigationItem-border-width-right-tertiary)
var(--mafui-navigationItem-border-style-right-tertiary) var(--mafui-navigationItem-color-border-right-tertiary);
border-bottom: var(--mafui-navigationItem-border-width-bottom-tertiary)
var(--mafui-navigationItem-border-style-bottom-tertiary) var(--mafui-navigationItem-color-border-bottom-tertiary);
border-left: var(--mafui-navigationItem-border-width-left-tertiary)
var(--mafui-navigationItem-border-style-left-tertiary) var(--mafui-navigationItem-color-border-left-tertiary);
Comment on lines +72 to +79

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure about having 4 variables one per border, I think is better to define the combinations we need and put an specific name:

  • all 4 borders
  • only bottom border
  • only right / left border

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the specification you provided is also 4, but the one in the code provides a bit more flexibility.
lets discuss it more plz. @moalobaidat thoughts?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean?
I provided 3 options only:

  • one with all borders active, like a button
image
  • one for "stacked" elements (border-bottom by default but if we stack from bottom to top the border will be border-top)
image
  • one for inline elements, it will be right border by default and left border in RTL mode for this I haven't found any example so I think we can ommit

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@abu-seini-maf - Just added my comment above

}

.nav-item.nav-item--disabled {
outline: none;
opacity: 0.5;
cursor: not-allowed;
}

.nav-item.nav-item--highlight {
color: var(--sl-color-neutral-900);
font-family: var(--mafui-navigationItem-font-family-highlight);
font-size: var(--mafui-navigationItem-font-size-highlight);
font-weight: var(--mafui-navigationItem-font-weight-highlight);
line-height: var(--mafui-navigationItem-line-height-highlight);
letter-spacing: var(--mafui-navigationItem-letter-spacing-highlight);
color: var(--mafui-navigationItem-font-color-highlight);
border-top: var(--mafui-navigationItem-border-width-top-highlight)
var(--mafui-navigationItem-border-style-top-highlight) var(--mafui-navigationItem-color-border-top-highlight);
border-right: var(--mafui-navigationItem-border-width-right-highlight)
var(--mafui-navigationItem-border-style-right-highlight) var(--mafui-navigationItem-color-border-right-highlight);
border-bottom: var(--mafui-navigationItem-border-width-bottom-highlight)
var(--mafui-navigationItem-border-style-bottom-highlight)
var(--mafui-navigationItem-color-border-bottom-highlight);
border-left: var(--mafui-navigationItem-border-width-left-highlight)
var(--mafui-navigationItem-border-style-left-highlight) var(--mafui-navigationItem-color-border-left-highlight);
}

.nav-item.nav-item--loading {
Expand Down Expand Up @@ -111,18 +172,118 @@ export default css`

:host(:hover:not([aria-disabled='true'], :focus-visible)) .nav-item,
.nav-item--subnav-expanded {
background-color: var(--sl-color-neutral-100);
color: var(--sl-color-neutral-1000);
background-color: var(--mafui-navigationItem-color-background-primary-hover);
color: var(--mafui-navigationItem-font-color-primary-hover);

border-top: var(--mafui-navigationItem-border-width-top-primary-hover)
var(--mafui-navigationItem-border-style-top-primary-hover)
var(--mafui-navigationItem-color-border-top-primary-hover);
border-right: var(--mafui-navigationItem-border-width-right-primary-hover)
var(--mafui-navigationItem-border-style-right-primary-hover)
var(--mafui-navigationItem-color-border-right-primary-hover);
border-bottom: var(--mafui-navigationItem-border-width-bottom-primary-hover)
var(--mafui-navigationItem-border-style-bottom-primary-hover)
var(--mafui-navigationItem-color-border-bottom-primary-hover);
border-left: var(--mafui-navigationItem-border-width-left-primary-hover)
var(--mafui-navigationItem-border-style-left-primary-hover)
var(--mafui-navigationItem-color-border-left-primary-hover);
}

:host(:focus-visible) .nav-item {
outline: none;
background-color: var(--sl-color-primary-600);
color: var(--sl-color-neutral-0);
opacity: 1;
background-color: var(--mafui-navigationItem-color-background-primary-focus);
color: var(--mafui-navigationItem-font-color-primary-focus);
border-top: var(--mafui-navigationItem-border-width-top-primary-focus)
var(--mafui-navigationItem-border-style-top-primary-focus)
var(--mafui-navigationItem-color-border-top-primary-focus);
border-right: var(--mafui-navigationItem-border-width-right-primary-focus)
var(--mafui-navigationItem-border-style-right-primary-focus)
var(--mafui-navigationItem-color-border-right-primary-focus);
border-bottom: var(--mafui-navigationItem-border-width-bottom-primary-focus)
var(--mafui-navigationItem-border-style-bottom-primary-focus)
var(--mafui-navigationItem-color-border-bottom-primary-hover);
border-left: var(--mafui-navigationItem-border-width-left-primary-focus)
var(--mafui-navigationItem-border-style-left-primary-focus)
var(--mafui-navigationItem-color-border-left-primary-focus);
}

:host([level='level-1']:hover:not([aria-disabled='true'], :focus-visible)) .nav-item,
:host([level='level-1']) .nav-item--subnav-expanded {
background-color: var(--mafui-navigationItem-color-background-secondary-hover);
color: var(--mafui-navigationItem-font-color-secondary-hover);

border-top: var(--mafui-navigationItem-border-width-top-secondary-hover)
var(--mafui-navigationItem-border-style-top-secondary-hover)
var(--mafui-navigationItem-color-border-top-secondary-hover);
border-right: var(--mafui-navigationItem-border-width-right-secondary-hover)
var(--mafui-navigationItem-border-style-right-secondary-hover)
var(--mafui-navigationItem-color-border-right-secondary-hover);
border-bottom: var(--mafui-navigationItem-border-width-bottom-secondary-hover)
var(--mafui-navigationItem-border-style-bottom-secondary-hover)
var(--mafui-navigationItem-color-border-bottom-secondary-hover);
border-left: var(--mafui-navigationItem-border-width-left-secondary-hover)
var(--mafui-navigationItem-border-style-left-secondary-hover)
var(--mafui-navigationItem-color-border-left-secondary-hover);
}

:host([level='level-1']:focus-visible) .nav-item {
outline: none;
opacity: 1;
background-color: var(--mafui-navigationItem-color-background-secondary-focus);
color: var(--mafui-navigationItem-font-color-secondary-focus);
border-top: var(--mafui-navigationItem-border-width-top-secondary-focus)
var(--mafui-navigationItem-border-style-top-secondary-focus)
var(--mafui-navigationItem-color-border-top-secondary-focus);
border-right: var(--mafui-navigationItem-border-width-right-secondary-focus)
var(--mafui-navigationItem-border-style-right-secondary-focus)
var(--mafui-navigationItem-color-border-right-secondary-focus);
border-bottom: var(--mafui-navigationItem-border-width-bottom-secondary-focus)
var(--mafui-navigationItem-border-style-bottom-secondary-focus)
var(--mafui-navigationItem-color-border-bottom-secondary-hover);
border-left: var(--mafui-navigationItem-border-width-left-secondary-focus)
var(--mafui-navigationItem-border-style-left-secondary-focus)
var(--mafui-navigationItem-color-border-left-secondary-focus);
}

:host([level='level-2']:hover:not([aria-disabled='true'], :focus-visible)) .nav-item,
:host([level='level-2']) .nav-item--subnav-expanded {
background-color: var(--mafui-navigationItem-color-background-tertiary-hover);
color: var(--mafui-navigationItem-font-color-tertiary-hover);

border-top: var(--mafui-navigationItem-border-width-top-tertiary-hover)
var(--mafui-navigationItem-border-style-top-tertiary-hover)
var(--mafui-navigationItem-color-border-top-tertiary-hover);
border-right: var(--mafui-navigationItem-border-width-right-tertiary-hover)
var(--mafui-navigationItem-border-style-right-tertiary-hover)
var(--mafui-navigationItem-color-border-right-tertiary-hover);
border-bottom: var(--mafui-navigationItem-border-width-bottom-tertiary-hover)
var(--mafui-navigationItem-border-style-bottom-tertiary-hover)
var(--mafui-navigationItem-color-border-bottom-tertiary-hover);
border-left: var(--mafui-navigationItem-border-width-left-tertiary-hover)
var(--mafui-navigationItem-border-style-left-tertiary-hover)
var(--mafui-navigationItem-color-border-left-tertiary-hover);
}

:host([level='level-2']:focus-visible) .nav-item {
outline: none;
opacity: 1;
background-color: var(--mafui-navigationItem-color-background-tertiary-focus);
color: var(--mafui-navigationItem-font-color-tertiary-focus);
border-top: var(--mafui-navigationItem-border-width-top-tertiary-focus)
var(--mafui-navigationItem-border-style-top-tertiary-focus)
var(--mafui-navigationItem-color-border-top-tertiary-focus);
border-right: var(--mafui-navigationItem-border-width-right-tertiary-focus)
var(--mafui-navigationItem-border-style-right-tertiary-focus)
var(--mafui-navigationItem-color-border-right-tertiary-focus);
border-bottom: var(--mafui-navigationItem-border-width-bottom-tertiary-focus)
var(--mafui-navigationItem-border-style-bottom-tertiary-focus)
var(--mafui-navigationItem-color-border-bottom-tertiary-hover);
border-left: var(--mafui-navigationItem-border-width-left-tertiary-focus)
var(--mafui-navigationItem-border-style-left-tertiary-focus)
var(--mafui-navigationItem-color-border-left-tertiary-focus);
}

.nav-item .nav-item__check,
.nav-item .nav-item__chevron {
flex: 0 0 auto;
display: flex;
Expand Down Expand Up @@ -169,6 +330,13 @@ export default css`
max-height: var(--auto-size-available-height) !important;
}

::slotted(mf-navigation[slot='subnav']) {
background: red;
}
::slotted(mf-navigation[slot='subnav']) mf-nav-item {
background: red;
}

.nav-item--wide sl-popup::part(popup) {
left: 0;
width: 100%;
Expand Down
4 changes: 2 additions & 2 deletions src/components/mf-nav-item/subnav-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ export class SubnavController implements ReactiveController {
} else {
this.enableSubnav(false);
this.host.updateComplete.then(() => {
if (navItems[0] instanceof HTMLElement) {
navItems[0].focus();
if (navItems![0] instanceof HTMLElement) {
navItems![0].focus();
}
});
this.host.requestUpdate();
Expand Down
Loading
Loading