Skip to content

Commit

Permalink
Fix/773 frontend responsiveness complete seedlot register (#797)
Browse files Browse the repository at this point in the history
* fix: create breadcrumb component

* feat: breadcrumb component created

* feat: breadcrumb component added to registration

* fix: fixing media query value

* fix: registration progress vertical

* fix: markup fixes

* feat: BCBreadcrumb component created

* fix: eslint error fixes

* fix: updating code standards

* fix: change component name

* fix: changing render logic to ternary

* fix: fixing typo

* fix: breadcrumbs to constants file

* Revert "fix: breadcrumbs to constants file"

This reverts commit 697b32d.

* fix: breadcrumb data moved to constant file

* fix: markup fixes

* fix: changing screen size check logic

* fix: refactor breadcrumbs

* fix: use constant

* fix: use hook

* fix: change break point

* fix: combo button, detail and dashboard page, remove stack

* fix: prefix

---------

Co-authored-by: mgaseta <105936322+mgaseta@users.noreply.github.com>
Co-authored-by: Craig Yu <craig.yu93@gmail.com>
  • Loading branch information
3 people authored Feb 6, 2024
1 parent 0ad4cc3 commit f18e3f6
Show file tree
Hide file tree
Showing 20 changed files with 413 additions and 217 deletions.
3 changes: 3 additions & 0 deletions frontend/src/components/Breadcrumbs/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const DEFAULT_MAX_CRUMBS = 4;
export const DEFAULT_MAX_CRUMBS_SM = 2;
export const DEFAULT_MAX_CRUMBS_MD = 3;
8 changes: 8 additions & 0 deletions frontend/src/components/Breadcrumbs/definitions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export type CrumbType = {
name: string,
path: string
}

export type BreadcrumbsProps = {
crumbs: CrumbType[]
}
110 changes: 110 additions & 0 deletions frontend/src/components/Breadcrumbs/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import {
Breadcrumb,
BreadcrumbItem,
OverflowMenu,
OverflowMenuItem
} from '@carbon/react';

import useWindowSize from '../../hooks/UseWindowSize';
import { MEDIUM_SCREEN_WIDTH, SMALL_SCREEN_WIDTH } from '../../shared-constants/shared-constants';

import { BreadcrumbsProps, CrumbType } from './definitions';
import { DEFAULT_MAX_CRUMBS, DEFAULT_MAX_CRUMBS_MD, DEFAULT_MAX_CRUMBS_SM } from './constants';

import './styles.scss';

const Breadcrumbs = ({ crumbs }: BreadcrumbsProps) => {
if (!crumbs.length) {
return null;
}

const navigate = useNavigate();
const windowSize = useWindowSize();
const [displayedCrumbs, setDisplayedCrumbs] = useState<CrumbType[]>(() => crumbs);
const [overflowCrumbs, setOverflowCrumbs] = useState<CrumbType[]>([]);

/**
* Adjust the config of breadcrumbs every time the window size changes.
*/
useEffect(() => {
const width = windowSize.innerWidth;
let maxCrumbs = DEFAULT_MAX_CRUMBS;

if (width <= MEDIUM_SCREEN_WIDTH) {
maxCrumbs = DEFAULT_MAX_CRUMBS_MD;
}

if (width <= SMALL_SCREEN_WIDTH) {
maxCrumbs = DEFAULT_MAX_CRUMBS_SM;
}

const crumbsLen = crumbs.length;

if (crumbsLen > maxCrumbs) {
const diff = crumbsLen - maxCrumbs;
setOverflowCrumbs(crumbs.slice(1, diff + 1));
setDisplayedCrumbs(crumbs.slice(0, 1).concat(crumbs.slice(diff + 1)));
} else {
setOverflowCrumbs([]);
setDisplayedCrumbs(crumbs);
}
}, [windowSize.innerWidth, crumbs]);

if (overflowCrumbs.length === 0) {
return (
<div className="breadcrumbs-container">
<Breadcrumb>
{
displayedCrumbs.map((crumb) => (
<BreadcrumbItem
onClick={() => navigate(crumb.path)}
key={crumb.name}
>
{crumb.name}
</BreadcrumbItem>
))
}
</Breadcrumb>
</div>
);
}

return (
<div className="breadcrumbs-container">
<Breadcrumb>
<BreadcrumbItem
onClick={() => navigate(displayedCrumbs[0].path)}
>
{displayedCrumbs[0].name}
</BreadcrumbItem>
<BreadcrumbItem>
<OverflowMenu>
{
overflowCrumbs.map((overflowCrumb) => (
<OverflowMenuItem
key={overflowCrumb.name}
itemText={overflowCrumb.name}
onClick={() => navigate(overflowCrumb.path)}
/>
))
}
</OverflowMenu>
</BreadcrumbItem>
{
displayedCrumbs.slice(1).map((crumb) => (
<BreadcrumbItem
onClick={() => navigate(crumb.path)}
key={crumb.name}
>
{crumb.name}
</BreadcrumbItem>
))
}
</Breadcrumb>
</div>
);
};

export default Breadcrumbs;
8 changes: 8 additions & 0 deletions frontend/src/components/Breadcrumbs/styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@use '@bcgov-nr/nr-theme/design-tokens/variables.scss' as vars;

.breadcrumbs-container {
.#{vars.$bcgov-prefix}--breadcrumb {
display: flex;
flex-wrap: nowrap;
}
}
2 changes: 1 addition & 1 deletion frontend/src/components/ComboButton/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const ComboButton = ({
items,
menuOptionsClass
}: ComboButtonProps) => (
<div className="combo-button-wrapper">
<div className="combo-button-container">
<Button
className="combo-button"
size="md"
Expand Down
80 changes: 39 additions & 41 deletions frontend/src/components/ComboButton/styles.scss
Original file line number Diff line number Diff line change
@@ -1,44 +1,42 @@
@use '@bcgov-nr/nr-theme/design-tokens/variables.scss' as vars;

.combo-button {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
padding-right: 1.25rem;
}

.combo-options {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
background: var(--#{vars.$bcgov-prefix}-background-brand);
border-left: solid white 1px;
}

.combo-options svg,
.combo-options.#{vars.$bcgov-prefix}--overflow-menu.#{vars.$bcgov-prefix}--overflow-menu--open svg {
fill: white;
}

.combo-options:hover {
background-color: var(--#{vars.$bcgov-prefix}-button-primary-hover);
}

.combo-options.#{vars.$bcgov-prefix}--overflow-menu:focus {
outline-color: white;
outline-width: 1px;
}

button.combo-options + .#{vars.$bcgov-prefix}--popover {
display: none;
}

.combo-options.#{vars.$bcgov-prefix}--overflow-menu.#{vars.$bcgov-prefix}--overflow-menu--open {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
box-shadow: 0 2px 6px var(--#{vars.$bcgov-prefix}-shadow, rgba(0, 0, 0, 0.3));
background-color: var(--#{vars.$bcgov-prefix}-button-primary-active);
transition: none;
}

.#{vars.$bcgov-prefix}--overflow-menu-options[data-floating-menu-direction=bottom]:not(.#{vars.$bcgov-prefix}--breadcrumb-menu-options)::after {
top: 0;
.combo-button-container {
display: flex;
flex-direction: row;
height: fit-content;

.combo-button {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
padding-right: 1.25rem;
}

.combo-options {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
background: var(--#{vars.$bcgov-prefix}-background-brand);
border-left: solid white 1px;
}

svg,
.#{vars.$bcgov-prefix}--overflow-menu.#{vars.$bcgov-prefix}--overflow-menu--open svg {
fill: white;
}

.combo-options.#{vars.$bcgov-prefix}--overflow-menu:focus {
outline-color: white;
outline-width: 1px;
}

.#{vars.$bcgov-prefix}--popover {
display: none;
}

.#{vars.$bcgov-prefix}--overflow-menu.#{vars.$bcgov-prefix}--overflow-menu--open {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
box-shadow: 0 2px 6px var(--#{vars.$bcgov-prefix}-shadow, rgba(0, 0, 0, 0.3));
background-color: var(--#{vars.$bcgov-prefix}-button-primary-active);
transition: none;
}
}
115 changes: 61 additions & 54 deletions frontend/src/components/SeedlotRegistrationProgress/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,69 +4,76 @@ import {
ProgressIndicator,
ProgressStep
} from '@carbon/react';

import { ProgressIndicatorConfig } from '../../views/Seedlot/SeedlotRegFormClassA/definitions';
import { MEDIUM_SCREEN_WIDTH } from '../../shared-constants/shared-constants';
import useWindowSize from '../../hooks/UseWindowSize';

import './styles.scss';

interface SeedlotRegistrationProgressProps {
progressStatus: ProgressIndicatorConfig;
className?: string;
interactFunction?: Function;
}

const SeedlotRegistrationProgress = ({
progressStatus,
className,
interactFunction
}: SeedlotRegistrationProgressProps) => (
<ProgressIndicator
// Needs to feed it a -1 value otherwise step 1 will stuck at current
currentIndex={-1}
className={className}
spaceEqually
onChange={interactFunction ?? null}
>
<ProgressStep
label="Collection"
secondaryLabel="Step 1"
complete={progressStatus.collection.isComplete}
current={progressStatus.collection.isCurrent}
invalid={progressStatus.collection.isInvalid}
/>
<ProgressStep
label="Ownership"
secondaryLabel="Step 2"
complete={progressStatus.ownership.isComplete}
current={progressStatus.ownership.isCurrent}
invalid={progressStatus.ownership.isInvalid}
/>
<ProgressStep
label="Interim storage"
secondaryLabel="Step 3"
complete={progressStatus.interim.isComplete}
current={progressStatus.interim.isCurrent}
invalid={progressStatus.interim.isInvalid}
/>
<ProgressStep
label="Orchard"
secondaryLabel="Step 4"
complete={progressStatus.orchard.isComplete}
current={progressStatus.orchard.isCurrent}
invalid={progressStatus.orchard.isInvalid}
/>
<ProgressStep
label="Parent tree and SMP"
secondaryLabel="Step 5"
complete={progressStatus.parent.isComplete}
current={progressStatus.parent.isCurrent}
invalid={progressStatus.parent.isInvalid}
/>
<ProgressStep
label="Extraction and storage"
secondaryLabel="Step 6"
complete={progressStatus.extraction.isComplete}
current={progressStatus.extraction.isCurrent}
invalid={progressStatus.extraction.isInvalid}
/>
</ProgressIndicator>
);
}: SeedlotRegistrationProgressProps) => {
const widowSize = useWindowSize();
return (
<ProgressIndicator
// Needs to feed it a -1 value otherwise step 1 will stuck at current
className="spar-seedlot-reg-progress-bar"
currentIndex={-1}
spaceEqually
onChange={interactFunction ?? null}
vertical={widowSize.innerWidth < MEDIUM_SCREEN_WIDTH}
>
<ProgressStep
label="Collection"
secondaryLabel="Step 1"
complete={progressStatus.collection.isComplete}
current={progressStatus.collection.isCurrent}
invalid={progressStatus.collection.isInvalid}
/>
<ProgressStep
label="Ownership"
secondaryLabel="Step 2"
complete={progressStatus.ownership.isComplete}
current={progressStatus.ownership.isCurrent}
invalid={progressStatus.ownership.isInvalid}
/>
<ProgressStep
label="Interim storage"
secondaryLabel="Step 3"
complete={progressStatus.interim.isComplete}
current={progressStatus.interim.isCurrent}
invalid={progressStatus.interim.isInvalid}
/>
<ProgressStep
label="Orchard"
secondaryLabel="Step 4"
complete={progressStatus.orchard.isComplete}
current={progressStatus.orchard.isCurrent}
invalid={progressStatus.orchard.isInvalid}
/>
<ProgressStep
label="Parent tree and SMP"
secondaryLabel="Step 5"
complete={progressStatus.parent.isComplete}
current={progressStatus.parent.isCurrent}
invalid={progressStatus.parent.isInvalid}
/>
<ProgressStep
label="Extraction and storage"
secondaryLabel="Step 6"
complete={progressStatus.extraction.isComplete}
current={progressStatus.extraction.isCurrent}
invalid={progressStatus.extraction.isInvalid}
/>
</ProgressIndicator>
);
};

export default SeedlotRegistrationProgress;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@use '@bcgov-nr/nr-theme/design-tokens/variables.scss' as vars;

.spar-seedlot-reg-progress-bar {
.#{vars.$bcgov-prefix}--progress-step {
min-inline-size: unset;
}
}
29 changes: 29 additions & 0 deletions frontend/src/hooks/UseWindowSize.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { useEffect, useState } from 'react';

type windowSizeType = {
innerWidth: number,
innerHeight: number
}

const useWindowSize = () => {
const [windowSize, setWindowSize] = useState<windowSizeType>({
innerWidth: window.innerWidth,
innerHeight: window.innerHeight
});

useEffect(() => {
const windowSizeHandler = () => {
const { innerWidth, innerHeight } = window;
setWindowSize({ innerWidth, innerHeight });
};
window.addEventListener('resize', windowSizeHandler);

return () => {
window.removeEventListener('resize', windowSizeHandler);
};
}, []);

return windowSize;
};

export default useWindowSize;
Loading

0 comments on commit f18e3f6

Please sign in to comment.