diff --git a/apps/client/src/common/components/view-params-editor/ViewParamsEditor.module.scss b/apps/client/src/common/components/view-params-editor/ViewParamsEditor.module.scss index 6de2400e0..919e0d8ef 100644 --- a/apps/client/src/common/components/view-params-editor/ViewParamsEditor.module.scss +++ b/apps/client/src/common/components/view-params-editor/ViewParamsEditor.module.scss @@ -1,6 +1,6 @@ .drawerFooter { display: flex; - justify-content: end; + justify-content: end; gap: $section-spacing; button { @@ -25,39 +25,11 @@ } } -.label { - font-size: $inner-section-text-size; - color: $label-gray; +.sectionList { display: flex; flex-direction: column; - gap: 0.25rem; -} - -.section { - color: $ui-white; - font-size: 1rem; - - &:not(:first-child) { - margin-top: 2rem; - } -} - -.fieldSet { - display: flex; - padding: $section-spacing 0; - flex-direction: column; - gap: $element-spacing; - margin-left: 0.5rem; -} - -.title { - font-size: $inner-section-text-size; - display: block; - width: 100%; -} - -.description { - font-size: $inner-section-text-size; - display: block; - color: $modal-note-color; + min-height: 100%; + gap: 2rem; + overflow-y: scroll; + padding-right: 0.5rem; } diff --git a/apps/client/src/common/components/view-params-editor/ViewParamsEditor.tsx b/apps/client/src/common/components/view-params-editor/ViewParamsEditor.tsx index 65363e08c..a91ff18d5 100644 --- a/apps/client/src/common/components/view-params-editor/ViewParamsEditor.tsx +++ b/apps/client/src/common/components/view-params-editor/ViewParamsEditor.tsx @@ -15,8 +15,8 @@ import { IoAlertCircle } from '@react-icons/all-files/io5/IoAlertCircle'; import useViewSettings from '../../../common/hooks-query/useViewSettings'; -import ParamInput from './ParamInput'; -import { isSection, ViewOption } from './types'; +import { ViewOption } from './types'; +import ViewParamsSection from './ViewParamsSection'; import style from './ViewParamsEditor.module.scss'; @@ -40,15 +40,15 @@ const getURLSearchParamsFromObj = (paramsObj: ViewParamsObj, paramFields: ViewOp // Convert paramFields to an object that contains default values const defaultValues: Record = {}; - paramFields.forEach((option) => { - if (!isSection(option)) { + paramFields.forEach((section) => { + section.options.forEach((option) => { defaultValues[option.id] = String(option.defaultValue); - } - // extract persisted values - if ('type' in option && option.type === 'persist') { - newSearchParams.set(option.id, option.value); - } + // extract persisted values + if ('type' in option && option.type === 'persist') { + newSearchParams.set(option.id, option.value); + } + }); }); // compare which values are different from the default values @@ -138,30 +138,15 @@ export default function ViewParamsEditor({ viewOptions }: EditFormDrawerProps) { This view style is being modified by a custom CSS file.
)} -
- {viewOptions.map((option) => { - if (isSection(option)) { - return ( -
- {option.section} -
- ); - } - - if (option.type === 'persist') { - return null; - } - - return ( -
- -
- ); - })} + + {viewOptions.map((section) => ( + + ))} diff --git a/apps/client/src/common/components/view-params-editor/ViewParamsSection.module.scss b/apps/client/src/common/components/view-params-editor/ViewParamsSection.module.scss new file mode 100644 index 000000000..7959d3254 --- /dev/null +++ b/apps/client/src/common/components/view-params-editor/ViewParamsSection.module.scss @@ -0,0 +1,50 @@ +.section { + color: $ui-white; + font-size: 1rem; +} + +.sectionHeader { + display: flex; + justify-content: space-between; + align-items: center; + height: 2rem; + + &.collapsible { + cursor: pointer; + + &:hover { + border-bottom: 1px solid $white-10; + } + } +} + +.label { + margin-top: $section-spacing; + font-size: $inner-section-text-size; + color: $label-gray; + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.title { + font-size: $inner-section-text-size; + display: block; + width: 100%; +} + +.description { + font-size: $inner-section-text-size; + display: block; + color: $modal-note-color; +} + +.closed { + transition: rotate $transition-time-feedback; + rotate: 0deg; +} + +.open { + transition: rotate $transition-time-feedback; + rotate: 180deg; +} diff --git a/apps/client/src/common/components/view-params-editor/ViewParamsSection.tsx b/apps/client/src/common/components/view-params-editor/ViewParamsSection.tsx new file mode 100644 index 000000000..e72d839e5 --- /dev/null +++ b/apps/client/src/common/components/view-params-editor/ViewParamsSection.tsx @@ -0,0 +1,54 @@ +import { useLocalStorage } from '@mantine/hooks'; +import { IoChevronDown } from '@react-icons/all-files/io5/IoChevronDown'; + +import { cx } from '../../utils/styleUtils'; + +import ParamInput from './ParamInput'; +import { type ParamField } from './types'; + +import style from './ViewParamsSection.module.scss'; + +interface ViewParamsSectionProps { + title: string; + collapsible?: boolean; + options: ParamField[]; +} + +export default function ViewParamsSection(props: ViewParamsSectionProps) { + const { title, collapsible, options } = props; + + const [collapsed, setCollapsed] = useLocalStorage({ key: `params-${title}`, defaultValue: false }); + + const handleCollapse = () => { + if (collapsible) { + setCollapsed((prev) => !prev); + } + }; + + return ( +
+
+ {title} + {collapsible && } +
+ + {!collapsed && ( + <> + {options.map((option) => { + if (option.type === 'persist') { + return null; + } + + return ( + + ); + })} + + )} +
+ ); +} diff --git a/apps/client/src/common/components/view-params-editor/types.ts b/apps/client/src/common/components/view-params-editor/types.ts index 0bcac397d..18d5310ec 100644 --- a/apps/client/src/common/components/view-params-editor/types.ts +++ b/apps/client/src/common/components/view-params-editor/types.ts @@ -1,7 +1,3 @@ -type ParamSection = { - section: string; -}; - type BaseField = { id: string; title: string; @@ -28,11 +24,9 @@ type PersistedField = { type: 'persist'; defaultValue?: string; value: string }; export type ParamField = BaseField & (OptionsField | MultiOptionsField | StringField | NumberField | BooleanField | ColourField | PersistedField); -export type ViewOption = ParamSection | ParamField; -/** - * Type assertion utility checks whether an entry is a section separator - */ -export function isSection(entry: ViewOption): entry is ParamSection { - return 'section' in entry; -} +export type ViewOption = { + title: string; + options: ParamField[]; + collapsible?: boolean; +};