Skip to content

Commit

Permalink
Merge branch 'main' into feat/public-layout-component
Browse files Browse the repository at this point in the history
  • Loading branch information
georgylobko authored Jan 24, 2025
2 parents f61d5c0 + 76a85a0 commit 63e9618
Show file tree
Hide file tree
Showing 14 changed files with 288 additions and 46 deletions.
89 changes: 84 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
"@types/glob": "^7.2.0",
"@types/jest": "^29.5.13",
"@types/lodash": "^4.14.176",
"@types/node": "^18.18.5",
"@types/node": "^20.17.14",
"@types/react": "^16.14.20",
"@types/react-dom": "^16.9.14",
"@types/react-router": "^5.1.18",
Expand Down
22 changes: 22 additions & 0 deletions pages/multiselect/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,25 @@ export const deselectAriaLabel = (option: MultiselectProps.Option) => {
const label = option?.value || option?.label;
return label ? `Deselect ${label}` : 'no label';
};

export const getInlineAriaLabel = (selectedOptions: MultiselectProps.Options) => {
let label;

if (selectedOptions.length === 0) {
label = 0;
}

if (selectedOptions.length === 1) {
label = selectedOptions[0].label;
}

if (selectedOptions.length === 2) {
label = `${selectedOptions[0].label} and ${selectedOptions[1].label}`;
}

if (selectedOptions.length > 2) {
label = `${selectedOptions[0].label}, ${selectedOptions[1].label}, and ${selectedOptions.length - 2} more`;
}

return label + ' selected';
};
7 changes: 4 additions & 3 deletions pages/multiselect/multiselect.test.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as React from 'react';
import Box from '~components/box';
import Multiselect, { MultiselectProps } from '~components/multiselect';

import { deselectAriaLabel, i18nStrings } from './constants';
import { deselectAriaLabel, getInlineAriaLabel, i18nStrings } from './constants';

const _selectedOptions1 = [
{
Expand Down Expand Up @@ -113,6 +113,7 @@ const options2 = [
],
},
];

export default function MultiselectPage() {
const [selectedOptions1, setSelectedOptions1] = React.useState<MultiselectProps.Options>(_selectedOptions1);
const [selectedOptions2, setSelectedOptions2] = React.useState<MultiselectProps.Options>(_selectedOptions1);
Expand Down Expand Up @@ -235,14 +236,14 @@ export default function MultiselectPage() {
<Box variant="h1">Test: Inline tokens</Box>
<div style={{ width: 200 }}>
<Multiselect
{...{ inlineTokens: true }}
inlineTokens={true}
statusType="pending"
filteringType="none"
options={options1}
placeholder={'Choose option'}
selectedOptions={selectedOptions7}
i18nStrings={i18nStrings}
ariaLabel={`${selectedOptions7.length} accounts selected`}
ariaLabel={getInlineAriaLabel(selectedOptions7)}
onChange={event => {
setSelectedOptions7(event.detail.selectedOptions);
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11259,6 +11259,12 @@ use the \`id\` attribute, consider setting it on a parent element instead.",
"optional": true,
"type": "string",
},
{
"description": "Shows tokens inside the trigger instead of below it.",
"name": "inlineTokens",
"optional": true,
"type": "boolean",
},
{
"description": "Overrides the invalidation state. Usually the invalid state
comes from the parent \`FormField\`component,
Expand Down
2 changes: 1 addition & 1 deletion src/attribute-editor/row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export const Row = React.memo(
errorIconAriaLabel: i18nStrings.errorIconAriaLabel,
warningIconAriaLabel: i18nStrings.warningIconAriaLabel,
}}
__hideLabel={index !== 0 && layout.rows.length === 1}
__hideLabel={index !== 0 && removeButtonOnSameLine}
controlId={defIndex === 0 ? firstControlId : undefined}
>
{render(item, index, control)}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import { applyDropdownPositionRelativeToViewport } from '../../../../../lib/components/internal/components/dropdown/dropdown-position';

describe('applyDropdownPositionRelativeToViewport', () => {
const triggerRect = {
blockSize: 50,
inlineSize: 100,
insetBlockStart: 100,
insetInlineStart: 100,
insetBlockEnd: 150,
insetInlineEnd: 200,
};

const baseDropdownPosition = {
blockSize: '100px',
inlineSize: '100px',
insetInlineStart: '100px',
dropBlockStart: false,
dropInlineStart: false,
};

test("sets block end when the dropdown is anchored to the trigger's block start (expands up)", () => {
const dropdownElement = document.createElement('div');
applyDropdownPositionRelativeToViewport({
dropdownElement,
triggerRect,
position: { ...baseDropdownPosition, dropBlockStart: true },
isMobile: false,
});
expect(dropdownElement.style.insetBlockEnd).toBeTruthy();
expect(dropdownElement.style.insetBlockStart).toBeFalsy();
});

test("aligns block start with the trigger's block end when the dropdown is anchored to the trigger's block end (expands down)", () => {
const dropdownElement = document.createElement('div');
applyDropdownPositionRelativeToViewport({
dropdownElement,
triggerRect,
position: baseDropdownPosition,
isMobile: false,
});
expect(dropdownElement.style.insetBlockEnd).toBeFalsy();
expect(dropdownElement.style.insetBlockStart).toEqual(`${triggerRect.insetBlockEnd}px`);
});

test("aligns inline start with the trigger's inline start when the dropdown is anchored to the trigger's inline start (anchored from the left in LTR)", () => {
const dropdownElement = document.createElement('div');
applyDropdownPositionRelativeToViewport({
dropdownElement,
triggerRect,
position: baseDropdownPosition,
isMobile: false,
});
expect(dropdownElement.style.insetInlineStart).toEqual(`${triggerRect.insetInlineStart}px`);
});

test("sets inline end when the dropdown is anchored to the trigger's inline start (anchored from the right in LTR)", () => {
const dropdownElement = document.createElement('div');
applyDropdownPositionRelativeToViewport({
dropdownElement,
triggerRect,
position: { ...baseDropdownPosition, dropInlineStart: true },
isMobile: false,
});
expect(dropdownElement.style.insetInlineStart).toBeTruthy();
});

test('uses fixed position on desktop', () => {
const dropdownElement = document.createElement('div');
applyDropdownPositionRelativeToViewport({
dropdownElement,
triggerRect,
position: baseDropdownPosition,
isMobile: false,
});
expect(dropdownElement.style.position).toEqual('fixed');
});

test('uses absolute position on mobile', () => {
const dropdownElement = document.createElement('div');
applyDropdownPositionRelativeToViewport({
dropdownElement,
triggerRect,
position: baseDropdownPosition,
isMobile: true,
});
expect(dropdownElement.style.position).toEqual('absolute');
});
});
5 changes: 3 additions & 2 deletions src/internal/components/dropdown/dropdown-fit-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { getLogicalBoundingClientRect } from '@cloudscape-design/component-toolk

import { getBreakpointValue } from '../../breakpoints';
import { BoundingBox, getOverflowParentDimensions, getOverflowParents } from '../../utils/scrollable-containers';
import { LogicalDOMRect } from './dropdown-position';

import styles from './styles.css.js';

Expand Down Expand Up @@ -361,7 +362,7 @@ export const calculatePosition = (
isMobile: boolean,
minWidth?: number,
stretchBeyondTriggerWidth?: boolean
): [DropdownPosition, DOMRect] => {
): [DropdownPosition, LogicalDOMRect] => {
// cleaning previously assigned values,
// so that they are not reused in case of screen resize and similar events
verticalContainerElement.style.maxBlockSize = '';
Expand Down Expand Up @@ -393,6 +394,6 @@ export const calculatePosition = (
isMobile,
stretchBeyondTriggerWidth,
});
const triggerBox = triggerElement.getBoundingClientRect();
const triggerBox = getLogicalBoundingClientRect(triggerElement);
return [position, triggerBox];
};
Loading

0 comments on commit 63e9618

Please sign in to comment.