-
Notifications
You must be signed in to change notification settings - Fork 312
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Caleb Pollman <[email protected]> Co-authored-by: Jordan Van Ness <[email protected]>
- Loading branch information
1 parent
e52db7b
commit d73bd9c
Showing
106 changed files
with
3,426 additions
and
365 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
--- | ||
"@aws-amplify/ui": minor | ||
"@aws-amplify/ui-react": minor | ||
--- | ||
|
||
feat(ui): experimental component theming | ||
|
||
This feature lets you fully style and theme built-in components even if there is no design token available. For example, previously you could not add a box shadow or gradient background to the built-in Button component unless you wrote plain CSS. Now you can style every CSS property for all the built-in components with type-safety! | ||
|
||
This also lets you define your own components and style them in the same type-safe way with zero runtime computation. | ||
|
||
### defineComponentTheme() | ||
|
||
```ts | ||
import { defineComponentTheme } from '@aws-amplify/ui-react/server'; | ||
|
||
export const buttonTheme = defineComponentTheme({ | ||
// because 'button' is a built-in component, we get type-safety and hints | ||
// based on the theme shape of our button | ||
name: 'button', | ||
theme: (tokens) => { | ||
return { | ||
textAlign: 'center', | ||
padding: tokens.space.xl, | ||
_modifiers: { | ||
primary: { | ||
backgroundColor: tokens.colors.primary[20], | ||
}, | ||
}, | ||
}; | ||
}, | ||
}); | ||
``` | ||
|
||
|
||
### createTheme() | ||
|
||
The theme object passed to `createTheme` now has an optional `components` array which is an array of component themes. | ||
|
||
```ts | ||
export const theme = createTheme({ | ||
name: 'my-theme', | ||
components: [ | ||
buttonTheme, | ||
customComponentTheme, | ||
] | ||
}) | ||
``` | ||
|
||
### React Server Component support for theming | ||
|
||
You no longer need to use the `<ThemeProvider>` and rely on React context to theme Amplify UI (you still can though!). There is a new import path for RSC-compliant code: '@aws-amplify/ui-react/server' which you can use to import `createTheme` and `defineComponentTheme` as well as a new React Server Component: `<ThemeStyle />` which will inject the styles of your theme into the page. | ||
|
||
|
||
```tsx | ||
import { ThemeStyle, createTheme } from '@aws-amplify/ui-react/server'; | ||
|
||
const theme = createTheme({ | ||
//... | ||
}) | ||
|
||
export default function RootLayout({ | ||
children, | ||
}: { | ||
children: React.ReactNode; | ||
}) { | ||
return ( | ||
<div {...theme.containerProps({ colorMode: 'system' })}> | ||
{children} | ||
<ThemeStyle theme={theme} /> | ||
</div> | ||
) | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"extends": "next/core-web-vitals", | ||
"rules": { | ||
"react-hooks/exhaustive-deps": "error" // override next eslint default | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
.yarn/install-state.gz | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# local env files | ||
.env*.local | ||
|
||
# vercel | ||
.vercel | ||
|
||
# typescript | ||
*.tsbuildinfo | ||
next-env.d.ts |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/** @type {import('next').NextConfig} */ | ||
const nextConfig = {}; | ||
|
||
module.exports = nextConfig; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"name": "@aws-amplify/ui-next-app-example", | ||
"version": "0.0.1", | ||
"private": true, | ||
"scripts": { | ||
"dev": "next dev", | ||
"build": "next build", | ||
"start": "next start", | ||
"lint": "next lint" | ||
}, | ||
"dependencies": { | ||
"@aws-amplify/ui-react": "^6.1.0", | ||
"next": "^14.1.1", | ||
"react": "18.2.0", | ||
"react-dom": "^18", | ||
"react-icons": "^4.3.1" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^14.14.31", | ||
"eslint-config-next": "^13.5.5" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module.exports = { | ||
plugins: { | ||
autoprefixer: {}, | ||
}, | ||
}; |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
@import '@aws-amplify/ui-react/styles/reset.css'; | ||
@import '@aws-amplify/ui-react/styles.css'; | ||
|
||
[data-amplify-theme] { | ||
background-color: var(--amplify-colors-background-primary); | ||
color: var(--amplify-colors-font-primary); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import type { Metadata } from 'next'; | ||
import './globals.css'; | ||
|
||
export const metadata: Metadata = { | ||
title: 'Amplify UI Next App Router Example', | ||
description: 'Generated by create next app', | ||
}; | ||
|
||
export default function RootLayout({ | ||
children, | ||
}: { | ||
children: React.ReactNode; | ||
}) { | ||
return ( | ||
<html lang="en"> | ||
<body>{children}</body> | ||
</html> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { Avatar } from '@/components/Avatar'; | ||
import { theme } from '@/theme'; | ||
import Link from 'next/link'; | ||
|
||
export default function Home() { | ||
return ( | ||
<main> | ||
<Link href="/theme">Theme</Link> | ||
<Link href="/theme-switcher">Theme Switcher</Link> | ||
<Avatar /> | ||
|
||
<div {...theme.containerProps({ colorMode: 'dark' })}> | ||
<h2>{`I'm dark`}</h2> | ||
<Avatar /> | ||
</div> | ||
</main> | ||
); | ||
} |
25 changes: 25 additions & 0 deletions
25
examples/next-app-router/src/app/theme-switcher/layout.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import * as React from 'react'; | ||
import type { ColorMode } from '@aws-amplify/ui-react'; | ||
import { ThemeStyle } from '@aws-amplify/ui-react/server'; | ||
import { theme } from '@/theme'; | ||
import { Header } from '@/components/Header'; | ||
import ThemeToggle from '@/components/ThemeToggle'; | ||
import { cookies } from 'next/headers'; | ||
|
||
export default function Layout({ children }: { children: React.ReactNode }) { | ||
const cookieStore = cookies(); | ||
const colorMode = (cookieStore.get('colorMode')?.value ?? | ||
'dark') as ColorMode; | ||
|
||
return ( | ||
<div {...theme.containerProps({ colorMode })}> | ||
{/* Header */} | ||
<Header> | ||
Amplify UI RSC | ||
<ThemeToggle initialValue={colorMode} /> | ||
</Header> | ||
{children} | ||
<ThemeStyle theme={theme} /> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { ThemeStyle } from '@aws-amplify/ui-react/server'; | ||
import { Avatar } from '@/components/Avatar'; | ||
import { theme } from '@/theme'; | ||
|
||
export default function ThemeSwitcherPage() { | ||
return ( | ||
<div | ||
className="flex w-full flex-row" | ||
style={{ | ||
backgroundColor: `var(--breakpoint-large, #f90)`, | ||
}} | ||
> | ||
<Avatar size="small" /> | ||
<Avatar /> | ||
<Avatar size="large" /> | ||
<div {...theme.containerProps({ colorMode: 'dark' })}> | ||
<div | ||
className="flex w-full flex-row" | ||
style={{ | ||
backgroundColor: `${theme.tokens.colors.background.primary}`, | ||
}} | ||
> | ||
<Avatar size="small" /> | ||
<Avatar /> | ||
<Avatar size="large" /> | ||
</div> | ||
</div> | ||
<ThemeStyle theme={theme} /> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { | ||
ThemeStyle, | ||
createComponentClasses, | ||
} from '@aws-amplify/ui-react/server'; | ||
import { theme } from '@/theme'; | ||
|
||
const headingClasses = createComponentClasses({ name: 'heading' }); | ||
|
||
export default function RootLayout({ | ||
children, | ||
}: { | ||
children: React.ReactNode; | ||
}) { | ||
return ( | ||
<div className="flex w-full flex-row"> | ||
<div className="flex-1 p-2"> | ||
<h2 className={headingClasses({ _modifiers: ['2'] })}>Custom theme</h2> | ||
|
||
<ThemeStyle theme={theme} /> | ||
<section {...theme.containerProps({ colorMode: 'dark' })}> | ||
{children} | ||
</section> | ||
</div> | ||
<div className="flex-1 p-2"> | ||
<h2 className={headingClasses({ _modifiers: ['2'] })}>Default theme</h2> | ||
{children} | ||
</div> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
'use client'; | ||
import { Avatar } from '@/components/Avatar'; | ||
import { MyClientComponent } from '@/components/ClientComponent'; | ||
import { MyServerComponent } from '@/components/ServerComponent'; | ||
import { theme } from '@/theme'; | ||
import { | ||
Alert, | ||
Badge, | ||
BadgeProps, | ||
Button, | ||
ButtonProps, | ||
Flex, | ||
Heading, | ||
Text, | ||
} from '@aws-amplify/ui-react'; | ||
|
||
const colorThemes: BadgeProps['variation'][] = [ | ||
undefined, | ||
'success', | ||
'info', | ||
'warning', | ||
'error', | ||
]; | ||
|
||
export default function ThemePage() { | ||
return ( | ||
<Flex direction="column"> | ||
<Heading level={3}>Badges</Heading> | ||
<Flex direction="row"> | ||
{colorThemes.map((colorTheme, i) => ( | ||
<Badge key={`${i}-${colorTheme}`} variation={colorTheme}> | ||
{colorTheme || 'default'} | ||
</Badge> | ||
))} | ||
</Flex> | ||
<Heading level={3}>Buttons</Heading> | ||
<Flex direction="row"> | ||
{colorThemes.map((colorTheme, i) => ( | ||
<Button key={`${i}-${colorTheme}`} colorTheme={colorTheme}> | ||
{colorTheme || 'default'} | ||
</Button> | ||
))} | ||
</Flex> | ||
<Flex direction="row"> | ||
{colorThemes.map((colorTheme, i) => ( | ||
<Button | ||
key={`${i}-${colorTheme}`} | ||
variation="link" | ||
colorTheme={colorTheme} | ||
> | ||
{colorTheme || 'default'} | ||
</Button> | ||
))} | ||
</Flex> | ||
<Flex direction="row"> | ||
{colorThemes.map((colorTheme, i) => ( | ||
<Button | ||
key={`${i}-${colorTheme}`} | ||
variation="primary" | ||
colorTheme={colorTheme} | ||
> | ||
{colorTheme || 'default'} | ||
</Button> | ||
))} | ||
</Flex> | ||
<Avatar isDisabled /> | ||
<MyClientComponent /> | ||
<MyServerComponent /> | ||
<Text color={theme.tokens.colors.font.success}>Success!</Text> | ||
<Alert heading="Hello" /> | ||
<Alert heading="Hello success" variation="success" /> | ||
<Alert heading="Hello" variation="info" /> | ||
</Flex> | ||
); | ||
} |
Oops, something went wrong.