create-thunderous 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/reference-project/package.json +2 -2
- package/reference-project/src/_layout.html +14 -26
- package/reference-project/src/about/about-data.server.ts +2 -2
- package/reference-project/src/about/contact.html +3 -1
- package/reference-project/src/about/index.html +3 -3
- package/reference-project/src/component-registry.ts +7 -0
- package/reference-project/src/components/crumb.ts +44 -0
- package/reference-project/src/components/feature.ts +147 -0
- package/reference-project/src/components/page.ts +58 -69
- package/reference-project/src/index.html +4 -4
- package/reference-project/src/theme.ts +57 -0
- package/reference-project/src/components/my-component.ts +0 -163
package/package.json
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"eslint": "^9.38.0",
|
|
29
29
|
"prettier": "^3.6.2",
|
|
30
30
|
"serve": "^14.2.5",
|
|
31
|
-
"thunderous-server": "^0.0.
|
|
31
|
+
"thunderous-server": "^0.0.4",
|
|
32
32
|
"tsx": "^4.20.6",
|
|
33
33
|
"typescript": "^5.9.3",
|
|
34
34
|
"typescript-eslint": "^8.46.2",
|
|
@@ -36,6 +36,6 @@
|
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"thunderous": "^2.4.2",
|
|
39
|
-
"thunderous-csr": "^0.0.
|
|
39
|
+
"thunderous-csr": "^0.0.3"
|
|
40
40
|
}
|
|
41
41
|
}
|
|
@@ -6,46 +6,34 @@
|
|
|
6
6
|
<link rel="stylesheet" href="/global.css" />
|
|
7
7
|
</head>
|
|
8
8
|
<body>
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
<!-- This view element is used for CSR navigation, only this element will be replaced when navigating -->
|
|
10
|
+
<t-view id="main-content">
|
|
11
|
+
<x-page expr:prominent="pathname === '/'">
|
|
12
|
+
<h1 slot="header">
|
|
13
|
+
<script expr>
|
|
14
|
+
title === '' ? 'Home' : title;
|
|
15
|
+
</script>
|
|
16
|
+
</h1>
|
|
15
17
|
|
|
16
|
-
<!-- We can use multiple views to render different content in different regions - see main-content for more details -->
|
|
17
|
-
<t-view id="breadcrumbs">
|
|
18
18
|
<nav slot="header">
|
|
19
19
|
<p>
|
|
20
20
|
<script expr>
|
|
21
|
-
breadcrumbs.map(
|
|
22
|
-
(crumb, index) => html`
|
|
23
|
-
<a href="${crumb.pathname}">${crumb.name}</a>
|
|
24
|
-
${index < breadcrumbs.length - 1 ? html`<span> | </span>` : ''}
|
|
25
|
-
`,
|
|
26
|
-
);
|
|
21
|
+
breadcrumbs.map((crumb) => html`<x-crumb href="${crumb.pathname}">${crumb.name}</x-crumb>`);
|
|
27
22
|
</script>
|
|
28
23
|
</p>
|
|
29
24
|
</nav>
|
|
30
|
-
</t-view>
|
|
31
25
|
|
|
32
|
-
<!-- This view element is used for CSR navigation, only this element will be replaced when navigating -->
|
|
33
|
-
<t-view id="main-content">
|
|
34
26
|
<!-- This is where page content is inserted when this layout is used -->
|
|
35
27
|
<slot></slot>
|
|
36
|
-
</
|
|
37
|
-
</t-
|
|
28
|
+
</x-page>
|
|
29
|
+
</t-view>
|
|
38
30
|
|
|
39
|
-
<script isomorphic>
|
|
40
|
-
import { View } from 'thunderous-csr';
|
|
41
|
-
import { Page } from './components/page';
|
|
42
|
-
View.define('t-view');
|
|
43
|
-
Page.define('t-page');
|
|
44
|
-
</script>
|
|
31
|
+
<script isomorphic src="/component-registry.ts"></script>
|
|
45
32
|
|
|
46
|
-
<!-- This makes some handy data available to the template, like breadcrumbs -->
|
|
47
33
|
<script server>
|
|
48
34
|
import { getMeta } from 'thunderous-server';
|
|
35
|
+
|
|
36
|
+
// This makes some handy data available to the template, like breadcrumbs
|
|
49
37
|
export default getMeta();
|
|
50
38
|
</script>
|
|
51
39
|
</body>
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
// that is, any file ending with .server.ts will ONLY be evaluated on the server.
|
|
3
3
|
// This is useful to avoid inadvertently exposing sensitive data to the client.
|
|
4
4
|
export default {
|
|
5
|
-
|
|
6
|
-
description: 'We build fast static sites.',
|
|
5
|
+
title: 'About Us',
|
|
6
|
+
description: 'We build fast static sites with Thunderous.',
|
|
7
7
|
};
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
<h2>
|
|
5
5
|
<script expr>
|
|
6
|
-
|
|
6
|
+
title;
|
|
7
7
|
</script>
|
|
8
8
|
</h2>
|
|
9
9
|
<p>
|
|
@@ -12,5 +12,5 @@
|
|
|
12
12
|
</script>
|
|
13
13
|
</p>
|
|
14
14
|
|
|
15
|
-
<!-- <script server> tags also support files via the
|
|
16
|
-
<script server
|
|
15
|
+
<!-- <script server> tags also support files via the src attribute -->
|
|
16
|
+
<script server src="./about-data.server.ts"></script>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { createSignal, css, customElement, html } from 'thunderous';
|
|
2
|
+
import { theme } from '../theme';
|
|
3
|
+
|
|
4
|
+
export const Crumb = customElement(({ adoptStyleSheet, attrSignals }) => {
|
|
5
|
+
const [getHref] = attrSignals['href'] ?? createSignal('');
|
|
6
|
+
|
|
7
|
+
adoptStyleSheet(theme);
|
|
8
|
+
adoptStyleSheet(stylesheet);
|
|
9
|
+
|
|
10
|
+
return html`
|
|
11
|
+
<span class="crumb">
|
|
12
|
+
<a href="${getHref()}">
|
|
13
|
+
<slot></slot>
|
|
14
|
+
</a>
|
|
15
|
+
</span>
|
|
16
|
+
`;
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const stylesheet = css`
|
|
20
|
+
a {
|
|
21
|
+
color: var(--color-brand-1);
|
|
22
|
+
text-decoration: none;
|
|
23
|
+
font-weight: 600;
|
|
24
|
+
transition: color 180ms ease;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
a:hover,
|
|
28
|
+
a:focus-visible {
|
|
29
|
+
color: var(--color-brand-1-1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
a:focus-visible {
|
|
33
|
+
outline: 2px solid color-mix(in srgb, var(--color-brand-1) 50%, white 20%);
|
|
34
|
+
outline-offset: 3px;
|
|
35
|
+
border-radius: 0.25rem;
|
|
36
|
+
}
|
|
37
|
+
:host(:not(:last-child)) {
|
|
38
|
+
.crumb::after {
|
|
39
|
+
content: ' > ';
|
|
40
|
+
display: inline-block;
|
|
41
|
+
padding: 0 0.5em;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
`;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { customElement, html, css, createSignal } from 'thunderous';
|
|
2
|
+
import { theme } from '../theme';
|
|
3
|
+
|
|
4
|
+
export const Feature = customElement(({ adoptStyleSheet, attrSignals }) => {
|
|
5
|
+
const [getHref] = attrSignals['href'] ?? createSignal('');
|
|
6
|
+
const [getButtonText] = attrSignals['buttontext'] ?? createSignal('Learn More');
|
|
7
|
+
|
|
8
|
+
adoptStyleSheet(theme);
|
|
9
|
+
adoptStyleSheet(stylesheet);
|
|
10
|
+
|
|
11
|
+
return html`
|
|
12
|
+
<div class="feature">
|
|
13
|
+
<slot></slot>
|
|
14
|
+
${getHref() !== '' ? html`<a href=${getHref()}>${getButtonText()}</a>` : ''}
|
|
15
|
+
</div>
|
|
16
|
+
`;
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const stylesheet = css`
|
|
20
|
+
:host {
|
|
21
|
+
display: block;
|
|
22
|
+
font-size: 2rem;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
::slotted(*) {
|
|
26
|
+
margin: 0;
|
|
27
|
+
color: var(--color-neutral-2);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.feature {
|
|
31
|
+
text-align: center;
|
|
32
|
+
position: relative;
|
|
33
|
+
overflow: hidden;
|
|
34
|
+
padding: 2em 3em;
|
|
35
|
+
border-radius: 20px;
|
|
36
|
+
border: 1px solid var(--color-surface-2-2);
|
|
37
|
+
background:
|
|
38
|
+
linear-gradient(135deg, rgba(99, 102, 241, 0.22), rgba(14, 165, 233, 0.16)),
|
|
39
|
+
linear-gradient(180deg, var(--color-surface-2), var(--color-surface-2-1));
|
|
40
|
+
backdrop-filter: blur(18px) saturate(160%);
|
|
41
|
+
-webkit-backdrop-filter: blur(18px) saturate(160%);
|
|
42
|
+
box-shadow: var(--shadow-2);
|
|
43
|
+
isolation: isolate;
|
|
44
|
+
margin: 1em auto;
|
|
45
|
+
max-width: 20em;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.feature::before,
|
|
49
|
+
.feature::after {
|
|
50
|
+
content: '';
|
|
51
|
+
position: absolute;
|
|
52
|
+
inset: auto;
|
|
53
|
+
border-radius: 999px;
|
|
54
|
+
filter: blur(10px);
|
|
55
|
+
opacity: 0.8;
|
|
56
|
+
z-index: -1;
|
|
57
|
+
pointer-events: none;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.feature::before {
|
|
61
|
+
top: -60px;
|
|
62
|
+
right: -40px;
|
|
63
|
+
width: 180px;
|
|
64
|
+
height: 180px;
|
|
65
|
+
background: radial-gradient(circle, rgba(125, 211, 252, 0.35), transparent 65%);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.feature::after {
|
|
69
|
+
bottom: -70px;
|
|
70
|
+
left: -30px;
|
|
71
|
+
width: 160px;
|
|
72
|
+
height: 160px;
|
|
73
|
+
background: radial-gradient(circle, rgba(196, 181, 253, 0.28), transparent 65%);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.feature p {
|
|
77
|
+
margin: 0;
|
|
78
|
+
font-size: 1rem;
|
|
79
|
+
line-height: 1.75;
|
|
80
|
+
letter-spacing: 0.01em;
|
|
81
|
+
color: var(--color-neutral-2);
|
|
82
|
+
text-wrap: pretty;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.feature a {
|
|
86
|
+
display: inline-flex;
|
|
87
|
+
align-items: center;
|
|
88
|
+
justify-content: center;
|
|
89
|
+
gap: 0.5em;
|
|
90
|
+
margin: 1.5em 0 0.5em;
|
|
91
|
+
padding: 0.85em 1.25em;
|
|
92
|
+
border-radius: 999px;
|
|
93
|
+
border: 1px solid color-mix(in srgb, var(--color-surface-2-2) 85%, white 15%);
|
|
94
|
+
background:
|
|
95
|
+
linear-gradient(135deg, var(--color-brand-2), var(--color-brand-2-1)),
|
|
96
|
+
linear-gradient(180deg, var(--color-surface-2), var(--color-surface-2-1));
|
|
97
|
+
box-shadow:
|
|
98
|
+
0 10px 30px color-mix(in srgb, var(--color-brand-2-1) 28%, transparent),
|
|
99
|
+
inset 0 1px 0 color-mix(in srgb, white 35%, transparent);
|
|
100
|
+
color: var(--color-neutral-2);
|
|
101
|
+
font-weight: 700;
|
|
102
|
+
line-height: 1;
|
|
103
|
+
letter-spacing: 0.01em;
|
|
104
|
+
text-decoration: none;
|
|
105
|
+
white-space: nowrap;
|
|
106
|
+
transition:
|
|
107
|
+
transform 180ms ease,
|
|
108
|
+
box-shadow 180ms ease,
|
|
109
|
+
filter 180ms ease,
|
|
110
|
+
border-color 180ms ease,
|
|
111
|
+
color 180ms ease;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.feature a:hover,
|
|
115
|
+
.feature a:focus-visible {
|
|
116
|
+
transform: translateY(-2px);
|
|
117
|
+
filter: brightness(1.05);
|
|
118
|
+
border-color: color-mix(in srgb, var(--color-brand-2) 55%, var(--color-surface-2-2));
|
|
119
|
+
box-shadow:
|
|
120
|
+
0 16px 36px color-mix(in srgb, var(--color-brand-2-1) 36%, transparent),
|
|
121
|
+
inset 0 1px 0 color-mix(in srgb, white 45%, transparent);
|
|
122
|
+
color: var(--color-neutral-2);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.feature a:active {
|
|
126
|
+
transform: translateY(0);
|
|
127
|
+
box-shadow:
|
|
128
|
+
0 8px 20px color-mix(in srgb, var(--color-brand-2-1) 22%, transparent),
|
|
129
|
+
inset 0 1px 0 color-mix(in srgb, white 25%, transparent);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.feature a:focus-visible {
|
|
133
|
+
outline: 2px solid color-mix(in srgb, var(--color-brand-2) 65%, white 35%);
|
|
134
|
+
outline-offset: 4px;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.feature a::after {
|
|
138
|
+
content: '→';
|
|
139
|
+
font-size: 0.95em;
|
|
140
|
+
transition: transform 180ms ease;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.feature a:hover::after,
|
|
144
|
+
.feature a:focus-visible::after {
|
|
145
|
+
transform: translateX(3px);
|
|
146
|
+
}
|
|
147
|
+
`;
|
|
@@ -1,52 +1,41 @@
|
|
|
1
1
|
import { customElement, html, css } from 'thunderous';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
},
|
|
34
|
-
);
|
|
2
|
+
import { theme } from '../theme';
|
|
3
|
+
|
|
4
|
+
export const Page = customElement(({ adoptStyleSheet }) => {
|
|
5
|
+
adoptStyleSheet(theme);
|
|
6
|
+
adoptStyleSheet(stylesheet);
|
|
7
|
+
|
|
8
|
+
return html`
|
|
9
|
+
<div class="page">
|
|
10
|
+
<header>
|
|
11
|
+
<slot name="header"></slot>
|
|
12
|
+
<nav class="header-nav">
|
|
13
|
+
<a href="/">Home</a>
|
|
14
|
+
<a href="/about">About Us</a>
|
|
15
|
+
<a href="/about/contact">Contact Us</a>
|
|
16
|
+
</nav>
|
|
17
|
+
</header>
|
|
18
|
+
<main>
|
|
19
|
+
<slot></slot>
|
|
20
|
+
</main>
|
|
21
|
+
<footer>
|
|
22
|
+
<nav class="footer-nav">
|
|
23
|
+
<a href="/">Home</a> | <a href="/about">About Us</a> | <a href="/about/contact">Contact Us</a>
|
|
24
|
+
</nav>
|
|
25
|
+
<slot name="footer"></slot>
|
|
26
|
+
<small
|
|
27
|
+
>© ${new Date().getFullYear()} — Powered by <a href="https://thunderous.dev">Thunderous</a></small
|
|
28
|
+
>
|
|
29
|
+
</footer>
|
|
30
|
+
</div>
|
|
31
|
+
`;
|
|
32
|
+
});
|
|
35
33
|
|
|
36
34
|
const stylesheet = css`
|
|
37
35
|
:host {
|
|
38
36
|
display: block;
|
|
39
37
|
height: 100%;
|
|
40
38
|
width: 100%;
|
|
41
|
-
|
|
42
|
-
--bg-1: rgba(255, 255, 255, 0.06);
|
|
43
|
-
--bg-2: rgba(255, 255, 255, 0.03);
|
|
44
|
-
--border: rgba(255, 255, 255, 0.1);
|
|
45
|
-
--text: #e5eefc;
|
|
46
|
-
--muted: #9fb0d1;
|
|
47
|
-
--link: #8fb4ff;
|
|
48
|
-
--link-hover: #2a4692;
|
|
49
|
-
--shadow: 0 10px 30px rgba(0, 0, 0, 0.18);
|
|
50
39
|
}
|
|
51
40
|
.page {
|
|
52
41
|
display: grid;
|
|
@@ -55,10 +44,10 @@ const stylesheet = css`
|
|
|
55
44
|
min-width: 320px;
|
|
56
45
|
min-height: 100vh;
|
|
57
46
|
background:
|
|
58
|
-
radial-gradient(circle at top left,
|
|
59
|
-
radial-gradient(circle at bottom right,
|
|
60
|
-
linear-gradient(180deg,
|
|
61
|
-
color:
|
|
47
|
+
radial-gradient(circle at top left, var(--color-accent-1), transparent 30%),
|
|
48
|
+
radial-gradient(circle at bottom right, var(--color-accent-1-1), transparent 35%),
|
|
49
|
+
linear-gradient(180deg, var(--color-page-1) 0%, var(--color-page-1-1) 45%, var(--color-page-1-2) 100%);
|
|
50
|
+
color: var(--color-page-1-c);
|
|
62
51
|
font-family: 'Plus Jakarta Sans', Inter, ui-sans-serif, system-ui, sans-serif;
|
|
63
52
|
font-size: 1rem;
|
|
64
53
|
line-height: 1.6;
|
|
@@ -69,7 +58,7 @@ const stylesheet = css`
|
|
|
69
58
|
-moz-osx-font-smoothing: grayscale;
|
|
70
59
|
-webkit-font-smoothing: antialiased;
|
|
71
60
|
}
|
|
72
|
-
.page
|
|
61
|
+
:host([prominent]) .page {
|
|
73
62
|
align-items: center;
|
|
74
63
|
}
|
|
75
64
|
.header-nav {
|
|
@@ -78,16 +67,16 @@ const stylesheet = css`
|
|
|
78
67
|
gap: 0.75rem;
|
|
79
68
|
align-items: center;
|
|
80
69
|
padding: 0.75rem 1rem;
|
|
81
|
-
border: 1px solid var(--
|
|
70
|
+
border: 1px solid var(--color-surface-1-2);
|
|
82
71
|
border-radius: 999px;
|
|
83
72
|
background: linear-gradient(
|
|
84
73
|
135deg,
|
|
85
|
-
color-mix(in srgb, var(--
|
|
86
|
-
color-mix(in srgb, var(--
|
|
74
|
+
color-mix(in srgb, var(--color-surface-1) 88%, transparent),
|
|
75
|
+
color-mix(in srgb, var(--color-surface-1-1) 92%, transparent)
|
|
87
76
|
);
|
|
88
77
|
backdrop-filter: blur(18px) saturate(160%);
|
|
89
78
|
-webkit-backdrop-filter: blur(18px) saturate(160%);
|
|
90
|
-
box-shadow: var(--shadow);
|
|
79
|
+
box-shadow: var(--shadow-1);
|
|
91
80
|
}
|
|
92
81
|
|
|
93
82
|
.header-nav a {
|
|
@@ -97,7 +86,7 @@ const stylesheet = css`
|
|
|
97
86
|
justify-content: center;
|
|
98
87
|
padding: 0.7rem 1rem;
|
|
99
88
|
border-radius: 999px;
|
|
100
|
-
color: var(--
|
|
89
|
+
color: var(--color-neutral-1);
|
|
101
90
|
font-weight: 600;
|
|
102
91
|
line-height: 1;
|
|
103
92
|
letter-spacing: 0.01em;
|
|
@@ -114,7 +103,7 @@ const stylesheet = css`
|
|
|
114
103
|
position: absolute;
|
|
115
104
|
inset: 0;
|
|
116
105
|
border-radius: inherit;
|
|
117
|
-
background: linear-gradient(135deg, var(--
|
|
106
|
+
background: linear-gradient(135deg, var(--color-brand-1), var(--color-brand-1-1));
|
|
118
107
|
opacity: 0;
|
|
119
108
|
transform: scale(0.96);
|
|
120
109
|
transition:
|
|
@@ -125,10 +114,10 @@ const stylesheet = css`
|
|
|
125
114
|
|
|
126
115
|
.header-nav a:hover,
|
|
127
116
|
.header-nav a:focus-visible {
|
|
128
|
-
color: var(--
|
|
117
|
+
color: var(--color-neutral-1);
|
|
129
118
|
transform: translateY(-1px);
|
|
130
119
|
box-shadow:
|
|
131
|
-
0 10px 24px color-mix(in srgb, var(--
|
|
120
|
+
0 10px 24px color-mix(in srgb, var(--color-brand-1-1) 22%, transparent),
|
|
132
121
|
inset 0 1px 0 color-mix(in srgb, white 30%, transparent);
|
|
133
122
|
}
|
|
134
123
|
|
|
@@ -143,15 +132,15 @@ const stylesheet = css`
|
|
|
143
132
|
}
|
|
144
133
|
|
|
145
134
|
.header-nav a:focus-visible {
|
|
146
|
-
outline: 2px solid color-mix(in srgb, var(--
|
|
135
|
+
outline: 2px solid color-mix(in srgb, var(--color-brand-1) 65%, white 35%);
|
|
147
136
|
outline-offset: 4px;
|
|
148
137
|
}
|
|
149
138
|
|
|
150
139
|
header {
|
|
151
|
-
padding: 1em 1.5em;
|
|
140
|
+
padding: 1em 1.5em 0;
|
|
152
141
|
}
|
|
153
142
|
main {
|
|
154
|
-
padding:
|
|
143
|
+
padding: 2em 1.5em 4em;
|
|
155
144
|
}
|
|
156
145
|
|
|
157
146
|
footer {
|
|
@@ -159,9 +148,9 @@ const stylesheet = css`
|
|
|
159
148
|
place-items: center;
|
|
160
149
|
gap: 1.5rem;
|
|
161
150
|
padding: 2rem 1.5rem;
|
|
162
|
-
border-top: 1px solid var(--
|
|
163
|
-
background: linear-gradient(180deg, var(--
|
|
164
|
-
color: var(--
|
|
151
|
+
border-top: 1px solid var(--color-surface-1-2);
|
|
152
|
+
background: linear-gradient(180deg, var(--color-surface-1-1), transparent);
|
|
153
|
+
color: var(--color-neutral-1-1);
|
|
165
154
|
}
|
|
166
155
|
|
|
167
156
|
.footer-nav {
|
|
@@ -184,7 +173,7 @@ const stylesheet = css`
|
|
|
184
173
|
align-items: center;
|
|
185
174
|
padding: 0.35rem 0.2rem;
|
|
186
175
|
border-radius: 0.5rem;
|
|
187
|
-
color: var(--
|
|
176
|
+
color: var(--color-neutral-1-1);
|
|
188
177
|
font-weight: 500;
|
|
189
178
|
text-decoration: none;
|
|
190
179
|
transition:
|
|
@@ -198,8 +187,8 @@ const stylesheet = css`
|
|
|
198
187
|
|
|
199
188
|
.footer-nav a:hover,
|
|
200
189
|
.footer-nav a:focus-visible {
|
|
201
|
-
color: var(--
|
|
202
|
-
background: color-mix(in srgb, var(--
|
|
190
|
+
color: var(--color-neutral-1);
|
|
191
|
+
background: color-mix(in srgb, var(--color-surface-1) 70%, transparent);
|
|
203
192
|
box-shadow: none;
|
|
204
193
|
transform: none;
|
|
205
194
|
}
|
|
@@ -209,19 +198,19 @@ const stylesheet = css`
|
|
|
209
198
|
}
|
|
210
199
|
|
|
211
200
|
.footer-nav a:focus-visible {
|
|
212
|
-
outline: 2px solid color-mix(in srgb, var(--
|
|
201
|
+
outline: 2px solid color-mix(in srgb, var(--color-brand-1) 50%, white 20%);
|
|
213
202
|
outline-offset: 3px;
|
|
214
203
|
}
|
|
215
204
|
|
|
216
205
|
footer small {
|
|
217
206
|
display: block;
|
|
218
|
-
color: var(--
|
|
207
|
+
color: var(--color-neutral-1-1);
|
|
219
208
|
font-size: 0.875rem;
|
|
220
209
|
line-height: 1.6;
|
|
221
210
|
}
|
|
222
211
|
|
|
223
212
|
footer small a {
|
|
224
|
-
color: var(--
|
|
213
|
+
color: var(--color-brand-1);
|
|
225
214
|
text-decoration: none;
|
|
226
215
|
font-weight: 600;
|
|
227
216
|
transition: color 180ms ease;
|
|
@@ -229,11 +218,11 @@ const stylesheet = css`
|
|
|
229
218
|
|
|
230
219
|
footer small a:hover,
|
|
231
220
|
footer small a:focus-visible {
|
|
232
|
-
color: var(--
|
|
221
|
+
color: var(--color-brand-1-1);
|
|
233
222
|
}
|
|
234
223
|
|
|
235
224
|
footer small a:focus-visible {
|
|
236
|
-
outline: 2px solid color-mix(in srgb, var(--
|
|
225
|
+
outline: 2px solid color-mix(in srgb, var(--color-brand-1) 50%, white 20%);
|
|
237
226
|
outline-offset: 3px;
|
|
238
227
|
border-radius: 0.25rem;
|
|
239
228
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<?layout href="_layout.html">
|
|
2
2
|
|
|
3
|
-
<
|
|
3
|
+
<x-feature href="https://thunderous.dev" buttontext="Read the Docs">
|
|
4
4
|
<script expr>
|
|
5
5
|
// These <script expr> tags are evaluated in-place as expressions and replaced by the result.
|
|
6
6
|
html`<p>The ${stack} stack is dead simple and feels like there's no framework at all.</p>`;
|
|
7
7
|
</script>
|
|
8
|
-
</
|
|
8
|
+
</x-feature>
|
|
9
9
|
|
|
10
10
|
<script>
|
|
11
11
|
// This is ordinary client-only code.
|
|
@@ -23,10 +23,10 @@
|
|
|
23
23
|
// This code runs on both the client and server.
|
|
24
24
|
// Isomorphic scripts are always modules.
|
|
25
25
|
// Since it runs on the client, it will also vendorize NPM dependencies.
|
|
26
|
-
import {
|
|
26
|
+
import { Feature } from './components/feature';
|
|
27
27
|
|
|
28
28
|
// Thunderous components render declarative shadow DOM when defined on the server.
|
|
29
|
-
|
|
29
|
+
Feature.define('x-feature');
|
|
30
30
|
</script>
|
|
31
31
|
|
|
32
32
|
<script server>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { css } from "thunderous";
|
|
2
|
+
|
|
3
|
+
export const theme = css`
|
|
4
|
+
:host {
|
|
5
|
+
--color-page-1: #0f172a;
|
|
6
|
+
--color-page-1-1: #111827;
|
|
7
|
+
--color-page-1-2: #0b1120;
|
|
8
|
+
--color-page-1-c: #eaf2ff;
|
|
9
|
+
--color-accent-1: rgba(99, 102, 241, 0.22);
|
|
10
|
+
--color-accent-1-1: rgba(14, 165, 233, 0.18);
|
|
11
|
+
|
|
12
|
+
--color-surface-1: rgba(255, 255, 255, 0.06);
|
|
13
|
+
--color-surface-1-1: rgba(255, 255, 255, 0.03);
|
|
14
|
+
--color-surface-1-2: rgba(255, 255, 255, 0.1);
|
|
15
|
+
--color-neutral-1: #e5eefc;
|
|
16
|
+
--color-neutral-1-1: #9fb0d1;
|
|
17
|
+
--color-brand-1: #8fb4ff;
|
|
18
|
+
--color-brand-1-1: #2a4692;
|
|
19
|
+
--shadow-1: 0 10px 30px rgba(0, 0, 0, 0.18);
|
|
20
|
+
|
|
21
|
+
--color-surface-2: rgba(255, 255, 255, 0.72);
|
|
22
|
+
--color-surface-2-1: rgba(255, 255, 255, 0.5);
|
|
23
|
+
--color-surface-2-2: rgba(255, 255, 255, 0.35);
|
|
24
|
+
--color-neutral-2: #1e293b;
|
|
25
|
+
--color-neutral-2-1: #b8c7e6;
|
|
26
|
+
--color-brand-2: #7dd3fc;
|
|
27
|
+
--color-brand-2-1: #c4b5fd;
|
|
28
|
+
--shadow-2: 0 18px 50px rgba(15, 23, 42, 0.35);
|
|
29
|
+
|
|
30
|
+
@media (prefers-color-scheme: light) {
|
|
31
|
+
--color-page-1: #f0f4fa;
|
|
32
|
+
--color-page-1-1: #e8edf5;
|
|
33
|
+
--color-page-1-2: #f5f7fb;
|
|
34
|
+
--color-page-1-c: #1e293b;
|
|
35
|
+
--color-accent-1: rgba(99, 102, 241, 0.1);
|
|
36
|
+
--color-accent-1-1: rgba(14, 165, 233, 0.08);
|
|
37
|
+
|
|
38
|
+
--color-surface-1: rgba(255, 255, 255, 0.7);
|
|
39
|
+
--color-surface-1-1: rgba(255, 255, 255, 0.5);
|
|
40
|
+
--color-surface-1-2: rgba(99, 102, 241, 0.16);
|
|
41
|
+
--color-neutral-1: #1e293b;
|
|
42
|
+
--color-neutral-1-1: #475569;
|
|
43
|
+
--color-brand-1: #2563eb;
|
|
44
|
+
--color-brand-1-1: #7c3aed;
|
|
45
|
+
--shadow-1: 0 10px 30px rgba(51, 65, 85, 0.1);
|
|
46
|
+
|
|
47
|
+
--color-surface-2: rgba(255, 255, 255, 0.92);
|
|
48
|
+
--color-surface-2-1: rgba(245, 248, 255, 0.85);
|
|
49
|
+
--color-surface-2-2: rgba(99, 102, 241, 0.18);
|
|
50
|
+
--color-neutral-2: #1e293b;
|
|
51
|
+
--color-neutral-2-1: #475569;
|
|
52
|
+
--color-brand-2: #4f46e5;
|
|
53
|
+
--color-brand-2-1: #7c3aed;
|
|
54
|
+
--shadow-2: 0 18px 40px rgba(51, 65, 85, 0.12);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
`;
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import { customElement, html, css } from 'thunderous';
|
|
2
|
-
|
|
3
|
-
export const MyComponent = customElement(({ clientOnlyCallback, adoptStyleSheet }) => {
|
|
4
|
-
clientOnlyCallback(() => {
|
|
5
|
-
console.log('MyComponent has been mounted on the client side.');
|
|
6
|
-
});
|
|
7
|
-
adoptStyleSheet(stylesheet);
|
|
8
|
-
return html`
|
|
9
|
-
<div class="my-component">
|
|
10
|
-
<slot></slot>
|
|
11
|
-
<a href="https://thunderous.dev">Learn More</a>
|
|
12
|
-
</div>
|
|
13
|
-
`;
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
const stylesheet = css`
|
|
17
|
-
:host {
|
|
18
|
-
display: block;
|
|
19
|
-
font-size: 2rem;
|
|
20
|
-
|
|
21
|
-
--bg-1: rgba(255, 255, 255, 0.72);
|
|
22
|
-
--bg-2: rgba(255, 255, 255, 0.5);
|
|
23
|
-
--border: rgba(255, 255, 255, 0.35);
|
|
24
|
-
--text: #1e293b;
|
|
25
|
-
--muted: #b8c7e6;
|
|
26
|
-
--link: #7dd3fc;
|
|
27
|
-
--link-hover: #c4b5fd;
|
|
28
|
-
--shadow: 0 18px 50px rgba(15, 23, 42, 0.35);
|
|
29
|
-
|
|
30
|
-
@media (prefers-color-scheme: light) {
|
|
31
|
-
--bg-1: rgba(255, 255, 255, 0.88);
|
|
32
|
-
--bg-2: rgba(240, 249, 255, 0.74);
|
|
33
|
-
--border: rgba(99, 102, 241, 0.16);
|
|
34
|
-
--text: #1e293b;
|
|
35
|
-
--muted: #475569;
|
|
36
|
-
--link: #2563eb;
|
|
37
|
-
--link-hover: #7c3aed;
|
|
38
|
-
--shadow: 0 18px 40px rgba(51, 65, 85, 0.14);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
::slotted(*) {
|
|
43
|
-
margin: 0;
|
|
44
|
-
color: var(--text);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
.my-component {
|
|
48
|
-
text-align: center;
|
|
49
|
-
position: relative;
|
|
50
|
-
overflow: hidden;
|
|
51
|
-
padding: 1.25em 1.5em;
|
|
52
|
-
border-radius: 20px;
|
|
53
|
-
border: 1px solid var(--border);
|
|
54
|
-
background:
|
|
55
|
-
linear-gradient(135deg, rgba(99, 102, 241, 0.22), rgba(14, 165, 233, 0.16)),
|
|
56
|
-
linear-gradient(180deg, var(--bg-1), var(--bg-2));
|
|
57
|
-
backdrop-filter: blur(18px) saturate(160%);
|
|
58
|
-
-webkit-backdrop-filter: blur(18px) saturate(160%);
|
|
59
|
-
box-shadow: var(--shadow);
|
|
60
|
-
isolation: isolate;
|
|
61
|
-
margin: 1em auto;
|
|
62
|
-
max-width: 20em;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
.my-component::before,
|
|
66
|
-
.my-component::after {
|
|
67
|
-
content: '';
|
|
68
|
-
position: absolute;
|
|
69
|
-
inset: auto;
|
|
70
|
-
border-radius: 999px;
|
|
71
|
-
filter: blur(10px);
|
|
72
|
-
opacity: 0.8;
|
|
73
|
-
z-index: -1;
|
|
74
|
-
pointer-events: none;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
.my-component::before {
|
|
78
|
-
top: -60px;
|
|
79
|
-
right: -40px;
|
|
80
|
-
width: 180px;
|
|
81
|
-
height: 180px;
|
|
82
|
-
background: radial-gradient(circle, rgba(125, 211, 252, 0.35), transparent 65%);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
.my-component::after {
|
|
86
|
-
bottom: -70px;
|
|
87
|
-
left: -30px;
|
|
88
|
-
width: 160px;
|
|
89
|
-
height: 160px;
|
|
90
|
-
background: radial-gradient(circle, rgba(196, 181, 253, 0.28), transparent 65%);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
.my-component p {
|
|
94
|
-
margin: 0;
|
|
95
|
-
font-size: 1rem;
|
|
96
|
-
line-height: 1.75;
|
|
97
|
-
letter-spacing: 0.01em;
|
|
98
|
-
color: var(--text);
|
|
99
|
-
text-wrap: pretty;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
.my-component a {
|
|
103
|
-
display: inline-flex;
|
|
104
|
-
align-items: center;
|
|
105
|
-
justify-content: center;
|
|
106
|
-
gap: 0.5rem;
|
|
107
|
-
margin-top: 1rem;
|
|
108
|
-
padding: 0.85rem 1.25rem;
|
|
109
|
-
border-radius: 999px;
|
|
110
|
-
border: 1px solid color-mix(in srgb, var(--border) 85%, white 15%);
|
|
111
|
-
background:
|
|
112
|
-
linear-gradient(135deg, var(--link), var(--link-hover)), linear-gradient(180deg, var(--bg-1), var(--bg-2));
|
|
113
|
-
box-shadow:
|
|
114
|
-
0 10px 30px color-mix(in srgb, var(--link-hover) 28%, transparent),
|
|
115
|
-
inset 0 1px 0 color-mix(in srgb, white 35%, transparent);
|
|
116
|
-
color: var(--text);
|
|
117
|
-
font-weight: 700;
|
|
118
|
-
line-height: 1;
|
|
119
|
-
letter-spacing: 0.01em;
|
|
120
|
-
text-decoration: none;
|
|
121
|
-
white-space: nowrap;
|
|
122
|
-
transition:
|
|
123
|
-
transform 180ms ease,
|
|
124
|
-
box-shadow 180ms ease,
|
|
125
|
-
filter 180ms ease,
|
|
126
|
-
border-color 180ms ease,
|
|
127
|
-
color 180ms ease;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
.my-component a:hover,
|
|
131
|
-
.my-component a:focus-visible {
|
|
132
|
-
transform: translateY(-2px);
|
|
133
|
-
filter: brightness(1.05);
|
|
134
|
-
border-color: color-mix(in srgb, var(--link) 55%, var(--border));
|
|
135
|
-
box-shadow:
|
|
136
|
-
0 16px 36px color-mix(in srgb, var(--link-hover) 36%, transparent),
|
|
137
|
-
inset 0 1px 0 color-mix(in srgb, white 45%, transparent);
|
|
138
|
-
color: var(--text);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
.my-component a:active {
|
|
142
|
-
transform: translateY(0);
|
|
143
|
-
box-shadow:
|
|
144
|
-
0 8px 20px color-mix(in srgb, var(--link-hover) 22%, transparent),
|
|
145
|
-
inset 0 1px 0 color-mix(in srgb, white 25%, transparent);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
.my-component a:focus-visible {
|
|
149
|
-
outline: 2px solid color-mix(in srgb, var(--link) 65%, white 35%);
|
|
150
|
-
outline-offset: 4px;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
.my-component a::after {
|
|
154
|
-
content: '→';
|
|
155
|
-
font-size: 0.95em;
|
|
156
|
-
transition: transform 180ms ease;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
.my-component a:hover::after,
|
|
160
|
-
.my-component a:focus-visible::after {
|
|
161
|
-
transform: translateX(3px);
|
|
162
|
-
}
|
|
163
|
-
`;
|