♻️ 函数式调用 snackbar

This commit is contained in:
BTMuli
2023-08-28 16:20:37 +08:00
parent 923aae692f
commit 598ce68a40
5 changed files with 125 additions and 147 deletions

View File

@@ -64,13 +64,11 @@
<span>暂无数据请尝试刷新</span> <span>暂无数据请尝试刷新</span>
</div> </div>
</div> </div>
<v-snackbar v-model="snackbar" :color="snackbarColor" timeout="1500">
{{ snackbarText }}
</v-snackbar>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
// vue // vue
import { computed, onMounted, ref } from "vue"; import { computed, onMounted, ref } from "vue";
import snackbar from "../../components/func/snackbar";
import ToLoading from "../../components/overlay/to-loading.vue"; import ToLoading from "../../components/overlay/to-loading.vue";
import TSubLine from "../../components/main/t-subline.vue"; import TSubLine from "../../components/main/t-subline.vue";
import TuaOverview from "../../components/userAbyss/tua-overview.vue"; import TuaOverview from "../../components/userAbyss/tua-overview.vue";
@@ -89,10 +87,6 @@ const userStore = useUserStore();
const loading = ref<boolean>(true); const loading = ref<boolean>(true);
const loadingTitle = ref<string>(); const loadingTitle = ref<string>();
const loadingSub = ref<string>(); const loadingSub = ref<string>();
// snackbar
const snackbar = ref<boolean>(false);
const snackbarColor = ref<string>("success");
const snackbarText = ref<string>();
// data // data
const userTab = ref<number>(0); const userTab = ref<number>(0);
@@ -152,9 +146,10 @@ function toAbyss(id: number): void {
if (abyssFind) { if (abyssFind) {
curAbyss.value = abyssFind; curAbyss.value = abyssFind;
} else { } else {
snackbarColor.value = "error"; snackbar({
snackbarText.value = "未找到该深渊数据"; text: "未找到该深渊数据",
snackbar.value = true; color: "error",
});
} }
} }
@@ -184,20 +179,18 @@ async function uploadAbyss(): Promise<void> {
return; return;
} }
loadingTitle.value = "正在转换角色数据"; loadingTitle.value = "正在转换角色数据";
transAbyss.avatars = Hutao.Abyss.utils.transAvatars(roles); transAbyss.Avatars = Hutao.Abyss.utils.transAvatars(roles);
loadingTitle.value = "正在上传深渊数据"; loadingTitle.value = "正在上传深渊数据";
const res = await Hutao.Abyss.postData(transAbyss); const res = await Hutao.Abyss.postData(transAbyss);
if (res.retcode === 0) {
snackbarColor.value = "success";
snackbarText.value = res.message;
} else {
snackbarColor.value = "error";
snackbarText.value = res.message;
}
loading.value = false; loading.value = false;
setTimeout(() => { if (res.retcode === 0) {
snackbar.value = true; snackbar({ text: <string>res.message });
}, 200); } else {
snackbar({
text: <string>res.message,
color: "error",
});
}
} }
</script> </script>
<style lang="css" scoped> <style lang="css" scoped>

View File

@@ -101,11 +101,11 @@
</v-card> </v-card>
</div> </div>
</div> </div>
<v-snackbar v-model="snackbar" timeout="1500" color="error"> {{ snackbarText }} </v-snackbar>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
// vue // vue
import { computed, onMounted, ref } from "vue"; import { computed, onMounted, ref } from "vue";
import snackbar from "../../components/func/snackbar";
import ToLoading from "../../components/overlay/to-loading.vue"; import ToLoading from "../../components/overlay/to-loading.vue";
// utils // utils
import { createTGWindow } from "../../utils/TGWindow"; import { createTGWindow } from "../../utils/TGWindow";
@@ -116,9 +116,6 @@ import Mys from "../../plugins/Mys";
// loading // loading
const loading = ref<boolean>(true); const loading = ref<boolean>(true);
const allCards = computed(() => AppGCGData); const allCards = computed(() => AppGCGData);
// snackbar
const snackbar = ref<boolean>(false);
const snackbarText = ref<string>("");
// search // search
const doSearch = ref<boolean>(false); const doSearch = ref<boolean>(false);
const search = ref<string>(""); const search = ref<string>("");
@@ -142,8 +139,10 @@ function toOuter(cardName: string, cardId: number): void {
console.log(cardName, cardId); console.log(cardName, cardId);
// 若不存在 contentId // 若不存在 contentId
if (cardId === -1) { if (cardId === -1) {
snackbarText.value = "该卡牌暂无外部链接"; snackbar({
snackbar.value = true; text: "该卡牌暂无外部链接",
color: "error",
});
return; return;
} }
const url = Mys.Api.Obc.replace("{contentId}", cardId.toString()); const url = Mys.Api.Obc.replace("{contentId}", cardId.toString());
@@ -168,8 +167,10 @@ async function searchCard(): Promise<void> {
console.log(res); console.log(res);
loading.value = false; loading.value = false;
if (res.length === 0) { if (res.length === 0) {
snackbarText.value = "未找到相关卡牌"; snackbar({
snackbar.value = true; text: "未找到相关卡牌",
color: "error",
});
doSearch.value = false; doSearch.value = false;
} else { } else {
CardsInfoS.value = res; CardsInfoS.value = res;

View File

@@ -103,10 +103,6 @@
</v-list> </v-list>
</div> </div>
</div> </div>
<!-- 弹窗提示 -->
<v-snackbar v-model="snackbar" timeout="1500" :color="snackbarColor" top>
{{ snackbarText }}
</v-snackbar>
</div> </div>
</template> </template>
@@ -114,6 +110,7 @@
// vue // vue
import { onMounted, ref, onBeforeMount, computed } from "vue"; import { onMounted, ref, onBeforeMount, computed } from "vue";
import ToLoading from "../../components/overlay/to-loading.vue"; import ToLoading from "../../components/overlay/to-loading.vue";
import snackbar from "../../components/func/snackbar";
// tauri // tauri
import { dialog, fs } from "@tauri-apps/api"; import { dialog, fs } from "@tauri-apps/api";
// Store // Store
@@ -159,9 +156,6 @@ const emptyHeight = computed(() => {
const translateY = ref<string>("0px"); const translateY = ref<string>("0px");
// render // render
const search = ref<string>(""); const search = ref<string>("");
const snackbar = ref<boolean>(false);
const snackbarText = ref<string>("");
const snackbarColor = ref<string>("#F5810A");
onBeforeMount(async () => { onBeforeMount(async () => {
const { total, fin } = await TGSqlite.getAchievementsOverview(); const { total, fin } = await TGSqlite.getAchievementsOverview();
@@ -219,8 +213,10 @@ function handleScroll(e: Event): void {
async function selectSeries(index: number): Promise<void> { async function selectSeries(index: number): Promise<void> {
// 如果选中的是已经选中的系列,则不进行操作 // 如果选中的是已经选中的系列,则不进行操作
if (selectedSeries.value === index) { if (selectedSeries.value === index) {
snackbarText.value = "已经选中该系列"; snackbar({
snackbar.value = true; color: "warn",
text: "已经选中该系列",
});
return; return;
} }
loading.value = true; loading.value = true;
@@ -241,9 +237,10 @@ function openImg(): void {
async function searchCard(): Promise<void> { async function searchCard(): Promise<void> {
if (search.value === "") { if (search.value === "") {
snackbarColor.value = "#F5810A"; snackbar({
snackbarText.value = "请输入搜索内容"; color: "error",
snackbar.value = true; text: "请输入搜索内容",
});
return; return;
} }
selectedSeries.value = -1; selectedSeries.value = -1;
@@ -251,9 +248,10 @@ async function searchCard(): Promise<void> {
loading.value = true; loading.value = true;
selectedAchievement.value = await TGSqlite.searchAchievements(search.value); selectedAchievement.value = await TGSqlite.searchAchievements(search.value);
if (selectedAchievement.value.length === 0) { if (selectedAchievement.value.length === 0) {
snackbarColor.value = "#F5810A"; snackbar({
snackbarText.value = "没有找到对应的成就"; color: "error",
snackbar.value = true; text: "没有找到对应的成就",
});
} }
loading.value = false; loading.value = false;
} }
@@ -271,8 +269,10 @@ async function importJson(): Promise<void> {
if (selectedFile && (await verifyUiafData(<string>selectedFile))) { if (selectedFile && (await verifyUiafData(<string>selectedFile))) {
const remoteRaw: string | false = await readUiafData(<string>selectedFile); const remoteRaw: string | false = await readUiafData(<string>selectedFile);
if (remoteRaw === false) { if (remoteRaw === false) {
snackbarText.value = "读取 UIAF 数据失败,请检查文件是否符合规范"; snackbar({
snackbar.value = true; color: "error",
text: "读取 UIAF 数据失败,请检查文件是否符合规范",
});
return; return;
} }
loadingTitle.value = "正在解析数据"; loadingTitle.value = "正在解析数据";
@@ -290,9 +290,10 @@ async function importJson(): Promise<void> {
async function exportJson(): Promise<void> { async function exportJson(): Promise<void> {
// 判断是否有数据 // 判断是否有数据
if (achievementsStore.finAchievements === 0) { if (achievementsStore.finAchievements === 0) {
snackbarColor.value = "#F5810A"; snackbar({
snackbarText.value = "没有可导出的数据"; color: "error",
snackbar.value = true; text: "没有可导出的数据",
});
return; return;
} }
// 获取本地数据 // 获取本地数据
@@ -311,17 +312,16 @@ async function exportJson(): Promise<void> {
}); });
if (isSave) { if (isSave) {
await fs.writeTextFile(isSave, JSON.stringify(UiafData)); await fs.writeTextFile(isSave, JSON.stringify(UiafData));
snackbarColor.value = "#00BFA5"; snackbar({ text: "导出成功" });
snackbarText.value = "导出成功";
snackbar.value = true;
} else { } else {
snackbarColor.value = "#F5810A"; snackbar({
snackbarText.value = "导出已取消"; color: "warn",
snackbar.value = true; text: "导出已取消",
});
} }
} }
function getIcon(series: number): string { function getIcon(series: number): string | undefined {
return AppAchievementSeriesData.find((item) => item.id === series)?.icon; return AppAchievementSeriesData.find((item) => item.id === series)?.icon;
} }
</script> </script>

View File

@@ -177,10 +177,6 @@
<v-list-item-subtitle>{{ appStore.dataPath.userDataDir }}</v-list-item-subtitle> <v-list-item-subtitle>{{ appStore.dataPath.userDataDir }}</v-list-item-subtitle>
</v-list-item> </v-list-item>
</v-list> </v-list>
<!-- 弹窗提示条 -->
<v-snackbar v-model="snackbar" timeout="1500" :color="snackbarColor">
{{ snackbarText }}
</v-snackbar>
<!-- 确认弹窗 --> <!-- 确认弹窗 -->
<ToConfirm <ToConfirm
v-model="confirmShow" v-model="confirmShow"
@@ -195,6 +191,7 @@
<script lang="ts" setup> <script lang="ts" setup>
// vue // vue
import { computed, onMounted, ref } from "vue"; import { computed, onMounted, ref } from "vue";
import snackbar from "../../components/func/snackbar";
import ToLoading from "../../components/overlay/to-loading.vue"; import ToLoading from "../../components/overlay/to-loading.vue";
import ToConfirm from "../../components/overlay/to-confirm.vue"; import ToConfirm from "../../components/overlay/to-confirm.vue";
// tauri // tauri
@@ -243,11 +240,6 @@ const userInfo = computed(() => {
}; };
}); });
// snackbar
const snackbar = ref<boolean>(false);
const snackbarText = ref<string>("");
const snackbarColor = ref<string>("success");
// confirm // confirm
const confirmText = ref<string>(""); const confirmText = ref<string>("");
const isConfirmInput = ref<boolean>(false); const isConfirmInput = ref<boolean>(false);
@@ -269,9 +261,10 @@ onMounted(async () => {
userStore.cookie = JSON.parse(ck.value); userStore.cookie = JSON.parse(ck.value);
} }
} catch (e) { } catch (e) {
snackbarText.value = "读取数据库失败!"; snackbar({
snackbarColor.value = "warn"; color: "error",
snackbar.value = true; text: "读取数据库失败!",
});
} }
loading.value = false; loading.value = false;
}); });
@@ -398,9 +391,7 @@ async function backupData(): Promise<void> {
const abyss = await TGSqlite.getAbyss(); const abyss = await TGSqlite.getAbyss();
await backupAbyssData(abyss); await backupAbyssData(abyss);
loading.value = false; loading.value = false;
snackbarText.value = "数据已备份!"; snackbar({ text: "数据已备份!" });
snackbarColor.value = "success";
snackbar.value = true;
} }
async function restoreData(): Promise<void> { async function restoreData(): Promise<void> {
@@ -419,13 +410,8 @@ async function restoreData(): Promise<void> {
if (!res) { if (!res) {
fail.push("深渊数据"); fail.push("深渊数据");
} }
if (fail.length > 0) { if (fail.length > 0) snackbar({ text: `${fail.join("、")} 恢复失败!`, color: "error" });
snackbarText.value = `${fail.join("、")} 恢复失败!`; else snackbar({ text: "数据已恢复!" });
snackbarColor.value = "error";
} else {
snackbarText.value = "数据已恢复!";
snackbarColor.value = "success";
}
const cookie = await TGSqlite.getCookie(); const cookie = await TGSqlite.getCookie();
userStore.initCookie(cookie); userStore.initCookie(cookie);
loading.value = false; loading.value = false;
@@ -437,8 +423,7 @@ async function delTempData(): Promise<void> {
recursive: true, recursive: true,
}); });
await fs.createDir("tempData", { dir: fs.BaseDirectory.AppLocalData }); await fs.createDir("tempData", { dir: fs.BaseDirectory.AppLocalData });
snackbarText.value = "临时数据已删除!"; snackbar({ text: "临时数据已删除!" });
snackbar.value = true;
} }
async function delUserData(): Promise<void> { async function delUserData(): Promise<void> {
@@ -446,8 +431,7 @@ async function delUserData(): Promise<void> {
dir: fs.BaseDirectory.AppLocalData, dir: fs.BaseDirectory.AppLocalData,
recursive: true, recursive: true,
}); });
snackbarText.value = "用户数据已删除!"; snackbar({ text: "用户数据已删除!" });
snackbar.value = true;
achievementsStore.init(); achievementsStore.init();
await fs.createDir("userData", { dir: fs.BaseDirectory.AppLocalData }); await fs.createDir("userData", { dir: fs.BaseDirectory.AppLocalData });
} }
@@ -457,8 +441,7 @@ function initAppData(): void {
appStore.init(); appStore.init();
homeStore.init(); homeStore.init();
achievementsStore.init(); achievementsStore.init();
snackbarText.value = "已恢复默认配置!即将刷新页面..."; snackbar({ text: "已恢复默认配置!即将刷新页面..." });
snackbar.value = true;
setTimeout(() => { setTimeout(() => {
window.location.reload(); window.location.reload();
}, 1500); }, 1500);
@@ -467,10 +450,8 @@ function initAppData(): void {
// 开启 dev 模式 // 开启 dev 模式
function submitDevMode(): void { function submitDevMode(): void {
appStore.devMode appStore.devMode
? (snackbarText.value = "已关闭 dev 模式!") ? snackbar({ text: "已关闭 dev 模式!" })
: (snackbarText.value = "已开启 dev 模式!"); : snackbar({ text: "已开启 dev 模式!" });
snackbarColor.value = "success";
snackbar.value = true;
} }
// 修改首页显示 // 修改首页显示
@@ -478,16 +459,15 @@ function submitHome(): void {
// 获取已选 // 获取已选
const show = showHome.value; const show = showHome.value;
if (show.length < 1) { if (show.length < 1) {
snackbarText.value = "请至少选择一个!"; snackbar({
snackbarColor.value = "error"; color: "error",
snackbar.value = true; text: "请至少选择一个!",
});
return; return;
} }
// 设置 // 设置
homeStore.setShowValue(show); homeStore.setShowValue(show);
snackbarText.value = "已修改!"; snackbar({ text: "已修改!" });
snackbarColor.value = "success";
snackbar.value = true;
} }
// 刷新用户数据 // 刷新用户数据
@@ -495,9 +475,10 @@ async function refreshUser(): Promise<void> {
const ck = userStore.cookie; const ck = userStore.cookie;
// ck = {} // ck = {}
if (Object.keys(ck).length < 1) { if (Object.keys(ck).length < 1) {
snackbarText.value = "请先输入 Cookie!"; snackbar({
snackbarColor.value = "error"; color: "error",
snackbar.value = true; text: "请先输入 Cookie!",
});
return; return;
} }
let failCount = 0; let failCount = 0;
@@ -552,13 +533,12 @@ async function refreshUser(): Promise<void> {
failCount++; failCount++;
} }
if (failCount > 0) { if (failCount > 0) {
snackbarText.value = "刷新失败!请重新输入 cookie!"; snackbar({
snackbarColor.value = "error"; color: "error",
snackbar.value = true; text: "刷新失败!请重新输入 cookie!",
});
} else { } else {
snackbarText.value = "刷新成功!"; snackbar({ text: "刷新成功!" });
snackbarColor.value = "success";
snackbar.value = true;
} }
loading.value = false; loading.value = false;
} }
@@ -567,9 +547,10 @@ async function refreshUser(): Promise<void> {
async function inputCookie(): Promise<void> { async function inputCookie(): Promise<void> {
const cookie = confirmInput.value; const cookie = confirmInput.value;
if (cookie === "") { if (cookie === "") {
snackbarText.value = "Cookie 为空!"; snackbar({
snackbarColor.value = "error"; color: "error",
snackbar.value = true; text: "Cookie 为空!",
});
return; return;
} }
loadingTitle.value = "正在获取 tokens..."; loadingTitle.value = "正在获取 tokens...";
@@ -581,9 +562,10 @@ async function inputCookie(): Promise<void> {
const uid = cookieObj.find((item) => item[0] === "login_uid")?.[1]; const uid = cookieObj.find((item) => item[0] === "login_uid")?.[1];
// 如果两者不存在 // 如果两者不存在
if (!ticket || !uid) { if (!ticket || !uid) {
snackbarText.value = "Cookie 无效!"; snackbar({
snackbarColor.value = "error"; color: "error",
snackbar.value = true; text: "Cookie 无效!",
});
return; return;
} }
try { try {
@@ -602,14 +584,15 @@ async function inputCookie(): Promise<void> {
await TGSqlite.saveAccount(resAccounts); await TGSqlite.saveAccount(resAccounts);
} }
loading.value = false; loading.value = false;
snackbarText.value = "Cookie 已保存!"; snackbar({
snackbarColor.value = "success"; text: "Cookie 已保存!",
snackbar.value = true; });
} catch (err) { } catch (err) {
loading.value = false; loading.value = false;
snackbarText.value = "Cookie 无效!"; snackbar({
snackbarColor.value = "error"; color: "error",
snackbar.value = true; text: "Cookie 无效!",
});
} }
} }
@@ -644,9 +627,9 @@ async function checkDB(): Promise<void> {
} }
} }
loading.value = false; loading.value = false;
snackbarText.value = "数据库已是最新!"; snackbar({
snackbarColor.value = "success"; text: "数据库已是最新!",
snackbar.value = true; });
} }
} }
@@ -656,9 +639,9 @@ async function resetDB(): Promise<void> {
loading.value = true; loading.value = true;
await TGSqlite.reset(); await TGSqlite.reset();
loading.value = false; loading.value = false;
snackbarText.value = "数据库已重置!请进行再次检查。"; snackbar({
snackbarColor.value = "success"; text: "数据库已重置!请进行再次检查。",
snackbar.value = true; });
// 刷新 // 刷新
window.location.reload(); window.location.reload();
} }
@@ -671,9 +654,9 @@ async function updateDB(): Promise<void> {
await TGSqlite.update(); await TGSqlite.update();
achievementsStore.lastVersion = await TGSqlite.getLatestAchievementVersion(); achievementsStore.lastVersion = await TGSqlite.getLatestAchievementVersion();
loading.value = false; loading.value = false;
snackbarText.value = "数据库已是最新!"; snackbar({
snackbarColor.value = "success"; text: "数据库已更新!",
snackbar.value = true; });
// 刷新 // 刷新
window.location.reload(); window.location.reload();
} }

View File

@@ -263,9 +263,6 @@
</div> </div>
</v-window-item> </v-window-item>
</v-window> </v-window>
<v-snackbar v-model="snackbar" timeout="1500" :color="snackbarColor">
{{ snackbarText }}
</v-snackbar>
<ToChannel v-model="showList" /> <ToChannel v-model="showList" />
</template> </template>
@@ -273,6 +270,7 @@
// vue // vue
import { onMounted, ref } from "vue"; import { onMounted, ref } from "vue";
import { useRoute, useRouter } from "vue-router"; import { useRoute, useRouter } from "vue-router";
import snackbar from "../components/func/snackbar";
import ToLoading from "../components/overlay/to-loading.vue"; import ToLoading from "../components/overlay/to-loading.vue";
import ToChannel from "../components/overlay/to-channel.vue"; import ToChannel from "../components/overlay/to-channel.vue";
// store // store
@@ -294,10 +292,6 @@ const appStore = useAppStore();
const loading = ref<boolean>(true); const loading = ref<boolean>(true);
const loadingTitle = ref<string>("正在加载"); const loadingTitle = ref<string>("正在加载");
const loadingSub = ref<boolean>(false); const loadingSub = ref<boolean>(false);
// snackbar
const snackbar = ref<boolean>(false);
const snackbarText = ref<string>("");
const snackbarColor = ref<string>("success");
// search // search
const search = ref<string>(""); const search = ref<string>("");
@@ -373,9 +367,10 @@ async function switchAnno(): Promise<void> {
async function loadMore(data: "notice" | "activity" | "news"): Promise<void> { async function loadMore(data: "notice" | "activity" | "news"): Promise<void> {
loadingSub.value = true; loadingSub.value = true;
if (rawData.value[data].isLast) { if (rawData.value[data].isLast) {
snackbarText.value = "已经是最后一页了"; snackbar({
snackbarColor.value = "#35acce"; text: "已经是最后一页了",
snackbar.value = true; color: "warn",
});
loadingSub.value = false; loadingSub.value = false;
return; return;
} }
@@ -389,9 +384,10 @@ async function loadMore(data: "notice" | "activity" | "news"): Promise<void> {
const getCard = Mys.News.card[data](getData); const getCard = Mys.News.card[data](getData);
postData.value[data] = postData.value[data].concat(getCard); postData.value[data] = postData.value[data].concat(getCard);
if (rawData.value[data].isLast) { if (rawData.value[data].isLast) {
snackbarText.value = "已经是最后一页了"; snackbar({
snackbarColor.value = "#35acce"; text: "已经是最后一页了",
snackbar.value = true; color: "warn",
});
loadingSub.value = false; loadingSub.value = false;
loading.value = false; loading.value = false;
return; return;
@@ -407,7 +403,6 @@ async function toPost(item: TGApp.Plugins.Mys.News.RenderCard | string): Promise
const path = router.resolve({ const path = router.resolve({
name: "帖子详情", name: "帖子详情",
params: { params: {
// eslint-disable-next-line camelcase
post_id: item, post_id: item,
}, },
}).href; }).href;
@@ -428,7 +423,6 @@ async function toJson(item: TGApp.Plugins.Mys.News.RenderCard | string): Promise
const path = router.resolve({ const path = router.resolve({
name: "帖子详情JSON", name: "帖子详情JSON",
params: { params: {
// eslint-disable-next-line camelcase
post_id: item, post_id: item,
}, },
}).href; }).href;
@@ -446,9 +440,10 @@ async function toJson(item: TGApp.Plugins.Mys.News.RenderCard | string): Promise
async function searchPost(): Promise<void> { async function searchPost(): Promise<void> {
if (search.value === "") { if (search.value === "") {
snackbarText.value = "请输入搜索内容"; snackbar({
snackbarColor.value = "error"; text: "请输入搜索内容",
snackbar.value = true; color: "error",
});
return; return;
} }
if (!isNaN(Number(search.value))) { if (!isNaN(Number(search.value))) {
@@ -457,9 +452,10 @@ async function searchPost(): Promise<void> {
await toJson(search.value); await toJson(search.value);
} }
} else { } else {
snackbarText.value = "请输入搜索内容"; snackbar({
snackbarColor.value = "error"; text: "请输入搜索内容",
snackbar.value = true; color: "error",
});
} }
} }
</script> </script>
@@ -519,8 +515,13 @@ async function searchPost(): Promise<void> {
position: relative; position: relative;
height: 50px; height: 50px;
color: var(--common-text-title); color: var(--common-text-title);
transition: padding-top 0.3s linear, padding-bottom 0.3s linear, background 0.3s linear, transition:
font-size 0.3s linear, line-height 0.3s linear, white-space 0.3s linear; padding-top 0.3s linear,
padding-bottom 0.3s linear,
background 0.3s linear,
font-size 0.3s linear,
line-height 0.3s linear,
white-space 0.3s linear;
} }
.news-card-title:hover { .news-card-title:hover {