consolidate all colors into one file
This commit is contained in:
parent
f47a919b03
commit
428767b195
@ -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;
|
||||
|
@ -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',
|
||||
|
@ -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;
|
||||
|
@ -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';
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,10 +45,11 @@
|
||||
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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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 };
|
||||
}
|
||||
}
|
||||
|
@ -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 };
|
||||
}
|
||||
}
|
@ -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
40
styles/_colors.scss
Normal 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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user