@aditokmo/react-setup-cli 0.1.2 → 0.1.3
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/README.md +5 -7
- package/dist/index.js +24 -1
- package/dist/mapper.js +11 -1
- package/dist/packages.js +3 -0
- package/dist/questions.js +17 -1
- package/dist/utils.js +5 -0
- package/package.json +1 -1
- package/templates/base/index.html +2 -1
- package/templates/base/src/modules/common/pages/NotFound.tsx +1 -1
- package/templates/{base/src/styles → styles/css/src}/404.css +15 -19
- package/templates/styles/css/src/main.css +70 -0
- package/templates/styles/css/src/variables.css +15 -0
- package/templates/styles/scss/src/404.scss +103 -0
- package/templates/styles/scss/src/_index.scss +2 -0
- package/templates/styles/scss/src/_mixins.scss +27 -0
- package/templates/styles/scss/src/_variables.scss +16 -0
- package/templates/styles/scss/src/main.scss +20 -0
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@aditokmo/react-setup-cli)
|
|
4
4
|
|
|
5
|
-
A React CLI built
|
|
5
|
+
A React CLI built on top of Vite that helps you build and structure projects in seconds. It eliminates manual setup by configuring your favorite tools into a **clean, modular architecture** automatically.
|
|
6
6
|
|
|
7
7
|
**Note:** This package is a CLI tool. Do not install it with `npm i`. Instead check `Quick Start` down below.
|
|
8
8
|
|
|
@@ -42,9 +42,7 @@ yarn dlx @aditokmo/react-setup-cli
|
|
|
42
42
|
|
|
43
43
|
---
|
|
44
44
|
|
|
45
|
-
##
|
|
46
|
-
|
|
47
|
-
This CLI isn't just a downloader it is architectural choice designed to enforce professional standards.
|
|
45
|
+
## About Arhitecture
|
|
48
46
|
|
|
49
47
|
### Feature-Based Structure
|
|
50
48
|
|
|
@@ -68,10 +66,10 @@ You can choose between CSS, SCSS (soon), or Tailwind CSS. While I personally rec
|
|
|
68
66
|
|
|
69
67
|
### Routing
|
|
70
68
|
|
|
71
|
-
The CLI offers two
|
|
69
|
+
The CLI offers two options: React Router and TanStack Router.
|
|
72
70
|
|
|
73
|
-
-
|
|
74
|
-
-
|
|
71
|
+
- React Router is the industry standard that most developers are familiar with.
|
|
72
|
+
- TanStack Router is included for those who want a fully type-safe routing experience with built-in data loading capabilities. Whichever you choose, the CLI doesn't just install the library it will generate a `routes/` directory system to help you easily separate your public pages from protected pages.
|
|
75
73
|
|
|
76
74
|
### Package Manager Detection
|
|
77
75
|
|
package/dist/index.js
CHANGED
|
@@ -3,9 +3,10 @@ import fs from 'fs-extra';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { execSync } from 'child_process';
|
|
5
5
|
import { askQuestions } from './questions.js';
|
|
6
|
-
import { copyTemplate, patchViteConfig, finalizeViteConfig, patchAppFile, finalizeAppFile, detectPackageManager } from './utils.js';
|
|
6
|
+
import { copyTemplate, patchViteConfig, finalizeViteConfig, patchAppFile, finalizeAppFile, detectPackageManager, patchIndexHTMLFile } from './utils.js';
|
|
7
7
|
import { collectDependencies } from './installers.js';
|
|
8
8
|
import { fileURLToPath } from 'url';
|
|
9
|
+
import { FONT_QUERIES } from './mapper.js';
|
|
9
10
|
const __filename = fileURLToPath(import.meta.url);
|
|
10
11
|
const __dirname = path.dirname(__filename);
|
|
11
12
|
async function main() {
|
|
@@ -19,6 +20,7 @@ async function main() {
|
|
|
19
20
|
projectDir = path.join(process.cwd(), answers.projectName);
|
|
20
21
|
const templateRoot = path.join(__dirname, '../templates');
|
|
21
22
|
const appFilePath = path.join(projectDir, 'src', 'App.tsx');
|
|
23
|
+
const indexHTMLPath = path.join(projectDir, 'src', 'index.html');
|
|
22
24
|
const viteConfigPath = path.join(projectDir, 'vite.config.ts');
|
|
23
25
|
fs.ensureDirSync(projectDir);
|
|
24
26
|
copyTemplate(path.join(templateRoot, 'base'), projectDir);
|
|
@@ -30,6 +32,27 @@ async function main() {
|
|
|
30
32
|
if (answers.style === 'css') {
|
|
31
33
|
copyTemplate(path.join(templateRoot, 'styles', 'css', 'src'), path.join(projectDir, 'src/styles'));
|
|
32
34
|
}
|
|
35
|
+
if (answers.style === 'scss') {
|
|
36
|
+
copyTemplate(path.join(templateRoot, 'styles', 'scss', 'src'), path.join(projectDir, 'src/styles'));
|
|
37
|
+
patchIndexHTMLFile(path.join(projectDir, 'index.html'), '<link rel="stylesheet" href="./src/styles/main.css" />', '<link rel="stylesheet" href="./src/styles/main.scss" />');
|
|
38
|
+
}
|
|
39
|
+
// Fonts
|
|
40
|
+
if (answers?.fonts && answers.fonts.length > 0) {
|
|
41
|
+
const fontString = answers.fonts
|
|
42
|
+
.map(name => FONT_QUERIES[name])
|
|
43
|
+
.join('&');
|
|
44
|
+
const url = `https://fonts.googleapis.com/css2?${fontString}&display=swap`;
|
|
45
|
+
const content = `
|
|
46
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
47
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
48
|
+
<link href="${url}" rel="stylesheet">`;
|
|
49
|
+
patchIndexHTMLFile(path.join(projectDir, 'index.html'), '<!-- [HEAD_LINK_IMPORT] -->', content);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
let html = fs.readFileSync(indexHTMLPath, 'utf-8');
|
|
53
|
+
html = html.replace('', '');
|
|
54
|
+
fs.writeFileSync(indexHTMLPath, html);
|
|
55
|
+
}
|
|
33
56
|
// State Management
|
|
34
57
|
if (answers.reactQuery) {
|
|
35
58
|
copyTemplate(path.join(templateRoot, 'state', 'react-query', 'src', 'provider'), path.join(projectDir, 'src/providers'));
|
package/dist/mapper.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { fontAwesomeIconsInstaller, phosphorIconsInstaller, reactFormHookInstaller, reactHotToastInstaller, reactIconsInstaller, reactQueryInstaller, reactRouterInstaller, reactToastifyInstaller, sonnerInstaller, tailwindInstaller, tanstackFormInstaller, tanstackRouterInstaller, yupInstaller, zodInstaller, zustandInstaller } from './packages.js';
|
|
1
|
+
import { fontAwesomeIconsInstaller, phosphorIconsInstaller, reactFormHookInstaller, reactHotToastInstaller, reactIconsInstaller, reactQueryInstaller, reactRouterInstaller, reactToastifyInstaller, scssInstaller, sonnerInstaller, tailwindInstaller, tanstackFormInstaller, tanstackRouterInstaller, yupInstaller, zodInstaller, zustandInstaller } from './packages.js';
|
|
2
2
|
export const installers = {
|
|
3
3
|
'reactQuery': reactQueryInstaller,
|
|
4
4
|
'zustand': zustandInstaller,
|
|
5
5
|
'react-router': reactRouterInstaller,
|
|
6
6
|
'tanstack-router': tanstackRouterInstaller,
|
|
7
7
|
'tailwind': tailwindInstaller,
|
|
8
|
+
'scss': scssInstaller,
|
|
8
9
|
'react-icons': reactIconsInstaller,
|
|
9
10
|
'font-awesome': fontAwesomeIconsInstaller,
|
|
10
11
|
'phosphor-icons': phosphorIconsInstaller,
|
|
@@ -16,3 +17,12 @@ export const installers = {
|
|
|
16
17
|
'zod': zodInstaller,
|
|
17
18
|
'yup': yupInstaller,
|
|
18
19
|
};
|
|
20
|
+
export const FONT_QUERIES = {
|
|
21
|
+
"geist": "family=Geist:wght@100..900",
|
|
22
|
+
"inter": "family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900",
|
|
23
|
+
"lato": "family=Lato:ital,wght@0,100;0,300;0,400;0,700;0,900;1,100;1,300;1,400;1,700;1,900",
|
|
24
|
+
"montserrat": "family=Montserrat:ital,wght@0,100..900;1,100..900",
|
|
25
|
+
"open-sans": "family=Open+Sans:ital,wght@0,300..800;1,300..800",
|
|
26
|
+
"poppins": "family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900",
|
|
27
|
+
"roboto": "family=Roboto:ital,wght@0,100..900;1,100..900"
|
|
28
|
+
};
|
package/dist/packages.js
CHANGED
|
@@ -11,6 +11,9 @@ export const zustandInstaller = {
|
|
|
11
11
|
export const tailwindInstaller = {
|
|
12
12
|
dependency: ['tailwindcss', '@tailwindcss/vite'],
|
|
13
13
|
};
|
|
14
|
+
export const scssInstaller = {
|
|
15
|
+
devDependency: ['sass']
|
|
16
|
+
};
|
|
14
17
|
// Icons
|
|
15
18
|
export const reactIconsInstaller = {
|
|
16
19
|
dependency: ['react-icons'],
|
package/dist/questions.js
CHANGED
|
@@ -11,6 +11,7 @@ export async function askQuestions() {
|
|
|
11
11
|
options: [
|
|
12
12
|
{ value: 'tailwind', label: 'Tailwind' },
|
|
13
13
|
{ value: 'css', label: 'CSS' },
|
|
14
|
+
{ value: 'scss', label: 'SCSS' },
|
|
14
15
|
],
|
|
15
16
|
}),
|
|
16
17
|
shadcn: ({ results }) => {
|
|
@@ -38,6 +39,19 @@ export async function askQuestions() {
|
|
|
38
39
|
required: false,
|
|
39
40
|
});
|
|
40
41
|
},
|
|
42
|
+
fonts: () => multiselect({
|
|
43
|
+
message: 'Use space to select your fonts',
|
|
44
|
+
options: [
|
|
45
|
+
{ value: 'geist', label: 'Geist' },
|
|
46
|
+
{ value: 'inter', label: 'Inter' },
|
|
47
|
+
{ value: 'lato', label: 'Lato' },
|
|
48
|
+
{ value: 'montserrat', label: 'Montserrat' },
|
|
49
|
+
{ value: 'open-sans', label: 'Open Sans' },
|
|
50
|
+
{ value: 'poppins', label: 'Poppins' },
|
|
51
|
+
{ value: 'roboto', label: 'Roboto' }
|
|
52
|
+
],
|
|
53
|
+
required: false
|
|
54
|
+
}),
|
|
41
55
|
icons: () => select({
|
|
42
56
|
message: 'Choose icon library:',
|
|
43
57
|
options: [
|
|
@@ -95,7 +109,8 @@ export async function askQuestions() {
|
|
|
95
109
|
isCancel(results.shadcnComponents) ||
|
|
96
110
|
isCancel(results.icons) ||
|
|
97
111
|
isCancel(results.toast) ||
|
|
98
|
-
isCancel(results.reactQuery)
|
|
112
|
+
isCancel(results.reactQuery) ||
|
|
113
|
+
isCancel(results.fonts)) {
|
|
99
114
|
cancel('Setup cancelled.');
|
|
100
115
|
process.exit(0);
|
|
101
116
|
}
|
|
@@ -103,5 +118,6 @@ export async function askQuestions() {
|
|
|
103
118
|
...results,
|
|
104
119
|
shadcn: results.shadcn,
|
|
105
120
|
shadcnComponents: (results.shadcnComponents ?? []),
|
|
121
|
+
fonts: (results.fonts ?? [])
|
|
106
122
|
};
|
|
107
123
|
}
|
package/dist/utils.js
CHANGED
|
@@ -6,6 +6,11 @@ export function copyTemplate(src, path) {
|
|
|
6
6
|
}
|
|
7
7
|
fs.copySync(src, path, { overwrite: true });
|
|
8
8
|
}
|
|
9
|
+
export function patchIndexHTMLFile(filePath, importLine, newContent) {
|
|
10
|
+
let htmlContent = fs.readFileSync(filePath, 'utf-8');
|
|
11
|
+
htmlContent = htmlContent.replace(importLine, newContent);
|
|
12
|
+
fs.writeFileSync(filePath, htmlContent);
|
|
13
|
+
}
|
|
9
14
|
export function patchAppFile(filePath, importLine, openTag, closeTag) {
|
|
10
15
|
if (!fs.existsSync(filePath))
|
|
11
16
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aditokmo/react-setup-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "A fast React CLI to jumpstart your projects. It sets up your libraries and organizes a scalable folder structure so you can skip the configuration and go straight to coding.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!
|
|
1
|
+
<!doctype html>
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<link rel="stylesheet" href="./src/styles/main.css" />
|
|
8
8
|
<title>vite-project</title>
|
|
9
|
+
<!-- [HEAD_LINK_IMPORT] -->
|
|
9
10
|
</head>
|
|
10
11
|
<body>
|
|
11
12
|
<div id="root"></div>
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
@import "./variables.css";
|
|
2
|
+
|
|
1
3
|
.not-found-wrapper {
|
|
2
4
|
display: flex;
|
|
3
5
|
flex-direction: column;
|
|
@@ -6,25 +8,25 @@
|
|
|
6
8
|
min-height: 100vh;
|
|
7
9
|
padding: 20px;
|
|
8
10
|
text-align: center;
|
|
9
|
-
font-family:
|
|
10
|
-
background:
|
|
11
|
+
font-family: var(--font-main);
|
|
12
|
+
background: var(--bg-light);
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
.not-found-content {
|
|
14
16
|
padding: 100px 70px;
|
|
15
|
-
background:
|
|
17
|
+
background: var(--white);
|
|
16
18
|
max-width: 700px;
|
|
17
19
|
width: 100%;
|
|
18
20
|
display: flex;
|
|
19
21
|
flex-direction: column;
|
|
20
22
|
justify-content: center;
|
|
21
23
|
align-items: center;
|
|
22
|
-
border-radius:
|
|
23
|
-
box-shadow:
|
|
24
|
+
border-radius: var(--radius-lg);
|
|
25
|
+
box-shadow: var(--shadow-main);
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
.not-found-content span {
|
|
27
|
-
color:
|
|
29
|
+
color: var(--text-muted);
|
|
28
30
|
font-weight: 700;
|
|
29
31
|
font-size: 6rem;
|
|
30
32
|
line-height: 1;
|
|
@@ -34,12 +36,12 @@
|
|
|
34
36
|
font-size: 2.5rem;
|
|
35
37
|
font-weight: 600;
|
|
36
38
|
margin: 0;
|
|
37
|
-
color:
|
|
39
|
+
color: var(--text-dark);
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
.not-found-content p {
|
|
41
43
|
font-size: 1rem;
|
|
42
|
-
color:
|
|
44
|
+
color: var(--text-muted);
|
|
43
45
|
max-width: 360px;
|
|
44
46
|
width: 100%;
|
|
45
47
|
margin: 10px 0;
|
|
@@ -47,11 +49,11 @@
|
|
|
47
49
|
|
|
48
50
|
.not-found-content a {
|
|
49
51
|
font-size: 0.9rem;
|
|
50
|
-
color:
|
|
51
|
-
background-color:
|
|
52
|
+
color: var(--white);
|
|
53
|
+
background-color: var(--primary-blue);
|
|
52
54
|
padding: 10px 30px;
|
|
53
55
|
margin-top: 20px;
|
|
54
|
-
border-radius:
|
|
56
|
+
border-radius: var(--radius-sm);
|
|
55
57
|
transition: 0.2s;
|
|
56
58
|
cursor: pointer;
|
|
57
59
|
text-decoration: none;
|
|
@@ -59,7 +61,7 @@
|
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
.not-found-content a:hover {
|
|
62
|
-
background:
|
|
64
|
+
background: var(--primary-blue-hover);
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
@media (max-width: 768px) {
|
|
@@ -67,12 +69,10 @@
|
|
|
67
69
|
padding: 60px 40px;
|
|
68
70
|
max-width: 90%;
|
|
69
71
|
}
|
|
70
|
-
|
|
71
72
|
.not-found-content span {
|
|
72
73
|
font-size: 4.5rem;
|
|
73
74
|
margin-bottom: 20px;
|
|
74
75
|
}
|
|
75
|
-
|
|
76
76
|
.not-found-content h1 {
|
|
77
77
|
font-size: 2rem;
|
|
78
78
|
}
|
|
@@ -81,22 +81,18 @@
|
|
|
81
81
|
@media (max-width: 480px) {
|
|
82
82
|
.not-found-content {
|
|
83
83
|
padding: 40px 20px;
|
|
84
|
-
border-radius:
|
|
84
|
+
border-radius: var(--radius-md);
|
|
85
85
|
}
|
|
86
|
-
|
|
87
86
|
.not-found-content span {
|
|
88
87
|
font-size: 3.5rem;
|
|
89
88
|
margin-bottom: 20px;
|
|
90
89
|
}
|
|
91
|
-
|
|
92
90
|
.not-found-content h1 {
|
|
93
91
|
font-size: 1.5rem;
|
|
94
92
|
}
|
|
95
|
-
|
|
96
93
|
.not-found-content p {
|
|
97
94
|
font-size: 0.9rem;
|
|
98
95
|
}
|
|
99
|
-
|
|
100
96
|
.not-found-content a {
|
|
101
97
|
width: 100%;
|
|
102
98
|
box-sizing: border-box;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
@import "./variables.css";
|
|
2
|
+
|
|
3
|
+
* {
|
|
4
|
+
margin: 0;
|
|
5
|
+
padding: 0;
|
|
6
|
+
box-sizing: border-box;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
html {
|
|
10
|
+
scroll-behavior: smooth;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
body {
|
|
14
|
+
font-family: var(--font-main);
|
|
15
|
+
background-color: var(--white);
|
|
16
|
+
color: var(--text-dark);
|
|
17
|
+
line-height: 1.6;
|
|
18
|
+
min-height: 100vh;
|
|
19
|
+
-webkit-font-smoothing: antialiased;
|
|
20
|
+
-moz-osx-font-smoothing: grayscale;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
h1,
|
|
24
|
+
h2,
|
|
25
|
+
h3,
|
|
26
|
+
h4,
|
|
27
|
+
h5,
|
|
28
|
+
h6 {
|
|
29
|
+
color: var(--text-dark);
|
|
30
|
+
font-weight: 600;
|
|
31
|
+
line-height: 1.2;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
p {
|
|
35
|
+
color: var(--text-muted);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.container {
|
|
39
|
+
width: 100%;
|
|
40
|
+
max-width: 1200px;
|
|
41
|
+
margin: 0 auto;
|
|
42
|
+
padding: 0 20px;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.flex-center {
|
|
46
|
+
display: flex;
|
|
47
|
+
align-items: center;
|
|
48
|
+
justify-content: center;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
a {
|
|
52
|
+
text-decoration: none;
|
|
53
|
+
color: var(--primary-blue);
|
|
54
|
+
transition: 0.3s ease;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
a:hover {
|
|
58
|
+
color: var(--primary-blue-hover);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
button {
|
|
62
|
+
font-family: inherit;
|
|
63
|
+
cursor: pointer;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
img {
|
|
67
|
+
max-width: 100%;
|
|
68
|
+
height: auto;
|
|
69
|
+
display: block;
|
|
70
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--primary-blue: #37538a;
|
|
3
|
+
--primary-blue-hover: #263c67;
|
|
4
|
+
--bg-light: #e6edfc;
|
|
5
|
+
--white: #ffffff;
|
|
6
|
+
--text-dark: #111111;
|
|
7
|
+
--text-muted: #666666;
|
|
8
|
+
|
|
9
|
+
--font-main: "Arial", sans-serif;
|
|
10
|
+
|
|
11
|
+
--shadow-main: 0px 0px 14px -14px rgba(0, 0, 0, 0.75);
|
|
12
|
+
--radius-lg: 24px;
|
|
13
|
+
--radius-md: 16px;
|
|
14
|
+
--radius-sm: 10px;
|
|
15
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
@use "./index.scss" as *;
|
|
2
|
+
|
|
3
|
+
.not-found-wrapper {
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
align-items: center;
|
|
7
|
+
justify-content: center;
|
|
8
|
+
min-height: 100vh;
|
|
9
|
+
padding: 20px;
|
|
10
|
+
text-align: center;
|
|
11
|
+
font-family: $font-main;
|
|
12
|
+
background: $bg-light;
|
|
13
|
+
|
|
14
|
+
.not-found-content {
|
|
15
|
+
padding: 100px 70px;
|
|
16
|
+
background: $white;
|
|
17
|
+
max-width: 700px;
|
|
18
|
+
width: 100%;
|
|
19
|
+
display: flex;
|
|
20
|
+
flex-direction: column;
|
|
21
|
+
justify-content: center;
|
|
22
|
+
align-items: center;
|
|
23
|
+
border-radius: $radius-lg;
|
|
24
|
+
box-shadow: $shadow-main;
|
|
25
|
+
|
|
26
|
+
span {
|
|
27
|
+
color: $text-muted;
|
|
28
|
+
font-weight: 700;
|
|
29
|
+
font-size: 6rem;
|
|
30
|
+
line-height: 1;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
h1 {
|
|
34
|
+
font-size: 2.5rem;
|
|
35
|
+
font-weight: 600;
|
|
36
|
+
margin: 0;
|
|
37
|
+
color: $text-dark;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
p {
|
|
41
|
+
font-size: 1rem;
|
|
42
|
+
color: $text-muted;
|
|
43
|
+
max-width: 360px;
|
|
44
|
+
width: 100%;
|
|
45
|
+
margin: 10px 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
a {
|
|
49
|
+
font-size: 0.9rem;
|
|
50
|
+
color: $white;
|
|
51
|
+
background-color: $primary-blue;
|
|
52
|
+
padding: 10px 30px;
|
|
53
|
+
margin-top: 20px;
|
|
54
|
+
border-radius: $radius-sm;
|
|
55
|
+
transition: 0.2s;
|
|
56
|
+
cursor: pointer;
|
|
57
|
+
text-decoration: none;
|
|
58
|
+
display: inline-block;
|
|
59
|
+
|
|
60
|
+
&:hover {
|
|
61
|
+
background: $primary-blue-hover;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@media (max-width: 768px) {
|
|
66
|
+
padding: 60px 40px;
|
|
67
|
+
max-width: 90%;
|
|
68
|
+
|
|
69
|
+
span {
|
|
70
|
+
font-size: 4.5rem;
|
|
71
|
+
margin-bottom: 20px;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
h1 {
|
|
75
|
+
font-size: 2rem;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@media (max-width: 480px) {
|
|
80
|
+
padding: 40px 20px;
|
|
81
|
+
border-radius: $radius-md;
|
|
82
|
+
|
|
83
|
+
span {
|
|
84
|
+
font-size: 3.5rem;
|
|
85
|
+
margin-bottom: 20px;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
h1 {
|
|
89
|
+
font-size: 1.5rem;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
p {
|
|
93
|
+
font-size: 0.9rem;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
a {
|
|
97
|
+
width: 100%;
|
|
98
|
+
box-sizing: border-box;
|
|
99
|
+
text-align: center;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
$breakpoint-tablet: 768px;
|
|
2
|
+
$breakpoint-mobile: 480px;
|
|
3
|
+
|
|
4
|
+
@mixin tablet {
|
|
5
|
+
@media (max-width: #{$breakpoint-tablet}) {
|
|
6
|
+
@content;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@mixin mobile {
|
|
11
|
+
@media (max-width: #{$breakpoint-mobile}) {
|
|
12
|
+
@content;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// helpers
|
|
17
|
+
@mixin flex-center {
|
|
18
|
+
display: flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
justify-content: center;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@mixin text-truncate {
|
|
24
|
+
overflow: hidden;
|
|
25
|
+
text-overflow: ellipsis;
|
|
26
|
+
white-space: nowrap;
|
|
27
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Brand Colors
|
|
2
|
+
$primary: #37538a;
|
|
3
|
+
$primary-dark: #263c67;
|
|
4
|
+
$accent: #e6edfc;
|
|
5
|
+
|
|
6
|
+
// Neutrals
|
|
7
|
+
$white: #ffffff;
|
|
8
|
+
$black: #111111;
|
|
9
|
+
$gray: #666666;
|
|
10
|
+
|
|
11
|
+
// Fonts
|
|
12
|
+
$font-main: "Arial", sans-serif;
|
|
13
|
+
|
|
14
|
+
// Breakpoints
|
|
15
|
+
$breakpoint-tablet: 768px;
|
|
16
|
+
$breakpoint-mobile: 480px;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
@use "index" as *;
|
|
2
|
+
|
|
3
|
+
* {
|
|
4
|
+
margin: 0;
|
|
5
|
+
padding: 0;
|
|
6
|
+
box-sizing: border-box;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
body {
|
|
10
|
+
font-family: $font-main;
|
|
11
|
+
background-color: $white;
|
|
12
|
+
color: $black;
|
|
13
|
+
line-height: 1.5;
|
|
14
|
+
-webkit-font-smoothing: antialiased;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
a {
|
|
18
|
+
text-decoration: none;
|
|
19
|
+
color: inherit;
|
|
20
|
+
}
|