Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ import { axe, formatRules } from "../../test/accessibility/axe-helper";
import DxcBreadcrumbs from "./Breadcrumbs";
import { disabledRules as rules } from "../../test/accessibility/rules/specific/breadcrumbs/disabledRules";

(global as any).ResizeObserver = class ResizeObserver {
observe() {}

unobserve() {}

disconnect() {}
};

const disabledRules = {
rules: formatRules(rules),
};
Expand Down
2 changes: 1 addition & 1 deletion packages/lib/src/dropdown/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ const DxcDropdown = ({

const triggerRef = useRef<HTMLButtonElement | null>(null);
const menuRef = useRef<HTMLUListElement | null>(null);
const width = useWidth(triggerRef.current);
const width = useWidth(triggerRef);

const handleOnOpenMenu = () => {
changeIsOpen(true);
Expand Down
8 changes: 8 additions & 0 deletions packages/lib/src/header/Header.accessibility.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ import DxcFlex from "../flex/Flex";
import DxcLink from "../link/Link";
import DxcHeader from "./Header";

(global as any).ResizeObserver = class ResizeObserver {
observe() {}

unobserve() {}

disconnect() {}
};

const disabledRules = {
rules: formatRules(rules),
};
Expand Down
18 changes: 18 additions & 0 deletions packages/lib/src/paginator/Paginator.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ export default {
component: DxcPaginator,
} as Meta<typeof DxcPaginator>;

const customViewports = {
resizedScreen: {
name: "Custom viewport",
styles: {
width: "400px",
height: "1600px",
},
},
};

const Paginator = () => (
<>
<ExampleContainer>
Expand Down Expand Up @@ -67,3 +77,11 @@ type Story = StoryObj<typeof DxcPaginator>;
export const Chromatic: Story = {
render: Paginator,
};

export const ResponsivePaginator: Story = {
render: Paginator,
parameters: {
viewport: { viewports: customViewports, defaultViewport: "resizedScreen" },
chromatic: { viewports: [400] },
},
};
119 changes: 66 additions & 53 deletions packages/lib/src/paginator/Paginator.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,65 @@
import { useContext } from "react";
import { useContext, useRef } from "react";
import styled from "@emotion/styled";
import DxcButton from "../button/Button";
import DxcSelect from "../select/Select";
import PaginatorPropsType from "./types";
import { HalstackLanguageContext } from "../HalstackContext";
import { responsiveSizes } from "../common/variables";
import useWidth from "../utils/useWidth";
import { isResponsive } from "./utils";

const DxcPaginatorContainer = styled.div<{ width: number }>`
display: flex;
justify-content: ${({ width }) => (isResponsive(width) ? "center" : "flex-end")};
flex-wrap: ${({ width }) => (isResponsive(width) ? "wrap" : "nowrap")};
gap: ${({ width }) => (isResponsive(width) ? "var(--spacing-gap-s)" : "0")};
align-items: center;
width: 100%;
min-height: 48px;
box-sizing: border-box;
font-family: var(--typography-font-family);
font-size: var(--typography-label-m);
font-weight: var(--typography-label-regular);
background-color: var(--color-bg-neutral-lighter);
color: var(--color-fg-neutral-dark);
padding: var(--spacing-padding-xs) var(--spacing-padding-xl);
`;

const ItemsPerPageContainer = styled.span<{ width: number }>`
display: flex;
align-items: center;
gap: var(--spacing-gap-s);
margin-right: ${({ width }) => (isResponsive(width) ? "0" : "var(--spacing-gap-ml)")};
`;

const SelectContainer = styled.div`
min-width: 6.25rem;
`;

const TotalItemsContainer = styled.span<{ width: number }>`
margin-right: ${({ width }) => (isResponsive(width) ? "0" : "var(--spacing-gap-xxl)")};
`;

const GoToPageContainer = styled.div`
display: flex;
align-items: center;
gap: var(--spacing-gap-ml);
`;

const ButtonsContainer = styled.div`
display: flex;
align-items: center;
gap: var(--spacing-gap-s);
flex-shrink: 0;
`;

const PageToSelectContainer = styled.span<{ width: number }>`
display: flex;
align-items: center;
gap: var(--spacing-gap-s);
flex-shrink: 0;
flex-wrap: wrap;
`;

const DxcPaginator = ({
currentPage = 1,
Expand All @@ -26,58 +82,13 @@ const DxcPaginator = ({

const translatedLabels = useContext(HalstackLanguageContext);

const DxcPaginatorContainer = styled.div`
display: flex;
justify-content: flex-end;
align-items: center;
width: 100%;
min-height: 48px;
box-sizing: border-box;
font-family: var(--typography-font-family);
font-size: var(--typography-label-m);
font-weight: var(--typography-label-regular);
background-color: var(--color-bg-neutral-lighter);
color: var(--color-fg-neutral-dark);
padding: var(--spacing-padding-xs) var(--spacing-padding-xl);
`;

const ItemsPerPageContainer = styled.span`
display: flex;
align-items: center;
gap: var(--spacing-gap-s);
margin-right: var(--spacing-gap-ml);
`;

const SelectContainer = styled.div`
min-width: 6.25rem;
`;

const TotalItemsContainer = styled.span`
margin-right: var(--spacing-gap-xxl);
`;

const GoToPageContainer = styled.div`
display: flex;
align-items: center;
gap: var(--spacing-gap-ml);
`;

const ButtonsContainer = styled.div`
display: flex;
align-items: center;
gap: var(--spacing-gap-s);
`;

const PageToSelectContainer = styled.span`
display: flex;
align-items: center;
gap: var(--spacing-gap-s);
`;
const containerRef = useRef<HTMLDivElement | null>(null);
const width = useWidth(containerRef);

return (
<DxcPaginatorContainer>
<DxcPaginatorContainer ref={containerRef} width={width}>
{itemsPerPageOptions && (
<ItemsPerPageContainer>
<ItemsPerPageContainer width={width}>
<span>{translatedLabels.paginator.itemsPerPageText}</span>
<SelectContainer>
<DxcSelect
Expand All @@ -95,7 +106,7 @@ const DxcPaginator = ({
</SelectContainer>
</ItemsPerPageContainer>
)}
<TotalItemsContainer>
<TotalItemsContainer width={width}>
{translatedLabels.paginator.minToMaxOfText(minItemsPerPage, maxItemsPerPage, totalItems)}
</TotalItemsContainer>
<GoToPageContainer>
Expand Down Expand Up @@ -127,8 +138,10 @@ const DxcPaginator = ({
</ButtonsContainer>
)}
{showGoToPage ? (
<PageToSelectContainer>
<span>{translatedLabels.paginator.goToPageText} </span>
<PageToSelectContainer width={width}>
{(width >= Number(responsiveSizes.small) * 16 || !onPageChange) && (
<span>{translatedLabels.paginator.goToPageText}</span>
)}
<SelectContainer>
<DxcSelect
options={Array.from(Array(totalPages), (e, num) => ({
Expand Down
3 changes: 3 additions & 0 deletions packages/lib/src/paginator/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { responsiveSizes } from "../common/variables";

export const isResponsive = (width: number) => width && width <= Number(responsiveSizes.medium) * 16;
2 changes: 1 addition & 1 deletion packages/lib/src/select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ const DxcSelect = forwardRef<RefType, SelectPropsType>(
const selectRef = useRef<HTMLDivElement | null>(null);
const selectSearchInputRef = useRef<HTMLInputElement | null>(null);

const width = useWidth(selectRef.current);
const width = useWidth(selectRef);
const translatedLabels = useContext(HalstackLanguageContext);

const optionalItem = useMemo(() => ({ label: placeholder, value: "" }), [placeholder]);
Expand Down
2 changes: 1 addition & 1 deletion packages/lib/src/tabs/Tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ const DxcTabs = ({ children, iconPosition = "left", margin, tabIndex = 0 }: Tabs
const refTabListContainer = useRef<HTMLDivElement | null>(null);
const refTabList = useRef<HTMLDivElement | null>(null);
const translatedLabels = useContext(HalstackLanguageContext);
const viewWidth = useWidth(refTabList.current);
const viewWidth = useWidth(refTabList);
const contextValue = useMemo(() => {
const focusedChild = innerFocusIndex != null ? childrenArray[innerFocusIndex] : null;
return {
Expand Down
2 changes: 1 addition & 1 deletion packages/lib/src/text-input/TextInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ const DxcTextInput = forwardRef<RefType, TextInputPropsType>(
const [isAutosuggestError, changeIsAutosuggestError] = useState(false);
const [filteredSuggestions, changeFilteredSuggestions] = useState<string[]>([]);
const [visualFocusIndex, changeVisualFocusIndex] = useState(-1);
const width = useWidth(inputContainerRef.current);
const width = useWidth(inputContainerRef);

const getNumberErrorMessage = (checkedValue: number) =>
numberInputContext?.minNumber != null && checkedValue < numberInputContext?.minNumber
Expand Down
10 changes: 6 additions & 4 deletions packages/lib/src/utils/useWidth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import { useLayoutEffect, useState } from "react";

/**
* Custom hook to get the width of an element and keep it updated when it changes.
* @param target
* @returns
* @param target
* @returns
*/
const useWidth = <T extends Element>(target: T | null) => {
const useWidth = <T extends Element>(ref: React.RefObject<T>) => {
const [width, setWidth] = useState(0);

useLayoutEffect(() => {
const target = ref?.current;

if (target != null) {
setWidth(target.getBoundingClientRect().width);

Expand All @@ -23,7 +25,7 @@ const useWidth = <T extends Element>(target: T | null) => {
triggerObserver.unobserve(target);
};
}
}, [target]);
}, []);

return width;
};
Expand Down