Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions pages/date-range-picker/common.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ interface DateRangePickerPageSettings {
showRelativeOptions?: boolean;
invalid?: boolean;
warning?: boolean;
readOnly?: boolean;
rangeSelectorMode?: DateRangePickerProps.RangeSelectorMode;
absoluteFormat?: DateRangePickerProps.AbsoluteFormat;
dateInputFormat?: DateRangePickerProps['dateInputFormat'];
Expand All @@ -36,6 +37,7 @@ const defaultSettings: Required<DateRangePickerPageSettings> = {
showRelativeOptions: true,
invalid: false,
warning: false,
readOnly: false,
rangeSelectorMode: 'default',
absoluteFormat: 'iso',
dateInputFormat: 'iso',
Expand Down Expand Up @@ -81,6 +83,7 @@ export function useDateRangePickerSettings(
const showRelativeOptions = parseBoolean(def('showRelativeOptions'), urlParams.showRelativeOptions);
const invalid = parseBoolean(def('invalid'), urlParams.invalid);
const warning = parseBoolean(def('warning'), urlParams.warning);
const readOnly = parseBoolean(def('readOnly'), urlParams.readOnly);
const rangeSelectorMode = urlParams.rangeSelectorMode ?? def('rangeSelectorMode');
const absoluteFormat = urlParams.absoluteFormat ?? def('absoluteFormat');
const timeInputFormat = urlParams.timeInputFormat ?? def('timeInputFormat');
Expand All @@ -98,6 +101,7 @@ export function useDateRangePickerSettings(
showRelativeOptions,
invalid,
warning,
readOnly,
rangeSelectorMode,
absoluteFormat,
dateInputFormat,
Expand Down Expand Up @@ -204,6 +208,7 @@ export function useDateRangePickerSettings(
granularity: monthOnly ? 'month' : 'day',
invalid,
warning,
readOnly,
rangeSelectorMode,
absoluteFormat,
dateInputFormat,
Expand Down Expand Up @@ -251,6 +256,7 @@ export function Settings({
showRelativeOptions,
invalid,
warning,
readOnly,
rangeSelectorMode,
absoluteFormat,
dateInputFormat,
Expand Down Expand Up @@ -381,6 +387,9 @@ export function Settings({
<Checkbox checked={warning} onChange={({ detail }) => setSettings({ warning: detail.checked })}>
Warning
</Checkbox>
<Checkbox checked={readOnly} onChange={({ detail }) => setSettings({ readOnly: detail.checked })}>
Read-only
</Checkbox>
<Checkbox
checked={expandToViewport}
onChange={({ detail }) => setSettings({ expandToViewport: detail.checked })}
Expand Down
5 changes: 5 additions & 0 deletions pages/file-token-group/permutations.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ const permutations = createPermutations<Omit<FileTokenGroupProps, 'onDismiss'>>(
alignment: ['horizontal', 'vertical'],
limit: [undefined, 0],
},
{
items: [[{ file: file1 }, { file: file2 }]],
readOnly: [true],
alignment: ['horizontal', 'vertical'],
},
]);

export default function FileTokenGroupPermutations() {
Expand Down
9 changes: 9 additions & 0 deletions pages/multiselect/multiselect.sync.example.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import * as React from 'react';

import Box from '~components/box';
import Checkbox from '~components/checkbox';
import { NonCancelableCustomEvent } from '~components/interfaces';
import Multiselect, { MultiselectProps } from '~components/multiselect';
import { SelectProps } from '~components/select';
Expand Down Expand Up @@ -37,10 +38,16 @@ export default function MultiselectPage() {
selectableOptions[15],
]);
const [selectedOptions2, setSelectedOptions2] = React.useState<MultiselectProps.Options>([]);
const [readOnly, setReadOnly] = React.useState(false);

return (
<article>
<Box padding="l">
<Box padding="s">
<Checkbox checked={readOnly} onChange={({ detail }) => setReadOnly(detail.checked)}>
Read-only
</Checkbox>
</Box>
<Box padding="s">
<Box variant="h1">Multiselect with filteringType = none</Box>
<Box margin={{ bottom: 'xxs' }} color="text-label">
Expand All @@ -59,6 +66,7 @@ export default function MultiselectPage() {
noMatch={<b>No match</b>}
loadingText="Fetching equipment"
selectedAriaLabel="Selected"
readOnly={readOnly}
onBlur={onBlur}
onFocus={onFocus}
onLoadItems={onLoadItems}
Expand Down Expand Up @@ -91,6 +99,7 @@ export default function MultiselectPage() {
noMatch={<b>No match</b>}
loadingText="Fetching equipment"
selectedAriaLabel="Selected"
readOnly={readOnly}
onBlur={onBlur}
onFocus={onFocus}
onLoadItems={onLoadItems}
Expand Down
9 changes: 9 additions & 0 deletions pages/select/select.sync.example.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import * as React from 'react';

import Box from '~components/box';
import Checkbox from '~components/checkbox';
import Select from '~components/select';

import { generateOptions } from './generate-options';
Expand All @@ -24,10 +25,16 @@ const onBlur = () => {
export default function SelectPage() {
const [selectedOption1, setSelectedOption1] = React.useState(null);
const [selectedOption2, setSelectedOption2] = React.useState(null);
const [readOnly, setReadOnly] = React.useState(false);

return (
<article>
<Box padding="l">
<Box padding="s">
<Checkbox checked={readOnly} onChange={({ detail }) => setReadOnly(detail.checked)}>
Read-only
</Checkbox>
</Box>
<Box padding="s">
<Box variant="h1">Select with filteringType = none</Box>
<Box margin={{ bottom: 'xxs' }} color="text-label">
Expand All @@ -46,6 +53,7 @@ export default function SelectPage() {
noMatch={<b>No match</b>}
loadingText="Fetching equipment"
selectedAriaLabel="Selected"
readOnly={readOnly}
onBlur={onBlur}
onFocus={onFocus}
onLoadItems={onLoadItems}
Expand Down Expand Up @@ -75,6 +83,7 @@ export default function SelectPage() {
noMatch={<b>No match</b>}
loadingText="Fetching equipment"
selectedAriaLabel="Selected"
readOnly={readOnly}
onBlur={onBlur}
onFocus={onFocus}
onLoadItems={onLoadItems}
Expand Down
8 changes: 7 additions & 1 deletion pages/token-group/simple.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import React, { useState } from 'react';

import Box from '~components/box';
import Checkbox from '~components/checkbox';
import TokenGroup, { TokenGroupProps } from '~components/token-group';

const generateItems = (numberOfItems: number) => {
Expand All @@ -20,6 +21,7 @@ const i18nStrings: TokenGroupProps.I18nStrings = {

export default function TokenGroupPage() {
const [items, setItems] = useState(generateItems(10));
const [readOnly, setReadOnly] = useState(false);

const onDismiss = (event: { detail: { itemIndex: number } }) => {
const newItems = [...items];
Expand All @@ -30,7 +32,11 @@ export default function TokenGroupPage() {
return (
<Box padding="xl">
<h1>Token Group</h1>
<TokenGroup items={items} onDismiss={onDismiss} i18nStrings={i18nStrings} limit={5} />
<Checkbox checked={readOnly} onChange={({ detail }) => setReadOnly(detail.checked)}>
Read-only
</Checkbox>
<br />
<TokenGroup items={items} onDismiss={onDismiss} i18nStrings={i18nStrings} limit={5} readOnly={readOnly} />
</Box>
);
}
36 changes: 36 additions & 0 deletions src/date-range-picker/__integ__/date-range-picker.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,40 @@ describe('Date Range Picker', () => {
}, granularity)
);
});

describe('Read-only mode', () => {
const setupReadOnlyTest = (testFn: (page: DateRangePickerPage, browser: WebdriverIO.Browser) => Promise<void>) => {
return useBrowser(async browser => {
const params = new URLSearchParams({ readOnly: 'true' });
const page = new DateRangePickerPage(createWrapper().findDateRangePicker().getElement(), browser);
await browser.url(`#/light/date-range-picker/with-value?${params}`);
await page.waitForLoad();
await testFn(page, browser);
});
};

test(
'trigger text is selectable via the Selection API',
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test should assert that the text is selectable via user interaction, not via the Selection API. The Selection API can be used for verification.

One way you can select text in tests is by double-clicking, with the caveat that the will only select part of the text (in this case, "2018") when it contains separators such as dashes.

Proposed:

    test(
      'trigger text is selectable',
      setupReadOnlyTest(async (page, browser) => {
        const triggerSelector = page.dateRangePickerTrigger;
        const triggerText = await page.getTriggerText();
        expect(triggerText).toContain('2018-01-09');

        const element = browser.$(triggerSelector);
        await element.doubleClick();

        const selectedText = await browser.execute(() => window.getSelection()?.toString());
        expect(selectedText).not.toBeFalsy();
        expect(triggerText).toContain(selectedText);
      })

setupReadOnlyTest(async (page, browser) => {
const triggerSelector = page.dateRangePickerTrigger;
const triggerText = await page.getTriggerText();
expect(triggerText).toContain('2018-01-09');

await browser.execute(selector => {
const trigger = document.querySelector(selector);
if (trigger) {
const range = document.createRange();
range.selectNodeContents(trigger);
const selection = window.getSelection();
selection?.removeAllRanges();
selection?.addRange(range);
}
}, triggerSelector);

const selectedText = await browser.execute(() => window.getSelection()?.toString() ?? '');
expect(selectedText).toContain('2018-01-09');
expect(selectedText).toContain('2018-01-19');
})
);
});
});
4 changes: 4 additions & 0 deletions src/date-range-picker/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ $calendar-header-color: awsui.$color-text-body-default;

.label-text {
@include styles.form-placeholder;
// Placeholder text is purely decorative and not intended to be interacted
// with. Disable selection so that it doesn't become selectable inside the
// read-only trigger (which enables text selection).
user-select: none;
}

.label-token-nowrap {
Expand Down
2 changes: 1 addition & 1 deletion src/file-token-group/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,9 @@
&.read-only {
border-color: awsui.$color-border-input-disabled;
background-color: awsui.$color-background-container-content;
pointer-events: none;

> .dismiss-button {
pointer-events: none;
color: awsui.$color-text-button-inline-icon-disabled;

&:hover {
Expand Down
7 changes: 7 additions & 0 deletions src/internal/components/button-trigger/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ $padding-block-inner-filtering-token: 0px;
@include styles.form-readonly-element;
}

// Allow selecting text (e.g. to copy the selected value) in all read-only
// button-triggers, including those inside filtering tokens. Individual
// placeholder elements opt out via `user-select: none`.
&.readonly:not(&.disabled) {
user-select: text;
}

&:focus {
outline: none;
text-decoration: none;
Expand Down
4 changes: 4 additions & 0 deletions src/select/parts/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@

.placeholder {
@include styles.form-placeholder;
// Placeholder text is purely decorative and not intended to be interacted
// with. Disable selection so that it doesn't become selectable inside
// read-only triggers (which enable text selection).
user-select: none;
}

$checkbox-size: awsui.$size-control;
Expand Down
4 changes: 2 additions & 2 deletions src/token/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,9 @@

.token-box-readonly,
.token-box-disabled {
pointer-events: none;

> .dismiss-button {
cursor: initial;
pointer-events: none;
}
}

Expand All @@ -126,6 +125,7 @@
}

.token-box-disabled {
pointer-events: none;
border-color: var(#{custom-props.$tokenStyleBorderColorDisabled}, awsui.$color-border-control-disabled);
background: var(#{custom-props.$tokenStyleBackgroundDisabled}, awsui.$color-background-container-content);
color: awsui.$color-text-disabled;
Expand Down
Loading