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

feat: add auto close to nav-item inside header and main-navigation #2344

Merged
merged 8 commits into from
Apr 11, 2024
17 changes: 14 additions & 3 deletions packages/components/src/components/header/header.lite.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import {
onMount,
onUpdate,
Show,
Slot,
useMetadata,
useRef,
useStore
} from '@builder.io/mitosis';
import { DBHeaderState, DBHeaderProps } from './model';
import { DBHeaderProps, DBHeaderState } from './model';
import { addAttributeToChildren, cls, uuid } from '../../utils';
import { DBButton } from '../button';
import { DBDrawer } from '../drawer';
import { DEFAULT_ID } from '../../shared/constants';
import { isEventTargetNavigationItem } from '../../utils/navigation';

useMetadata({
isAttachedToShadowDom: true
Expand All @@ -31,6 +31,11 @@ export default function DBHeader(props: DBHeaderProps) {
if (props.onToggle) {
props.onToggle(!props.drawerOpen);
}
},
handleNavigationItemClick: (event: unknown) => {
if (isEventTargetNavigationItem(event)) {
state.toggle();
}
}
});

Expand Down Expand Up @@ -72,7 +77,13 @@ export default function DBHeader(props: DBHeaderProps) {
open={props.drawerOpen}
onClose={() => state.toggle()}>
<div class="db-header-drawer-navigation">
<div class="db-header-navigation">{props.children}</div>
<div
class="db-header-navigation"
onClick={(event) =>
state.handleNavigationItemClick(event)
}>
{props.children}
</div>
<div class="db-header-meta-navigation">
<Slot name="meta-navigation" />
</div>
Expand Down
4 changes: 3 additions & 1 deletion packages/components/src/components/header/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
GlobalProps,
GlobalState,
InitializedState,
NavigationBehaviourState,
ToggleEventProps,
ToggleEventState
} from '../../shared/model';
Expand Down Expand Up @@ -38,4 +39,5 @@ export interface DBHeaderDefaultState {
export type DBHeaderState = DBHeaderDefaultState &
GlobalState &
ToggleEventState<HTMLElement> &
InitializedState;
InitializedState &
NavigationBehaviourState;
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import {
onMount,
Show,
onUpdate,
useMetadata,
useRef,
useStore
} from '@builder.io/mitosis';
import { DBMainNavigationState, DBMainNavigationProps } from './model';
import { DBMainNavigationProps, DBMainNavigationState } from './model';
import { cls, uuid } from '../../utils';
import { DEFAULT_ID } from '../../shared/constants';
import { isEventTargetNavigationItem } from '../../utils/navigation';

useMetadata({
isAttachedToShadowDom: true
Expand All @@ -17,20 +18,44 @@ export default function DBMainNavigation(props: DBMainNavigationProps) {
const ref = useRef<HTMLDivElement>(null);
// jscpd:ignore-start
const state = useStore<DBMainNavigationState>({
_id: DEFAULT_ID
_id: DEFAULT_ID,
initialized: false,
forceClose: false,
handleNavigationItemClick: (event: unknown) => {
if (isEventTargetNavigationItem(event)) {
state.forceClose = true;
}
}
});

onMount(() => {
state._id = props.id || 'main-navigation-' + uuid();
state.initialized = true;
});

onUpdate(() => {
if (ref && state.initialized) {
state.initialized = false;
}
}, [ref, state.initialized]);

onUpdate(() => {
if (state.forceClose) {
requestAnimationFrame(() => {
state.forceClose = false;
});
}
}, [state.forceClose]);

// jscpd:ignore-end

return (
<nav
ref={ref}
id={state._id}
class={cls('db-main-navigation', props.className)}>
class={cls('db-main-navigation', props.className)}
onClick={(event) => state.handleNavigationItemClick(event)}
data-force-close={state.forceClose}>
<menu>{props.children}</menu>
</nav>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,12 @@
}
}
}

&[data-force-close="true"] {
& > menu menu {
@include screen-sizes.screen("md") {
display: none;
}
}
}
}
16 changes: 13 additions & 3 deletions packages/components/src/components/main-navigation/model.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
import { GlobalProps, GlobalState } from '../../shared/model';
import {
GlobalProps,
GlobalState,
InitializedState,
NavigationBehaviourState
} from '../../shared/model';

export interface DBMainNavigationDefaultProps {}

export type DBMainNavigationProps = DBMainNavigationDefaultProps & GlobalProps;

export interface DBMainNavigationDefaultState {}
export interface DBMainNavigationDefaultState {
forceClose: boolean;
}

export type DBMainNavigationState = DBMainNavigationDefaultState & GlobalState;
export type DBMainNavigationState = DBMainNavigationDefaultState &
InitializedState &
GlobalState &
NavigationBehaviourState;
4 changes: 4 additions & 0 deletions packages/components/src/shared/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ export type PlacementProps = {
| 'bottom-end';
};

export type NavigationBehaviourState = {
handleNavigationItemClick: (event: unknown) => void;
};

export type GapProps = {
/**
* If the absolute element should have a gap between the parent element.
Expand Down
11 changes: 11 additions & 0 deletions packages/components/src/utils/navigation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const isEventTargetNavigationItem = (event: unknown): boolean => {
const { target } = event as { target: HTMLElement };
return Boolean(
!target?.classList?.contains('db-navigation-item-expand-button') &&
target?.parentElement?.classList.contains('db-navigation-item')
);
};

export default {
isEventTargetNavigationItem
};
Loading