animal-island-vue-style

SkillDev tools

A Kawaii Vue UI component library 一个可爱的 Vue UI 组件库

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the animal-island-vue-style skill

What this skill tells your AI

The instructions your AI receives, as published by guokaigdg/animal-island-vue in skill/SKILL.md and read by ahel’s review.

1. Design Tokens

色彩系统

// 主色(薄荷青绿)
@primary-color: #19c8b9;
@primary-color-hover: #3dd4c6;
@primary-color-active: #11a89b;
@primary-color-bg: #e6f9f6;

// 文字(温暖棕色系)
@text-color: #794f27; // 主文字(header/sidebar)
@text-color-body: #725d42; // 正文(组件内文字)
@text-color-secondary: #9f927d; // 次级文字
@text-color-muted: #8a7b66; // 浅棕(modal body)
@text-color-disabled: #c4b89e; // 禁用

// 边框
@border-color: #9f927d;
@border-color-light: #c4b89e; // 输入框边框
@border-color-hover: #a89878; // 输入框 hover

// 背景(奶油米白)
@bg-color: #f8f8f0; // 主背景
@bg-color-content: rgb(247, 243, 223); // 内容区(Modal、Card)
@bg-color-secondary: #f0e8d8;
@bg-color-disabled: #f0ece2;
@bg-color-input: rgb(247, 243, 223); // 输入框背景
@bg-color-input-dis: #ece8dc; // 输入框禁用

// 状态色
@success-color: #6fba2c;
@success-color-active: #5a9e1e;
@warning-color: #f5c31c;
@warning-color-active: #dba90e;
@error-color: #e05a5a;
@error-color-active: #c94444;

// 游戏特殊色
@focus-yellow: #ffcc00; // 焦点高亮(非蓝色)
@focus-yellow-dark: #e0b800; // 焦点阴影
@sidebar-active-bg: #b7c6e5; // 侧边栏选中背景
@sidebar-hover-bg: #d6dff0; // 侧边栏 hover 背景

// 3D 阴影色
@shadow-btn: #bdaea0; // 按钮 3D 阴影
@shadow-input: #d4c9b4; // 输入框 3D 阴影
@shadow-switch-on: #5a9e1e; // Switch 开启 3D 阴影

应用调色板(Card color prop 可选值):

color 值背景色文字色
defaultrgb(247, 243, 223)#725d42
app-pink#f8a6b2#fff
purple#b77dee#fff
app-blue#889df0#fff
app-yellow#f7cd67#725d42
app-orange#e59266#fff
app-teal#82d5bb#fff
app-green#8ac68a#fff
app-red#fc736d#fff
lime-green#d1da49#3d5a1a
yellow-green#ecdf52#725d42
brown#9a835a#fff
warm-peach-pink#e18c6f#fff

字体

项目使用两款 Google Fonts 圆体字,必须按以下方式引入,本地未安装时通过在线地址加载:

<!-- 在 index.html <head> 中引入 -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
    href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;500;600;700;800;900&family=Noto+Sans+SC:wght@400;500;700&display=swap"
    rel="stylesheet"
/>

或在 CSS / Less 入口文件顶部:

@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@400;500;600;700;800;900&family=Noto+Sans+SC:wght@400;500;700&display=swap');
font-family:
    Nunito,
    'Noto Sans SC',
    -apple-system,
    'PingFang SC',
    'Hiragino Sans GB',
    'Microsoft YaHei',
    sans-serif;
字体用途Google Fonts key
Nunito主字体,拉丁字符family=Nunito
Noto Sans SC中文字体,简体覆盖family=Noto+Sans+SC

Vue 版本同时通过 @fontsource/*src/index.ts 直接 import 字体子集(nunito / noto-sans-sc / zen-maru-gothic),库消费者无需手动 <link>;如果你脱离组件库自实现,按上文 <link> 引入即可。如需扩展日文字符,自行 @import Zen Maru Gothic 或类似字体并追加到 font-family 末尾。

字重分级:

  • 正文内容:500

  • 按钮文字、标题、菜单项:600–700

  • 数字强调(时间数字、时钟):900

  • placeholder / 说明文字:400

字间距:letter-spacing: 0.01em(正文)/ 0.02em(按钮/标题)/ 1.5px(星期大写)

禁止使用细体(weight < 400)或等宽字体。


间距 / 圆角 / 边框

间距:xs=4px  sm=8px  md=12px  lg=16px  xl=24px
圆角:sm=12px  base=18px  lg=24px  pill=50px(按钮/输入框)
边框:默认 2px solid,输入框 2.5px,大尺寸输入框 3px

阴影

/* 卡片/容器阴影(暖色调,非冷黑)*/
box-shadow: 0 3px 10px 0 rgba(61, 52, 40, 0.1); /* 基础 */
box-shadow: 0 8px 24px 0 rgba(61, 52, 40, 0.14); /* 较大 */
/* Card 默认无 box-shadow(依赖 border / pattern 营造层次,不靠悬浮阴影)*/

/* 默认/虚线/文字/链接按钮阴影(柔和 elevation —— 非 3D 厚阴影)*/
box-shadow: 0 2px 4px 0 rgba(61, 52, 40, 0.06); /* btn-default 静止:--animal-shadow-sm */
box-shadow: 0 3px 10px 0 rgba(61, 52, 40, 0.1); /* btn-default hover:--animal-shadow-base */
/* active 回落到 --animal-shadow-sm,translateY(0) */

/* 游戏按键 3D 立体阴影(仅 primary / danger-primary 按钮;Input 仅 shadow={true} 时启用;Switch 仅 track inset 阴影,handle 无 box-shadow)*/
box-shadow: 0 5px 0 0 #bdaea0; /* primary 按钮默认 */
box-shadow: 0 6px 0 0 #bdaea0; /* primary 按钮 hover */
box-shadow: 0 1px 0 0 #bdaea0; /* primary 按钮 active */
box-shadow: 0 5px 0 0 #c94444; /* danger-primary 按钮默认(hover 6 / active 1) */
box-shadow: 0 3px 0 0 #d4c9b4; /* 输入框 shadow={true} 中号 */
box-shadow: 0 2px 0 0 #d4c9b4; /* 输入框 shadow={true} 小号 */
box-shadow: 0 4px 0 0 #d4c9b4; /* 输入框 shadow={true} 大号 */
/* Switch 仅 track 有 inset 阴影:inset 0 2px 4px rgba(114,93,66,0.15) (OFF) / inset 0 2px 4px rgba(90,158,30,0.20) (ON);handle 无 outer box-shadow */

重要:只有 primary 风格按钮(含 danger primary)才使用 0 5px 0 0 这种像素级 3D 厚阴影;default / dashed / text / link 用上面的柔和 elevation 阴影。把 3D 阴影套到所有按钮上会让界面变得过重过游戏化。


动效

transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1); /* 通用 */
transition: all 0.15s; /* 快速(clear 按钮等)*/
transition: all 0.3s ease; /* 卡片 */
transition: grid-template-rows 0.3s cubic-bezier(0.4, 0, 0.2, 1); /* 手风琴 */

/* Hover:上浮 */
transform: translateY(-1px); /* 按钮 / 输入框 */
transform: translateY(-2px); /* 卡片 */
/* Switch handle: 始终 translateY(-50%) 垂直居中,无 hover 上浮 */

/* Active:下压(游戏按键反馈)*/
transform: translateY(2px); /* 按钮 active */

/* 出现动画 */
@keyframes animal-zoom-in {
    from {
        opacity: 0;
        transform: scale(0.92);
    }
    to {
        opacity: 1;
        transform: scale(1);
    }
}
@keyframes animal-fade-in {
    from {
        opacity: 0;
    }
    to {
        opacity: 1;
    }
}
@keyframes ac-fade-up {
    from {
        opacity: 0;
        transform: translateY(8px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

2. 组件精确样式规范

BackTop

返回顶部按钮,钱袋图标浮窗,固定在右下角(position: fixed),滚动超过 visibilityHeight px 后出现。

属性说明默认值
visibilityHeight滚动多少 px 后显示400
duration滚动动画时长(ms)300
target滚动容器函数() => window
onClick点击回调-
className自定义类名-
style自定义样式-
<BackTop :visibilityHeight="400" />
<BackTop :duration="800" />
<BackTop :target="() => containerRef" :visibilityHeight="200" />

Button

属性smallmiddlelarge
height32px45px48px
padding0 16px0 20px0 32px
font-size12px14px16px
border-radius12px50px24px
border-width2px2px2px

primary 按钮精确值(仅 primary / danger-primary 用 3D 厚阴影):

color: #794f27;
background: #f8f8f0;
border-color: #f8f8f0;
font-weight: 600;
letter-spacing: 0.02em;
line-height: 1;
box-shadow: 0 5px 0 0 #bdaea0;

/* hover */
transform: translateY(-1px);
box-shadow: 0 6px 0 0 #bdaea0;

/* active */
transform: translateY(2px);
box-shadow: 0 1px 0 0 #bdaea0;

/* focus-visible */
outline: 2px solid #19c8b9;
outline-offset: 2px;

/* disabled */
opacity: 0.5;

default / dashed / text / link 按钮(柔和 elevation):

/* 静止 */
box-shadow: var(--animal-shadow-sm); /* 0 2px 4px 0 rgba(61,52,40,0.06) */

/* hover */
color: #19c8b9;
border-color: #19c8b9;
box-shadow: var(--animal-shadow-base); /* 0 3px 10px 0 rgba(61,52,40,0.10) */
transform: translateY(-1px);

/* active */
color: #11a89b;
border-color: #11a89b;
transform: translateY(0);
box-shadow: var(--animal-shadow-sm); /* 回落到静止态 */

不要把 primary 那套 0 5px / 6px / 1px #bdaea0 套到 default / dashed 上 —— 整体会显得过重过 cartoon。

loading 斜纹动画(精确值):

background: #0ec4b6;
border: 4px solid #4de2da;
color: #fff;
background-image: repeating-linear-gradient(-45deg, #0ec4b6, #0ec4b6 10px, #01b0a7 10px, #01b0a7 20px);
background-size: 28.28px 28.28px;
animation: animal-btn-loading 1s linear infinite;

@keyframes animal-btn-loading {
    0% {
        background-position: 0 0;
    }
    100% {
        background-position: -28.28px 0;
    }
}

danger primary 按钮:

color: #fff;
box-shadow: 0 5px 0 0 #c94444; /* error-active */

Input

⚠️ shadow prop 默认 false:默认无阴影,下表的 box-shadow 仅在 <Input shadow /> 显式开启时生效。status (error/warning) 阴影与 focus 黄色光晕不受此 prop 控制。

属性smallmiddlelarge
height32px40px48px
padding0 14px0 18px0 22px
font-size12px14px16px
border-radius40px50px50px
border-width2.5px2.5px3px
box-shadow(仅 shadow={true}0 2px 0 0 #d4c9b40 3px 0 0 #d4c9b40 4px 0 0 #d4c9b4

精确颜色值:

background: rgb(247, 243, 223);
border: 2.5px solid #c4b89e;
/* 默认无 box-shadow;shadow={true} 时按上表中号取 0 3px 0 0 #d4c9b4 */

/* 文字 */
color: #725d42;
font-weight: 500;
letter-spacing: 0.01em;

/* placeholder */
color: #c4b89e;
font-weight: 400;

/* prefix/suffix */
color: #a0936e;

/* prefix margin-right */
margin-right: 6px;

/* suffix margin-left */
margin-left: 6px;

/* hover */
border-color: #a89878;
box-shadow: 0 3px 0 0 #c4b89e;

/* focus */
border-color: #ffcc00;
box-shadow:
    0 3px 0 0 #e0b800,
    0 0 0 3px rgba(255, 204, 0, 0.15);

/* disabled */
background: #ece8dc;
border-color: #d4c9b4;
box-shadow: none;
opacity: 0.6;
color: #c4b89e;

/* error */
box-shadow: 0 3px 0 0 #c94444;

/* warning */
box-shadow: 0 3px 0 0 #dba90e;

clear 按钮:

width: 20px;
height: 20px;
margin-left: 4px;
color: #c4b89e;
font-size: 13px;
font-weight: 700;
border-radius: 50%;
transition: all 0.15s;
/* hover */
color: #725d42;
background: rgba(114, 93, 66, 0.1);

Switch

默认尺寸:

min-width: 52px;
height: 28px;
border: 2.5px solid #c4b89e;
border-radius: 50px;
background: #d4c9b4;
box-shadow: inset 0 2px 4px rgba(114, 93, 66, 0.15);

/* handle */
width: 21px;
height: 21px;
top: 50%;
left: 2px;
transform: translateY(-50%); /* 垂直居中 */
background: rgb(247, 243, 223);
border: 2.5px solid #bdaea0;
border-radius: 50%;
/* handle 无 outer box-shadow,仅靠 border 与 track inset 阴影分层 */

/* 开启态 */
background: #86d67a;
border-color: #6fba2c;
box-shadow: inset 0 2px 4px rgba(90, 158, 30, 0.2);
/* handle 开启后 left */
left: calc(100% - 24px);
border-color: #5a9e1e;

/* focus-visible */
outline: 2px solid #ffcc00;
outline-offset: 2px;

/* disabled */
opacity: 0.5;

small 尺寸:

min-width: 38px;
height: 20px;
border-width: 2px;
/* handle */
width: 14px;
height: 14px;
top: 1px;
left: 1px;
box-shadow: 0 2px 0 0 #bdaea0;
/* 开启 handle left */
left: calc(100% - 16px);
box-shadow: 0 2px 0 0 #5a9e1e;

inner 文字(#checked / #unchecked 插槽):

font-size: 11px;
font-weight: 700;
color: #fff;
line-height: 1;
letter-spacing: 0.02em;
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
padding: 0 8px 0 28px; /* 未开启 */
padding: 0 28px 0 8px; /* 开启 */
/* small 版 */
padding: 0 6px 0 20px;
font-size: 9px;

loading spinner:

width: 11px;
height: 11px;
border: 2px solid #6fba2c;
border-right-color: transparent;
border-radius: 50%;
animation: animal-spin 0.6s linear infinite;
/* 关闭态 */
border-color: #a89878;
@keyframes animal-spin {
    to {
        transform: rotate(360deg);
    }
}

Card

/* 默认 */
border-radius: 20px;
background: rgb(247, 243, 223);
padding: 16px 24px;
color: #725d42;
font-weight: 500;
/* 默认 NO box-shadow(依赖 border / pattern 分层,不靠悬浮阴影)*/
transition: all 0.3s ease;
/* hover */
transform: translateY(-2px);

/* dashed 类型 */
border: 2px dashed #e8dcc8;
background: rgb(250, 248, 242);
box-shadow: none;

/* pattern 叠加(pattern !== 'none' 时,纯 CSS 实现,**无 png/svg**) */
/* 双层 radial-gradient 点阵 + 同色调 1.5px solid 边框 + pastel 浅底,
   13 种命名(default / app-pink / purple / app-blue / app-yellow / app-orange /
   app-teal / app-green / app-red / lime-green / yellow-green / brown / warm-peach-pink)
   与 Card.color 同名,但呈现为浅底波点"墙纸"而非实色块。 */
/* 例:pattern="app-pink" */
background:
    radial-gradient(circle, rgba(248, 166, 178, 0.18) 1.5px, transparent 1.5px) 0 0/28px 28px,
    radial-gradient(circle, rgba(255, 200, 210, 0.12) 1px, transparent 1px) 7px 7px/14px 14px,
    #fde4e8;
border: 1.5px solid #f8a6b2;
color: #a85565;
/* 当 color 与 pattern 同时设置时,pattern 视觉上覆盖 color */

旧版 Card type="title" 在 v0.9.x 移除,章节标题请使用独立的 <Title> 组件(见下文)。


Title(飘带 Ribbon 章节标题)

替代旧 Card type="title",渲染游戏风飘带横幅:燕尾两端 + 折角阴影 + 微透视正面主体。 源码:src/components/Title/Title.vue(scoped Less,BEM 类名 animal-title__*)。

/* 默认(绿色配色,可被 .animal-title--color-* 覆盖) */
--rf: #27d039; /* front 正面 */
--rb: #20992a; /* back  燕尾 */
--rk: #115017; /* fold  折角阴影 */
--rt: #fff; /* text  文字色 */

font-family: Nunito, 'Noto Sans SC', sans-serif;
font-weight: 800; /* 外层 wrapper */
/* .animal-title__text 内层文字 font-weight 900;padding-top 0.11em CJK 光学居中 */

/* 飘带主体 */
display: inline-flex;
height: 2em;
padding: 0 1.6em;
letter-spacing: 0.04em;
filter: drop-shadow(0 0.08em 0.12em rgba(0, 0, 0, 0.05));

/* 燕尾(左/右)—— clip-path 鱼尾形 */
.animal-title__back--left {
    clip-path: polygon(100% 0%, 100% 100%, 0% 100%, 30% 50%, 0% 0%);
}
.animal-title__back--right {
    clip-path: polygon(0% 0%, 100% 0%, 70% 50%, 100% 100%, 0% 100%);
}
width: 1.7em;
height: 1.7em;
bottom: -0.4em;

/* 折角阴影 —— CSS border 三角 */
.animal-title__fold--left {
    border-width: 0 0.95em 0.45em 0;
    border-color: transparent var(--rk) transparent transparent;
}
.animal-title__fold--right {
    border-width: 0 0 0.45em 0.95em;
    border-color: transparent transparent transparent var(--rk);
}

/* 正面主体 */
.animal-title__front {
    inset: 0 0.1em;
    border-radius: 0.2em;
    transform: perspective(11.5em) rotateX(3deg);
}

尺寸(SIZE_MAP 通过 inline font-size 注入;所有内部 em 自动缩放):

sizefont-size
small14px
middle20px
large28px

13 种颜色覆盖:在 wrapper 上叠加 .animal-title--color-app-pink / .animal-title--color-purple / .animal-title--color-app-blue / .animal-title--color-app-yellow / .animal-title--color-app-orange / .animal-title--color-app-teal / .animal-title--color-app-green / .animal-title--color-app-red / .animal-title--color-lime-green / .animal-title--color-yellow-green / .animal-title--color-brown / .animal-title--color-warm-peach-pink 之一;每个类同时覆盖 --rf / --rb / --rk / --rt 四个变量。详见 Title.vue <style scoped> 末尾的 13 行 .animal-title--color-* 定义。

例:

.animal-title--color-app-yellow {
    --rf: #f7cd67;
    --rb: #d4a030;
    --rk: #8a6010;
    --rt: #725d42;
}
.animal-title--color-purple {
    --rf: #b77dee;
    --rb: #9050d0;
    --rk: #5a1a9a;
    --rt: #fff;
}

Collapse

/* 外层卡片 */
border-radius: 18px;
border: 2px solid #9f927d;
margin-bottom: 12px;
/* disabled */ opacity: 0.6;

/* 问题栏 */
padding: 16px 24px;
gap: 12px;

/* 图标圆圈 */
width: 28px; height: 28px;
background: #19c8b9;
color: #fff;
border-radius: 50%;
font-size: 18px; font-weight: 700;
box-shadow: 0 2px 4px rgba(25, 200, 185, 0.3);
/* 展开时 */ transform: rotate(180deg);

/* 叶子装饰 */
opacity: 0.5;
/* 展开时 */ opacity: 1; transform: rotate(45deg);

/* 问题文字 */
font-size: 16px; font-weight: 600; line-height: 1.4;

/* 答案展开(CSS Grid trick,无 JS)*/
display: grid;
grid-template-rows: 0fr;
transition: grid-template-rows 0.3s cubic-bezier(0.4, 0, 0.2, 1);
/* 展开 */ grid-template-rows: 1fr;
/* 内层 */ overflow: hidden;

/* 答案文字 */
padding: 0 24px;
font-size: 14px; line-height: 1.7;
/* 展开后 padding-bottom */ 24px;

Tabs

scoped Less + BEM;类名根 .animal-tabs,内部使用 __list / __item / __icon / __leaf / __content 等子元素。

/* 外层容器 */
.animal-tabs {
    background: rgb(247, 243, 223);
    border-radius: 20px;
    border: 2px solid #9f927d;
    overflow: hidden;
}

/* 标签列表 */
.animal-tabs__list {
    display: flex;
    gap: 4px;
    padding: 12px;
    background: rgba(255, 255, 255, 0.6);
    border-bottom: 2px solid #c4b89e;
}

/* 标签项 */
.animal-tabs__item {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 14px;
    background: transparent;
    border: none;
    border-radius: 50px;
    cursor: pointer;
    font-size: 14px;
    font-weight: 500;
    color: #8a7b66;
    transition: all 0.2s ease;
}
/* hover */
.animal-tabs__item:hover {
    background: rgba(25, 200, 185, 0.1);
    color: #725d42;
}
/* 激活状态 — 实心 teal 胶囊 + 奶油色字 */
.animal-tabs__item.animal-tabs__item--active {
    background: #0cc0b5;
    color: #fff9e3;
    font-weight: 600;
}
.animal-tabs__item--active.animal-tabs__item--shadow {
    box-shadow: 0 3px 0 0 #d4c9b4; /* 仅 shadow opt-in 时启用 */
}

/* 标签图标 */
.animal-tabs__icon {
    font-size: 10px;
}
/* 激活时图标放大 */
.animal-tabs__item--active .animal-tabs__icon {
    transform: scale(1.2);
}

/* 叶子装饰动画 */
.animal-tabs__leaf {
    position: absolute;
    right: -6px;
    top: -3px;
    font-size: 12px;
    animation: leafWiggle 2s ease-in-out infinite;
}
/* leafAnimation={false} 时追加 .animal-tabs__leaf--static 修饰符去除 animation */

@keyframes leafWiggle {
    0%,
    100% {
        transform: rotate(0deg);
    }
    25% {
        transform: rotate(-10deg);
    }
    75% {
        transform: rotate(10deg);
    }
}

/* 内容区 */
.animal-tabs__content {
    padding: 24px;
    animation: fadeIn 0.25s ease;
}

@keyframes fadeIn {
    from {
        opacity: 0;
        transform: translateY(4px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

Modal

SVG clip-path 完整 path d 值(精确还原 blob 轮廓):

<template>
    <svg style="position: absolute; width: 0; height: 0" aria-hidden="true">
        <defs>
            <clipPath id="animal-modal-clip" clipPathUnits="objectBoundingBox">
                <path
                    d="M0.501,0.005 L0.501,0.005 L0.523,0.005 L0.549,0.006
          C0.704,0.01,0.796,0.017,0.825,0.027
          L0.827,0.028
          C0.872,0.045,0.939,0.044,0.978,0.17
          C1,0.254,1,0.365,0.99,0.505
          L0.988,0.513
          C0.979,0.558,0.971,0.598,0.965,0.633
          C0.956,0.689,0.979,0.77,0.964,0.865
          C0.953,0.928,0.921,0.966,0.869,0.979
          C0.821,0.986,0.773,0.992,0.726,0.995
          L0.712,0.996 L0.694,0.997
          C0.648,1,0.586,1,0.507,1
          L0.501,1 L0.464,1
          C0.385,1,0.325,0.998,0.283,0.995
          C0.234,0.992,0.184,0.987,0.133,0.979
          C0.081,0.966,0.05,0.928,0.039,0.865
          C0.023,0.77,0.047,0.689,0.037,0.633
          C0.031,0.595,0.023,0.552,0.013,0.505
          C-0.006,0.365,-0.002,0.254,0.024,0.17
          C0.064,0.045,0.13,0.045,0.174,0.028
          L0.175,0.028
          C0.204,0.017,0.303,0.009,0.474,0.005
          L0.501,0.005"
                />
            </clipPath>
        </defs>
    </svg>
</template>

Modal 精确样式:

/* 遮罩 */
background: rgba(0, 0, 0, 0.35);
animation: animal-fade-in 0.25s ease;
z-index: 1000;

/* 弹窗容器 */
max-width: calc(100vw - 32px);
max-height: calc(100vh - 64px);
animation: animal-zoom-in 0.3s ease;

/* 裁切内容区 */
clip-path: url(#animal-modal-clip);
background: rgb(247, 243, 223);
color: rgb(128, 115, 89);
padding: 48px 48px 32px 48px;

/* 标题 */
font-size: 28px;
font-weight: 700;
color: rgba(114, 93, 66, 1);
padding-bottom: 15px;

/* 关闭按钮 */
width: 32px;
height: 32px;
font-size: 22px;
color: rgba(114, 93, 66, 0.6);
border-radius: 50%;
transition: all 0.2s;
/* hover */
background: rgba(114, 93, 66, 0.1);
color: rgba(114, 93, 66, 1);

/* body */
font-size: 20px;
font-weight: 600;
line-height: 1.6;
color: #8a7b66;
padding-bottom: 20px;

/* footer */
gap: 12px;

/* 普通按钮 */
height: 40px;
padding: 0 24px;
font-size: 18px;
border: 2px solid rgba(114, 93, 66, 0.3);
border-radius: 39.81px;
transition: all 0.2s;
line-height: 1;
/* hover */
border-color: rgba(114, 93, 66, 0.6);
background: rgba(114, 93, 66, 0.08);

/* 主按钮(确认)*/
color: rgba(114, 93, 66, 1);
background: rgba(255, 204, 0, 1); /* 游戏黄色!*/
border-color: rgba(255, 204, 0, 1);
/* hover */
background: rgba(255, 204, 0, 0.85);
border-color: rgba(255, 204, 0, 0.85);


Footer

<template>
    <Footer />
    <!-- 14 个 🎄 居中一行(高 80px) -->
    <Footer seamless />
    <!-- 🎄 铺满整行(space-between) -->
</template>
.animal-footer {
    // 14 个 🎄 emoji 居中一行(flex + letter-spacing),非图片
    width: 100%;
    height: 80px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 28px;
    letter-spacing: 12px;
}
.animal-footer--seamless {
    justify-content: space-between;
    padding: 0 8px;
    letter-spacing: 0;
}
  • type prop(原 sea 海浪类型与森林像素图均已移除),仅保留 seamless prop。

Divider

<template>
    <Divider type="line-brown" />
    <!-- 默认 -->
    <Divider type="line-teal" />
    <Divider type="line-white" />
    <Divider type="line-yellow" />
    <Divider type="wave-yellow" />
</template>
.animal-divider {
    width: 100%;
    height: 12px;
    background: url('./img/divider-line-brown.svg') center/contain no-repeat;
}
.animal-divider--line-teal {
    background-image: url('./img/divider-line-teal.svg');
}
.animal-divider--line-white {
    background-image: url('./img/divider-line-white.svg');
}
.animal-divider--line-yellow {
    background-image: url('./img/divider-line-yellow.svg');
}
.animal-divider--wave-yellow {
    background-image: url('./img/wave-yellow.svg');
}

默认 SVG 色值参考:#D8D0C3(米褐),viewBox="0 0 297 14"


Cursor

<template>
    <Cursor>
        <App />
        <!-- 此范围内所有元素变为光标 -->
    </Cursor>

    <!-- type="raindrop":蓝色雨滴光标 -->
    <Cursor type="raindrop">
        <MapCanvas />
    </Cursor>

    <!-- forceAll=false:保留交互语义(a/button 仍是 pointer,input 仍是 text) -->
    <Cursor :force-all="false">
        <FormPage />
    </Cursor>
</template>

Props:type'default' | 'raindrop',默认 'default')、forceAll(boolean,默认 true)。

样式文件为 普通全局 CSS(非 scoped;类名固定为 animal-cursor,挂在根 <div> 上):

/* 内联 SVG data-URI(无外部图片资源):28×28 几何箭头,hotspot 6 4 */
.animal-cursor--force,
.animal-cursor--force * {
    cursor: url("data:image/svg+xml,...") 6 4, default !important;
}

/* type="raindrop":32×32 蓝色水滴,hotspot 16 6 */
.animal-cursor--force.animal-cursor--raindrop,
.animal-cursor--force.animal-cursor--raindrop * {
    cursor: url("data:image/svg+xml,...") 16 6, default !important;
}

/* forceAll=false(scoped 模式):容器自身用自定义光标,后代恢复 auto,
   交互元素(a/button/select 等)恢复 pointer、文本输入恢复 text、禁用态 not-allowed */
.animal-cursor.animal-cursor--scoped { cursor: url("data:image/svg+xml,...") 6 4, default !important; }
.animal-cursor--scoped * { cursor: auto !important; }
  • 使用 !important 覆盖默认光标

  • ⚠️ 此组件不能用 scoped:scoped 选择器无法穿透 slot 内容;必须以全局 CSS 形式注册(<style> 不带 scoped,或全局样式入口引入)


Background

装饰背景壁纸容器(纯 CSS + 内联 SVG,零图片资源),子内容渲染在图案之上。

<template>
    <!-- dots 波点壁纸(默认):两层错位圆点(28px 大点 + 14px 小点,绿色系 #bfe3bf 底) -->
    <Background style="height: 200px" />

    <!-- sprinkles 圆柱形彩色针糖壁纸:三层互质 tile(190×170 / 230×195 / 255×215),
         内联 SVG 胶囊(圆角矩形 + 竖向高光渐变模拟圆柱受光),重复周期约 220000×280000px,
         视觉上随机散落;#fdf3e3 奶油底 -->
    <Background type="sprinkles" :style="{ minHeight: '200px', padding: '24px' }">
        <p>内容渲染在图案背景之上</p>
    </Background>
</template>

Shortened here. Read the whole file on GitHub.

Signals

GitHub stars
196
Forks
20
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
animal-island-vue-style
Source
github.com/guokaigdg/animal-island-vue