Skip to content

Commit

Permalink
interactive method selector for offline docs
Browse files Browse the repository at this point in the history
  • Loading branch information
seungpark committed Dec 26, 2024
1 parent fd1b162 commit 703405b
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 11 deletions.
21 changes: 19 additions & 2 deletions src/components/MethodSelector/MethodOptionContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,27 @@ import React from 'react';
import { css, cx } from '@leafygreen-ui/emotion';
import ComponentFactory from '../ComponentFactory';
import { theme } from '../../theme/docsTheme';
import { isOfflineDocsBuild } from '../../utils/is-offline-docs-build';
import { OFFLINE_CONTENT_CLASSNAME } from '../../utils/head-scripts/offline-ui/method-selector';
import MethodDescription from './MethodDescription';

const METHOD_DESCRIPTION_NAME = 'method-description';

const displayStyle = (isSelectedOption) => css`
${!isSelectedOption && 'display: none;'}
${!isSelectedOption && !isOfflineDocsBuild && 'display: none;'}
`;

export const getTestId = (optionId) => `method-option-content-${optionId}`;

const containerStyle = css`
margin-top: ${theme.size.default};
${isOfflineDocsBuild &&
`
&[aria-expanded=false] {
display: none;
}
`}
`;

const MethodOptionContent = ({
Expand All @@ -27,7 +36,15 @@ const MethodOptionContent = ({
const methodDescription = children.find(({ name }) => name === METHOD_DESCRIPTION_NAME);

return (
<div className={cx(containerStyle, displayStyle(isSelectedOption))} data-testid={getTestId(id)}>
<div
aria-expanded={isSelectedOption}
className={cx(
containerStyle,
displayStyle(isSelectedOption),
isOfflineDocsBuild ? OFFLINE_CONTENT_CLASSNAME : ''
)}
data-testid={getTestId(id)}
>
{methodDescription && <MethodDescription nodeData={methodDescription} />}
{children.map((node, index) => {
if (node.name === METHOD_DESCRIPTION_NAME) return null;
Expand Down
23 changes: 17 additions & 6 deletions src/components/MethodSelector/MethodSelector.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { theme } from '../../theme/docsTheme';
import { getLocalValue, setLocalValue } from '../../utils/browser-storage';
import { reportAnalytics } from '../../utils/report-analytics';
import { ContentsContext } from '../Contents/contents-context';
import { isOfflineDocsBuild } from '../../utils/is-offline-docs-build';
import { OFFLINE_CLASSNAME } from '../../utils/head-scripts/offline-ui/method-selector';
import MethodOptionContent from './MethodOptionContent';

const STORAGE_KEY = 'methodSelectorId';
Expand Down Expand Up @@ -129,7 +131,7 @@ const MethodSelector = ({ nodeData: { children } }) => {

return (
<>
<div className={optionsContainer}>
<div className={cx(optionsContainer, isOfflineDocsBuild ? OFFLINE_CLASSNAME : '')}>
<RadioBoxGroup
className={cx(radioBoxGroupStyle(children.length))}
size={'full'}
Expand All @@ -146,17 +148,26 @@ const MethodSelector = ({ nodeData: { children } }) => {
>
{children.map(({ options: { title, id } }, index) => {
return (
<RadioBox key={id} className={cx(radioBoxStyle)} value={`${id}-${index}`} checked={selectedMethod === id}>
<RadioBox
id={id}
key={id}
className={cx(radioBoxStyle)}
value={`${id}-${index}`}
checked={selectedMethod === id}
>
{title}
</RadioBox>
);
})}
</RadioBoxGroup>
{/* Keep separate div for triangle to allow for relative positioning */}
<div className={cx(lineStyle)}>
<div className={cx(triangleStyle(optionCount, selectedIdx))} />
<hr className={cx(hrStyle)} />
</div>
{/* Offline docs will not have this triangle indicator */}
{!isOfflineDocsBuild && (
<div className={cx(lineStyle)}>
<div className={cx(triangleStyle(optionCount, selectedIdx))} />
<hr className={cx(hrStyle)} />
</div>
)}
</div>
{children.map((child, index) => {
if (child.name !== 'method-option') return null;
Expand Down
12 changes: 9 additions & 3 deletions src/utils/head-scripts/offline-ui/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import bindTabUI from './tabs';
import bindCollapsibleUI from './collapsible';
import updateSidenavHeight from './sidenav';
import bindTabsSelectorsUI from './tabs-selectors';
import bindMethodSelectorUI from './method-selector';

const OFFLINE_UI_CLASSNAME = 'snooty-offline-ui';

const getScript = ({ key, fn }) => (
Expand All @@ -13,6 +15,10 @@ const getScript = ({ key, fn }) => (
/>
);

export const OFFLINE_HEAD_SCRIPTS = [bindTabUI, updateSidenavHeight, bindTabsSelectorsUI, bindCollapsibleUI].map(
(fn, idx) => getScript({ key: `offline-docs-ui-${idx}`, fn })
);
export const OFFLINE_HEAD_SCRIPTS = [
bindTabUI,
updateSidenavHeight,
bindTabsSelectorsUI,
bindCollapsibleUI,
bindMethodSelectorUI,
].map((fn, idx) => getScript({ key: `offline-docs-ui-${idx}`, fn }));
45 changes: 45 additions & 0 deletions src/utils/head-scripts/offline-ui/method-selector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
function bindMethodSelectorUI() {
const onContentLoaded = () => {
try {
// find all method selectors
const methodSelectorComponents = document.querySelectorAll('.offline-method-selector');
for (const methodSelectorComponent of methodSelectorComponents) {
// find the button group role=group
const buttonGroup = methodSelectorComponent.querySelector('[role=group]');

// find the radio box inputs within button group and bind action
const buttons = buttonGroup?.querySelectorAll('input') ?? [];
console.log('buttons');
console.log(buttons);

// find all the content within method selectors
const contentDivs =
methodSelectorComponent.parentElement?.querySelectorAll('.offline-method-selector-content') ?? [];

// for each input, find value `{name}-{index}` ie. `driver-0`
// find data-testid=[method-option-content-{name}] and show
for (let idx = 0; idx < buttons.length; idx++) {
const button = buttons[idx];
button.addEventListener('click', (e) => {
console.log('click');
const id = (button.getAttribute('value') || '').split('-')[0];
console.log('id ', id);
const targetTestId = 'method-option-content-' + id;
for (const contentDiv of contentDivs) {
contentDiv.setAttribute('aria-expanded', targetTestId === contentDiv.getAttribute('data-testid'));
}
});
}
}
} catch (e) {
console.error(e);
}
};

document.addEventListener('DOMContentLoaded', onContentLoaded, false);
}

export default bindMethodSelectorUI;

export const OFFLINE_CLASSNAME = `offline-method-selector`;
export const OFFLINE_CONTENT_CLASSNAME = `offline-method-selector-content`;

0 comments on commit 703405b

Please sign in to comment.