Skip to content
Draft
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
3 changes: 3 additions & 0 deletions build-tools/tasks/package-json.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ function getComponentsExports() {
// Plugin api
'./internal/plugins': './internal/plugins/index.js',
'./internal/plugins/widget': './internal/plugins/widget.js',
// Public plugin api
'./plugins': './plugins/index.js',
// Public internal components
'./internal/tooltip-do-not-use': './internal/tooltip-do-not-use/index.js',
'./internal/do-not-use/chart-filter': './internal/do-not-use/chart-filter.js',
Expand All @@ -32,6 +34,7 @@ function getComponentsExports() {
'./internal/do-not-use/i18n': './internal/do-not-use/i18n.js',
'./internal/do-not-use/tooltip': './internal/do-not-use/tooltip.js',
'./internal/do-not-use/drag-handle': './internal/do-not-use/drag-handle.js',
'./internal/do-not-use/feature-prompt': './internal/do-not-use/feature-prompt/index.js',
'./internal/widget-exports': './internal/widget-exports.js',
'./test-utils/dom/internal/drag-handle': './test-utils/dom/internal/drag-handle.js',
'./test-utils/selectors/internal/drag-handle': './test-utils/selectors/internal/drag-handle.js',
Expand Down
1 change: 1 addition & 0 deletions build-tools/utils/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ function listPublicItems(baseDir) {
elem !== 'test-utils' &&
elem !== 'i18n' &&
elem !== 'theming' &&
elem !== 'plugins' &&
elem !== 'contexts'
);
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@
{
"path": "lib/components/internal/widget-exports.js",
"brotli": false,
"limit": "1150 kB",
"limit": "1250 kB",
"ignore": "react-dom"
}
],
Expand Down
205 changes: 162 additions & 43 deletions pages/feature-notifications/feature-prompt.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,128 @@
// SPDX-License-Identifier: Apache-2.0
import React, { useEffect, useRef } from 'react';

import { AppLayout, Box, Button, Header, Icon, Link, SpaceBetween } from '~components';
import { AppLayout, Badge, Box, Button, Header, Icon, Link, SpaceBetween } from '~components';
import { I18nProvider } from '~components/i18n';
import messages from '~components/i18n/messages/all.all';
import FeaturePrompt, { FeaturePromptProps } from '~components/internal/do-not-use/feature-prompt';
import {
FeatureNotificationsPersistenceConfig,
registerFeatureNotifications,
} from '~components/internal/plugins/widget';
import { mount, unmount } from '~mount';

import { Breadcrumbs, Containers, Navigation, Tools } from '../app-layout/utils/content-blocks';
import labels from '../app-layout/utils/labels';
import * as toolsContent from '../app-layout/utils/tools-content';
import ScreenshotArea from '../utils/screenshot-area';

registerFeatureNotifications({
id: 'local-feature-notifications',
suppressFeaturePrompt: false,
featuresPageLink: '/new-amazing-features',
filterFeatures: () => true,
features: [
{
id: '1',
header: <Box fontWeight="bold">New feature, events with more resource tags</Box>,
content: (
<Box variant="p">
You can now enrich CloudTrail events with additional information by adding resources tags and IAM global keys
in CloudTrail lake.{' '}
<Link variant="primary" external={true} href="https://amazon.com">
Learn more
</Link>
</Box>
),
contentCategory: (
<Box fontSize="body-s" color="text-label">
Event coverage
</Box>
),
releaseDate: new Date('2025-11-01'),
},
{
id: '2',
header: (
<Box fontWeight="bold">Enhanced filtering options for CloudTrail events ingested into event data stores</Box>
),
content: (
<>
<Box variant="p">
More enhanced filtering options provide tighter control over your AWS activity data, improving the
efficiency and precision of security, compliance, and operational investigations.{' '}
<Link variant="primary" external={true} href="https://amazon.com">
View user guide
</Link>
</Box>
<Box margin={{ top: 'xs' }}>
<Button>Create an Enhanced trail</Button>
</Box>
</>
),
releaseDate: new Date('2025-07-28'),
},
{
id: '3',
header: <Box fontWeight="bold">Introducing Application Map</Box>,
content: (
<>
<Box variant="p">
Use application map to automatically discover and organize your services into groups based on your business
needs. Identify root cause faster instead of troubleshooting isolated symptoms with operational signals such
as SLOs, health indicators, and top insights in a contextual drawer.{' '}
<Link variant="primary" href="#">
Learn more
</Link>
</Box>
</>
),
contentCategory: <Badge>Operational investigations</Badge>,
releaseDate: new Date('2025-08-01'),
},
],
mountItem: (container, data) => {
mount(data, container);

return () => unmount(container);
},
persistenceConfig: {
uniqueKey: 'feature-notifications',
},
// DON'T USE
...{
__persistFeatureNotifications: async function (
persistenceConfig: FeatureNotificationsPersistenceConfig,
value: Record<string, string>
) {
const result = await new Promise<void>(resolve =>
setTimeout(() => {
localStorage.setItem(persistenceConfig.uniqueKey, JSON.stringify(value));
resolve();
}, 150)
);
return result;
},
__retrieveFeatureNotifications: async function (persistenceConfig: FeatureNotificationsPersistenceConfig) {
const result = await new Promise<Record<string, string>>(resolve =>
setTimeout(
() =>
resolve(
localStorage.getItem(persistenceConfig.uniqueKey)
? JSON.parse(localStorage.getItem(persistenceConfig.uniqueKey)!)
: {}
),
150
)
);
return result;
},
},
});

export default function () {
const featurePromptRef = useRef<FeaturePromptProps.Ref>(null);
const triggerRef = useRef<HTMLButtonElement>(null);

useEffect(() => {
const root = document.createElement('div');
Expand All @@ -34,48 +145,56 @@ export default function () {

return (
<ScreenshotArea gutters={false}>
<FeaturePrompt
ref={featurePromptRef}
onDismiss={() => {
// handle focus behavior here
}}
position="bottom"
header={
<Box fontWeight="bold">
<Icon name="gen-ai" /> Our AI buddy is smarter than ever
</Box>
}
content={
<Box>
It supports filtering with plain language, reports generation with .pdf, and so much more! See{' '}
<Link href="#">top 10 things it can do for you</Link>.
</Box>
}
getTrack={() => document.querySelector('#settings-icon')}
/>
<AppLayout
ariaLabels={labels}
breadcrumbs={<Breadcrumbs />}
navigation={<Navigation />}
tools={<Tools>{toolsContent.long}</Tools>}
content={
<>
<div style={{ marginBlockEnd: '1rem' }}>
<Header variant="h1" description="Basic demo">
Demo page
</Header>
</div>
<Button
onClick={() => {
featurePromptRef.current?.show();
}}
>
show a feature prompt
</Button>
<Containers />
</>
}
/>
<I18nProvider messages={[messages]} locale="en">
<FeaturePrompt
ref={featurePromptRef}
onDismiss={() => {
triggerRef.current?.focus();
}}
position="bottom"
header={
<Box fontWeight="bold">
<Icon name="gen-ai" /> Our AI buddy is smarter than ever
</Box>
}
content={
<Box>
It supports filtering with plain language, reports generation with .pdf, and so much more! See{' '}
<Link href="#">top 10 things it can do for you</Link>.
</Box>
}
getTrack={() => document.querySelector('#settings-icon')}
trackKey="settings-icon"
/>
<AppLayout
ariaLabels={labels}
analyticsMetadata={{
flowType: 'home',
instanceIdentifier: 'demo-page',
}}
breadcrumbs={<Breadcrumbs />}
navigation={<Navigation />}
tools={<Tools>{toolsContent.long}</Tools>}
content={
<>
<div style={{ marginBlockEnd: '1rem' }}>
<Header variant="h1" description="Basic demo">
Demo page
</Header>
</div>
<Button
ref={triggerRef}
onClick={() => {
featurePromptRef.current?.show();
}}
>
show a feature prompt
</Button>
<Containers />
</>
}
/>
</I18nProvider>
</ScreenshotArea>
);
}
1 change: 1 addition & 0 deletions src/__tests__/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export function getAllComponents(): string[] {
name !== 'test-utils' &&
name !== 'theming' &&
name !== 'contexts' &&
name !== 'plugins' &&
name !== 'i18n' &&
!name.includes('.') &&
!name.includes('LICENSE') &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ Map {
"toolbar": 0,
},
},
"featureNotificationsProps": {
"drawerId": undefined,
"renderLatestFeaturePrompt": [Function],
},
"toolbarProps": {
"activeDrawerId": null,
"ariaLabels": {
Expand Down Expand Up @@ -1003,6 +1007,10 @@ Map {
"toolbar": 0,
},
},
"featureNotificationsProps": {
"drawerId": undefined,
"renderLatestFeaturePrompt": [Function],
},
"toolbarProps": {
"activeDrawerId": null,
"ariaLabels": {
Expand Down Expand Up @@ -2053,6 +2061,10 @@ Map {
"toolbar": 0,
},
},
"featureNotificationsProps": {
"drawerId": undefined,
"renderLatestFeaturePrompt": [Function],
},
"toolbarProps": {
"activeDrawerId": "security",
"ariaLabels": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ Map {
"toolbar": 0,
},
},
"featureNotificationsProps": {
"drawerId": undefined,
"renderLatestFeaturePrompt": [Function],
},
"toolbarProps": {
"activeDrawerId": null,
"ariaLabels": {
Expand Down Expand Up @@ -1004,6 +1008,10 @@ Map {
"toolbar": 0,
},
},
"featureNotificationsProps": {
"drawerId": undefined,
"renderLatestFeaturePrompt": [Function],
},
"toolbarProps": {
"activeDrawerId": null,
"ariaLabels": {
Expand Down
Loading
Loading