Skip to content

Commit 2bf51e8

Browse files
docs: add NextJS app router example (#4714)
Co-authored-by: Lukas Harbarth <[email protected]>
1 parent d4ddb9c commit 2bf51e8

File tree

20 files changed

+4671
-0
lines changed

20 files changed

+4671
-0
lines changed

.github/workflows/examples.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ jobs:
1616
strategy:
1717
matrix:
1818
path:
19+
- nextjs-app
1920
- nextjs-pages
2021
- vite-ts
2122
fail-fast: false

examples/nextjs-app/.eslintrc.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"root": true,
3+
"extends": "next/core-web-vitals"
4+
}

examples/nextjs-app/.gitignore

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
8+
# testing
9+
/coverage
10+
11+
# next.js
12+
/.next/
13+
/out/
14+
15+
# production
16+
/build
17+
18+
# misc
19+
.DS_Store
20+
*.pem
21+
22+
# debug
23+
npm-debug.log*
24+
yarn-debug.log*
25+
yarn-error.log*
26+
27+
# local env files
28+
.env*.local
29+
30+
# vercel
31+
.vercel
32+
33+
# typescript
34+
*.tsbuildinfo
35+
next-env.d.ts

examples/nextjs-app/README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
## UI5 Web Components React - Next.js App Router Example
2+
3+
This example shows how to use the [Next.js](https://nextjs.org/) App Router with UI5 Web Components for React.
4+
5+
## How to use this template
6+
7+
```bash
8+
npx degit SAP/ui5-webcomponents-react/examples/nextjs-app#main my-project
9+
cd my-project
10+
```
11+
12+
## Getting Started
13+
14+
First, install the node_modules:
15+
16+
```bash
17+
npm install
18+
# or
19+
yarn install
20+
# or
21+
pnpm install
22+
```
23+
24+
Then, run the development server:
25+
26+
```bash
27+
npm run dev
28+
# or
29+
yarn dev
30+
# or
31+
pnpm dev
32+
```
33+
34+
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
35+
36+
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
37+
38+
## Learn More
39+
40+
To learn more about Next.js, take a look at the following resources:
41+
42+
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
43+
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
44+
45+
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
'use client';
2+
3+
import { useServerInsertedHTML } from 'next/navigation';
4+
import { useEffect, useState } from 'react';
5+
import { createGenerateId, JssProvider, SheetsRegistry } from 'react-jss';
6+
7+
export function CssRegistry({ children }: { children: React.ReactNode }) {
8+
const [registry] = useState(() => new SheetsRegistry());
9+
const generateId = createGenerateId();
10+
11+
useServerInsertedHTML(() => {
12+
return (
13+
<>
14+
<style id="server-side-styles">{registry.toString()}</style>
15+
</>
16+
);
17+
});
18+
19+
useEffect(() => {
20+
const style = document.getElementById('server-side-styles');
21+
if (style) {
22+
style.parentNode?.removeChild(style);
23+
}
24+
}, []);
25+
26+
return (
27+
<JssProvider registry={registry} generateId={generateId}>
28+
{children}
29+
</JssProvider>
30+
);
31+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
'use client';
2+
3+
import navBackIcon from '@ui5/webcomponents-icons/dist/nav-back.js';
4+
import { Button, ShellBar } from '@ui5/webcomponents-react';
5+
import '@ui5/webcomponents-react/dist/Assets.js';
6+
import { usePathname, useRouter } from 'next/navigation';
7+
8+
export function AppShell() {
9+
const router = useRouter();
10+
const pathname = usePathname();
11+
12+
return (
13+
<>
14+
<ShellBar
15+
primaryTitle={'UI5 Web Components for React Examples'}
16+
secondaryTitle={'NextJS - App Router'}
17+
startButton={
18+
pathname !== '/' && (
19+
<Button
20+
icon={navBackIcon}
21+
onClick={() => {
22+
router.back();
23+
}}
24+
/>
25+
)
26+
}
27+
/>
28+
</>
29+
);
30+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
'use client';
2+
3+
import { Todo } from '@/app/mockData/todos';
4+
import { List, ListItemType, ListPropTypes, StandardListItem, ValueState } from '@ui5/webcomponents-react';
5+
import { useRouter } from 'next/navigation';
6+
7+
interface TodoListProps {
8+
items: Todo[];
9+
}
10+
11+
export function TodoList({ items }: TodoListProps) {
12+
const router = useRouter();
13+
const handleTodoClick: ListPropTypes['onItemClick'] = (event) => {
14+
router.push(`/todos/${event.detail.item.dataset.id}`);
15+
};
16+
17+
return (
18+
<List onItemClick={handleTodoClick}>
19+
{items.map((todo) => {
20+
return (
21+
<StandardListItem
22+
key={todo.id}
23+
data-id={todo.id}
24+
type={ListItemType.Navigation}
25+
additionalText={`${!todo.completed ? 'Not ' : ''}Completed`}
26+
additionalTextState={todo.completed ? ValueState.Success : ValueState.None}
27+
>
28+
{todo.title}
29+
</StandardListItem>
30+
);
31+
})}
32+
</List>
33+
);
34+
}

examples/nextjs-app/app/favicon.ico

25.3 KB
Binary file not shown.

examples/nextjs-app/app/globals.css

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* to prevent flickering, only show the web-component when its custom-element is defined */
2+
:not(:defined) {
3+
display: none;
4+
}
5+
6+
html,
7+
body {
8+
max-width: 100vw;
9+
overflow-x: hidden;
10+
padding: 0;
11+
margin: 0;
12+
}
13+
14+
.appShell {
15+
height: 100vh;
16+
width: 100vw;
17+
overflow: hidden;
18+
}
19+
20+
.appScrollContainer {
21+
height: calc(100vh - 3.25rem);
22+
width: 100vw;
23+
overflow-y: auto;
24+
position: relative;
25+
}

examples/nextjs-app/app/layout.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { AppShell } from '@/app/components/AppShell';
2+
import { CssRegistry } from '@/app/CssRegistry';
3+
import { ThemeProvider } from '@ui5/webcomponents-react';
4+
import './globals.css';
5+
6+
export default function RootLayout({ children }: { children: React.ReactNode }) {
7+
return (
8+
<html lang="en">
9+
<head>
10+
<script
11+
data-ui5-config
12+
type="application/json"
13+
dangerouslySetInnerHTML={{
14+
__html: JSON.stringify({
15+
theme: 'sap_horizon'
16+
})
17+
}}
18+
/>
19+
</head>
20+
<body>
21+
<div className="appShell">
22+
<CssRegistry>
23+
<ThemeProvider>
24+
<AppShell />
25+
<div className="appScrollContainer">{children}</div>
26+
</ThemeProvider>
27+
</CssRegistry>
28+
</div>
29+
</body>
30+
</html>
31+
);
32+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.container {
2+
width: 100%;
3+
height: 100%;
4+
display: flex;
5+
align-items: center;
6+
justify-content: center;
7+
}

examples/nextjs-app/app/loading.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { BusyIndicator, BusyIndicatorSize } from '@ui5/webcomponents-react';
2+
import classes from './loading.module.css';
3+
4+
export default function HomeLoading() {
5+
return (
6+
<div className={classes.container}>
7+
<BusyIndicator active size={BusyIndicatorSize.Large} delay={0} />
8+
</div>
9+
);
10+
}

0 commit comments

Comments
 (0)