Skip to content

Commit

Permalink
Fixed some bugs and accessibility issues
Browse files Browse the repository at this point in the history
This commit includes a fix for the bug when moving questions back and forth and also a bug with the list of page options. This update also addresses some accessibility issues.
  • Loading branch information
natashapl committed Jul 26, 2024
1 parent bca169d commit 02dfdef
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 44 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, {
PropsWithChildren,
ReactElement,
useMemo,
useEffect,
useState,
useRef,
Expand Down Expand Up @@ -34,8 +35,6 @@ export const PatternEditActions = ({ children }: PatternEditActionsProps) => {
}));
const [targetPage, setTargetPage] = useState('');
const [moveToPosition, setMoveToPosition] = useState('');
const [isPatternInFieldset, setIsPatternInFieldset] = useState(false);
const [isFieldset, setIsFieldset] = useState(false);
const [dropdownOpen, setDropdownOpen] = useState(false);

const dropdownRef = useRef<HTMLDivElement>(null);
Expand All @@ -49,44 +48,54 @@ export const PatternEditActions = ({ children }: PatternEditActionsProps) => {
);
const movePatternToPage = useFormManagerStore(state => state.movePattern);
const focusPatternId = useFormManagerStore(state => state.focus?.pattern.id);
const focusPatternType = useFormManagerStore(
state => state.focus?.pattern.type
);
const focusPatternType = useFormManagerStore(state => state.focus?.pattern.type);

useEffect(() => {
if (focusPatternId) {
// Check if the focused pattern is inside a fieldset
const fieldset = patterns.find(
p => p.type === 'fieldset' && p.data.patterns.includes(focusPatternId)
);
if (fieldset && !isPatternInFieldset) {
setIsPatternInFieldset(true);
} else if (!fieldset && isPatternInFieldset) {
setIsPatternInFieldset(false);
}
}
}, [focusPatternId, patterns, isPatternInFieldset]);
const isPatternInFieldset = useMemo(() => {
if (!focusPatternId) return false;
return patterns.some(
p => p.type === 'fieldset' && p.data.patterns.includes(focusPatternId)
);
}, [focusPatternId, patterns]);

useEffect(() => {
// Check if the focus pattern type is fieldset
setIsFieldset(focusPatternType === 'fieldset');
}, [focusPatternType]);
const isFieldset = focusPatternType === 'fieldset';

const useAvailablePages = (focusPatternId: string | undefined) => {
const pages = useFormManagerStore(state =>
Object.values(state.session.form.patterns).filter(p => p.type === 'page')
);

const currentPageIndex = pages.findIndex(page =>
page.data.patterns.includes(focusPatternId || '')
);

const page1Count = pages.reduce((count, page) => count + (page.data.title === 'Page 1' ? 1 : 0), 0);

const availablePages: PageWithLabel[] =
page1Count > 1
? pages.slice(1).map((page, index) => {
if (index + 1 === currentPageIndex) {
return { ...page, specialLabel: 'Current page' };
}
return page;
})
: pages.map((page, index) => {
if (index === currentPageIndex) {
return { ...page, specialLabel: 'Current page' };
}
return page;
});

return availablePages;
};

const availablePages = useAvailablePages(focusPatternId);

// Find the index of the current page
const currentPageIndex = pages.findIndex(page =>
page.data.patterns.includes(focusPatternId || '')
);

const sourcePage = pages[currentPageIndex]?.id;

// Remove the first entry and include the current page with a special label
const availablePages: PageWithLabel[] = pages.slice(1).map((page, index) => {
if (index + 1 === currentPageIndex) {
return { ...page, specialLabel: 'Current page' };
}
return page;
});

const handleMovePattern = () => {
if (focusPatternId && targetPage) {
const isPageMove = focusPatternType === 'page';
Expand All @@ -113,15 +122,24 @@ export const PatternEditActions = ({ children }: PatternEditActionsProps) => {
setDropdownOpen(false);
}
};
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === 'Escape') {
setDropdownOpen(false);
buttonRef.current?.focus();
}
};

useEffect(() => {
if (dropdownOpen) {
document.addEventListener('mousedown', handleClickOutside);
dropdownRef.current?.addEventListener('keydown', handleKeyDown);
} else {
document.removeEventListener('mousedown', handleClickOutside);
dropdownRef.current?.removeEventListener('keydown', handleKeyDown);
}
return () => {
document.removeEventListener('mousedown', handleClickOutside);
dropdownRef.current?.removeEventListener('keydown', handleKeyDown);
};
}, [dropdownOpen]);

Expand Down Expand Up @@ -163,6 +181,8 @@ export const PatternEditActions = ({ children }: PatternEditActionsProps) => {
className="usa-button--outline usa-button--unstyled margin-right-0 padding-top-1 padding-left-05 padding-bottom-05"
type="button"
ref={buttonRef}
aria-haspopup="true"
aria-expanded={dropdownOpen ? "true" : "false"}
onClick={event => {
event.preventDefault();
toggleDropdown();
Expand All @@ -184,7 +204,10 @@ export const PatternEditActions = ({ children }: PatternEditActionsProps) => {
</button>
</p>
{dropdownOpen && (
<div className={`${styles.dropDown} padding-2`}>
<div
className={`${styles.dropDown} padding-2`}
tabIndex={-1}
>
<div
className={`${styles.moveToPagePosition} margin-bottom-1`}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@
max-width: 21rem;
}

.draggableListWrapper:has(.patternActionWrapper .dropDown select:focus),
.draggableListWrapper:has(.patternActionWrapper .dropDown:focus ) {
outline: 0;
}

.patternActionWrapper .dropdownMenu div {
padding: 8px;
cursor: pointer;
Expand Down
31 changes: 19 additions & 12 deletions packages/forms/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,26 +220,31 @@ export const movePatternBetweenPages = (
position: string,
isPageMove: boolean = false
): Blueprint => {

const sourcePage = bp.patterns[sourcePageId] as PagePattern;
const targetPage = bp.patterns[targetPageId] as PagePattern;

if (!sourcePage || !targetPage) {
throw new Error('Source or target page not found.');
}

if (sourcePage.type !== 'page' || targetPage.type !== 'page') {
throw new Error('Pattern is not a page.');
}

let updatedSourcePatterns;
let updatedTargetPatterns;

const sourcePagePatterns = sourcePage.data.patterns;
const indexToRemove = sourcePagePatterns.indexOf(patternId);
const newPattern = sourcePagePatterns.splice(indexToRemove, 1).toString();
let updatedSourcePatterns: PatternId[];
let updatedTargetPatterns: PatternId[];

if (isPageMove) {
// Moving a pattern within the source page
const sourcePagePatterns = sourcePage.data.patterns;
const indexToRemove = sourcePagePatterns.indexOf(patternId);

if (indexToRemove === -1) {
throw new Error('Pattern ID not found in the source page.');
throw new Error(`Pattern ID ${patternId} not found in the source page.`);
}

const newPattern = sourcePagePatterns.splice(indexToRemove, 1).toString();

updatedSourcePatterns = [
...sourcePagePatterns.slice(0, indexToRemove),
...sourcePagePatterns.slice(indexToRemove + 1),
Expand All @@ -250,14 +255,15 @@ export const movePatternBetweenPages = (
? [newPattern, ...updatedSourcePatterns]
: [...updatedSourcePatterns, newPattern];
} else {
// Moving a pattern between pages
const indexToRemove = sourcePage.data.patterns.indexOf(patternId);

if (indexToRemove === -1) {
throw new Error('Pattern ID not found in the source page.');
throw new Error(`Pattern ID ${patternId} not found in the source page.`);
}

updatedSourcePatterns = [
...sourcePagePatterns.slice(0, indexToRemove),
...sourcePagePatterns.slice(indexToRemove + 1),
...sourcePage.data.patterns.slice(0, indexToRemove),
...sourcePage.data.patterns.slice(indexToRemove + 1),
];

updatedTargetPatterns =
Expand Down Expand Up @@ -288,6 +294,7 @@ export const movePatternBetweenPages = (
};
};


export const addPatternToFieldset = (
bp: Blueprint,
fieldsetPatternId: PatternId,
Expand Down

0 comments on commit 02dfdef

Please sign in to comment.