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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-thunderous",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "A CLI tool to scaffold a new project using the Thunderous stack.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -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.2",
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.2"
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
- <t-page>
10
- <h1 slot="header">
11
- <script expr>
12
- title === '' ? 'Home' : title;
13
- </script>
14
- </h1>
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
- </t-view>
37
- </t-page>
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
- teamName: 'Thunderous Team',
6
- description: 'We build fast static sites.',
5
+ title: 'About Us',
6
+ description: 'We build fast static sites with Thunderous.',
7
7
  };
@@ -3,4 +3,6 @@
3
3
  <!-- This directly reflects the native behavior of static sites. No complex route configs needed! -->
4
4
  <?layout href="../_layout.html">
5
5
 
6
- <p>Contact Us</p>
6
+ <h2>Contact Us</h2>
7
+
8
+ <p>Get in touch with us at contact@example.com.</p>
@@ -3,7 +3,7 @@
3
3
 
4
4
  <h2>
5
5
  <script expr>
6
- teamName;
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 href attribute -->
16
- <script server href="./about-data.server.ts"></script>
15
+ <!-- <script server> tags also support files via the src attribute -->
16
+ <script server src="./about-data.server.ts"></script>
@@ -0,0 +1,7 @@
1
+ import { View } from "thunderous-csr";
2
+ import { Page } from "./components/page";
3
+ import { Crumb } from "./components/crumb";
4
+
5
+ View.define("t-view");
6
+ Page.define("x-page");
7
+ Crumb.define("x-crumb");
@@ -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
- export const Page = customElement(
4
- ({ adoptStyleSheet, propSignals }) => {
5
- adoptStyleSheet(stylesheet);
6
- const { prominent } = propSignals;
7
- const prominentClass = prominent ? 'prominent' : '';
8
- return html`
9
- <div class="page ${prominentClass}">
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>&copy; ${new Date().getFullYear()} &mdash; Powered by <a href="https://thunderous.dev">Thunderous</a></small>
27
- </footer>
28
- </div>
29
- `;
30
- },
31
- {
32
- attributesAsProperties: [['prominent', Boolean]],
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
+ >&copy; ${new Date().getFullYear()} &mdash; 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, rgba(99, 102, 241, 0.22), transparent 30%),
59
- radial-gradient(circle at bottom right, rgba(14, 165, 233, 0.18), transparent 35%),
60
- linear-gradient(180deg, #0f172a 0%, #111827 45%, #0b1120 100%);
61
- color: #eaf2ff;
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.prominent {
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(--border);
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(--bg-1) 88%, transparent),
86
- color-mix(in srgb, var(--bg-2) 92%, transparent)
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(--text);
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(--link), var(--link-hover));
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(--text);
117
+ color: var(--color-neutral-1);
129
118
  transform: translateY(-1px);
130
119
  box-shadow:
131
- 0 10px 24px color-mix(in srgb, var(--link-hover) 22%, transparent),
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(--link) 65%, white 35%);
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: 3em 1.5em;
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(--border);
163
- background: linear-gradient(180deg, var(--bg-2), transparent);
164
- color: var(--muted);
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(--muted);
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(--text);
202
- background: color-mix(in srgb, var(--bg-1) 70%, transparent);
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(--link) 50%, white 20%);
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(--muted);
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(--link);
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(--link-hover);
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(--link) 50%, white 20%);
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
- <my-component>
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
- </my-component>
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 { MyComponent } from './components/my-component';
26
+ import { Feature } from './components/feature';
27
27
 
28
28
  // Thunderous components render declarative shadow DOM when defined on the server.
29
- MyComponent.define('my-component');
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
- `;