Skip to content

Commit

Permalink
feat: add OnboardingMenu component (#121)
Browse files Browse the repository at this point in the history
  • Loading branch information
nikita-jpg authored Mar 19, 2024
1 parent 261f7ca commit e296ed4
Show file tree
Hide file tree
Showing 12 changed files with 1,124 additions and 0 deletions.
98 changes: 98 additions & 0 deletions src/components/OnboardingMenu/OnboardingMenu.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
@use '../variables.scss';
@use '@gravity-ui/uikit/styles/mixins';

$block: '.#{variables.$ns}onboarding-menu';

#{$block} {
max-width: 280px;

background: none;
width: fit-content;

&__content {
box-shadow: 0 2px 8px 0 var(--g-color-sfx-shadow-light);
display: flex;
flex-direction: column;
overflow: hidden;

box-sizing: border-box;
width: 210px;

background-color: var(--g-color-base-brand);
border-radius: 16px;

&_expand {
width: 280px;
border-radius: 20px;
height: fit-content;
min-height: 300px;
}
}

&__title {
display: flex;
align-items: center;
justify-content: center;

margin-block-end: var(--g-spacing-1);

background: none;
border: none;
cursor: pointer;
width: 100%;

padding: 0;

color: var(--g-color-text-brand-contrast);
@include mixins.text-subheader-2();
overflow: hidden;
text-overflow: ellipsis;
text-wrap: nowrap;

&_expand {
margin-block-end: var(--g-spacing-2);
@include mixins.text-subheader-3();
}
}

&__title-icon {
flex-shrink: 0;
margin-inline: var(--g-spacing-2) var(--g-spacing-2);
}

&__header {
padding: var(--g-spacing-2) var(--g-spacing-4) var(--g-spacing-3) var(--g-spacing-4);

&_expand {
padding: var(--g-spacing-3) var(--g-spacing-5) var(--g-spacing-4) var(--g-spacing-5);
}
}

&__lining {
overflow-y: auto;
max-height: 684px;

box-sizing: border-box;

flex: 1 1 auto;

padding: var(--g-spacing-2) 0px;

margin-inline: 1px;

margin-block-end: var(--g-spacing-4);
background-color: var(--g-color-base-float);

border-radius: var(--g-border-radius-xl);
}

&__buttons {
display: flex;
gap: var(--g-spacing-2);
justify-content: space-between;

max-width: 100%;
padding-inline: var(--g-spacing-5);
margin-block-end: var(--g-spacing-5);
}
}
141 changes: 141 additions & 0 deletions src/components/OnboardingMenu/OnboardingMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import React from 'react';

import {Button, Icon, IconData, Progress} from '@gravity-ui/uikit';

import {block} from '../utils/cn';

import {OnboardingMenuItem} from './components/OnboardingMenuItem';
import {OnboardingMenuItemImage} from './components/OnboardingMenuItemImage';
import {OnboardingMenuItemText} from './components/OnboardingMenuItemText';
import i18n from './i18n';

import './OnboardingMenu.scss';

const cnOnboardingMenu = block('onboarding-menu');

export type OnboardingMenuProps = {
title: React.ReactNode;
progress: number;
icon?: IconData;

defaultExpanded: boolean;
children?: React.ReactNode;

collapseButtonText?: string;
completeButtonText?: string;
className?: string;

onExpand?: (expanded: boolean) => void;
onCompleteClick: (event: React.MouseEvent) => void;
onCollapseClick?: (event: React.MouseEvent) => void;
};

const OnboardingMenuParent = ({
title,
progress,
icon,
defaultExpanded,
onExpand,
onCollapseClick,
onCompleteClick,
collapseButtonText,
completeButtonText,
className,
children,
}: OnboardingMenuProps) => {
const [expand, setExpand] = React.useState(defaultExpanded);

const onExpandCallback = () => {
const newExpand = !expand;

setExpand(newExpand);
if (onExpand) {
onExpand(newExpand);
}
};

const onCollapseClickCallback = (event: React.MouseEvent) => {
const newExpand = !expand;

setExpand(newExpand);
if (onCollapseClick) {
onCollapseClick(event);
}
if (onExpand) {
onExpand(newExpand);
}
};

return (
<div className={cnOnboardingMenu(null, className)}>
<div className={cnOnboardingMenu('content', {expand: expand})}>
<div className={cnOnboardingMenu('header', {expand: expand})}>
<button
className={cnOnboardingMenu('title', {expand: expand})}
onClick={onExpandCallback}
tabIndex={0}
>
{icon ? (
<Icon
data={icon}
width={20}
height={20}
className={cnOnboardingMenu('title-icon')}
/>
) : null}

{/* <span>
{title}
</span> */}
{title}
</button>
<Progress
size={expand ? 's' : 'xs'}
stack={[
{
value: progress,
color: 'var(--g-color-base-positive-heavy)',
},
{
value: 100 - progress,
color: 'var(--g-color-base-background)',
},
]}
/>
</div>

{expand && (
<React.Fragment>
<div className={cnOnboardingMenu('lining')}>{children}</div>
<div className={cnOnboardingMenu('buttons')}>
<Button
view="normal-contrast"
size="m"
onClick={onCollapseClickCallback}
width="max"
>
{collapseButtonText ?? i18n('collapse')}
</Button>
<Button
view="outlined-contrast"
onClick={onCompleteClick}
size="m"
width="max"
>
{completeButtonText ?? i18n('complete')}
</Button>
</div>
</React.Fragment>
)}
</div>
</div>
);
};

OnboardingMenuParent.displayName = 'OnboardingMenu';

export const OnboardingMenu = Object.assign(OnboardingMenuParent, {
Item: OnboardingMenuItem,
ItemText: OnboardingMenuItemText,
ItemImage: OnboardingMenuItemImage,
});
Loading

0 comments on commit e296ed4

Please sign in to comment.