consolidate all colors into one file

This commit is contained in:
Evert Prants 2022-09-12 22:31:58 +03:00
parent f47a919b03
commit 919039a572
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
17 changed files with 191 additions and 170 deletions

View File

@ -4,7 +4,7 @@
border-radius: 8px;
gap: 1rem;
padding: 0.5rem;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.25);
box-shadow: 0 0 8px var(--box-shadow-color);
.titleWrap {
display: flex;

View File

@ -27,7 +27,7 @@ import { FormControl } from '../common/Form/FormControl/FormControl';
import toast from 'react-hot-toast';
import { Button } from '../common/Button/Button';
import userHasPrivileges from '../../lib/utils/has-privileges';
import { publishJSON } from '../../lib/utils/swr-fetcher';
import { publishJSON } from '../../lib/utils/fetch';
const LINK_NAMES = {
redirect_uri: 'Redirect URI',

View File

@ -4,7 +4,7 @@
border-radius: 8px;
gap: 1rem;
padding: 0.5rem;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.25);
box-shadow: 0 0 8px var(--box-shadow-color);
.titleWrap {
display: flex;

View File

@ -12,7 +12,7 @@ import { UPLOADS_URL } from '../../lib/constants';
import { Paginator } from '../common/Paginator/Paginator';
import { Dropdown } from '../common/Dropdown/Dropdown';
import toast from 'react-hot-toast';
import { publishJSON } from '../../lib/utils/swr-fetcher';
import { publishJSON } from '../../lib/utils/fetch';
import { useForm } from '../../lib/hooks/useForm';
import { ModalProps } from '../../lib/types/modal.interface';
import { Button } from '../common/Button/Button';

View File

@ -2,70 +2,68 @@
appearance: none;
padding: 0.5rem 1.5rem;
border-radius: 4px;
transition: background linear 0.33s;
transition: background linear 0.15s;
--btn-background: transparent;
--btn-color: #000;
--btn-border: #ddd;
color: var(--btn-color);
background: var(--btn-background);
border: 1px solid var(--btn-border);
&:not([disabled]) {
cursor: pointer;
}
&.default {
border: 1px solid #b9b9b9;
background: linear-gradient(
180deg,
rgb(246 246 246) 0%,
rgb(241 241 241) 100%
);
--btn-color: var(--button-default-color);
--btn-border: var(--button-default-border);
--btn-background: var(--button-default-background);
&[disabled] {
--btn-background: var(--button-default-disabled);
--btn-color: var(--button-default-disabled-color);
}
&:not([disabled]) {
&:hover,
&:focus-visible {
background: linear-gradient(
180deg,
rgb(255 255 255) 0%,
rgb(250 250 250) 100%
);
--btn-background: var(--button-default-hover);
}
&:active {
background: linear-gradient(
180deg,
rgb(241 241 241) 0%,
rgb(246 246 246) 100%
);
--btn-background: var(--button-default-active);
}
}
}
&.primary {
border: 1px solid #00aaff;
background: linear-gradient(
180deg,
rgb(133 216 255) 0%,
rgba(59, 190, 255, 1) 100%
);
--btn-color: var(--button-primary-color);
--btn-border: 1px solid var(--button-primary-border);
--btn-background: var(--button-primary-background);
&[disabled] {
--btn-background: var(--button-primary-disabled);
--btn-color: var(--button-primary-disabled-color);
}
&:not([disabled]) {
&:hover,
&:focus-visible {
background: linear-gradient(
180deg,
rgb(145 220 255) 0%,
rgb(84 198 255) 100%
);
--btn-background: var(--button-primary-hover);
}
&:active {
background: linear-gradient(
180deg,
rgb(77, 196, 255) 0%,
rgb(124, 213, 255) 100%
);
--btn-background: var(--button-primary-active);
}
}
}
&.link {
border: 0;
background: transparent;
color: #0090d8;
--btn-border: transparent;
--btn-background: transparent;
--btn-color: var(--button-link-color);
&:not([disabled]) {
&:hover,

View File

@ -2,6 +2,6 @@
max-width: 1080px;
margin: 0 auto;
padding: 1rem;
background-color: #fff;
background-color: var(--container-main);
min-height: calc(100vh - 54px);
}

View File

@ -3,8 +3,9 @@
.toggle {
appearance: none;
border: 1px solid #ddd;
background: #ffffff;
border: 1px solid var(--container-main-border);
transition: background-color linear 0.15s;
background-color: var(--container-main);
border-radius: 4px;
width: 32px;
height: 32px;
@ -13,7 +14,7 @@
&.active,
&:hover,
&:focus-visible {
background-color: rgb(240, 240, 240);
background-color: var(--container-main-secondary);
}
&.active {
@ -35,8 +36,8 @@
flex-direction: column;
top: 100%;
min-width: 140px;
background-color: #fff;
border: 1px solid #ddd;
background-color: var(--container-main);
border: 1px solid var(--container-main-border);
border-radius: 4px;
a,
@ -44,15 +45,16 @@
appearance: none;
border: 0;
background: transparent;
transition: background-color linear 0.15s;
font-size: 1rem;
text-align: left;
padding: 0.5rem 0.5rem;
border-bottom: 1px solid #ddd;
border-bottom: 1px solid var(--container-main-border);
cursor: pointer;
&:hover,
&:focus-visible {
background-color: rgb(240, 240, 240);
background-color: var(--container-main-secondary);
}
&:last-child {

View File

@ -32,13 +32,15 @@
font-size: 14px;
font-family: inherit;
font-weight: 400;
border: 1px solid #a4a4a4;
box-shadow: inset 0 0 4px #0000001f;
color: var(--form-field-color);
background: var(--form-field-background);
border: 1px solid var(--form-field-border);
box-shadow: inset 0 0 4px var(--form-field-box-shadow);
+ span {
font-size: 0.875rem;
margin-top: 0.25rem;
color: rgb(100, 100, 100);
color: var(--form-field-helper-color);
}
}

View File

@ -1,13 +1,15 @@
.nav {
display: flex;
background-color: #2eb9ff;
border-bottom: 4px solid #00aaff;
color: var(--nav-text-color);
background-color: var(--nav-main-color);
border-bottom: 4px solid var(--nav-secondary-color);
.inner {
display: flex;
max-width: 1080px;
width: 100%;
margin: 0 auto;
ul {
list-style: none;
display: flex;
@ -26,7 +28,7 @@
font-weight: bold;
a {
background-color: #00aaff;
background-color: var(--nav-secondary-color);
}
}

View File

@ -3,14 +3,15 @@
flex-direction: column;
max-width: 480px;
margin: 0 auto;
background-color: #fff;
background-color: var(--container-main);
margin-top: 8%;
border-radius: 8px;
box-shadow: 0 8px 32px #0000006b;
box-shadow: 0 8px 32px var(--modal-shadow-color);
color: var(--text-color-main);
.header {
padding: 1rem;
border-bottom: 1px solid #ddd;
border-bottom: 1px solid var(--container-main-border);
display: flex;
justify-content: space-between;
@ -29,7 +30,7 @@
.footer {
padding: 1rem;
border-top: 1px solid #ddd;
border-top: 1px solid var(--container-main-border);
gap: 0.5rem;
display: flex;
justify-content: flex-end;

View File

@ -5,7 +5,7 @@
.pageButton {
appearance: none;
padding: 0.5rem 0.75rem;
border: 1px solid #ddd;
border: 1px solid var(--container-main-border);
&.previous {
border-top-left-radius: 8px;

View File

@ -1,8 +1,24 @@
import { API_URL } from '../constants';
import { CurrentUserDto } from '../types/user-response.interface';
import { fetchBearer, fetchToken } from '../utils/fetch';
import { API_URL, CLIENT_ID, CLIENT_SECRET, TOKEN_URL } from '../constants';
export const getUserInfo = async (accessToken: string) =>
await fetchBearer<CurrentUserDto>(accessToken, `${API_URL}/user`);
fetch(`${API_URL}/user`, {
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
}).then((res) => res.json());
export const getAccessToken = async (code: string) => await fetchToken(code);
export const getAccessToken = async (code: string) =>
fetch(TOKEN_URL, {
headers: {
Authorization: `Basic ${Buffer.from(
`${CLIENT_ID}:${CLIENT_SECRET}`
).toString('base64')}`,
'Content-Type': 'application/json',
},
method: 'POST',
body: JSON.stringify({
grant_type: 'authorization_code',
code,
}),
}).then((res) => res.json());

View File

@ -1,32 +1,68 @@
import { CLIENT_ID, CLIENT_SECRET, TOKEN_URL } from '../constants';
import { OAuth2TokenDto } from '../types/token-response.interface';
export default async function fetchJson<JSON = unknown>(
input: RequestInfo,
init?: RequestInit
): Promise<JSON> {
const response = await fetch(input, { ...init, credentials: 'include' });
export async function fetchBearer<T>(
accessToken: string,
url: string,
...options: any[]
): Promise<T> {
return fetch(url, {
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
...options,
}).then((res) => res.json());
// if the server replies, there's always some data in json
// if there's a network error, it will throw at the previous line
const data = await response.json();
// response.ok is true when res.status is 2xx
// https://developer.mozilla.org/en-US/docs/Web/API/Response/ok
if (response.ok) {
return data;
}
throw new FetchError({
message: response.statusText,
response,
data,
});
}
export async function fetchToken(code: string): Promise<OAuth2TokenDto> {
return fetch(TOKEN_URL, {
export async function publishJSON(
input: RequestInfo,
method: string = 'POST',
body?: Object,
init?: RequestInit
) {
return fetchJson(input, {
...init,
method,
headers: {
Authorization: `Basic ${Buffer.from(
`${CLIENT_ID}:${CLIENT_SECRET}`
).toString('base64')}`,
'Content-Type': 'application/json',
},
method: 'POST',
body: JSON.stringify({
grant_type: 'authorization_code',
code,
}),
}).then((res) => res.json());
body: JSON.stringify(body),
});
}
export class FetchError extends Error {
response: Response;
data: {
message: string;
};
constructor({
message,
response,
data,
}: {
message: string;
response: Response;
data: {
message: string;
};
}) {
// Pass remaining arguments (including vendor specific ones) to parent constructor
super(message);
// Maintains proper stack trace for where our error was thrown (only available on V8)
if (Error.captureStackTrace) {
Error.captureStackTrace(this, FetchError);
}
this.name = 'FetchError';
this.response = response;
this.data = data ?? { message: message };
}
}

View File

@ -1,68 +0,0 @@
export default async function fetchJson<JSON = unknown>(
input: RequestInfo,
init?: RequestInit
): Promise<JSON> {
const response = await fetch(input, { ...init, credentials: 'include' });
// if the server replies, there's always some data in json
// if there's a network error, it will throw at the previous line
const data = await response.json();
// response.ok is true when res.status is 2xx
// https://developer.mozilla.org/en-US/docs/Web/API/Response/ok
if (response.ok) {
return data;
}
throw new FetchError({
message: response.statusText,
response,
data,
});
}
export async function publishJSON(
input: RequestInfo,
method: string = 'POST',
body?: Object,
init?: RequestInit
) {
return fetchJson(input, {
...init,
method,
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
}
export class FetchError extends Error {
response: Response;
data: {
message: string;
};
constructor({
message,
response,
data,
}: {
message: string;
response: Response;
data: {
message: string;
};
}) {
// Pass remaining arguments (including vendor specific ones) to parent constructor
super(message);
// Maintains proper stack trace for where our error was thrown (only available on V8)
if (Error.captureStackTrace) {
Error.captureStackTrace(this, FetchError);
}
this.name = 'FetchError';
this.response = response;
this.data = data ?? { message: message };
}
}

View File

@ -1,7 +1,7 @@
import '../styles/globals.scss';
import type { AppProps } from 'next/app';
import { SWRConfig } from 'swr';
import fetchJson from '../lib/utils/swr-fetcher';
import fetchJson from '../lib/utils/fetch';
import ModalRoot from '../components/common/Modal/ModalRoot/ModalRoot';
import { Toaster } from 'react-hot-toast';

40
styles/_colors.scss Normal file
View File

@ -0,0 +1,40 @@
:root {
--text-color-main: #000;
--background-main: rgb(231, 231, 231);
--container-main: #fff;
--container-main-border: #ddd;
--container-main-secondary: rgb(240, 240, 240);
--link-text-color: #0090d8;
--nav-text-color: #000;
--nav-main-color: #2eb9ff;
--nav-secondary-color: #00aaff;
--box-shadow-color: rgb(0 0 0 / 25%);
--modal-shadow-color: rgb(0 0 0 / 42%);
--button-default-color: #000;
--button-default-border: #b9b9b9;
--button-default-background: rgb(246 246 246);
--button-default-disabled: #ebebeb;
--button-default-disabled-color: #939393;
--button-default-hover: rgb(250 250 250);
--button-default-active: rgb(226, 226, 226);
--button-primary-color: #000;
--button-primary-border: #00aaff;
--button-primary-background: rgb(90, 200, 255);
--button-primary-disabled: rgb(39 131 177);
--button-primary-disabled-color: #484848;
--button-primary-hover: rgb(114, 208, 255);
--button-primary-active: rgb(70, 196, 255);
--button-link-color: #0090d8;
--form-field-color: #000;
--form-field-background: #fff;
--form-field-border: #a4a4a4;
--form-field-box-shadow: #0000001f;
--form-field-helper-color: rgb(100, 100, 100);
}

View File

@ -1,3 +1,4 @@
@import 'colors';
@import 'breakpoint';
@import 'focus';
@ -7,11 +8,12 @@ body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
background-color: rgb(231, 231, 231);
background-color: var(--background-main);
color: var(--text-color-main);
}
a {
color: #00aaff;
color: var(--link-text-color);
text-decoration: none;
&:hover {
@ -39,13 +41,3 @@ dl {
margin-top: 0.5rem;
}
}
@media (prefers-color-scheme: dark) {
html {
color-scheme: dark;
}
body {
color: white;
background: black;
}
}