Skip to content

Commit 25f9734

Browse files
authored
Merge branch 'main' into dev-v3-philosr-tooltip-v2
2 parents e744747 + 94344c6 commit 25f9734

File tree

122 files changed

+5884
-576
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

122 files changed

+5884
-576
lines changed

build-tools/utils/custom-css-properties.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ const customCssPropertiesList = [
110110
'stylePlaceholderFontSize',
111111
'stylePlaceholderFontStyle',
112112
'stylePlaceholderFontWeight',
113+
// Tabs style properties
114+
'styleTabsActiveIndicatorColor',
115+
'styleTabsActiveIndicatorWidth',
116+
'styleTabsActiveIndicatorBorderRadius',
117+
'styleTabsSeparatorColor',
118+
'styleTabsSeparatorWidth',
113119
// Alert focus ring properties
114120
'alertFocusRingBorderColor',
115121
'alertFocusRingBorderRadius',

build-tools/utils/pluralize.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const pluralizationMap = {
2828
DatePicker: 'DatePickers',
2929
DateRangePicker: 'DateRangePickers',
3030
Drawer: 'Drawers',
31+
ErrorBoundary: 'ErrorBoundaries',
3132
ExpandableSection: 'ExpandableSections',
3233
FileDropzone: 'FileDropzones',
3334
FileInput: 'FileInputs',

package-lock.json

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@
175175
{
176176
"path": "lib/components/internal/widget-exports.js",
177177
"brotli": false,
178-
"limit": "1040 kB",
178+
"limit": "1150 kB",
179179
"ignore": "react-dom"
180180
}
181181
],
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import React, { useContext, useState } from 'react';
5+
6+
import { Drawer, Header, Icon, SideNavigation, SpaceBetween, Toggle } from '~components';
7+
import AppLayout, { AppLayoutProps } from '~components/app-layout';
8+
import Box from '~components/box';
9+
import SplitPanel from '~components/split-panel';
10+
11+
import AppContext, { AppContextType } from '../app/app-context';
12+
import ScreenshotArea from '../utils/screenshot-area';
13+
import { Breadcrumbs } from './utils/content-blocks';
14+
import * as content from './utils/contents';
15+
import { drawerLabels } from './utils/drawers';
16+
import labels from './utils/labels';
17+
import { splitPaneli18nStrings } from './utils/strings';
18+
19+
type DrawerHeaderAndFooterDemoContext = React.Context<
20+
AppContextType<{
21+
drawerOpen: string | null;
22+
hasHeader: boolean;
23+
hasFooter: boolean;
24+
splitPanelPosition: AppLayoutProps.SplitPanelPreferences['position'];
25+
longHeader: boolean;
26+
longFooter: boolean;
27+
longContent: boolean;
28+
splitPanelOpen: boolean;
29+
}>
30+
>;
31+
32+
const getAriaLabels = (title: string) => {
33+
return {
34+
closeButton: `${title} close button`,
35+
drawerName: `${title}`,
36+
triggerButton: `${title} trigger button`,
37+
resizeHandle: `${title} resize handle`,
38+
};
39+
};
40+
41+
export default function () {
42+
const {
43+
urlParams: {
44+
splitPanelPosition,
45+
longHeader = false,
46+
longFooter = false,
47+
longContent = false,
48+
hasHeader = true,
49+
hasFooter = true,
50+
splitPanelOpen = false,
51+
},
52+
setUrlParams,
53+
} = useContext(AppContext as DrawerHeaderAndFooterDemoContext);
54+
55+
const [activeDrawerId, setActiveDrawerId] = useState<string | null>('sample-demo');
56+
57+
return (
58+
<ScreenshotArea gutters={false}>
59+
<AppLayout
60+
ariaLabels={{ ...labels, ...drawerLabels }}
61+
breadcrumbs={<Breadcrumbs />}
62+
navigation={
63+
<SideNavigation
64+
header={{
65+
href: '#',
66+
text: 'On the other side',
67+
}}
68+
items={[]}
69+
/>
70+
}
71+
splitPanelPreferences={{ position: splitPanelPosition }}
72+
onSplitPanelPreferencesChange={event => {
73+
const { position } = event.detail;
74+
setUrlParams({ splitPanelPosition: position === 'side' ? position : undefined });
75+
}}
76+
activeDrawerId={activeDrawerId}
77+
drawers={[
78+
{
79+
ariaLabels: getAriaLabels('sample-demo'),
80+
id: 'sample-demo',
81+
resizable: true,
82+
defaultSize: 420,
83+
content: (
84+
<Drawer
85+
header={hasHeader && (longHeader ? content.longHeader : content.shortHeader)}
86+
footer={hasFooter && (longFooter ? content.longFooter : content.shortFooter)}
87+
headerActions={[<Icon key="icon" name="add-plus" data-testid="drawer-header-action-button" />]}
88+
>
89+
{longContent ? content.longContent : content.shortContent}
90+
</Drawer>
91+
),
92+
trigger: {
93+
iconName: 'contact',
94+
},
95+
},
96+
]}
97+
onDrawerChange={event => {
98+
setActiveDrawerId(event.detail.activeDrawerId);
99+
}}
100+
contentType="table"
101+
splitPanelOpen={splitPanelOpen}
102+
onSplitPanelToggle={event => setUrlParams({ splitPanelOpen: event.detail.open })}
103+
splitPanel={
104+
<SplitPanel header="Split panel header" i18nStrings={splitPaneli18nStrings}>
105+
<Box>Content</Box>
106+
</SplitPanel>
107+
}
108+
content={
109+
<SpaceBetween size="xs">
110+
<Header variant="h1" description="Sometimes all you need is a large cappuchino.">
111+
Drawers with Footer Demo
112+
</Header>
113+
{activeDrawerId === 'sample-demo' && (
114+
<Toggle checked={longContent} onChange={({ detail }) => setUrlParams({ longContent: detail.checked })}>
115+
Long content
116+
</Toggle>
117+
)}
118+
119+
<Toggle
120+
checked={hasHeader}
121+
onChange={({ detail }) => setUrlParams({ hasHeader: detail.checked })}
122+
disabled={!activeDrawerId}
123+
>
124+
Has Header
125+
</Toggle>
126+
127+
{hasHeader && activeDrawerId === 'sample-demo' && (
128+
<Box margin={{ left: 'l' }}>
129+
<Toggle
130+
checked={longHeader}
131+
onChange={({ detail }) => setUrlParams({ longHeader: detail.checked })}
132+
disabled={!activeDrawerId}
133+
>
134+
Long Header
135+
</Toggle>
136+
</Box>
137+
)}
138+
139+
{activeDrawerId === 'sample-demo' && (
140+
<Toggle checked={hasFooter} onChange={({ detail }) => setUrlParams({ hasFooter: detail.checked })}>
141+
Has Footer
142+
</Toggle>
143+
)}
144+
145+
{hasFooter && activeDrawerId === 'sample-demo' && (
146+
<Box margin={{ left: 'l' }}>
147+
<Toggle checked={longFooter} onChange={({ detail }) => setUrlParams({ longFooter: detail.checked })}>
148+
Long Footer
149+
</Toggle>
150+
</Box>
151+
)}
152+
</SpaceBetween>
153+
}
154+
/>
155+
</ScreenshotArea>
156+
);
157+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
import React from 'react';
4+
5+
import { Box, ButtonGroup, Link, SpaceBetween } from '~components';
6+
import Icon from '~components/icon';
7+
import PromptInput from '~components/prompt-input';
8+
9+
export const longContent = (
10+
<>
11+
<span>
12+
Content: When you want to use CloudFront to distribute your content, you create a distribution and choose the
13+
configuration settings you want. For example:
14+
</span>
15+
<ul>
16+
<li>
17+
Your content origin—that is, the Amazon S3 bucket, MediaPackage channel, or HTTP server from which CloudFront
18+
gets the files to distribute. You can specify any combination of up to 25 Amazon S3 buckets, channels, and/or
19+
HTTP servers as your origins.
20+
</li>
21+
<li>
22+
Your content origin—that is, the Amazon S3 bucket, MediaPackage channel, or HTTP server from which CloudFront
23+
gets the files to distribute. You can specify any combination of up to 25 Amazon S3 buckets, channels, and/or
24+
HTTP servers as your origins.
25+
</li>
26+
<li>
27+
Your content origin—that is, the Amazon S3 bucket, MediaPackage channel, or HTTP server from which CloudFront
28+
gets the files to distribute. You can specify any combination of up to 25 Amazon S3 buckets, channels, and/or
29+
HTTP servers as your origins.
30+
</li>
31+
<li>Access—whether you want the files to be available to everyone or restrict access to some users.</li>
32+
<li>Security—whether you want CloudFront to require users to use HTTPS to access your content.</li>
33+
<li>
34+
Cookie or query-string forwarding—whether you want CloudFront to forward cookies or query strings to your
35+
origin.
36+
</li>
37+
<li>
38+
Geo-restrictions—whether you want CloudFront to prevent users in selected countries from accessing your content.
39+
</li>
40+
<li>Access logs—whether you want CloudFront to create access logs that show viewer activity.</li>
41+
</ul>
42+
<h3>
43+
Learn more <Icon name="external" />
44+
</h3>
45+
<ul>
46+
<li>
47+
<a
48+
href="https://docs.aws.amazon.com/en_pv/AmazonCloudFront/latest/DeveloperGuide/distribution-overview.html"
49+
rel="noopener noreferrer"
50+
target="_blank"
51+
>
52+
Overview of Distributions
53+
</a>
54+
</li>
55+
</ul>
56+
</>
57+
);
58+
59+
export const shortContent = (
60+
<span>
61+
Content: You can configure CloudFront to return a specific object (the default root object) when a user requests the
62+
root URL for your web distribution instead of requesting an object in your distribution. Specifying a default root
63+
object lets you avoid exposing the contents of your distribution or returning an error.
64+
</span>
65+
);
66+
67+
export const longHeader = <h2>Header: Lorem nesciunt praesentium voluptatem, molestias aliquid animi aspernatur!</h2>;
68+
69+
export const shortHeader = <h2>Header: Lorem nesciunt!</h2>;
70+
71+
export const longFooter = (
72+
<span>
73+
<SpaceBetween size="xs">
74+
<PromptInput
75+
value="Hey there, can you help me write some integration tests."
76+
disableSecondaryActionsPaddings={true}
77+
actionButtonAriaLabel={'Need Help?'}
78+
actionButtonIconName={'stop-circle'}
79+
maxRows={3}
80+
secondaryActions={
81+
<Box padding={{ left: 'xxs', top: 'xs' }}>
82+
<ButtonGroup
83+
ariaLabel="Additional chat input actions"
84+
items={[
85+
{
86+
type: 'icon-button',
87+
id: 'upload-files',
88+
iconName: 'upload',
89+
text: 'Upload files',
90+
},
91+
{
92+
type: 'icon-button',
93+
id: 'add-reference',
94+
iconName: 'at-symbol',
95+
text: 'Add reference or citation',
96+
},
97+
]}
98+
variant="icon"
99+
/>
100+
</Box>
101+
}
102+
/>
103+
<Box fontSize="body-s" color="text-body-secondary">
104+
Use of this service is subject to the{' '}
105+
<Link external={true} variant="primary" href="https://aws.amazon.com/machine-learning/responsible-ai/policy/">
106+
AWS Responsible AI Policy
107+
</Link>
108+
</Box>
109+
</SpaceBetween>
110+
</span>
111+
);
112+
113+
export const shortFooter = <span>Footer: Lorem nesciuntnatur!</span>;

pages/app/app-context.tsx

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ interface AppUrlParams {
1414
visualRefresh: boolean;
1515
motionDisabled: boolean;
1616
appLayoutWidget: boolean;
17+
mode?: Mode;
1718
}
1819

1920
export interface AppContextType<T = unknown> {
@@ -73,22 +74,34 @@ function formatQuery(params: AppUrlParams) {
7374
export function AppContextProvider({ children }: { children: React.ReactNode }) {
7475
const history = useHistory();
7576
const location = useLocation();
76-
const match = useRouteMatch<{ theme: string; mode: Mode; pageId: string }>('/:mode(light|dark)/:pageId*');
77-
const { mode, pageId } = match ? match.params : { mode: undefined, pageId: undefined };
77+
const matchWithVisualMode = useRouteMatch<{ mode: Mode; pageId: string }>('/:mode(light|dark)/:pageId*');
78+
const matchWithoutVisualMode = useRouteMatch<{ pageId: string }>('/:pageId*');
79+
const pageId = (matchWithVisualMode ?? matchWithoutVisualMode)?.params.pageId ?? undefined;
7880
const urlParams = parseQuery(location.search) as AppUrlParams;
81+
const mode = matchWithVisualMode?.params.mode ?? urlParams.mode ?? Mode.Light;
7982

8083
function setUrlParams(newParams: Partial<AppUrlParams>) {
81-
const pathname = [mode, pageId].filter(segment => !!segment).join('/') + '/';
82-
history.replace(`/${pathname}${formatQuery({ ...urlParams, ...newParams })}`);
84+
const formattedQuery = formatQuery({ ...urlParams, ...newParams });
85+
if (matchWithVisualMode) {
86+
const pathname = [matchWithVisualMode.params.mode, pageId].filter(segment => !!segment).join('/') + '/';
87+
history.replace(`/${pathname}${formatQuery({ ...urlParams, ...newParams })}`);
88+
} else {
89+
const newUrl = pageId ? `/${pageId}${formattedQuery}` : formattedQuery;
90+
history.replace(newUrl);
91+
}
8392
}
8493

8594
function updateMode(newMode: Mode) {
86-
const pathname = [newMode, pageId].filter(segment => !!segment).join('/') + '/';
87-
history.replace('/' + pathname + location.search + location.hash);
95+
if (matchWithVisualMode) {
96+
const pathname = [newMode, pageId].filter(segment => !!segment).join('/') + '/';
97+
history.replace('/' + pathname + location.search + location.hash);
98+
} else {
99+
setUrlParams({ mode: newMode });
100+
}
88101
}
89102

90103
return (
91-
<AppContext.Provider value={{ mode: mode!, pageId, urlParams, setUrlParams: setUrlParams, setMode: updateMode }}>
104+
<AppContext.Provider value={{ mode, pageId, urlParams, setUrlParams: setUrlParams, setMode: updateMode }}>
92105
{children}
93106
</AppContext.Provider>
94107
);

pages/app/index.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0
33

44
import React, { Suspense, useContext, useEffect } from 'react';
5-
import { HashRouter, Redirect } from 'react-router-dom';
5+
import { HashRouter } from 'react-router-dom';
66
import { createHashHistory } from 'history';
77

88
import { applyDensity, applyMode, disableMotion } from '@cloudscape-design/global-styles';
@@ -51,6 +51,8 @@ function isAppLayoutPage(pageId?: string) {
5151
'funnel-analytics/static-single-page-flow',
5252
'funnel-analytics/static-multi-page-flow',
5353
'charts.test',
54+
'error-boundary/demo-async-load',
55+
'error-boundary/demo-components',
5456
];
5557
return pageId !== undefined && appLayoutPages.some(match => pageId.includes(match));
5658
}
@@ -79,9 +81,6 @@ function App() {
7981
disableMotion(motionDisabled);
8082
}, [motionDisabled]);
8183

82-
if (!mode) {
83-
return <Redirect to="/light/" />;
84-
}
8584
return (
8685
<StrictModeWrapper pageId={pageId}>
8786
<Suspense fallback={<span>Loading...</span>}>

0 commit comments

Comments
 (0)