updated fe and added be
This commit is contained in:
parent
8ebda489dc
commit
84a080ca73
|
|
@ -16,6 +16,7 @@ dist-ssr
|
|||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.env
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
const mongoose = require('mongoose');
|
||||
|
||||
const connectDB = async () => {
|
||||
const conn = await mongoose.connect(process.env.MONGO_URI);
|
||||
console.log(`MongoDB Connected: ${conn.connection.host}`);
|
||||
};
|
||||
|
||||
mongoose.set('strictQuery', true);
|
||||
|
||||
module.exports = connectDB;
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
const mongoose = require('mongoose');
|
||||
|
||||
const IdeaSchema = new mongoose.Schema({
|
||||
text: {
|
||||
type: String,
|
||||
required: [true, 'Please add a text field'],
|
||||
},
|
||||
tag: {
|
||||
type: String,
|
||||
},
|
||||
username: {
|
||||
type: String,
|
||||
},
|
||||
date: {
|
||||
type: Date,
|
||||
default: Date.now,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = mongoose.model('Idea', IdeaSchema);
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"name": "randomideas",
|
||||
"version": "1.0.0",
|
||||
"description": "idea shring app",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
"start": "node server.js",
|
||||
"dev": "nodemon server.js"
|
||||
},
|
||||
"author": "Jason",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dotenv": "^16.4.5",
|
||||
"express": "^4.19.2",
|
||||
"mongoose": "^8.5.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.1.4"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const Idea = require('../models/Idea');
|
||||
|
||||
//get all ideas
|
||||
router.get('/', async (req, res) => {
|
||||
try {
|
||||
const ideas = await Idea.find();
|
||||
res.json({ success: true, data_base: ideas });
|
||||
} catch (error) {
|
||||
res.status(500).json({ success: false, error: 'Something went wrong' });
|
||||
}
|
||||
});
|
||||
|
||||
//get one idea
|
||||
router.get('/:id', async (req, res) => {
|
||||
try {
|
||||
const idea = await Idea.findById(req.params.id);
|
||||
res.json({ success: true, data_base: idea });
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
res.status(500).json({ message: false, error: 'Something went wrong' });
|
||||
}
|
||||
|
||||
res.json({ success: true, data_base: idea });
|
||||
});
|
||||
|
||||
//add an idea
|
||||
router.post('/', async (req, res) => {
|
||||
const idea = new Idea({
|
||||
text: req.body.text,
|
||||
tag: req.body.tag,
|
||||
username: req.body.username,
|
||||
});
|
||||
|
||||
try {
|
||||
const savedIdea = await idea.save();
|
||||
res.json({ success: true, data_base: savedIdea });
|
||||
} catch (error) {
|
||||
res.status(500).json({ success: false, error: 'Something went wrong' });
|
||||
}
|
||||
});
|
||||
|
||||
//update idea
|
||||
router.put('/:id', async (req, res) => {
|
||||
try {
|
||||
const updatedIdea = await Idea.findByIdAndUpdate(
|
||||
req.params.id,
|
||||
{
|
||||
$set: {
|
||||
text: req.body.text,
|
||||
tag: req.body.tag,
|
||||
},
|
||||
},
|
||||
{
|
||||
new: true, //if the id doesn't exist, a new record will be created
|
||||
}
|
||||
);
|
||||
res.json({ successs: true, data_base: updatedIdea });
|
||||
} catch (error) {
|
||||
console.loh(error);
|
||||
res.status(500).json({ success: false, error: 'Something went wrong' });
|
||||
}
|
||||
});
|
||||
|
||||
//delete an idea
|
||||
router.delete('/:id', async (req, res) => {
|
||||
try {
|
||||
await Idea.findByIdAndDelete(req.params.id);
|
||||
res.json({ sucess: true, data: {} });
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
res.status(500).json({ success: false, error: 'Something went wrong' });
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
const express = require('express');
|
||||
require('dotenv').config();
|
||||
const port = process.env.PORT || 5000;
|
||||
const connectDB = require('./config/db');
|
||||
|
||||
connectDB();
|
||||
|
||||
const app = express();
|
||||
|
||||
//Body parser middleware
|
||||
//used to send POST requests in the body
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: false }));
|
||||
|
||||
app.get('/', (req, res) => {
|
||||
res.json({ message: 'Welcome to the RandomIdeas API' });
|
||||
});
|
||||
|
||||
//registering the routes
|
||||
const ideasRouter = require('./routes/ideas');
|
||||
app.use('/api/ideas', ideasRouter);
|
||||
|
||||
app.listen(port, () => console.log(`Server listening on port ${port}`));
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
class IdeaForm {
|
||||
constructor() {
|
||||
this._formModal = document.querySelector('#form-modal');
|
||||
}
|
||||
|
||||
//add all event listeners in a function
|
||||
addEventListeners() {
|
||||
this._form.addEventListener('submit', this.handleSubmit.bind(this));
|
||||
}
|
||||
|
||||
handleSubmit(e) {
|
||||
e.preventDefault(); //stops the submit and allows us to determine when it should run
|
||||
|
||||
//grabs values from the form
|
||||
const idea = {
|
||||
text: this._form.elements.text.value,
|
||||
tag: this._form.elements.tag.value,
|
||||
username: this._form.elements.username.value,
|
||||
};
|
||||
|
||||
//clear form fields after submit
|
||||
this._form.elements.text.value = '';
|
||||
this._form.elements.tag.value = '';
|
||||
this._form.elements.username.value = '';
|
||||
|
||||
//using the dispatch event method of the document object to dispatch a custom event
|
||||
//to the Modal from the IdeaForm, telling the Modal to close the form on submit
|
||||
document.dispatchEvent(new Event('closemodal'));
|
||||
}
|
||||
|
||||
//create a render function like react that will output the HTML
|
||||
render() {
|
||||
this._formModal.innerHTML = `
|
||||
<form id="idea-form">
|
||||
<div class="form-control">
|
||||
<label for="idea-text">Enter a Username</label>
|
||||
<input type="text" name="username" id="username" />
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label for="idea-text">What's Your Idea?</label>
|
||||
<textarea name="text" id="idea-text"></textarea>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label for="tag">Tag</label>
|
||||
<input type="text" name="tag" id="tag" />
|
||||
</div>
|
||||
<button class="btn" type="submit" id="submit">Submit</button>
|
||||
</form>`;
|
||||
|
||||
this._form = document.querySelector('#idea-form');
|
||||
this.addEventListeners(); //added within the render function because the HTML above is only available
|
||||
//in the DOM after the render function is called.
|
||||
}
|
||||
}
|
||||
|
||||
export default IdeaForm;
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
//this class returns a list of cards to the DOM
|
||||
//by mapping (looping) over an array
|
||||
|
||||
class IdeaList {
|
||||
constructor() {
|
||||
this._ideaListEl = document.querySelector('#idea-list');
|
||||
this._ideas = [
|
||||
{
|
||||
id: 1,
|
||||
text: 'Idea 1',
|
||||
username: 'John',
|
||||
date: '02/01/2023',
|
||||
tag: 'Business',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
text: 'Idea 2',
|
||||
username: 'Jimmy',
|
||||
date: '02/01/2023',
|
||||
tag: 'Technology',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
text: 'Idea 3',
|
||||
username: 'Jill',
|
||||
date: '02/01/2023',
|
||||
tag: 'Fashion',
|
||||
},
|
||||
];
|
||||
|
||||
//adding a set (datatype)
|
||||
this._validTags = new Set();
|
||||
this._validTags.add('technology');
|
||||
this._validTags.add('software');
|
||||
this._validTags.add('business');
|
||||
this._validTags.add('education');
|
||||
this._validTags.add('health');
|
||||
this._validTags.add('inventions');
|
||||
}
|
||||
|
||||
getTagClass(tag) {
|
||||
tag = tag.toLowerCase();
|
||||
let tagClass = '';
|
||||
//check if the tag that is passed in is within the set
|
||||
if (this._validTags.has(tag)) {
|
||||
tagClass = `tag-${tag}`;
|
||||
} else {
|
||||
tagClass = '';
|
||||
}
|
||||
return tagClass;
|
||||
}
|
||||
|
||||
render() {
|
||||
//use map on the array, creating a card for each item in the array and display
|
||||
// them on the DOM
|
||||
//map takes in a function as a parameter
|
||||
|
||||
this._ideaListEl.innerHTML = this._ideas
|
||||
.map((idea) => {
|
||||
//passing the tag entered for each item into the getTagClass function on each iteration of the map
|
||||
const tagClass = this.getTagClass(idea.tag);
|
||||
//it will be treated as an array of template strings
|
||||
return `
|
||||
|
||||
<div class="card">
|
||||
<button class="delete"><i class="fas fa-times"></i></button>
|
||||
<h3>
|
||||
${idea.text}
|
||||
</h3>
|
||||
<p class="tag ${tagClass}">${idea.tag.toUpperCase()}</p>
|
||||
<p>
|
||||
Posted on <span class="date">${idea.date}</span> by
|
||||
<span class="author">${idea.username}</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
`;
|
||||
})
|
||||
.join(''); //to turn it back in to a string
|
||||
}
|
||||
}
|
||||
|
||||
export default IdeaList;
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
class Modal {
|
||||
constructor() {
|
||||
//selecting DOM elements in the constructor
|
||||
this._modal = document.querySelector('#modal');
|
||||
this._modalBtn = document.querySelector('#modal-btn');
|
||||
this.addEventListeners(); //so that this functions runs right away
|
||||
}
|
||||
|
||||
//add all event listeners in a function
|
||||
addEventListeners() {
|
||||
// this._modalBtn.addEventListener('click', this.open.bind(this)); //takes an event and call back function as parameter
|
||||
this._modalBtn.addEventListener('click', () => {
|
||||
this.open();
|
||||
}); //takes an event and call back function as parameter
|
||||
window.addEventListener('click', this.outsideClick.bind(this)); //takes an event and call back function as parameter
|
||||
// receiving event from IdeaForm and running a call back function
|
||||
document.addEventListener('closemodal', () => this.close());
|
||||
}
|
||||
|
||||
//class methods
|
||||
open() {
|
||||
this._modal.style.display = 'block';
|
||||
}
|
||||
|
||||
close() {
|
||||
this._modal.style.display = 'none';
|
||||
}
|
||||
|
||||
outsideClick(e) {
|
||||
if (e.target === this._modal) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Modal;
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
export function setupCounter(element) {
|
||||
let counter = 0
|
||||
const setCounter = (count) => {
|
||||
counter = count
|
||||
element.innerHTML = `count is ${counter}`
|
||||
}
|
||||
element.addEventListener('click', () => setCounter(counter + 1))
|
||||
setCounter(0)
|
||||
}
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap");
|
||||
|
||||
body {
|
||||
font-family: "Poppins", sans-serif;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: #333;
|
||||
background-color: #f4f4f4;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
header {
|
||||
padding: 10px 0;
|
||||
text-align: center;
|
||||
margin-bottom: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#modal-btn {
|
||||
border: none;
|
||||
background: none;
|
||||
color: green;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.modal-box {
|
||||
margin: 10% auto;
|
||||
width: 600px;
|
||||
|
||||
background-color: steelblue;
|
||||
color: #fff;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
animation-name: modalopen;
|
||||
animation-duration: var(--modal-duration);
|
||||
}
|
||||
|
||||
@keyframes modalopen {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
form input,
|
||||
form textarea {
|
||||
width: 95%;
|
||||
padding: 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
form textarea {
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
form label {
|
||||
display: block;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.btn {
|
||||
background-color: #333;
|
||||
color: #fff;
|
||||
border: none;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: inherit;
|
||||
margin-top: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.ideas {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
}
|
||||
|
||||
.ideas .card {
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
margin: 10px;
|
||||
padding: 20px 15px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.tag {
|
||||
display: inline-block;
|
||||
background-color: #333;
|
||||
color: #fff;
|
||||
padding: 5px 10px;
|
||||
border-radius: 5px;
|
||||
margin: 5px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tag-technology {
|
||||
background: steelblue;
|
||||
}
|
||||
|
||||
.tag-software {
|
||||
background: coral;
|
||||
}
|
||||
|
||||
.tag-business {
|
||||
background: green;
|
||||
}
|
||||
|
||||
.tag-education {
|
||||
background: purple;
|
||||
}
|
||||
|
||||
.tag-health {
|
||||
background: red;
|
||||
}
|
||||
|
||||
.tag-inventions {
|
||||
background: orange;
|
||||
}
|
||||
|
||||
.delete {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
color: red;
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.delete:hover {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.date {
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.modal-box {
|
||||
width: 90%;
|
||||
}
|
||||
}
|
||||
20
index.html
20
index.html
|
|
@ -1,13 +1,25 @@
|
|||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite App</title>
|
||||
<title>Random Ideas</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<header>
|
||||
<h1>Random Ideas</h1>
|
||||
<button id="modal-btn">
|
||||
<i class="fa-solid fa-plus fa-2x"></i>
|
||||
</button>
|
||||
</header>
|
||||
<div class="container">
|
||||
<div id="idea-list" class="ideas"></div>
|
||||
</div>
|
||||
|
||||
<div id="modal" class="modal">
|
||||
<div id="form-modal" class="modal-box"></div>
|
||||
</div>
|
||||
<script type="module" src="/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="32" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path fill="#F7DF1E" d="M0 0h256v256H0V0Z"></path><path d="m67.312 213.932l19.59-11.856c3.78 6.701 7.218 12.371 15.465 12.371c7.905 0 12.89-3.092 12.89-15.12v-81.798h24.057v82.138c0 24.917-14.606 36.259-35.916 36.259c-19.245 0-30.416-9.967-36.087-21.996m85.07-2.576l19.588-11.341c5.157 8.421 11.859 14.607 23.715 14.607c9.969 0 16.325-4.984 16.325-11.858c0-8.248-6.53-11.17-17.528-15.98l-6.013-2.58c-17.357-7.387-28.87-16.667-28.87-36.257c0-18.044 13.747-31.792 35.228-31.792c15.294 0 26.292 5.328 34.196 19.247l-18.732 12.03c-4.125-7.389-8.591-10.31-15.465-10.31c-7.046 0-11.514 4.468-11.514 10.31c0 7.217 4.468 10.14 14.778 14.608l6.014 2.577c20.45 8.765 31.963 17.7 31.963 37.804c0 21.654-17.012 33.51-39.867 33.51c-22.339 0-36.774-10.654-43.819-24.574"></path></svg>
|
||||
|
Before Width: | Height: | Size: 995 B |
33
main.js
33
main.js
|
|
@ -1,24 +1,11 @@
|
|||
import './style.css'
|
||||
import javascriptLogo from './javascript.svg'
|
||||
import viteLogo from '/vite.svg'
|
||||
import { setupCounter } from './counter.js'
|
||||
import Modal from './components/Modal';
|
||||
import IdeaForm from './components/IdeaForm';
|
||||
import IdeaList from './components/IdeaList';
|
||||
import '@fortawesome/fontawesome-free/css/all.css';
|
||||
import './css/style.css';
|
||||
|
||||
document.querySelector('#app').innerHTML = `
|
||||
<div>
|
||||
<a href="https://vitejs.dev" target="_blank">
|
||||
<img src="${viteLogo}" class="logo" alt="Vite logo" />
|
||||
</a>
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript" target="_blank">
|
||||
<img src="${javascriptLogo}" class="logo vanilla" alt="JavaScript logo" />
|
||||
</a>
|
||||
<h1>Hello Vite!</h1>
|
||||
<div class="card">
|
||||
<button id="counter" type="button"></button>
|
||||
</div>
|
||||
<p class="read-the-docs">
|
||||
Click on the Vite logo to learn more
|
||||
</p>
|
||||
</div>
|
||||
`
|
||||
|
||||
setupCounter(document.querySelector('#counter'))
|
||||
const modal = new Modal();
|
||||
const ideaForm = new IdeaForm();
|
||||
ideaForm.render();
|
||||
const ideaList = new IdeaList();
|
||||
ideaList.render();
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@
|
|||
"": {
|
||||
"name": "randomideas",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^6.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^5.3.4"
|
||||
}
|
||||
|
|
@ -402,6 +405,15 @@
|
|||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/fontawesome-free": {
|
||||
"version": "6.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.6.0.tgz",
|
||||
"integrity": "sha512-60G28ke/sXdtS9KZCpZSHHkCbdsOGEhIUGlwq6yhY74UpTiToIh8np7A8yphhM4BWsvNFtIvLpi4co+h9Mr9Ow==",
|
||||
"license": "(CC-BY-4.0 AND OFL-1.1 AND MIT)",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.19.0.tgz",
|
||||
|
|
|
|||
|
|
@ -10,5 +10,8 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"vite": "^5.3.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^6.6.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
96
style.css
96
style.css
|
|
@ -1,96 +0,0 @@
|
|||
:root {
|
||||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||
line-height: 1.5;
|
||||
font-weight: 400;
|
||||
|
||||
color-scheme: light dark;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
background-color: #242424;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
a:hover {
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
place-items: center;
|
||||
min-width: 320px;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
#app {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 6em;
|
||||
padding: 1.5em;
|
||||
will-change: filter;
|
||||
transition: filter 300ms;
|
||||
}
|
||||
.logo:hover {
|
||||
filter: drop-shadow(0 0 2em #646cffaa);
|
||||
}
|
||||
.logo.vanilla:hover {
|
||||
filter: drop-shadow(0 0 2em #f7df1eaa);
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
.read-the-docs {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
background-color: #1a1a1a;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.25s;
|
||||
}
|
||||
button:hover {
|
||||
border-color: #646cff;
|
||||
}
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: 4px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
color: #213547;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
a:hover {
|
||||
color: #747bff;
|
||||
}
|
||||
button {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue