Skip to content

Commit 283305e

Browse files
committed
feat: useQwikRouter
this makes it possible to put the routerhead in root as well
1 parent ac997ba commit 283305e

File tree

13 files changed

+256
-155
lines changed

13 files changed

+256
-155
lines changed

e2e/adapters-e2e/src/components/router-head/router-head.tsx

Lines changed: 0 additions & 24 deletions
This file was deleted.

e2e/adapters-e2e/src/root.tsx

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,33 @@
11
import { component$ } from '@qwik.dev/core';
2-
import { QwikRouterProvider, RouterOutlet } from '@qwik.dev/router';
3-
import { RouterHead } from './components/router-head/router-head';
2+
import { RouterOutlet, useDocumentHead, useLocation, useQwikRouter } from '@qwik.dev/router';
43

54
export default component$(() => {
6-
/**
7-
* The root of a QwikCity site always start with the <QwikCityProvider> component, immediately
8-
* followed by the document's <head> and <body>.
9-
*
10-
* Don't remove the `<head>` and `<body>` elements.
11-
*/
5+
useQwikRouter();
6+
7+
const head = useDocumentHead();
8+
const loc = useLocation();
129

1310
return (
14-
<QwikRouterProvider>
11+
<>
1512
<head>
1613
<meta charset="utf-8" />
17-
<RouterHead />
14+
<title>{head.title}</title>
15+
16+
<link rel="canonical" href={loc.url.href} />
17+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
18+
19+
{head.meta.map((m) => (
20+
<meta key={m.key} {...m} />
21+
))}
22+
23+
{head.links.map((l) => (
24+
<link key={l.key} {...l} />
25+
))}
26+
{/* we don't use styles or scripts here */}
1827
</head>
19-
<body lang="en">
28+
<body>
2029
<RouterOutlet />
2130
</body>
22-
</QwikRouterProvider>
31+
</>
2332
);
2433
});

packages/docs/src/root.tsx

Lines changed: 100 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
import { component$, useContextProvider, useStore } from '@qwik.dev/core';
22
import { Insights } from '@qwik.dev/core/insights';
3-
import { QwikRouterProvider, RouterOutlet, ServiceWorkerRegister } from '@qwik.dev/router';
3+
import {
4+
RouterOutlet,
5+
ServiceWorkerRegister,
6+
useDocumentHead,
7+
useLocation,
8+
useQwikRouter,
9+
} from '@qwik.dev/router';
410
import RealMetricsOptimization from './components/real-metrics-optimization/real-metrics-optimization';
5-
import { RouterHead } from './components/router-head/router-head';
611
import { BUILDER_PUBLIC_API_KEY } from './constants';
712
import { GlobalStore, type SiteStore } from './context';
813
import './global.css';
14+
import { ThemeScript } from './components/router-head/theme-script';
15+
import { Social } from './components/router-head/social';
16+
import { Vendor } from './components/router-head/vendor';
917

1018
export const uwu = /*javascript*/ `
1119
;(function () {
@@ -41,6 +49,10 @@ export const uwu = /*javascript*/ `
4149
`;
4250

4351
export default component$(() => {
52+
useQwikRouter();
53+
const head = useDocumentHead();
54+
const { url } = useLocation();
55+
4456
const store = useStore<SiteStore>({
4557
headerMenuOpen: false,
4658
sideMenuOpen: false,
@@ -49,12 +61,94 @@ export default component$(() => {
4961

5062
useContextProvider(GlobalStore, store);
5163

64+
const title = head.title
65+
? `${head.title} 📚 Qwik Documentation`
66+
: `Qwik - Framework reimagined for the edge`;
67+
const description =
68+
head.meta.find((m) => m.name === 'description')?.content ||
69+
`No hydration, auto lazy-loading, edge-optimized, and fun 🎉!`;
70+
71+
const OGImage = {
72+
imageURL: '',
73+
ogImgTitle: '',
74+
ogImgSubTitle: '' as string | undefined,
75+
76+
get URL() {
77+
//turn the title into array with [0] -> Title [1] -> subTitle
78+
const arrayedTitle = title.split(' | ');
79+
const ogImageUrl = new URL('https://opengraphqwik.vercel.app/api/og?level=1');
80+
81+
// biggerTitle
82+
this.ogImgTitle = arrayedTitle[0];
83+
//smallerTitle
84+
this.ogImgSubTitle = arrayedTitle[1]
85+
? arrayedTitle[1].replace(' 📚 Qwik Documentation', '')
86+
: undefined;
87+
88+
//decide whether or not to show dynamic OGimage or use docs default social card
89+
if (this.ogImgSubTitle == undefined || this.ogImgTitle == undefined) {
90+
this.imageURL = new URL(`/logos/social-card.jpg`, url).href;
91+
92+
return this.imageURL;
93+
} else {
94+
ogImageUrl.searchParams.set('title', this.ogImgTitle);
95+
ogImageUrl.searchParams.set('subtitle', this.ogImgSubTitle);
96+
// ogImageUrl.searchParams.set('level', this.routeLevel.toString());
97+
98+
this.imageURL = ogImageUrl.toString();
99+
100+
return this.imageURL;
101+
}
102+
},
103+
};
104+
52105
return (
53-
<QwikRouterProvider>
106+
<>
54107
<head>
55108
<meta charset="utf-8" />
109+
110+
<title>{title}</title>
111+
<meta name="description" content={description} />
112+
<link rel="canonical" href={head.frontmatter?.canonical || url.href} />
113+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
114+
<meta name="apple-mobile-web-app-title" content="Qwik" />
115+
<meta name="application-name" content="Qwik" />
116+
<meta name="apple-mobile-web-app-title" content="Qwik" />
117+
<meta name="theme-color" content="#006ce9" />
118+
<meta name="color-scheme" content="dark light" />
119+
120+
<link rel="apple-touch-icon" sizes="180x180" href="/favicons/apple-touch-icon.png" />
121+
<link rel="icon" href="/favicons/favicon.svg" type="image/svg+xml" />
122+
123+
{import.meta.env.PROD && (
124+
<>
125+
<Social title={title} description={description} href={url.href} ogImage={OGImage.URL} />
126+
<Vendor />
127+
</>
128+
)}
129+
130+
{/* The below are tags that were collected from all the `head` exports in the current route. */}
131+
{head.meta
132+
// Skip description because that was already added at the top
133+
.filter((s) => s.name !== 'description')
134+
.map((m, key) => (
135+
<meta key={key} {...m} />
136+
))}
137+
138+
{head.links.map((l, key) => (
139+
<link key={key} {...l} />
140+
))}
141+
142+
{head.styles.map((s, key) => (
143+
<style key={key} {...s.props} dangerouslySetInnerHTML={s.style} />
144+
))}
145+
146+
{head.scripts.map((s, key) => (
147+
<script key={key} {...s.props} dangerouslySetInnerHTML={s.script} />
148+
))}
149+
150+
<ThemeScript />
56151
<script dangerouslySetInnerHTML={uwu} />
57-
<RouterHead />
58152

59153
<ServiceWorkerRegister />
60154

@@ -67,10 +161,11 @@ export default component$(() => {
67161
'menu-open': store.sideMenuOpen,
68162
}}
69163
>
164+
{/* This renders the current route, including all Layout components. */}
70165
<RouterOutlet />
71166
<RealMetricsOptimization builderApiKey={BUILDER_PUBLIC_API_KEY} />
72167
</body>
73-
</QwikRouterProvider>
168+
</>
74169
);
75170
});
76171

packages/docs/src/routes/api/qwik-router/api.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -968,6 +968,20 @@
968968
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/runtime/src/use-functions.ts",
969969
"mdFile": "router.usepreventnavigate_.md"
970970
},
971+
{
972+
"name": "useQwikRouter",
973+
"id": "useqwikrouter",
974+
"hierarchy": [
975+
{
976+
"name": "useQwikRouter",
977+
"id": "useqwikrouter"
978+
}
979+
],
980+
"kind": "Function",
981+
"content": "```typescript\nuseQwikRouter: (props?: QwikRouterProps) => void\n```\n\n\n<table><thead><tr><th>\n\nParameter\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\nprops\n\n\n</td><td>\n\n[QwikRouterProps](#qwikrouterprops)\n\n\n</td><td>\n\n_(Optional)_\n\n\n</td></tr>\n</tbody></table>\n**Returns:**\n\nvoid",
982+
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/runtime/src/qwik-router-component.tsx",
983+
"mdFile": "router.useqwikrouter.md"
984+
},
971985
{
972986
"name": "valibot$",
973987
"id": "valibot_",

packages/docs/src/routes/api/qwik-router/index.mdx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2651,6 +2651,45 @@ void
26512651
26522652
[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/runtime/src/use-functions.ts)
26532653
2654+
## useQwikRouter
2655+
2656+
```typescript
2657+
useQwikRouter: (props?: QwikRouterProps) => void
2658+
```
2659+
2660+
<table><thead><tr><th>
2661+
2662+
Parameter
2663+
2664+
</th><th>
2665+
2666+
Type
2667+
2668+
</th><th>
2669+
2670+
Description
2671+
2672+
</th></tr></thead>
2673+
<tbody><tr><td>
2674+
2675+
props
2676+
2677+
</td><td>
2678+
2679+
[QwikRouterProps](#qwikrouterprops)
2680+
2681+
</td><td>
2682+
2683+
_(Optional)_
2684+
2685+
</td></tr>
2686+
</tbody></table>
2687+
**Returns:**
2688+
2689+
void
2690+
2691+
[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik-router/src/runtime/src/qwik-router-component.tsx)
2692+
26542693
## valibot$
26552694
26562695
> This API is provided as a beta preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.

packages/qwik-router/src/runtime/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export {
5555
QwikCityProvider,
5656
QwikRouterMockProvider,
5757
QwikRouterProvider,
58+
useQwikRouter,
5859
type QwikCityMockProps,
5960
type QwikCityProps,
6061
type QwikRouterMockProps,

packages/qwik-router/src/runtime/src/qwik-router-component.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ const preventNav: {
126126
const internalState = { navCount: 0 };
127127

128128
/** @public */
129-
export const QwikRouterProvider = component$<QwikRouterProps>((props) => {
129+
export const useQwikRouter = (props?: QwikRouterProps) => {
130130
useStyles$(`
131131
@layer qwik {
132132
@supports selector(html:active-view-transition-type(type)) {
@@ -722,7 +722,7 @@ export const QwikRouterProvider = component$<QwikRouterProps>((props) => {
722722
};
723723

724724
const _waitNextPage = () => {
725-
if (isServer || props.viewTransition === false) {
725+
if (isServer || props?.viewTransition === false) {
726726
return navigate();
727727
} else {
728728
const viewTransition = startViewTransition({
@@ -758,7 +758,11 @@ export const QwikRouterProvider = component$<QwikRouterProps>((props) => {
758758
run();
759759
}
760760
});
761+
};
761762

763+
/** @public */
764+
export const QwikRouterProvider = component$<QwikRouterProps>((props) => {
765+
useQwikRouter(props);
762766
return <Slot />;
763767
});
764768

packages/qwik-router/src/runtime/src/qwik-router.runtime.api.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,9 @@ export const usePreventNavigate$: (qrl: PreventNavigateCallback) => void;
527527
// @internal
528528
export const usePreventNavigateQrl: (fn: QRL<PreventNavigateCallback>) => void;
529529

530+
// @public (undocumented)
531+
export const useQwikRouter: (props?: QwikRouterProps) => void;
532+
530533
// Warning: (ae-forgotten-export) The symbol "ValibotConstructor" needs to be exported by the entry point index.d.ts
531534
//
532535
// @beta (undocumented)

starters/apps/empty/public/manifest.json

Lines changed: 0 additions & 9 deletions
This file was deleted.

starters/apps/empty/src/components/router-head/router-head.tsx

Lines changed: 0 additions & 32 deletions
This file was deleted.

0 commit comments

Comments
 (0)