Skip to content

Commit

Permalink
feat(Breadcrumbs): new component (#1497)
Browse files Browse the repository at this point in the history
  • Loading branch information
ValeraS authored Jun 13, 2024
1 parent 770d787 commit 5cdc675
Show file tree
Hide file tree
Showing 20 changed files with 1,635 additions and 0 deletions.
96 changes: 96 additions & 0 deletions src/components/lab/Breadcrumbs/BreadcrumbItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
'use client';

import React from 'react';

import type {Href, RouterOptions} from '../../types';
import {filterDOMProps} from '../../utils/filterDOMProps';

import type {BreadcrumbsItemProps} from './Breadcrumbs';
import {b, shouldClientNavigate} from './utils';

interface BreadcrumbProps extends BreadcrumbsItemProps {
onAction?: () => void;
current?: boolean;
itemType?: 'link' | 'menu';
disabled?: boolean;
navigate?: (href: Href, routerOptions: RouterOptions | undefined) => void;
}
export function BreadcrumbItem(props: BreadcrumbProps) {
const Element = props.href ? 'a' : 'span';
const domProps = filterDOMProps(props, {labelable: true});

let title = props.title;
if (!title && typeof props.children === 'string') {
title = props.children;
}

const handleAction = (event: React.MouseEvent | React.KeyboardEvent) => {
if (props.disabled || props.current) {
event.preventDefault();
return;
}

if (typeof props.onAction === 'function') {
props.onAction();
}

const target = event.currentTarget;
if (typeof props.navigate === 'function' && target instanceof HTMLAnchorElement) {
if (props.href && !event.isDefaultPrevented() && shouldClientNavigate(target, event)) {
event.preventDefault();
props.navigate(props.href, props.routerOptions);
}
}
};

const isDisabled = props.disabled || props.current;
let linkProps: React.AnchorHTMLAttributes<HTMLElement> = {
title,
onClick: handleAction,
'aria-disabled': isDisabled ? true : undefined,
};
if (Element === 'a') {
linkProps.href = props.href;
linkProps.hrefLang = props.hrefLang;
linkProps.target = props.target;
linkProps.rel = props.target === '_blank' && !props.rel ? 'noopener noreferrer' : props.rel;
linkProps.download = props.download;
linkProps.ping = props.ping;
linkProps.referrerPolicy = props.referrerPolicy;
} else {
linkProps.role = 'link';
linkProps.tabIndex = isDisabled ? undefined : 0;
linkProps.onKeyDown = (event: React.KeyboardEvent) => {
if (event.key === 'Enter') {
handleAction(event);
}
};
}

if (props.current) {
linkProps['aria-current'] = 'page';
}

if (props.itemType === 'menu') {
linkProps = {};
}

return (
<Element
{...domProps}
{...linkProps}
className={
props.itemType === 'menu'
? b('menu')
: b('link', {
'is-current': props.current,
'is-disabled': isDisabled && !props.current,
})
}
>
{props.children}
</Element>
);
}

BreadcrumbItem.displayName = 'Breadcrumbs.Item';
110 changes: 110 additions & 0 deletions src/components/lab/Breadcrumbs/Breadcrumbs.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
@use '../../variables';
@use '../../../../styles/mixins';

$block: '.#{variables.$ns}breadcrumbs2';

#{$block} {
display: flex;
flex-wrap: nowrap;
justify-content: flex-start;

list-style-type: none;
margin: 0;
padding: 0;

&__item {
position: relative;
display: flex;
align-items: center;
justify-content: flex-start;

height: 24px;
white-space: nowrap;
color: var(--g-color-text-primary);

&:last-child {
font-weight: var(--g-text-accent-font-weight);
overflow: hidden;

#{$block}__link {
@include mixins.overflow-ellipsis();
}
}

&_calculating:last-child {
overflow: visible;
}
}

&__link {
cursor: default;
position: relative;
text-decoration: none;
outline: none;
touch-action: manipulation;
-webkit-tap-highlight-color: transparent;

height: 24px;
line-height: 24px;
vertical-align: middle;
border-radius: var(--g-focus-border-radius);

color: inherit;

&_is-disabled {
color: var(--g-color-text-hint);
}

&:not([aria-disabled]) {
cursor: pointer;

&:hover {
color: var(--g-color-text-link-hover);
}
}

&:focus-visible {
outline: 2px solid var(--g-color-line-focus);
}
}

&__divider {
display: flex;
align-items: center;
color: var(--g-color-text-secondary);
padding: 0 var(--g-spacing-2);
}

&__more-button {
--g-button-border-radius: var(--g-focus-border-radius);
--g-button-focus-outline-offset: -2px;
}

&__menu {
margin-inline: calc(-1 * var(--g-spacing-2));
}

&__item:first-child &__menu {
margin-inline-start: 0;
}

&__popup_staircase {
$menu: '.#{variables.$ns}menu';
$staircaseLength: 10;
#{$menu} {
#{$menu}__list-item {
#{$menu}__item[class] {
padding-inline-start: 8px * $staircaseLength;
}
}

@for $i from 0 through $staircaseLength {
#{$menu}__list-item:nth-child(#{$i}) {
#{$menu}__item[class] {
padding-inline-start: 8px * $i;
}
}
}
}
}
}
Loading

0 comments on commit 5cdc675

Please sign in to comment.