From e9486e3c6dcd1c8cd939010d210a33fd6e311195 Mon Sep 17 00:00:00 2001 From: Miki Date: Tue, 17 Sep 2024 17:17:36 -0700 Subject: [PATCH] Allow limiting the allowed breakpoints when calling `getBreakpoint()` Also: * Limit allowed breakpoints to those provided by the `responsive` prop of Oui*Breadcrumbs Signed-off-by: Miki --- CHANGELOG.md | 2 + src/components/breadcrumbs/breadcrumbs.tsx | 31 ++++++++---- .../simplified_breadcrumbs.tsx | 49 ++++++++++++++++--- src/services/breakpoint.ts | 10 ++-- 4 files changed, 71 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7bc25799b..7e9a9c42e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - Remove scaling of heading elements ([#1389](https://github.com/opensearch-project/oui/pull/1389)) - Make the space between search bar and table rows match the compressed state of the search box ([#1391](https://github.com/opensearch-project/oui/pull/1391)) - Add CSS breakpoints to OuiBreakpointSize ([#1401](https://github.com/opensearch-project/oui/pull/1401)) +- Allow limiting the allowed breakpoints when calling `getBreakpoint()` ([#1401](https://github.com/opensearch-project/oui/pull/1401)) ### 🐛 Bug Fixes @@ -30,6 +31,7 @@ - Remove the unwanted OuiBreadcrumbs focus rectangle ([#1401](https://github.com/opensearch-project/oui/pull/1401)) - Correctly color the OuiBreadcrumbs when focused ([#1401](https://github.com/opensearch-project/oui/pull/1401)) - Display the last breadcrumb in a nested breadcrumb as a normal breadcrumb ([#1401](https://github.com/opensearch-project/oui/pull/1401)) +- Limit allowed breakpoints to those provided by the `responsive` prop of Oui*Breadcrumbs ([#1401](https://github.com/opensearch-project/oui/pull/1401)) ### 🚞 Infrastructure diff --git a/src/components/breadcrumbs/breadcrumbs.tsx b/src/components/breadcrumbs/breadcrumbs.tsx index 872f79a4d..983c7833e 100644 --- a/src/components/breadcrumbs/breadcrumbs.tsx +++ b/src/components/breadcrumbs/breadcrumbs.tsx @@ -196,12 +196,28 @@ export const OuiBreadcrumbs: FunctionComponent = ({ max = 5, ...rest }) => { + // Use the default object if they simply passed `true` for responsive + const responsiveObject = + typeof responsive === 'object' ? responsive : responsiveDefault; + + const allowedBreakpoints = responsive + ? (Object.keys(responsiveObject) as OuiBreakpointSize[]) + : undefined; + const [currentBreakpoint, setCurrentBreakpoint] = useState( - getBreakpoint(typeof window === 'undefined' ? -Infinity : window.innerWidth) + getBreakpoint( + typeof window === 'undefined' ? -Infinity : window.innerWidth, + undefined, + allowedBreakpoints + ) ); const functionToCallOnWindowResize = throttle(() => { - const newBreakpoint = getBreakpoint(window.innerWidth); + const newBreakpoint = getBreakpoint( + window.innerWidth, + undefined, + allowedBreakpoints + ); if (newBreakpoint !== currentBreakpoint) { setCurrentBreakpoint(newBreakpoint); } @@ -215,7 +231,7 @@ export const OuiBreadcrumbs: FunctionComponent = ({ return () => { window.removeEventListener('resize', functionToCallOnWindowResize); }; - }, [responsive, functionToCallOnWindowResize]); + }, [responsive, responsiveObject, functionToCallOnWindowResize]); const isInPopover = className === 'ouiBreadcrumbs__inPopover'; @@ -288,19 +304,14 @@ export const OuiBreadcrumbs: FunctionComponent = ({ return {wall}; }); - // Use the default object if they simply passed `true` for responsive - const responsiveObject = - typeof responsive === 'object' ? responsive : responsiveDefault; - // The max property collapses any breadcrumbs past the max quantity. // This is the same behavior we want for responsiveness. // So calculate the max value based on the combination of `max` and `responsive` // First, calculate the responsive max value const responsiveMax = - responsive && responsiveObject[currentBreakpoint as OuiBreakpointSize] - ? responsiveObject[currentBreakpoint as OuiBreakpointSize] - : null; + (responsive && responsiveObject[currentBreakpoint as OuiBreakpointSize]) || + null; // Second, if both max and responsiveMax are set, use the smaller of the two. Otherwise, use the one that is set. const calculatedMax: OuiBreadcrumbsProps['max'] = diff --git a/src/components/breadcrumbs/simplified_breadcrumbs/simplified_breadcrumbs.tsx b/src/components/breadcrumbs/simplified_breadcrumbs/simplified_breadcrumbs.tsx index 614245734..4dc790201 100644 --- a/src/components/breadcrumbs/simplified_breadcrumbs/simplified_breadcrumbs.tsx +++ b/src/components/breadcrumbs/simplified_breadcrumbs/simplified_breadcrumbs.tsx @@ -9,6 +9,25 @@ * GitHub history for details. */ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Fragment, FunctionComponent, @@ -155,12 +174,28 @@ export const OuiSimplifiedBreadcrumbs: FunctionComponent { + // Use the default object if they simply passed `true` for responsive + const responsiveObject = + typeof responsive === 'object' ? responsive : responsiveDefault; + + const allowedBreakpoints = responsive + ? (Object.keys(responsiveObject) as OuiBreakpointSize[]) + : undefined; + const [currentBreakpoint, setCurrentBreakpoint] = useState( - getBreakpoint(typeof window === 'undefined' ? -Infinity : window.innerWidth) + getBreakpoint( + typeof window === 'undefined' ? -Infinity : window.innerWidth, + undefined, + allowedBreakpoints + ) ); const functionToCallOnWindowResize = throttle(() => { - const newBreakpoint = getBreakpoint(window.innerWidth); + const newBreakpoint = getBreakpoint( + window.innerWidth, + undefined, + allowedBreakpoints + ); if (newBreakpoint !== currentBreakpoint) { setCurrentBreakpoint(newBreakpoint); } @@ -174,7 +209,9 @@ export const OuiSimplifiedBreadcrumbs: FunctionComponent { window.removeEventListener('resize', functionToCallOnWindowResize); }; - }, [responsive, functionToCallOnWindowResize]); + }, [responsive, responsiveObject, functionToCallOnWindowResize]); + + const isInPopover = className === 'ouiSimplifiedBreadcrumbs__inPopover'; const breadcrumbElements = breadcrumbs.map((breadcrumb, index) => { const { @@ -213,7 +250,7 @@ export const OuiSimplifiedBreadcrumbs: FunctionComponent {text} @@ -260,10 +297,6 @@ export const OuiSimplifiedBreadcrumbs: FunctionComponent breakpoints[key] <= width); + // Find the breakpoint (key) whose value is <= windowWidth starting with the largest first + return keysOf(BREAKPOINTS).find( + (key) => allowedBreakpoints.includes(key) && breakpoints[key] <= width + ); } /**