feat: several improvements, merge the latest changes

This commit is contained in:
Kamil Myśliwiec
2024-08-09 11:02:53 +02:00
33 changed files with 391 additions and 105 deletions

View File

@@ -2,7 +2,7 @@
Providers are a fundamental concept in Nest. Many of the basic Nest classes may be treated as a provider services, repositories, factories, helpers, and so on. The main idea of a provider is that it can be **injected** as a dependency; this means objects can create various relationships with each other, and the function of "wiring up" these objects can largely be delegated to the Nest runtime system.
<figure><img src="/assets/Components_1.png" /></figure>
<figure><img class="illustrative-image" src="/assets/Components_1.png" /></figure>
In the previous chapter, we built a simple `CatsController`. Controllers should handle HTTP requests and delegate more complex tasks to **providers**. Providers are plain JavaScript classes that are declared as `providers` in a [module](/modules).

View File

@@ -2,7 +2,7 @@
Controllers are responsible for handling incoming **requests** and returning **responses** to the client.
<figure><img src="/assets/Controllers_1.png" /></figure>
<figure><img class="illustrative-image" src="/assets/Controllers_1.png" /></figure>
A controller's purpose is to receive specific requests for the application. The **routing** mechanism controls which controller receives which requests. Frequently, each controller has more than one route, and different routes can perform different actions.

View File

@@ -3,7 +3,7 @@
Nest comes with a built-in **exceptions layer** which is responsible for processing all unhandled exceptions across an application. When an exception is not handled by your application code, it is caught by this layer, which then automatically sends an appropriate user-friendly response.
<figure>
<img src="/assets/Filter_1.png" />
<img class="illustrative-image" src="/assets/Filter_1.png" />
</figure>
Out of the box, this action is performed by a built-in **global exception filter**, which handles exceptions of type `HttpException` (and subclasses of it). When an exception is **unrecognized** (is neither `HttpException` nor a class that inherits from `HttpException`), the built-in exception filter generates the following default JSON response:

View File

@@ -4,7 +4,7 @@ In this set of articles, you'll learn the **core fundamentals** of Nest. To get
#### Language
We're in love with [TypeScript](https://www.typescriptlang.org/), but above all - we love [Node.js](https://nodejs.org/en/). That's why Nest is compatible with both TypeScript and **pure JavaScript**. Nest takes advantage of the latest language features, so to use it with vanilla JavaScript we need a [Babel](https://babeljs.io/) compiler.
We're in love with [TypeScript](https://www.typescriptlang.org/), but above all - we love [Node.js](https://nodejs.org/en/). That's why Nest is compatible with both TypeScript and pure JavaScript. Nest takes advantage of the latest language features, so to use it with vanilla JavaScript we need a [Babel](https://babeljs.io/) compiler.
We'll mostly use TypeScript in the examples we provide, but you can always **switch the code snippets** to vanilla JavaScript syntax (simply click to toggle the language button in the upper right hand corner of each snippet).

View File

@@ -6,7 +6,7 @@ A Nest application, as well as every application element, has a lifecycle manage
The following diagram depicts the sequence of key application lifecycle events, from the time the application is bootstrapped until the node process exits. We can divide the overall lifecycle into three phases: **initializing**, **running** and **terminating**. Using this lifecycle, you can plan for appropriate initialization of modules and services, manage active connections, and gracefully shutdown your application when it receives a termination signal.
<figure><img src="/assets/lifecycle-events.png" /></figure>
<figure><img class="illustrative-image" src="/assets/lifecycle-events.png" /></figure>
#### Lifecycle events

View File

@@ -2,7 +2,7 @@
A guard is a class annotated with the `@Injectable()` decorator, which implements the `CanActivate` interface.
<figure><img src="/assets/Guards_1.png" /></figure>
<figure><img class="illustrative-image" src="/assets/Guards_1.png" /></figure>
Guards have a **single responsibility**. They determine whether a given request will be handled by the route handler or not, depending on certain conditions (like permissions, roles, ACLs, etc.) present at run-time. This is often referred to as **authorization**. Authorization (and its cousin, **authentication**, with which it usually collaborates) has typically been handled by [middleware](/middleware) in traditional Express applications. Middleware is a fine choice for authentication, since things like token validation and attaching properties to the `request` object are not strongly connected with a particular route context (and its metadata).

View File

@@ -2,7 +2,7 @@
An interceptor is a class annotated with the `@Injectable()` decorator and implements the `NestInterceptor` interface.
<figure><img src="/assets/Interceptors_1.png" /></figure>
<figure><img class="illustrative-image" src="/assets/Interceptors_1.png" /></figure>
Interceptors have a set of useful capabilities which are inspired by the [Aspect Oriented Programming](https://en.wikipedia.org/wiki/Aspect-oriented_programming) (AOP) technique. They make it possible to:

View File

@@ -4,7 +4,7 @@ In addition to traditional (sometimes called monolithic) application architectur
In Nest, a microservice is fundamentally an application that uses a different **transport** layer than HTTP.
<figure><img src="/assets/Microservices_1.png" /></figure>
<figure><img class="illustrative-image" src="/assets/Microservices_1.png" /></figure>
Nest supports several built-in transport layer implementations, called **transporters**, which are responsible for transmitting messages between different microservice instances. Most transporters natively support both **request-response** and **event-based** message styles. Nest abstracts the implementation details of each transporter behind a canonical interface for both request-response and event-based messaging. This makes it easy to switch from one transport layer to another -- for example to leverage the specific reliability or performance features of a particular transport layer -- without impacting your application code.

View File

@@ -2,7 +2,7 @@
The [Redis](https://redis.io/) transporter implements the publish/subscribe messaging paradigm and leverages the [Pub/Sub](https://redis.io/topics/pubsub) feature of Redis. Published messages are categorized in channels, without knowing what subscribers (if any) will eventually receive the message. Each microservice can subscribe to any number of channels. In addition, more than one channel can be subscribed to at a time. Messages exchanged through channels are **fire-and-forget**, which means that if a message is published and there are no subscribers interested in it, the message is removed and cannot be recovered. Thus, you don't have a guarantee that either messages or events will be handled by at least one service. A single message can be subscribed to (and received) by multiple subscribers.
<figure><img src="/assets/Redis_1.png" /></figure>
<figure><img class="illustrative-image" src="/assets/Redis_1.png" /></figure>
#### Installation

View File

@@ -2,7 +2,7 @@
Middleware is a function which is called **before** the route handler. Middleware functions have access to the [request](https://expressjs.com/en/4x/api.html#req) and [response](https://expressjs.com/en/4x/api.html#res) objects, and the `next()` middleware function in the applications request-response cycle. The **next** middleware function is commonly denoted by a variable named `next`.
<figure><img src="/assets/Middlewares_1.png" /></figure>
<figure><img class="illustrative-image" src="/assets/Middlewares_1.png" /></figure>
Nest middleware are, by default, equivalent to [express](https://expressjs.com/en/guide/using-middleware.html) middleware. The following description from the official express documentation describes the capabilities of middleware:

View File

@@ -2,7 +2,7 @@
A module is a class annotated with a `@Module()` decorator. The `@Module()` decorator provides metadata that **Nest** makes use of to organize the application structure.
<figure><img src="/assets/Modules_1.png" /></figure>
<figure><img class="illustrative-image" src="/assets/Modules_1.png" /></figure>
Each application has at least one module, a **root module**. The root module is the starting point Nest uses to build the **application graph** - the internal data structure Nest uses to resolve module and provider relationships and dependencies. While very small applications may theoretically have just the root module, this is not the typical case. We want to emphasize that modules are **strongly** recommended as an effective way to organize your components. Thus, for most applications, the resulting architecture will employ multiple modules, each encapsulating a closely related set of **capabilities**.

View File

@@ -3,7 +3,7 @@
A pipe is a class annotated with the `@Injectable()` decorator, which implements the `PipeTransform` interface.
<figure>
<img src="/assets/Pipe_1.png" />
<img class="illustrative-image" src="/assets/Pipe_1.png" />
</figure>
Pipes have two typical use cases:

View File

@@ -4,7 +4,7 @@ Most of the concepts discussed elsewhere in this documentation, such as dependen
In Nest, a gateway is simply a class annotated with `@WebSocketGateway()` decorator. Technically, gateways are platform-agnostic which makes them compatible with any WebSockets library once an adapter is created. There are two WS platforms supported out-of-the-box: [socket.io](https://github.com/socketio/socket.io) and [ws](https://github.com/websockets/ws). You can choose the one that best suits your needs. Also, you can build your own adapter by following this [guide](/websockets/adapter).
<figure><img src="/assets/Gateways_1.png" /></figure>
<figure><img class="illustrative-image" src="/assets/Gateways_1.png" /></figure>
> info **Hint** Gateways can be treated as [providers](/providers); this means they can inject dependencies through the class constructor. Also, gateways can be injected by other classes (providers and controllers) as well.

View File

@@ -27,4 +27,5 @@
rel="nofollow">
<i class="fa-brands fa-discord"></i>
</a>
<app-theme-mode-toggle></app-theme-mode-toggle>
</div>

View File

@@ -1,4 +1,3 @@
@import '../../../scss/variables.scss';
@import '../../../scss/utils.scss';
.social-wrapper {
@@ -6,6 +5,7 @@
float: right;
padding-right: 40px;
position: relative;
display: flex;
a {
@extend .transition-fast;
@@ -21,7 +21,7 @@
position: relative;
&:hover {
fill: $red-color;
fill: var(--primary);
}
}
@@ -29,7 +29,7 @@
font-size: 20px;
}
&:hover {
color: $red-color;
color: var(--primary);
}
}
@include media(medium) {

View File

@@ -4,7 +4,7 @@
:host {
@extend .transition;
@extend .box-sizing;
background: variables.$black-color;
background: var(--header-background);
display: block;
padding: 40px 0;
margin: 0 -85px;
@@ -34,15 +34,13 @@ footer {
text-align: center;
a {
color: variables.$red-color;
color: var(--primary-5dp);
font-weight: 600;
@include utils.text-gradient();
&:hover {
color: variables.$red-color;
background: #fff;
}
}
@@ -73,12 +71,13 @@ footer {
font-size: 20px;
margin-left: 15px;
cursor: pointer;
color: #fff;
&:first-of-type {
font-size: 20px;
}
&:hover {
color: variables.$red-color;
color: var(--primary);
}
}

View File

@@ -2,10 +2,14 @@
@use '../../../scss/utils';
:host {
background: var(--header-background);
display: block;
width: 100%;
height: 70px;
position: fixed;
z-index: 10000;
width: 100%;
height: 105px;
height: 70px;
@media print {
position: relative;
@@ -46,7 +50,7 @@
header {
display: block;
position: relative;
background: variables.$black-color;
background: var(--header-background);
width: 100%;
height: 70px;
z-index: 10000;
@@ -129,7 +133,7 @@ header {
padding: 14px 25px;
@media (min-width: 1500px) {
margin-right: 80px;
margin-right: 30px;
}
@media (max-width: 1499px) {
@@ -142,8 +146,12 @@ header {
}
}
@media (max-width: 1250px) {
@media (max-width: 1350px) {
padding: 14px 5px;
li:nth-of-type(3) {
display: none;
}
}
@media (max-width: 1150px) {
@@ -213,7 +221,7 @@ header {
font-weight: 600;
&:hover {
color: variables.$red-color;
color: var(--primary-4dp);
}
}
@media print {
@@ -274,9 +282,9 @@ header {
position: relative;
&:hover {
color: variables.$red-color;
color: var(--primary);
&::after {
background: variables.$red-color;
background: var(--primary);
}
}
@@ -390,11 +398,11 @@ header {
&:active,
&:focus {
border-bottom-color: variables.$red-color;
border-bottom-color: var(--primary);
width: 190px;
}
@media (min-width: 1200px) and (max-width: 1300px) {
@media (max-width: 1300px) {
width: 190px;
}
}
@@ -459,7 +467,7 @@ header {
&::after,
&::before {
content: '';
background: variables.$red-color;
background: var(--primary);
display: block;
height: 2px;
position: absolute;

View File

@@ -55,25 +55,25 @@
}
.page-wrapper {
color: variables.$grey-color;
color: var(--color);
line-height: 26px;
a {
font-weight: 600;
color: variables.$red-color;
color: var(--primary-3dp);
&:hover {
color: #0894e2;
}
}
.content a {
transition: none;
@include utils.text-gradient();
&:hover {
background: #0894e2;
-webkit-background-clip: text !important;
-webkit-text-fill-color: transparent;
-webkit-background-clip: text;
}
}
@@ -108,7 +108,7 @@
h4,
h5,
h6 {
color: variables.$black-color;
color: var(--color-1dp);
}
h3 {
font-size: 24px;
@@ -142,7 +142,7 @@
}
}
h5 {
color: variables.$grey-color;
color: var(--color);
margin-top: 5px;
font-weight: 600;
font-size: 16px;
@@ -159,7 +159,7 @@
}
.sponsors-wrapper {
border-top: 1px solid #e8e8e8;
border-top: 1px solid var(--background-2dp);
padding: 10px 0 60px;
margin-top: 20px;
position: relative;
@@ -170,7 +170,7 @@
}
a {
color: variables.$red-color;
color: var(--primary);
font-weight: 600;
&:hover {
color: #0894e2;
@@ -180,11 +180,10 @@
h3 {
font-size: 24px;
font-weight: 700;
color: #1d1d1d;
}
h4 {
color: #1b2247;
color: var(--color-1dp);
font-weight: 600;
margin: 0;
font-size: 18px;
@@ -200,7 +199,7 @@
line-height: 26px;
font-size: 16px;
font-weight: 500;
color: #4e4e4e;
color: var(--color);
}
.logo-sponsor-container {
@@ -224,7 +223,7 @@
}
.logo-sponsor {
width: 160px;
filter: grayscale(1);
filter: var(--company-logo-filter);
&:hover {
filter: grayscale(0);
@@ -248,7 +247,7 @@
}
.btn-primary {
color: variables.$red-color;
color: var(--primary-4dp);
padding: 12px 20px;
display: inline-block;
border-radius: 2px;
@@ -375,7 +374,7 @@
}
.contact-us {
background: variables.$red-color;
background: var(--primary);
color: #fff;
padding: 20px 30px;
border-radius: 3px;
@@ -439,10 +438,11 @@
svg {
font-size: 17px;
color: variables.$black-color;
&:hover {
color: variables.$red-color;
}
color: var(--color-1dp);
}
a:hover svg {
color: var(--primary);
}
}
@@ -462,19 +462,19 @@
max-width: 130px;
max-height: 60px;
padding: 6px;
-webkit-filter: grayscale(100%);
filter: grayscale(100%);
opacity: 0.5;
-webkit-filter: var(--company-filter);
filter: var(--company-filter);
opacity: var(--company-logo-opacity);
&:hover {
-webkit-filter: grayscale(0%);
filter: grayscale(0%);
-webkit-filter: var(--company-filter-hover);
filter: var(--company-filter-hover);
opacity: 1;
}
}
.companies-list a {
color: #404040;
color: var(--color);
font-size: 15px;
font-weight: 400;
}
@@ -527,7 +527,7 @@
bottom: 20px;
overflow: hidden;
padding: 1em;
background: #fdfdfd;
background: var(--background-2dp) !important;
text-align: center;
line-height: 1.5;
font-size: 13px;
@@ -590,7 +590,7 @@
}
.algolia-autocomplete .algolia-docsearch-suggestion--highlight {
color: variables.$red-color;
color: var(--primary);
background: #fff2f4;
}

View File

@@ -10,7 +10,7 @@ h3 {
@extend .transition;
text-transform: uppercase;
font-weight: bold;
color: variables.$black-color;
color: var(--color-1dp);
font-size: 15px;
margin: 10px 0;
&:hover {
@@ -59,7 +59,7 @@ li {
}
a {
color: variables.$black-color;
color: var(--menu-color);
font-size: 14px;
text-decoration: none;
cursor: pointer;
@@ -85,10 +85,14 @@ li {
margin: 10px 0 15px;
}
.arrow-icon {
fill: var(--color);
}
&.opened {
.arrow-icon {
@include utils.transform(rotate(-90deg));
fill: variables.$red-color;
fill: var(--primary);
}
}
}
@@ -97,7 +101,7 @@ li {
cursor: pointer;
&:hover {
.arrow-icon {
color: variables.$red-color;
color: var(--primary);
}
}
}

View File

@@ -8,7 +8,7 @@
padding: 90px 17px 40px 24px;
width: 250px;
background: #f5f5f5;
background: var(--menu-background);
position: fixed !important;
bottom: 0;
top: 0;
@@ -68,12 +68,12 @@
}
.btn-version {
background: #dfdfdf;
background: var(--background-3dp);
margin-top: 5px;
color: #151515;
color: var(--color-1dp);
&:hover {
background: #cccccc;
background: var(--background-5dp);
}
}

View File

@@ -2,7 +2,7 @@
@use '../../../scss/utils';
.newsletter-wrapper {
background: #e8e8e8;
background: var(--background-3dp);
padding: 40px 85px;
overflow: hidden;
position: relative;
@@ -26,13 +26,13 @@
font-size: 18px;
font-weight: 600;
margin: 0 0 4px;
color: #111;
color: var(--color-1dp);
}
.newsletter-wrapper p {
font-size: 15px;
margin: 0;
color: #7b7b7b;
color: var(--color);
font-weight: 500;
line-height: 22px;
}
@@ -58,12 +58,14 @@
.newsletter-form .form-control {
border: 0;
font-size: 15px;
font-size: 14px;
font-family: 'Source Sans Pro';
height: 40px;
padding: 10px 20px;
background: #fdfdfd;
background: var(--background);
color: var(--color);
width: calc(100% - 70px);
box-shadow: -2px 2px 3px gainsboro;
// box-shadow: -2px 2px 3px var(--background);
border-radius: 3px;
max-width: 100%;
vertical-align: middle;
@@ -102,7 +104,7 @@
}
.newsletter-form .btn-success[disabled] {
background: #d3e6d4;
background: var(--background);
color: #1dd81c;
pointer-events: none;
}
@@ -115,7 +117,7 @@
position: absolute;
margin-top: -50px;
margin-left: 60px;
color: #dedede;
color: rgba(0,0,0,0.1);
z-index: 0;
transform: rotate(-30deg);
}

View File

@@ -0,0 +1,4 @@
<button class="theme-mode-toggle" (click)="toggleThemeMode()">
<span class="material-icons" *ngIf="!isDarkMode"> light_mode </span>
<span class="material-icons" *ngIf="isDarkMode"> dark_mode </span>
</button>

View File

@@ -0,0 +1,48 @@
:host {
display: block;
display: flex;
align-items: center;
justify-content: center;
}
.theme-mode-toggle {
// Button reset
border: none;
margin: 0;
padding: 0;
width: auto;
overflow: visible;
background: transparent;
font: inherit;
line-height: normal;
-webkit-font-smoothing: inherit;
-moz-osx-font-smoothing: inherit;
-webkit-appearance: none;
display: flex;
align-items: center;
justify-content: center;
margin-left: 15px;
cursor: pointer;
color: #fff;
padding-left: 15px;
position: relative;
&:hover {
color: var(--primary);
}
.material-icons {
font-size: 20px;
&::before {
content: '';
position: absolute;
background: #fff;
opacity: 0.2;
left: 0;
top: 0;
bottom: 0;
width: 2px;
}
}
}

View File

@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ThemeModeToggleComponent } from './theme-mode-toggle.component';
describe('ThemeModeToggleComponent', () => {
let component: ThemeModeToggleComponent;
let fixture: ComponentFixture<ThemeModeToggleComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ThemeModeToggleComponent],
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ThemeModeToggleComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,47 @@
import { Component, Inject, OnInit } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { MediaMatcher } from '@angular/cdk/layout';
import { StorageService } from '../../services/storage.service';
@Component({
selector: 'app-theme-mode-toggle',
templateUrl: './theme-mode-toggle.component.html',
styleUrls: ['./theme-mode-toggle.component.scss'],
})
export class ThemeModeToggleComponent implements OnInit {
isDarkMode: boolean;
constructor(
@Inject(DOCUMENT)
private readonly document: Document,
private readonly mediaMatcher: MediaMatcher,
private readonly storageService: StorageService,
) {}
ngOnInit() {
const userPrefersTheme =
this.mediaMatcher.matchMedia &&
this.mediaMatcher.matchMedia('(prefers-color-scheme: light)').matches;
// In case the user has used the toggle button, we prioritize it over the
// system settings
this.setThemeMode(this.getUserSettingsIsDarkMode() || userPrefersTheme);
}
toggleThemeMode() {
const isDarkMode = !this.isDarkMode;
this.storageService.set('theme-mode', isDarkMode.toString());
this.setThemeMode(isDarkMode);
}
private getUserSettingsIsDarkMode(): boolean {
return this.storageService.get('theme-mode') === 'true';
}
private setThemeMode(isDarkMode: boolean) {
this.isDarkMode = isDarkMode;
this.document.documentElement.setAttribute(
'mode',
isDarkMode ? 'dark' : 'light',
);
}
}

View File

@@ -26,7 +26,7 @@
top: 10px;
bottom: 10px;
width: 2px;
background: #efefef;
background: var(--background-4dp);
}
}
@@ -63,8 +63,8 @@
@include utils.transform(translateY(-50%));
content: '';
background: #fdfdfd;
border: 2px solid #efefef;
background: var(--background);
border: 2px solid var(--background-4dp);
left: -4px;
width: 6px;
height: 6px;
@@ -80,10 +80,10 @@
}
a {
color: #404040;
color: var(--color);
font-weight: normal;
&:hover {
color: variables.$red-color;
color: variables.$red-color;
@include utils.text-gradient();
}
}

View File

@@ -0,0 +1,28 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class StorageService {
set(key, val: unknown): void {
localStorage.setItem(key, JSON.stringify(val));
}
/**
* Returns the localStorage item for the given key, if any.
* Returns null elsewhere
*/
get(key: string): unknown | null {
const result = localStorage.getItem(key);
return result ? JSON.parse(result) : null;
}
remove(key: string): void {
const hasStorageKey = this.get(key);
if (hasStorageKey) {
localStorage.removeItem(key);
}
}
}

View File

@@ -1,5 +1,7 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { StorageService } from './services/storage.service';
import { ThemeModeToggleComponent } from './components/theme-mode-toggle/theme-mode-toggle.component';
import { BannerCoursesAuthComponent } from './components/banner-courses-auth/banner-courses-auth.component';
import { BannerCoursesGraphQLCodeFirstComponent } from './components/banner-courses-graphql-cf/banner-courses-graphql-cf.component';
import { BannerDevtoolsComponent } from './components/banner-devtools/banner-devtools.component';
@@ -24,6 +26,7 @@ import { ExtensionPipe } from './pipes/extension.pipe';
BannerCoursesGraphQLCodeFirstComponent,
BannerDevtoolsComponent,
BannerCoursesAuthComponent,
ThemeModeToggleComponent,
],
exports: [
ExtensionPipe,
@@ -36,6 +39,8 @@ import { ExtensionPipe } from './pipes/extension.pipe';
BannerCoursesGraphQLCodeFirstComponent,
BannerDevtoolsComponent,
BannerCoursesAuthComponent,
ThemeModeToggleComponent,
],
providers: [StorageService],
})
export class SharedModule {}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 86 KiB

View File

@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en">
<html mode="dark" lang="en">
<head>
<title>Documentation | NestJS - A progressive Node.js framework</title>
<base href="/" />

View File

@@ -25,11 +25,11 @@ code {
font-family: Inconsolata, Consolas, 'Courier New', monospace;
font-display: swap;
padding: 2px 6px;
color: #2876d2;
color: var(--inline-code-color);
border-radius: 4px;
font-size: 15px;
white-space: pre-wrap;
background: #f0f2f3;
background: var(--background-2dp);
}
code[class*='language-'],
@@ -65,7 +65,7 @@ pre[class*='language-'] {
pre[class*='language-'],
:not(pre) > code[class*='language-'] {
background: #1d1d1d;
background: var(--code-background);
// box-shadow: 0 5px 20px rgba(6, 6, 6, 0.35);
border-radius: 6px;
}

99
src/scss/theme.scss Normal file
View File

@@ -0,0 +1,99 @@
.light-mode {
--primary: #ea2845;
--primary-accent: #ea2868;
--primary-1dp: #d71e38;
--primary-2dp: #da2640;
--primary-3dp:#db2840;
--primary-4dp: #e40020;
--primary-5dp: #ff0023;
--primary-gradient: linear-gradient(90deg, var(--primary) 0%, var(--primary-accent) 100%);
--color: #404040;
--color-1dp: #151515;
--background: #fdfdfd;
--background-1dp: #f7f7f7;
--background-2dp: #f0f2f3;
--background-3dp: #e8e8e8;
--background-4dp: #efefef;
--background-5dp: #cccccc;
--header-background: #151515;
--menu-color: #151515;
--menu-background: #f5f5f5;
--inline-code-color: #2876d2;
--code-background: #1d1d1d;
--warning: #ffb36f;
--warning-color: #ed8529;
--warning-background: #fff5ec;
--info: #0894e2;
--info-color: #0894e2;
--info-background: rgba(8, 148, 226, 0.038);
--error: #ed2945;
--error-background: #f9eff1;
--company-filter: grayscale(100%);
--company-filter-hover: grayscale(0%);
--company-logo-filter: grayscale(1);
--company-logo-opacity: 0.5;
--images-filter: unset;
--images-box-shadow: 0 0 50px 0 rgba(0, 0, 0, 0.08);
}
.dark-mode {
--primary: #f23551;
--primary-accent: #e23770;
--primary-1dp: #f45f75;
--primary-2dp: #f4526a;
--primary-3dp: #f1455f;
--primary-4dp: #f23c57;
--primary-5dp: #f23551;
--primary-gradient: linear-gradient(90deg, var(--primary) 0%, var(--primary-accent) 100%);
--color: #dfdfe3;
--color-1dp: #d0d0d4;
--background: #1f1f22;
--background-1dp: #232327;
--background-2dp: #252528;
--background-3dp: #29292d;
--background-4dp: #3d3d41;
--background-5dp: #39393e;
--header-background: #1b1b1d;
--menu-color: #dfdfe3;
--menu-background: #242427;
--inline-code-color: #8ec2ff;
--code-background: #18181a;
--warning: #ffb36f;
--warning-color: #ed8529;
--warning-background: #504337;
--info: #0894e2;
--info-color: #0894e2;
--info-background: rgba(8, 148, 226, 0.038);
--error: #ff677c;
--error-background: #3a2f30;
--company-filter: contrast(0.5);
--company-filter-hover: opacity(1);
--company-logo-filter: contrast(0.5) grayscale(100%);
--company-logo-opacity: unset;
--images-filter: invert(1) contrast(0.85);
--images-box-shadow: 0 0 0px 0 rgba(0, 0, 0, 0.08);
}

View File

@@ -1,6 +1,7 @@
@use './scss/hljs';
@use './scss/variables';
@use './scss/utils';
@use './scss/theme.scss';
:root {
--docsearch-primary-color: #ed2945;
@@ -11,7 +12,14 @@
--docsearch-searchbox-shadow: none;
--primary-color: #ea2845;
--primary-accent-color: #ea2868;
--primary-gradient: linear-gradient(90deg, var(--primary-color) 0%, var(--primary-accent-color) 100%);
}
html[mode='dark'] {
@extend .dark-mode;
}
html[mode='light'] {
@extend .light-mode;
}
body {
@@ -19,11 +27,16 @@ body {
font-weight: 400;
// letter-spacing: 0.2px;
font-family: 'Source Sans Pro', 'Helvetica Neue', sans-serif;
background-color: #fdfdfd;
font-display: swap;
color: variables.$grey-color;
background-color: var(--background);
color: var(--color);
margin: 0;
-webkit-font-smoothing: antialiased;
-webkit-transition: background 200ms cubic-bezier(0.7, 0, 0.3, 1);
-moz-transition: background 200ms cubic-bezier(0.7, 0, 0.3, 1);
-ms-transition: background 200ms cubic-bezier(0.7, 0, 0.3, 1);
-o-transition: background 200ms cubic-bezier(0.7, 0, 0.3, 1);
transition: background 200ms cubic-bezier(0.7, 0, 0.3, 1);
}
a {
@@ -31,7 +44,7 @@ a {
}
strong {
color: #2d2d2d;
color: var(--color-1dp);
font-weight: 600;
}
@@ -51,7 +64,7 @@ blockquote {
line-height: 1.6;
position: relative;
margin: 35px 0;
background: #f9eff1;
background: var(--error-background);
padding: 20px;
border-radius: 3px;
@@ -82,24 +95,24 @@ blockquote {
}
&.warning {
background: #fff5ec;
background: var(--warning-background);
&::before {
background: #ffb36f;
background: var(--warning);
}
strong,
a {
color: #ed8529;
color: var(--warning-color);
}
}
&.info {
background: rgba(8, 148, 226, 0.038);
background: var(--info-background);
&::before {
background: #0894e2;
background: var(--info);
}
strong,
a {
color: #0894e2;
color: var(--info-color);
}
}
}
@@ -121,6 +134,11 @@ figure {
}
}
.illustrative-image {
filter: var(--images-filter);
box-shadow: var(--images-box-shadow);
}
figcaption {
color: rgba(variables.$silver-color, 0.9);
font-size: 16px;
@@ -149,27 +167,27 @@ tr {
th {
padding: 20px;
background: #efefef;
background: var(--background-1dp);
}
tr:nth-of-type(even) td {
background: #f7f7f7;
background: var(--background-1dp);
}
tr:nth-of-type(odd) td:first-of-type {
border-right: 1px solid #f0f2f3;
border-right: 1px solid var(--background-2dp);
@include utils.media(medium) {
border-right: 0;
border-bottom: 1px solid #f0f2f3;
border-bottom: 1px solid var(--background-2dp);
}
}
tr:nth-of-type(even) td:first-of-type {
border-right: 1px solid #fff;
border-right: 1px solid var(--background);
@include utils.media(medium) {
border-right: 0;
border-bottom: 1px solid #fff;
border-bottom: 1px solid var(--background);
}
}
@@ -184,13 +202,13 @@ tr td {
}
tr td span.table-code-asterisk {
color: #2876d2;
color: var(--inline-code-color);
font-weight: 700;
}
.file-tree {
background: #f9f9f9;
border: 4px solid #f5f5f5;
background: var(--code-background);
border: 4px solid rgba(var(--background-2dp), 0.8);
margin: 40px 0;
padding: 16px 32px;
@@ -198,7 +216,7 @@ tr td span.table-code-asterisk {
display: block;
line-height: 32px;
font-size: 15px;
color: #5a5a5a;
color: var(--color-1dp);
}
.children {
@@ -226,7 +244,7 @@ tr td span.table-code-asterisk {
}
.external {
background: #f7f7f7;
background: var(--background-2dp);
&::before {
background: #e8e8e8;