ui revamp 2

better cards UI, now I am going to merge the card colors page into it
This commit is contained in:
Guy Sandler 2026-02-12 19:13:30 -08:00
parent 81f200e5b7
commit 77cdc24df6
4 changed files with 100 additions and 116 deletions

View File

@ -115,7 +115,7 @@ h2 {margin-top: 20px;font-weight:600}
textarea {resize: vertical}
#premade-themes {min-height: 375px; grid-template-rows: repeat(6, 1fr)}
#premade-themes, #premade-darkmodes {display:grid;grid-template-columns: repeat(4, 1fr);gap: 3px;}
#error_log_output, #rk_output {min-height: 100px;}
#error_log_output, #rk_output {min-height: 100px;}
#image-tester {display: none;}
#alert {font-size:13px;background: #e7495ebd; backdrop-filter: blur(1px); border-radius: 8px; padding: 15px; margin: 20px;position: fixed; transition: .3s bottom; bottom: -400px; left: 0;z-index:100000;}
#alert:hover {cursor:pointer;}
@ -201,90 +201,17 @@ input[type="checkbox"]:checked {background: #8dd28d;}
::-webkit-scrollbar-thumb {background: #323232;border-radius:2px;}
::-webkit-scrollbar-button {background: #161616; height: 4px}
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
gap: 10px;
margin-bottom: 20px;
}
.course-card-button {
background: var(--inputbg);
border: 1px solid var(--borders);
border-radius: 8px;
padding: 15px 10px;
color: #e2e2e2;
font-family: inherit;
font-size: 12px;
font-weight: 600;
cursor: pointer;
transition: 0.2s all ease;
text-align: center;
min-height: 60px;
display: flex;
align-items: center;
justify-content: center;
}
.course-card-button:hover {
background: #adbcc724;
border-color: #56Caf0;
}
.course-card-button.active {
background: #56Caf0;
color: #000;
}
.card-edit-menu {
background: var(--containerbg);
border-radius: 10px;
padding: 20px;
margin-top: 15px;
}
.card-edit-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.card-edit-title {
font-size: 16px;
font-weight: 600;
color: #fff;
}
.card-close-btn {
background: none;
border: none;
color: #999;
font-size: 18px;
cursor: pointer;
padding: 5px;
}
.card-edit-section {
margin-bottom: 15px;
}
.card-edit-label {
font-size: 13px;
color: #c7c7c7;
margin-bottom: 5px;
display: block;
}
.card-image-preview {
width: 100px;
height: 60px;
background-size: cover;
background-position: center;
border-radius: 6px;
margin-top: 8px;
border: 1px solid var(--borders);
}
.card-grid {display: grid;grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));gap: 10px;margin-bottom: 20px;}
.course-card-button {background: var(--inputbg);border: 1px solid var(--borders);border-radius: 8px;padding: 15px 10px;color: #e2e2e2;font-family: inherit;font-size: 12px;font-weight: 600;cursor: pointer;transition: 0.2s all ease;text-align: center;min-height: 60px;display: flex;align-items: center;justify-content: center;}
.course-card-button:hover {background: #adbcc724;border-color: #56Caf0;}
.course-card-button.active {background: #56Caf0;color: #000;}
.card-edit-menu {background: var(--containerbg);border-radius: 10px;padding: 20px;margin-top: 15px;}
.card-edit-header {display: flex;justify-content: space-between;align-items: center;margin-bottom: 15px;}
.card-edit-title {font-size: 16px;font-weight: 600;color: #fff;}
.card-close-btn {background: none;border: none;color: #737373;font-size: 18px;cursor: pointer;padding: 8px;border-radius: 5px;}
.card-edit-section {margin-bottom: 15px;}
.card-edit-label {font-size: 13px;color: #c7c7c7;margin-bottom: 5px;display: block;}
.card-image-preview {width: 100px;height: 60px;background-size: cover;background-position: center;border-radius: 6px;margin-top: 8px;border: 1px solid var(--borders);}
@keyframes like {
0% {

View File

@ -737,7 +737,7 @@
<h3 class="header-small">Missing cards?</h3>
<div style="display: flex; gap: 10px; align-items: center;">
<input type="checkbox" id="card_method_dashboard"></input>
<span>Enable alternative card method</span>
<span>Get Active Cards From Dashboard</span>
</div>
</div>
</div>

View File

@ -79,7 +79,7 @@ chrome.runtime.onInstalled.addListener(function () {
"cumulative_gpa": { "name": "Cumulative GPA", "hidden": false, "weight": "dnc", "credits": 999, "gr": 3.21 },
"show_updates": false,
"card_method_date": false,
"card_method_dashboard": false,
"card_method_dashboard": true,
"card_limit": 25,
"remind": false,
"reminders": [],

View File

@ -108,7 +108,7 @@ const defaultOptions = {
"cumulative_gpa": { "name": "Cumulative GPA", "hidden": false, "weight": "dnc", "credits": 999, "gr": 3.21 },
"show_updates": false,
"card_method_date": false,
"card_method_dashboard": false,
"card_method_dashboard": true,
"card_limit": 25,
"scheduledReminder": false,
"scheduledReminderTime": { "hour": "09", "minute": "00" },
@ -1511,8 +1511,6 @@ function setCustomImage(key, val) {
let test = new Image();
test.onerror = () => {
displayAlert(true, "It seems that the image link you provided isn't working. Make sure to right click on any images you want to use and select \"copy image address\" to get the correct link.");
// ensures storage limit error will override previous error
updateCards(key, { "img": val });
}
test.onload = clearAlert;
@ -1597,12 +1595,24 @@ function displayAdvancedCards() {
console.error("Card grid element not found");
return;
}
cardGrid.innerHTML = "";
const customCards = storage.custom_cards || {};
const customCards2 = storage.custom_cards_2 || {};
const allCards = { ...customCards, ...customCards2 };
const allCards = {};
Object.keys(customCards).forEach((courseId) => {
allCards[courseId] = {
...customCards[courseId],
...(customCards2[courseId] || {}),
};
});
Object.keys(customCards2).forEach((courseId) => {
if (!allCards[courseId]) {
allCards[courseId] = customCards2[courseId];
}
});
if (Object.keys(allCards).length === 0) {
cardGrid.innerHTML = '<p style="text-align: center; color: #999; padding: 20px;">No course cards found. Visit your Canvas dashboard to load courses.</p>';
return;
@ -1620,8 +1630,6 @@ function displayAdvancedCards() {
if (editMenu) {
editMenu.style.display = "none";
}
document.getElementById("card-edit-menu").style.display = "none";
});
sendFromPopup("getCards");
}
@ -1629,9 +1637,18 @@ function displayAdvancedCards() {
function createCourseButton(courseId, courseData) {
const button = document.createElement("button");
button.className = "course-card-button";
button.textContent = courseData.name || `Course ${courseId}`;
const displayName =
courseData.name ||
courseData.default ||
courseData.code ||
`Course ${courseId}`;
button.textContent = displayName;
button.dataset.courseId = courseId;
if (courseData.img || courseData.hidden || courseData.hide) {
button.classList.add("customized");
}
button.addEventListener("click", () => {
document.querySelectorAll(".course-card-button").forEach(btn => btn.classList.remove("active"));
button.classList.add("active");
@ -1643,12 +1660,32 @@ function createCourseButton(courseId, courseData) {
function showCardEditMenu(courseId, courseData) {
const editMenu = document.getElementById("card-edit-menu");
const cardGrid = document.getElementById("card-grid");
if (cardGrid) cardGrid.style.display = "none";
editMenu.style.display = "block";
const displayName =
courseData.name ||
courseData.default ||
courseData.code ||
`Course ${courseId}`;
editMenu.innerHTML = `
<div class="card-edit-header">
<h3 class="card-edit-title">${courseData.name || `Course ${courseId}`}</h3>
<button class="card-close-btn" onclick="hideCardEditMenu()">×</button>
<h3 class="card-edit-title">${displayName}</h3>
<button class="card-close-btn" id="card-close-btn">close</button>
</div>
<div class="card-edit-section">
<label class="card-edit-label">Custom Name</label>
<input type="text" class="card-input" id="card-name-input"
value="${courseData.name || ""}" placeholder="Enter custom course name">
</div>
<div class="card-edit-section">
<label class="card-edit-label">Custom Code</label>
<input type="text" class="card-input" id="card-code-input"
value="${courseData.code || ""}" placeholder="Enter custom course code">
</div>
<div class="card-edit-section">
@ -1658,28 +1695,34 @@ function showCardEditMenu(courseId, courseData) {
<div class="card-image-preview" id="card-image-preview"></div>
</div>
<div class="card-edit-section">
<label class="card-edit-label">Course Link</label>
<input type="text" class="card-input" id="card-link-input"
value="${courseData.link || ""}" placeholder="Enter custom link or 'none'">
</div>
<div class="card-edit-section">
<label class="card-edit-label">Hide Card</label>
<div style="display: flex; align-items: center; gap: 8px;">
<input type="checkbox" id="card-hide-input" ${courseData.hide ? "checked" : ""}>
<input type="checkbox" id="card-hide-input" ${courseData.hidden || courseData.hide ? "checked" : ""}>
<span>Hide this card from dashboard</span>
</div>
</div>
<div style="display: flex; gap: 10px; margin-top: 20px;">
<button class="big-button" onclick="saveCardChanges('${courseId}')">Save Changes</button>
<button class="customization-button" onclick="resetCardToDefault('${courseId}')">Reset to Default</button>
<button class="big-button" id="save-card-btn">Save Changes</button>
<button class="customization-button" id="reset-card-btn">Reset to Default</button>
</div>
`;
document
.getElementById("card-close-btn")
.addEventListener("click", hideCardEditMenu);
document
.getElementById("save-card-btn")
.addEventListener("click", () => saveCardChanges(courseId));
document
.getElementById("reset-card-btn")
.addEventListener("click", () => resetCardToDefault(courseId));
updateImagePreview();
document.getElementById("card-image-input").addEventListener("input", updateImagePreview);
document
.getElementById("card-image-input")
.addEventListener("input", updateImagePreview);
}
function updateImagePreview() {
@ -1699,27 +1742,37 @@ function updateImagePreview() {
}
function saveCardChanges(courseId) {
const nameInput = document.getElementById("card-name-input");
const codeInput = document.getElementById("card-code-input");
const imageInput = document.getElementById("card-image-input");
const linkInput = document.getElementById("card-link-input");
const hideInput = document.getElementById("card-hide-input");
const updates = {
name: nameInput.value,
code: codeInput.value,
img: imageInput.value,
link: linkInput.value,
hidden: hideInput.checked,
hide: hideInput.checked,
};
updateCards(courseId, updates);
if (imageInput.value !== "" && imageInput.value !== "none") {
setCustomImage(courseId, imageInput.value);
} else {
updateCards(courseId, updates);
}
displayAlert(false, "Card settings saved successfully!");
hideCardEditMenu();
setTimeout(() => {
displayAdvancedCards();
}, 500);
}
function resetCardToDefault(courseId) {
updateCards(courseId, { img: "", link: "", hide: false });
updateCards(courseId, { name: "", code: "", img: "", hidden: false, hide: false });
displayAlert(false, "Card reset to default settings!");
setTimeout(() => {
@ -1728,11 +1781,15 @@ function resetCardToDefault(courseId) {
}
function hideCardEditMenu() {
document.getElementById("card-edit-menu").style.display = "none";
const editMenu = document.getElementById("card-edit-menu");
const cardGrid = document.getElementById("card-grid");
document.querySelectorAll(".course-card-button").forEach((btn) => {
btn.classList.remove("active");
});
if (editMenu) editMenu.style.display = "none";
if (cardGrid) cardGrid.style.display = "grid";
document
.querySelectorAll(".course-card-button")
.forEach((btn) => btn.classList.remove("active"));
}
function toggleDarkModeDisable(disabled) {