feat: 添加阅读设置页面与全局阅读配置功能
1. 新增阅读设置页面,支持调整字体大小、颜色、背景色和窗口大小 2. 新增全局设置store,持久化保存外观和阅读配置 3. 为窗口添加阴影和尺寸设置的权限与功能 4. 重构外观设置页面样式,统一配置项布局 5. 适配阅读页面样式,使用配置动态控制阅读样式
This commit is contained in:
parent
f64bd6aff9
commit
72728cf7ac
|
|
@ -9,6 +9,8 @@
|
|||
"core:window:allow-start-dragging",
|
||||
"core:window:allow-close",
|
||||
"core:window:allow-minimize",
|
||||
"core:window:allow-set-shadow",
|
||||
"core:window:allow-set-size",
|
||||
"opener:default",
|
||||
"dialog:default",
|
||||
"dialog:allow-open"
|
||||
|
|
|
|||
|
|
@ -28,4 +28,7 @@
|
|||
|
||||
/* 尺寸 */
|
||||
--titlebar-height: 38px;
|
||||
|
||||
--set-item-title-size: 14px;
|
||||
--set-item-desc-size: 12px;
|
||||
}
|
||||
|
|
@ -45,6 +45,15 @@ const routes = [
|
|||
title: "外观设置",
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/setting/reader-setting",
|
||||
name: "ReaderSetting",
|
||||
component: () => import("@/views/setting/ReaderSetting.vue"),
|
||||
meta: {
|
||||
isCache: true,
|
||||
title: "阅读设置",
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/setting/shortcut",
|
||||
name: "Shortcut",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
import { defineStore } from "pinia"
|
||||
|
||||
export const useSettingStore = defineStore("setting", {
|
||||
state: () => ({
|
||||
appearance: {
|
||||
theme: "light",
|
||||
showShadow: false,
|
||||
},
|
||||
reader: {
|
||||
fontSize: 12,
|
||||
showShadow: false,
|
||||
fontColor: "#000000",
|
||||
backgroundColor: "#ffffff",
|
||||
windowWidth: 300,
|
||||
windowHeight: 400,
|
||||
}
|
||||
}),
|
||||
|
||||
persist: true,
|
||||
})
|
||||
|
|
@ -16,6 +16,7 @@ declare module 'vue' {
|
|||
NAnchor: typeof import('naive-ui')['NAnchor']
|
||||
NAnchorLink: typeof import('naive-ui')['NAnchorLink']
|
||||
NButton: typeof import('naive-ui')['NButton']
|
||||
NColorPicker: typeof import('naive-ui')['NColorPicker']
|
||||
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
|
||||
NDescriptions: typeof import('naive-ui')['NDescriptions']
|
||||
NDescriptionsItem: typeof import('naive-ui')['NDescriptionsItem']
|
||||
|
|
@ -29,6 +30,7 @@ declare module 'vue' {
|
|||
NGrid: typeof import('naive-ui')['NGrid']
|
||||
NIcon: typeof import('naive-ui')['NIcon']
|
||||
NInput: typeof import('naive-ui')['NInput']
|
||||
NInputNumber: typeof import('naive-ui')['NInputNumber']
|
||||
NLayout: typeof import('naive-ui')['NLayout']
|
||||
NLayoutContent: typeof import('naive-ui')['NLayoutContent']
|
||||
NLayoutHeader: typeof import('naive-ui')['NLayoutHeader']
|
||||
|
|
@ -42,6 +44,7 @@ declare module 'vue' {
|
|||
NSpace: typeof import('naive-ui')['NSpace']
|
||||
NSpin: typeof import('naive-ui')['NSpin']
|
||||
NSwitch: typeof import('naive-ui')['NSwitch']
|
||||
NText: typeof import('naive-ui')['NText']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { h, type Component } from "vue"
|
||||
import {getCurrentWindow, LogicalSize} from '@tauri-apps/api/window'
|
||||
import { open } from "@tauri-apps/plugin-dialog"
|
||||
import { BookSearch24Regular } from "@vicons/fluent"
|
||||
import {
|
||||
|
|
@ -131,10 +131,13 @@ import { NIcon } from "naive-ui"
|
|||
import BookApi from "@/api/book"
|
||||
import BookCover from "@/components/BookCover.vue"
|
||||
import { useLoading } from "@/hooks/useLoading"
|
||||
import { useSettingStore } from '@/stores/setting'
|
||||
import type { Books, BookSaveParams } from "@/types/global"
|
||||
|
||||
const router = useRouter()
|
||||
const message = useMessage()
|
||||
const settingStore = useSettingStore()
|
||||
const appWindow = getCurrentWindow()
|
||||
const { withLoading } = useLoading()
|
||||
|
||||
const bookList = ref<Books[]>([])
|
||||
|
|
@ -280,6 +283,8 @@ const importBook = async () => {
|
|||
|
||||
onMounted(() => {
|
||||
getBookList()
|
||||
appWindow.setShadow(settingStore.appearance.showShadow)
|
||||
appWindow.setSize(new LogicalSize(800, 600))
|
||||
})
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="glass-panel" data-tauri-drag-region>
|
||||
<div class="glass-panel" :style="readerStyle" data-tauri-drag-region>
|
||||
<div class="reading-wrap">
|
||||
<div class="chapter-name">{{ chapter?.title || "加载中..." }}</div>
|
||||
|
||||
|
|
@ -28,8 +28,8 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick } from "vue"
|
||||
import { ArrowLeftOutlined } from "@vicons/antd"
|
||||
import { useSettingStore } from '@/stores/setting'
|
||||
import { getCurrentWindow, LogicalSize } from '@tauri-apps/api/window'
|
||||
import BookApi from "@/api/book"
|
||||
import { useLoading } from "@/hooks/useLoading"
|
||||
import type { Chapters } from "@/types/global"
|
||||
|
|
@ -37,6 +37,8 @@ import type { Chapters } from "@/types/global"
|
|||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const message = useMessage()
|
||||
const settingStore = useSettingStore()
|
||||
const appWindow = getCurrentWindow()
|
||||
const { withLoading } = useLoading()
|
||||
|
||||
const chapterId = computed(() => Number(route.query.id) || 0)
|
||||
|
|
@ -50,6 +52,12 @@ const goBack = () => router.back()
|
|||
|
||||
const currentText = computed(() => pages.value[currentPage.value] ?? "")
|
||||
|
||||
const readerStyle = computed(() => ({
|
||||
"--reader-font-size": `${settingStore.reader.fontSize}px`,
|
||||
"--reader-font-color": settingStore.reader.fontColor,
|
||||
"--reader-background-color": settingStore.reader.backgroundColor,
|
||||
}))
|
||||
|
||||
const pageInfo = computed(() => {
|
||||
if (pages.value.length === 0) return ""
|
||||
return `第 ${currentPage.value + 1} / ${pages.value.length} 页`
|
||||
|
|
@ -75,7 +83,7 @@ const paginate = () => {
|
|||
const el = pageEl.value
|
||||
if (!el) return
|
||||
|
||||
const fontSize = 6
|
||||
const fontSize = Math.max(1, Number(settingStore.reader.fontSize) || 12)
|
||||
const lineHeight = 1.8
|
||||
const width = el.clientWidth
|
||||
const height = el.clientHeight
|
||||
|
|
@ -129,6 +137,11 @@ const onKeydown = (e: KeyboardEvent) => {
|
|||
|
||||
const onResize = () => paginate()
|
||||
|
||||
watch(
|
||||
() => settingStore.reader.fontSize,
|
||||
() => nextTick(paginate)
|
||||
)
|
||||
|
||||
const loadChapter = async () => {
|
||||
if (!chapterId.value) {
|
||||
message.error("章节参数错误")
|
||||
|
|
@ -165,6 +178,8 @@ const switchChapter = async (offset: number) => {
|
|||
onMounted(() => {
|
||||
window.addEventListener("keydown", onKeydown)
|
||||
window.addEventListener("resize", onResize)
|
||||
appWindow.setShadow(settingStore.reader.showShadow)
|
||||
appWindow.setSize(new LogicalSize(settingStore.reader.windowWidth, settingStore.reader.windowHeight))
|
||||
loadChapter()
|
||||
})
|
||||
|
||||
|
|
@ -179,11 +194,10 @@ onUnmounted(() => {
|
|||
position: relative;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: rgba(20, 20, 20, 0.05);
|
||||
backdrop-filter: blur(20px);
|
||||
background: var(--reader-background-color);
|
||||
/* border: 1px solid rgba(255, 255, 255, 0.2); */
|
||||
padding: 20px;
|
||||
color: #3b3b3b;
|
||||
padding: 10px;
|
||||
color: var(--reader-font-color);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
|
|
@ -212,7 +226,7 @@ onUnmounted(() => {
|
|||
width: 100%;
|
||||
max-width: 720px;
|
||||
margin: 0 auto;
|
||||
padding: 44px 40px 16px;
|
||||
/* padding: 44px 40px 16px; */
|
||||
}
|
||||
|
||||
.chapter-name {
|
||||
|
|
@ -220,7 +234,7 @@ onUnmounted(() => {
|
|||
text-align: center;
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
color: #3b3b3b;
|
||||
color: var(--reader-font-color);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
|
|
@ -233,9 +247,9 @@ onUnmounted(() => {
|
|||
.page-text {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
font-size: 12px;
|
||||
font-size: var(--reader-font-size);
|
||||
line-height: 1.8;
|
||||
color: #3b3b3b;
|
||||
color: var(--reader-font-color);
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
text-align: justify;
|
||||
|
|
@ -252,7 +266,12 @@ onUnmounted(() => {
|
|||
|
||||
.page-info {
|
||||
font-size: 12px;
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
color: var(--reader-font-color);
|
||||
opacity: 0.65;
|
||||
}
|
||||
|
||||
.glass-panel :deep(.n-button) {
|
||||
color: var(--reader-font-color);
|
||||
}
|
||||
|
||||
.nav-btns {
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ const route = useRoute()
|
|||
|
||||
const menuItems = [
|
||||
{ label: "外观", name: "Appearance", href: "#appearance", icon: BgColorsOutlined },
|
||||
{ label: "阅读设置", name: "ReaderSetting", href: "#reader-setting", icon: BgColorsOutlined },
|
||||
{ label: "快捷键", name: "Shortcut", href: "#shortcut", icon: KeyOutlined },
|
||||
{ label: "关于", name: "About", href: "#about", icon: InfoCircleOutlined },
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,46 +1,52 @@
|
|||
<template>
|
||||
<div class="setting-page">
|
||||
<div class="appearance">
|
||||
<h2 class="page-title">外观</h2>
|
||||
<p class="page-desc">自定义应用的外观与阅读体验</p>
|
||||
|
||||
<div class="setting-group">
|
||||
<div class="group-title">主题</div>
|
||||
<div class="setting-item">
|
||||
<div class="item-info">
|
||||
<span class="item-label">主题模式</span>
|
||||
<span class="item-desc">选择应用的整体配色方案</span>
|
||||
</div>
|
||||
<n-radio-group v-model:value="theme" name="theme">
|
||||
<n-grid :cols="4">
|
||||
<n-gi :span="2">
|
||||
<div class="set-item-title">主题模式</div>
|
||||
<div class="set-item-desc">选择应用的整体配色方案</div>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<n-radio-group v-model:value="theme" size="small" name="theme">
|
||||
<n-radio-button value="light">浅色</n-radio-button>
|
||||
<n-radio-button value="dark">深色</n-radio-button>
|
||||
<n-radio-button value="system">跟随系统</n-radio-button>
|
||||
</n-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="setting-group">
|
||||
<div class="group-title">阅读</div>
|
||||
<div class="setting-item">
|
||||
<div class="item-info">
|
||||
<span class="item-label">自动换行</span>
|
||||
<span class="item-desc">长段落自动换行显示</span>
|
||||
</div>
|
||||
<n-switch v-model:value="wordWrap" />
|
||||
</div>
|
||||
</div>
|
||||
</n-gi>
|
||||
<n-gi :span="4">
|
||||
<n-divider style="margin: 16px 0" />
|
||||
</n-gi>
|
||||
<n-gi :span="3">
|
||||
<div class="set-item-title">窗口阴影</div>
|
||||
<div class="set-item-desc">是否显示应用窗口阴影效果</div>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<n-switch v-model:value="showShadow" />
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const theme = ref("light")
|
||||
const wordWrap = ref(true)
|
||||
import { getCurrentWindow } from '@tauri-apps/api/window';
|
||||
import { useSettingStore } from '@/stores/setting'
|
||||
|
||||
const settingStore = useSettingStore()
|
||||
|
||||
const theme = ref(settingStore.appearance.theme)
|
||||
const showShadow = ref(settingStore.appearance.showShadow)
|
||||
|
||||
watch(showShadow, (newVal) => {
|
||||
settingStore.appearance.showShadow = newVal
|
||||
getCurrentWindow().setShadow(newVal)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.setting-page {
|
||||
max-width: 760px;
|
||||
padding: 22px 26px 32px;
|
||||
.appearance {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
|
|
@ -56,74 +62,18 @@ const wordWrap = ref(true)
|
|||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
.setting-group {
|
||||
margin-bottom: 20px;
|
||||
.set-item-title {
|
||||
font-size: var(--set-item-title-size);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.group-title {
|
||||
margin-bottom: 6px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: var(--color-text-secondary);
|
||||
.set-item-desc {
|
||||
font-size: var(--set-item-desc-size);
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.setting-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
min-height: 56px;
|
||||
border-top: 1px solid var(--color-border);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
margin-bottom: 0;
|
||||
transition: background-color 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
background-color: color-mix(in srgb, var(--color-surface-hover) 42%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.item-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.item-label {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
.item-desc {
|
||||
font-size: 12px;
|
||||
color: var(--color-text-secondary);
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
:deep(.n-radio-group),
|
||||
:deep(.n-switch) {
|
||||
margin: 0 16px 0 12px;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.setting-page {
|
||||
padding: 18px 16px 24px;
|
||||
}
|
||||
|
||||
.setting-item {
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
.item-info {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
:deep(.n-radio-group),
|
||||
:deep(.n-switch) {
|
||||
margin: 0;
|
||||
}
|
||||
:deep(.n-radio-group) {
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,191 @@
|
|||
<template>
|
||||
<div class="reader-setting">
|
||||
<n-grid :cols="4" :x-gap="16" :y-gap="4">
|
||||
<n-gi :span="3">
|
||||
<div class="set-item-title">字体大小</div>
|
||||
<div class="set-item-desc">设置阅读模式字体大小</div>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<n-input-number v-model:value="fontSize" :min="8" :max="72" size="small" />
|
||||
</n-gi>
|
||||
<n-gi :span="4">
|
||||
<n-divider style="margin: 16px 0" />
|
||||
</n-gi>
|
||||
<n-gi :span="3">
|
||||
<div class="set-item-title">窗口阴影</div>
|
||||
<div class="set-item-desc">是否显示阅读模式窗口阴影效果</div>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<n-switch v-model:value="showShadow" />
|
||||
</n-gi>
|
||||
<n-gi :span="4">
|
||||
<n-divider style="margin: 16px 0" />
|
||||
</n-gi>
|
||||
<n-gi :span="3">
|
||||
<div class="set-item-title">字体颜色</div>
|
||||
<div class="set-item-desc">设置阅读模式字体颜色</div>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<div class="color-picker-control">
|
||||
<n-color-picker v-model:value="fontColor" show-alpha :modes="['hex']" placement="bottom-end">
|
||||
<template #trigger="{ value, onClick, ref: triggerRef }">
|
||||
<div :ref="triggerRef" class="color-swatch" :style="{ backgroundColor: value || '#000000' }"
|
||||
role="button" tabindex="0" aria-label="选择字体颜色" @click="onClick" @keydown.enter="onClick"
|
||||
@keydown.space.prevent="onClick" />
|
||||
</template>
|
||||
</n-color-picker>
|
||||
<div class="color-values">
|
||||
<span>{{ getColorDetails(fontColor).color }}</span>
|
||||
<small>透明度 {{ getColorDetails(fontColor).opacity }}%</small>
|
||||
</div>
|
||||
</div>
|
||||
</n-gi>
|
||||
<n-gi :span="4">
|
||||
<n-divider style="margin: 16px 0" />
|
||||
</n-gi>
|
||||
<n-gi :span="3">
|
||||
<div class="set-item-title">背景颜色/透明度</div>
|
||||
<div class="set-item-desc">设置阅读模式背景颜色&透明度</div>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<div class="color-picker-control">
|
||||
<n-color-picker v-model:value="backgroundColor" show-alpha :modes="['hex']" placement="bottom-end">
|
||||
<template #trigger="{ value, onClick, ref: triggerRef }">
|
||||
<div :ref="triggerRef" class="color-swatch" :style="{ backgroundColor: value || '#ffffff' }"
|
||||
role="button" tabindex="0" aria-label="选择背景颜色" @click="onClick" @keydown.enter="onClick"
|
||||
@keydown.space.prevent="onClick" />
|
||||
</template>
|
||||
</n-color-picker>
|
||||
<div class="color-values">
|
||||
<span>{{ getColorDetails(backgroundColor).color }}</span>
|
||||
<small>透明度 {{ getColorDetails(backgroundColor).opacity }}%</small>
|
||||
</div>
|
||||
</div>
|
||||
</n-gi>
|
||||
<n-gi :span="4">
|
||||
<n-divider style="margin: 16px 0" />
|
||||
</n-gi>
|
||||
<n-gi :span="3">
|
||||
<div class="set-item-title">窗口大小</div>
|
||||
<div class="set-item-desc">设置阅读模式窗口大小</div>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<n-input-number v-model:value="windowWidth" :min="100" :max="1920" size="small">
|
||||
<template #prefix>
|
||||
宽
|
||||
</template>
|
||||
</n-input-number>
|
||||
<n-input-number v-model:value="windowHeight" :min="100" :max="1080" size="small">
|
||||
<template #prefix>
|
||||
高
|
||||
</template>
|
||||
</n-input-number>
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useSettingStore } from '@/stores/setting'
|
||||
|
||||
const settingStore = useSettingStore()
|
||||
|
||||
const fontSize = ref(settingStore.reader.fontSize)
|
||||
const showShadow = ref(settingStore.reader.showShadow)
|
||||
const fontColor = ref(settingStore.reader.fontColor)
|
||||
const backgroundColor = ref(settingStore.reader.backgroundColor)
|
||||
const windowWidth = ref(settingStore.reader.windowWidth)
|
||||
const windowHeight = ref(settingStore.reader.windowHeight)
|
||||
|
||||
const getColorDetails = (value: string | null) => {
|
||||
const color = value || '#000000'
|
||||
const match = color.match(/^#([\da-f]{6})([\da-f]{2})$/i)
|
||||
|| color.match(/^#([\da-f]{3})([\da-f])$/i)
|
||||
const alphaMatch = color.match(/^rgba\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*,\s*([\d.]+)\s*\)$/i)
|
||||
const alpha = match
|
||||
? Math.round((parseInt(match[2].length === 1 ? match[2] + match[2] : match[2], 16) / 255) * 100)
|
||||
: alphaMatch
|
||||
? Math.round(Number(alphaMatch[1]) * 100)
|
||||
: 100
|
||||
|
||||
return {
|
||||
color: match ? `#${match[1].toUpperCase()}` : color,
|
||||
opacity: Math.min(100, Math.max(0, alpha)),
|
||||
}
|
||||
}
|
||||
|
||||
watch(fontSize, (newVal) => {
|
||||
settingStore.reader.fontSize = newVal
|
||||
})
|
||||
watch(showShadow, (newVal) => {
|
||||
settingStore.reader.showShadow = newVal
|
||||
// getCurrentWindow().setShadow(newVal)
|
||||
})
|
||||
watch(fontColor, (newVal) => {
|
||||
settingStore.reader.fontColor = newVal
|
||||
})
|
||||
watch(backgroundColor, (newVal) => {
|
||||
settingStore.reader.backgroundColor = newVal
|
||||
})
|
||||
watch(windowWidth, (newVal) => {
|
||||
settingStore.reader.windowWidth = newVal
|
||||
})
|
||||
watch(windowHeight, (newVal) => {
|
||||
settingStore.reader.windowHeight = newVal
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.reader-setting {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.set-item-title {
|
||||
font-size: var(--set-item-title-size);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.set-item-desc {
|
||||
font-size: var(--set-item-desc-size);
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
.color-picker-control {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.color-swatch {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border: 2px solid #ffffff;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
// background-image: linear-gradient(45deg, #d7d7d7 25%, transparent 25%), linear-gradient(-45deg, #d7d7d7 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #d7d7d7 75%), linear-gradient(-45deg, transparent 75%, #d7d7d7 75%);
|
||||
background-position: 0 0, 0 4px, 4px -4px, -4px 0;
|
||||
background-size: 8px 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||
|
||||
&:focus-visible {
|
||||
outline: 2px solid var(--color-accent);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.color-values {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1px;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
|
||||
small {
|
||||
color: var(--color-text-secondary);
|
||||
font-family: inherit;
|
||||
font-size: 11px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue