Skip to content

Commit

Permalink
FilterBar responsiveness (#5214)
Browse files Browse the repository at this point in the history
* Use container query to reflow Clear all button

* Adjust FilterButton to wrap text and expand in height

* Convert simple SCSS files to CSS

* Remove box shadow from FilterBar container

* Add instead of overwriting className in ButtonGroup

* Filter buttons go full width on small containers

* Add more toppings to multi-select example

* Avoid display:contents to fix jumpiness on popover open

* CSS tidy ups

* Add more detail to changeset

* Fix container query value
  • Loading branch information
dougmacknz authored Nov 1, 2024
1 parent c5a0383 commit f10f7a4
Show file tree
Hide file tree
Showing 21 changed files with 174 additions and 81 deletions.
10 changes: 10 additions & 0 deletions .changeset/new-pumpkins-sip.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"@kaizen/components": patch
---

FilterBar responsiveness and styling adjustments

- Box shadow removed from filter bar container
- Filter buttons will now expand in height and reflow text as required
- 'Clear all' button now reflows to a new line
- Filter buttons will go to full width on containers 767px in width or below
5 changes: 4 additions & 1 deletion packages/components/src/ButtonGroup/ButtonGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ export const ButtonGroup = ({
if (isFilterButton(button)) {
return React.cloneElement(child, {
children: React.cloneElement(button, {
classNameOverride: buttonClassNames,
classNameOverride: classnames(
button.props.classNameOverride,
buttonClassNames
),
}),
})
}
Expand Down
6 changes: 6 additions & 0 deletions packages/components/src/Filter/Filter/Filter.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/* keep max-width value in sync with other places using this container */
@container filter-bar-wrapper (max-width: 767px) {
.filter {
flex-basis: 100%;
}
}
7 changes: 6 additions & 1 deletion packages/components/src/Filter/Filter/Filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import React, {
useRef,
useState,
} from "react"
import classnames from "classnames"
import { FocusOn } from "react-focus-on"
import { OverrideClassName } from "~components/types/OverrideClassName"
import { FilterPopover } from "./subcomponents/FilterPopover"
import { FilterTriggerRef } from "./types"
import styles from "./Filter.module.css"

export type FilterProps = {
children: React.ReactNode
Expand Down Expand Up @@ -54,7 +56,10 @@ export const Filter = ({
}, [filterButtonRef.current?.triggerRef?.current, onMount])

return (
<div className={classNameOverride} {...restProps}>
<div
className={classnames(styles.filter, classNameOverride)}
{...restProps}
>
{React.cloneElement(trigger, {
ref: filterButtonRef,
})}
Expand Down
24 changes: 24 additions & 0 deletions packages/components/src/Filter/FilterBar/FilterBar.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
.wrapper {
container: filter-bar-wrapper / inline-size;
}

.filterBar {
display: flex;
padding: var(--spacing-8);
border-radius: var(--border-solid-border-radius);
background-color: var(--color-white);
}

/* keep max-width value in sync with other places using this container */
@container filter-bar-wrapper (max-width: 767px) {
.filterBar {
flex-direction: column;
}
}

.filtersContainer {
display: flex;
flex-grow: 1;
flex-wrap: wrap;
gap: var(--spacing-8);
}
19 changes: 0 additions & 19 deletions packages/components/src/Filter/FilterBar/FilterBar.module.scss

This file was deleted.

28 changes: 15 additions & 13 deletions packages/components/src/Filter/FilterBar/FilterBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
import { AddFiltersMenu } from "./subcomponents/AddFiltersMenu"
import { ClearAllButton } from "./subcomponents/ClearAllButton"
import { FiltersValues } from "./types"
import styles from "./FilterBar.module.scss"
import styles from "./FilterBar.module.css"

export type FilterBarProps<ValuesMap extends FiltersValues> = OverrideClassName<
Omit<FilterBarProviderProps<ValuesMap>, "children">
Expand All @@ -27,19 +27,21 @@ export const FilterBar = <ValuesMap extends FiltersValues>({
}: FilterBarProps<ValuesMap>): JSX.Element => (
<FilterBarProvider<ValuesMap> filters={filters} {...providerProps}>
{(activeFilters): JSX.Element => (
<div className={classnames(styles.filterBar, classNameOverride)}>
<div className={styles.filtersContainer}>
{Object.values(activeFilters).map(({ id, Component }) => (
// `id` will always be `string`, but keyof ValuesMap transformed it
<React.Fragment key={id as string}>
{React.cloneElement(Component, { id })}
</React.Fragment>
))}
<AddFiltersMenu />
</div>
<div className={styles.wrapper}>
<div className={classnames(styles.filterBar, classNameOverride)}>
<div className={styles.filtersContainer}>
{Object.values(activeFilters).map(({ id, Component }) => (
// `id` will always be `string`, but keyof ValuesMap transformed it
<React.Fragment key={id as string}>
{React.cloneElement(Component, { id })}
</React.Fragment>
))}
<AddFiltersMenu />
</div>

<div>
<ClearAllButton />
<div>
<ClearAllButton />
</div>
</div>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,11 @@ const filters = [
{ value: "none", label: "None" },
{ value: "pearls", label: "Pearls" },
{ value: "fruit-jelly", label: "Fruit Jelly" },
{ value: "peanuts", label: "Peanuts" },
{ value: "coconut", label: "Coconut" },
{ value: "aloe", label: "Aloe Vera" },
{ value: "mochi", label: "Mini Mochi" },
{ value: "popping-pearls", label: "Popping Pearls" },
]}
>
{(): JSX.Element => (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.filterBarButton {
width: 100%;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { forwardRef, useEffect } from "react"
import classnames from "classnames"
import { FilterTriggerRef } from "~components/Filter/Filter"
import { useFilterBarContext } from "~components/Filter/FilterBar/context/FilterBarContext"
import {
Expand All @@ -7,6 +8,7 @@ import {
FilterButtonRemovable,
} from "~components/Filter/FilterButton"
import { isRefObject } from "~components/utils/isRefObject"
import styles from "./FilterBarButton.module.css"

export type FilterBarButtonProps = FilterButtonProps & {
filterId: string
Expand All @@ -16,25 +18,41 @@ export type FilterBarButtonProps = FilterButtonProps & {
export const FilterBarButton = forwardRef<
FilterTriggerRef,
FilterBarButtonProps
>(({ filterId, isRemovable = false, ...props }, ref): JSX.Element => {
const { hideFilter, focusId, setFocus } = useFilterBarContext()
>(
(
{ filterId, isRemovable = false, classNameOverride, ...props },
ref
): JSX.Element => {
const { hideFilter, focusId, setFocus } = useFilterBarContext()

useEffect(() => {
if (focusId === filterId && isRefObject(ref)) {
ref?.current?.triggerRef?.current?.focus()
setFocus(undefined)
}
}, [focusId])
useEffect(() => {
if (focusId === filterId && isRefObject(ref)) {
ref?.current?.triggerRef?.current?.focus()
setFocus(undefined)
}
}, [focusId])

return isRemovable ? (
<FilterButtonRemovable
ref={ref}
triggerButtonProps={props}
removeButtonProps={{ onClick: () => hideFilter(filterId) }}
/>
) : (
<FilterButton ref={ref} {...props} />
)
})
return isRemovable ? (
<FilterButtonRemovable
ref={ref}
triggerButtonProps={props}
removeButtonProps={{ onClick: () => hideFilter(filterId) }}
classNameOverride={classnames(
classNameOverride,
styles.filterBarButton
)}
/>
) : (
<FilterButton
ref={ref}
classNameOverride={classnames(
classNameOverride,
styles.filterBarButton
)}
{...props}
/>
)
}
)

FilterBarButton.displayName = "FilterBar.Button"
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/* keep max-width value in sync with other places using this container */
@container filter-bar-wrapper (max-width: 767px) {
.filterMultiSelect {
flex-basis: 100%;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from "~components/Filter/FilterMultiSelect"
import { useFilterBarContext } from "../../context/FilterBarContext"
import { checkArraysMatch } from "../../utils/checkArraysMatch"
import styles from "./FilterBarMultiSelect.module.css"

export type FilterBarMultiSelectProps = Omit<
FilterMultiSelectProps,
Expand Down Expand Up @@ -97,6 +98,7 @@ export const FilterBarMultiSelect = ({
items={items}
isOpen={filterState.isOpen}
onOpenChange={(open): void => setFilterOpenState(id, open)}
className={styles.filterMultiSelect}
trigger={(): JSX.Element => {
const triggerProps = {
selectedOptionLabels: filterState.value
Expand All @@ -112,9 +114,13 @@ export const FilterBarMultiSelect = ({
<FilterMultiSelect.RemovableTrigger
{...triggerProps}
onRemove={() => hideFilter(id)}
classNameOverride={styles.triggerButton}
/>
) : (
<FilterMultiSelect.TriggerButton {...triggerProps} />
<FilterMultiSelect.TriggerButton
classNameOverride={styles.triggerButton}
{...triggerProps}
/>
)
}}
triggerRef={buttonRef}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
.filterButton {
gap: var(--spacing-6);
justify-content: space-between;
}

/* keep max-width value in sync with other places using this container */
@container filter-bar-wrapper (max-width: 767px) {
.filterButton {
flex-grow: 1;
}
}

.labelContainer {
display: inline-flex;
flex-wrap: wrap;
}

.hasSelectedValues {
font-weight: bold;
}

.labelSeparator {
margin-inline-end: var(--spacing-6);
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
FilterButtonBase,
FilterButtonBaseProps,
} from "../subcomponents/FilterButtonBase"
import styles from "./FilterButton.module.scss"
import styles from "./FilterButton.module.css"

export type FilterButtonProps = {
label: string
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.filterButtonBase {
height: 100%;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { forwardRef } from "react"
import { useIntl } from "@cultureamp/i18n-react-intl"
import classnames from "classnames"
import { ButtonGroup, ButtonGroupProps } from "~components/ButtonGroup"
import { FilterTriggerRef } from "~components/Filter/Filter"
import { Icon } from "~components/__future__/Icon"
Expand All @@ -11,6 +12,7 @@ import {
FilterButtonBase,
FilterButtonBaseProps,
} from "../subcomponents/FilterButtonBase"
import styles from "./FilterButtonRemovable.module.css"

export type FilterButtonRemovableProps = {
triggerButtonProps: FilterButtonProps & DataAttributes
Expand Down Expand Up @@ -49,7 +51,14 @@ export const FilterButtonRemovable = forwardRef<
<ButtonGroup {...restProps}>
<FilterButton ref={ref} {...triggerButtonProps} />
<Tooltip text={removeButtonLabel} display="inline-block" position="below">
<FilterButtonBase ref={removeButtonRef} {...removeButtonProps}>
<FilterButtonBase
ref={removeButtonRef}
classNameOverride={classnames(
styles.filterButtonBase,
restProps.classNameOverride
)}
{...removeButtonProps}
>
<Icon name="cancel" alt={removeButtonLabel} isFilled />
</FilterButtonBase>
</Tooltip>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
position: relative;
display: inline-flex;
align-items: center;
height: 3rem; // 48px
min-height: 3rem; // 48px
padding: $spacing-sm;
border-width: 0;
border-radius: $border-solid-border-radius;
Expand All @@ -24,7 +24,7 @@
line-height: $typography-button-secondary-line-height;
letter-spacing: $typography-button-secondary-letter-spacing;
color: $color-blue-500;
white-space: nowrap;
text-align: start;

&:hover,
&:active {
Expand Down
Loading

0 comments on commit f10f7a4

Please sign in to comment.