grove-ui-design
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGrove UI Design Skill
Grove UI设计技能
When to Activate
激活场景
Activate this skill when:
- Creating or enhancing pages for Grove sites
- Adding decorative nature elements (trees, clouds, weather effects)
- Implementing glassmorphism effects for readability
- Working with the seasonal theme system
- Building navigation patterns (navbar, mobile overflow menus)
- Creating "story" pages that guide users through content
- Ensuring mobile-friendly, accessible UI
- Choosing icons or visual elements
在以下场景激活本技能:
- 为Grove站点创建或优化页面
- 添加自然风格装饰元素(树木、云朵、天气效果)
- 实现玻璃态效果以提升可读性
- 运用季节主题系统
- 构建导航模式(导航栏、移动端溢出菜单)
- 创建引导用户浏览内容的“故事类”页面
- 确保UI适配移动端且支持无障碍访问
- 选择图标或视觉元素
The Grove Aesthetic
Grove美学风格
Grove is a place. It's nature-themed, warm, and inviting—like a midnight tea shop with good documentation.
Grove是一个场所。它以自然为主题,温暖且富有吸引力——就像一家有着优质文档的深夜茶店。
Core Principles
核心原则
Warm, introspective, queer, unapologetically building something meaningful.
Write with the warmth of a midnight tea shop and the clarity of good documentation.Every design choice should feel:
- Welcoming — like entering a cozy space
- Organic — natural, not rigid or corporate
- Readable — content-first, decorations enhance, never obstruct
- Alive — subtle animations, seasonal changes, randomization
温暖、内省、多元包容,专注打造有意义的产品。
文字风格兼具深夜茶店的温暖感与优质文档的清晰感。每一项设计选择都应具备以下特质:
- 有亲和力 —— 如同进入一个舒适的空间
- 有机自然 —— 自然随性,而非刻板的企业风格
- 可读性优先 —— 内容为核心,装饰仅作点缀,绝不干扰内容
- 鲜活生动 —— 包含微妙动画、季节变化与随机化效果
Grove Mode & Terminology (GroveTerm V2)
Grove模式与术语体系(GroveTerm V2)
Grove has a terminology system that automatically switches between Grove-themed terms and standard terms based on the user's Grove Mode setting. Always use GroveTerm components instead of hardcoding Grove terminology in UI.
By default, Grove Mode is OFF for new visitors. They see familiar terms: "Posts" instead of "Blooms", "Dashboard" instead of "Arbor", "Support" instead of "Porch". When users opt in via the footer toggle, they see the full nature-themed vocabulary with interactive definitions.
The Component Suite:
svelte
import { GroveTerm, GroveSwap, GroveText, GroveSwapText, GroveIntro } from '@autumnsgrove/groveengine/ui';
import groveTermManifest from '$lib/data/grove-term-manifest.json';| Component | Use Case | Behavior |
|---|---|---|
| Interactive terms with popup definitions | Colored underline when ON, click for popup. Shows standard term when OFF. |
| Silent text replacement | Reactively swaps text. No underline, no interaction. |
| Parse | Renders |
| Parse | Same parsing, silent swaps (no popups). |
| "We call it X" page banners | Standardized intro below page titles. |
Usage:
svelte
<!-- Interactive term with popup -->
<GroveTerm term="bloom" manifest={groveTermManifest} />
<!-- Custom display text -->
<GroveTerm term="wanderer" manifest={groveTermManifest}>wanderers</GroveTerm>
<!-- Silent swap (no popup, no underline) -->
<GroveSwap term="arbor" manifest={groveTermManifest} />
<!-- Parse [[term]] syntax in data strings (ideal for FAQ items, pricing, etc.) -->
<GroveText content="Your [[bloom|posts]] live in your [[garden|blog]]." manifest={groveTermManifest} />
<!-- Page intro banner: "we call it the Meadow" -->
<GroveIntro term="meadow" manifest={groveTermManifest} />Key Rules:
- Never hardcode Grove terms in user-facing UI. Always use GroveTerm components.
- Default is OFF for new visitors. Standard, familiar terminology first.
- URLs stay as Grove terms (,
/porch) regardless of display mode./garden - Brand terms (Grove) and subscription tiers (Seedling/Sapling/Oak/Evergreen) always show as-is.
- Use syntax for data-driven content (FAQ items, pricing fineprint, feature lists).
[[term]] - Grove Mode store: from
groveModeStore. Toggle lives in the footer.@autumnsgrove/groveengine/ui/stores
See for the full identity language documentation and for component source.
docs/grove-user-identity.mdpackages/engine/src/lib/ui/components/ui/groveterm/Grove拥有一套术语系统,可根据用户的Grove模式设置,自动在Grove主题术语与标准术语间切换。在UI中务必使用GroveTerm组件,而非硬编码Grove术语。
默认情况下,新访客的Grove模式为关闭状态,他们将看到熟悉的标准术语:用“Posts”代替“Blooms”,“Dashboard”代替“Arbor”,“Support”代替“Porch”。当用户通过页脚的开关开启Grove模式后,将看到完整的自然主题词汇,并可查看交互式定义。
组件套件:
svelte
import { GroveTerm, GroveSwap, GroveText, GroveSwapText, GroveIntro } from '@autumnsgrove/groveengine/ui';
import groveTermManifest from '$lib/data/grove-term-manifest.json';| 组件 | 使用场景 | 行为 |
|---|---|---|
| 带弹出式定义的交互式术语 | 开启模式时显示彩色下划线,点击可查看弹窗;关闭模式时显示标准术语。 |
| 静默文本替换 | 响应式替换文本,无下划线,无交互。 |
| 解析数据字符串中的 | 将 |
| 静默解析 | 解析规则相同,但仅做静默替换(无弹窗)。 |
| 页面标题下方的“我们称之为X”标准化介绍横幅 | 位于页面标题下方的标准化介绍横幅。 |
用法示例:
svelte
<!-- 带弹窗的交互式术语 -->
<GroveTerm term="bloom" manifest={groveTermManifest} />
<!-- 自定义显示文本 -->
<GroveTerm term="wanderer" manifest={groveTermManifest}>wanderers</GroveTerm>
<!-- 静默替换(无弹窗、无下划线) -->
<GroveSwap term="arbor" manifest={groveTermManifest} />
<!-- 解析数据字符串中的[[term]]语法(适用于FAQ、定价等场景) -->
<GroveText content="Your [[bloom|posts]] live in your [[garden|blog]]." manifest={groveTermManifest} />
<!-- 页面介绍横幅:“我们称之为Meadow” -->
<GroveIntro term="meadow" manifest={groveTermManifest} />核心规则:
- 切勿硬编码Grove术语到面向用户的UI中,务必使用GroveTerm组件。
- 默认关闭Grove模式,优先展示用户熟悉的标准术语。
- URL始终使用Grove术语(如、
/porch),不受显示模式影响。/garden - 品牌术语(Grove)与订阅层级(Seedling/Sapling/Oak/Evergreen)始终保持原样显示。
- 数据驱动型内容使用语法搭配GroveText组件。
[[term]] - Grove模式状态管理:从导入
@autumnsgrove/groveengine/ui/stores,开关位于页脚。groveModeStore
完整的身份语言文档请查看,组件源码请查看。
docs/grove-user-identity.mdpackages/engine/src/lib/ui/components/ui/groveterm/Glassmorphism Pattern
玻璃态设计模式
Glass effects create readability while revealing hints of background decoration.
玻璃效果可在保留背景装饰可见性的同时,提升内容可读性。
The Layering Formula
分层结构公式
Background (gradients, vines, nature)
↓
Decorative Elements (trees, clouds, particles)
↓
Glass Surface (translucent + blur)
↓
Content (text, cards, UI)背景(渐变、藤蔓、自然元素)
↓
装饰元素(树木、云朵、粒子效果)
↓
玻璃层(半透明 + 模糊)
↓
内容(文本、卡片、UI元素)Glass Components
玻璃态组件
svelte
import { Glass, GlassCard, GlassButton, GlassOverlay } from '@groveengine/ui/ui';
<!-- Container with glass effect -->
<Glass variant="tint" class="p-6 rounded-xl">
<p>Readable text over busy backgrounds</p>
</Glass>
<!-- Card with glass styling -->
<GlassCard title="Settings" variant="default" hoverable>
Content here
</GlassCard>
<!-- Glass button -->
<GlassButton variant="accent">Subscribe</GlassButton>svelte
import { Glass, GlassCard, GlassButton, GlassOverlay } from '@groveengine/ui/ui';
<!-- 带玻璃效果的容器 -->
<Glass variant="tint" class="p-6 rounded-xl">
<p>在复杂背景上依然可读的文本</p>
</Glass>
<!-- 玻璃风格卡片 -->
<GlassCard title="Settings" variant="default" hoverable>
内容区域
</GlassCard>
<!-- 玻璃态按钮 -->
<GlassButton variant="accent">Subscribe</GlassButton>Glass Variants
玻璃态变体
| Variant | Use Case | Light Mode | Dark Mode |
|---|---|---|---|
| Headers, navbars | 95% white | 95% slate |
| Text over backgrounds | 60% white | 50% slate |
| Content cards | 80% white | 70% slate |
| Callouts, highlights | 30% accent | 20% accent |
| Modal backdrops | 50% black | 60% black |
| Subtle backgrounds | 40% white | 30% slate |
| 变体 | 使用场景 | 亮色模式 | 暗色模式 |
|---|---|---|---|
| 页眉、导航栏 | 95% 白色 | 95% 石板灰 |
| 背景上的文本容器 | 60% 白色 | 50% 石板灰 |
| 内容卡片 | 80% 白色 | 70% 石板灰 |
| 提示框、高亮区域 | 30% 强调色 | 20% 强调色 |
| 模态框背景 | 50% 黑色 | 60% 黑色 |
| 微妙背景 | 40% 白色 | 30% 石板灰 |
CSS Utility Classes
CSS工具类
html
<!-- Apply directly to any element -->
<div class="glass rounded-xl p-4">Basic glass</div>
<div class="glass-tint p-6">Text container</div>
<div class="glass-accent p-4">Highlighted section</div>
<nav class="glass-surface sticky top-0">Navbar</nav>html
<!-- 直接应用于任意元素 -->
<div class="glass rounded-xl p-4">基础玻璃效果</div>
<div class="glass-tint p-6">文本容器</div>
<div class="glass-accent p-4">高亮区域</div>
<nav class="glass-surface sticky top-0">导航栏</nav>Key Pattern: Sticky Navigation
核心模式:粘性导航
svelte
<nav class="sticky top-[73px] z-30 bg-white/80 dark:bg-slate-900/80 backdrop-blur-sm border-b border-divider">
<!-- Navigation content -->
</nav>svelte
<nav class="sticky top-[73px] z-30 bg-white/80 dark:bg-slate-900/80 backdrop-blur-sm border-b border-divider">
<!-- 导航内容 -->
</nav>Seasonal Theme System
季节主题系统
Grove uses four seasons, each with distinct colors, weather effects, and moods.
Grove包含四个季节,每个季节都有独特的配色、天气效果与氛围。
Season Detection
季节检测
svelte
import { season } from '$lib/stores/season';
const isSpring = $derived($season === 'spring');
const isAutumn = $derived($season === 'autumn');
const isWinter = $derived($season === 'winter');
// Summer is the default (no flag needed)svelte
import { season } from '$lib/stores/season';
const isSpring = $derived($season === 'spring');
const isAutumn = $derived($season === 'autumn');
const isWinter = $derived($season === 'winter');
// 夏季为默认值(无需额外判断)Color Palette System
调色板系统
Import from: or
@autumnsgrove/groveengine/ui/nature$lib/components/nature/palette导入路径: 或
@autumnsgrove/groveengine/ui/nature$lib/components/nature/paletteCore Palettes (Year-Round)
核心调色板(全年通用)
typescript
import { greens, bark, earth, natural } from '@autumnsgrove/groveengine/ui/nature';
// Greens - organized dark-to-light for atmospheric depth
greens.darkForest // #0d4a1c - Background trees
greens.deepGreen // #166534 - Mid-distance
greens.grove // #16a34a - Grove brand primary
greens.meadow // #22c55e - Standard foliage
greens.spring // #4ade80 - Bright accent
greens.mint // #86efac - Light accent
greens.pale // #bbf7d0 - Foreground highlights
// Bark - warm wood tones
bark.darkBark // #3d2817 - Oak, older trees
bark.bark // #5d4037 - Standard trunk
bark.warmBark // #6B4423 - Pine, cedar
bark.lightBark // #8b6914 - Young trees
// Earth - ground elements
earth.soil, earth.mud, earth.clay, earth.sand, earth.stone, earth.pebble, earth.slate
// Natural - cream and off-whites
natural.cream, natural.aspenBark, natural.bone, natural.mushroom, natural.birchWhitetypescript
import { greens, bark, earth, natural } from '@autumnsgrove/groveengine/ui/nature';
// 绿色系 - 按从深到浅排序,营造空间层次感
greens.darkForest // #0d4a1c - 背景树木
greens.deepGreen // #166534 - 中景
greens.grove // #16a34a - Grove品牌主色
greens.meadow // #22c55e - 标准 foliage
greens.spring // #4ade80 - 亮色强调
greens.mint // #86efac - 浅色强调
greens.pale // #bbf7d0 - 前景高亮
// 树皮色 - 温暖木色调
bark.darkBark // #3d2817 - 橡树、老树
bark.bark // #5d4037 - 标准树干
bark.warmBark // #6B4423 - 松树、雪松
bark.lightBark // #8b6914 - 幼树
// 大地色 - 地面元素
earth.soil, earth.mud, earth.clay, earth.sand, earth.stone, earth.pebble, earth.slate
// 自然浅色系 - 奶油色与米白色
natural.cream, natural.aspenBark, natural.bone, natural.mushroom, natural.birchWhiteSpring Palettes
春季调色板
typescript
import { springFoliage, springSky, wildflowers, cherryBlossoms, cherryBlossomsPeak } from '@autumnsgrove/groveengine/ui/nature';
// Spring Foliage - yellow-green new growth
springFoliage.sprout // #65a30d - Distant new growth
springFoliage.newLeaf // #84cc16 - Classic spring lime
springFoliage.freshGreen // #a3e635 - Bright foreground
springFoliage.budding // #bef264 - Pale new leaf
springFoliage.tender // #d9f99d - Very pale
// Spring Sky
springSky.clear // #7dd3fc - Clear morning
springSky.soft // #bae6fd - Pale sky
// Wildflowers - unified meadow flower colors
wildflowers.buttercup // #facc15 - Yellow
wildflowers.daffodil // #fde047 - Pale yellow
wildflowers.crocus // #a78bfa - Purple crocus
wildflowers.violet // #8b5cf6 - Wild violets
wildflowers.purple // #a855f7 - Lupine, thistle
wildflowers.lavender // #c4b5fd - Distant masses
wildflowers.tulipPink // #f9a8d4 - Pink tulips
wildflowers.tulipRed // #fb7185 - Red tulips
wildflowers.white // #fefefe - Daisies, trillium
// Cherry Blossoms - summer standard
cherryBlossoms.deep // #db2777 - Dense centers
cherryBlossoms.standard // #ec4899 - Standard blossom
cherryBlossoms.light // #f472b6 - Light petals
cherryBlossoms.pale // #f9a8d4 - Pale blossoms
cherryBlossoms.falling // #fbcfe8 - Falling petals
// Cherry Blossoms Peak - vibrant spring (one shade brighter!)
cherryBlossomsPeak.deep // #ec4899
cherryBlossomsPeak.standard // #f472b6
cherryBlossomsPeak.light // #f9a8d4
cherryBlossomsPeak.pale // #fbcfe8
cherryBlossomsPeak.falling // #fce7f3typescript
import { springFoliage, springSky, wildflowers, cherryBlossoms, cherryBlossomsPeak } from '@autumnsgrove/groveengine/ui/nature';
// 春季 foliage - 黄绿色新叶
springFoliage.sprout // #65a30d - 远景新叶
springFoliage.newLeaf // #84cc16 - 经典春季石灰绿
springFoliage.freshGreen // #a3e635 - 明亮前景色
springFoliage.budding // #bef264 - 浅新叶
springFoliage.tender // #d9f99d - 极浅色
// 春季天空
springSky.clear // #7dd3fc - 晴朗清晨
springSky.soft // #bae6fd - 浅天空
// 野花 - 统一的草地花卉配色
wildflowers.buttercup // #facc15 - 黄色
wildflowers.daffodil // #fde047 - 浅黄色
wildflowers.crocus // #a78bfa - 紫色番红花
wildflowers.violet // #8b5cf6 - 野生紫罗兰
wildflowers.purple // #a855f7 - 羽扇豆、蓟
wildflowers.lavender // #c4b5fd - 远景花丛
wildflowers.tulipPink // #f9a8d4 - 粉色郁金香
wildflowers.tulipRed // #fb7185 - 红色郁金香
wildflowers.white // #fefefe - 雏菊、延龄草
// 樱花 - 夏季标准配色
cherryBlossoms.deep // #db2777 - 花丛中心
cherryBlossoms.standard // #ec4899 - 标准樱花
cherryBlossoms.light // #f472b6 - 浅色花瓣
cherryBlossoms.pale // #f9a8d4 - 浅樱花
cherryBlossoms.falling // #fbcfe8 - 飘落的花瓣
// 盛花期樱花 - 鲜艳春季配色(整体亮一个色阶!)
cherryBlossomsPeak.deep // #ec4899
cherryBlossomsPeak.standard // #f472b6
cherryBlossomsPeak.light // #f9a8d4
cherryBlossomsPeak.pale // #fbcfe8
cherryBlossomsPeak.falling // #fce7f3Unified Flowers Palette (NEW!)
统一花卉调色板(新增!)
The namespace consolidates all flower colors into one organized structure:
flowerstypescript
import { flowers } from '@autumnsgrove/groveengine/ui/nature';
// Meadow wildflowers (yellows, purples, pinks, whites)
flowers.wildflower.buttercup // #facc15 - Yellow
flowers.wildflower.daffodil // #fde047 - Pale yellow
flowers.wildflower.crocus // #a78bfa - Purple crocus
flowers.wildflower.violet // #8b5cf6 - Wild violets
flowers.wildflower.purple // #a855f7 - Lupine, thistle
flowers.wildflower.lavender // #c4b5fd - Distant masses
flowers.wildflower.tulipPink // #f9a8d4 - Pink tulips
flowers.wildflower.tulipRed // #fb7185 - Red tulips
flowers.wildflower.white // #fefefe - Daisies, trillium
// Cherry blossoms - standard summer
flowers.cherry.deep // #db2777
flowers.cherry.standard // #ec4899
flowers.cherry.light // #f472b6
flowers.cherry.pale // #f9a8d4
flowers.cherry.falling // #fbcfe8
// Cherry blossoms at peak bloom - vibrant spring
flowers.cherryPeak.deep // #ec4899
flowers.cherryPeak.standard // #f472b6
flowers.cherryPeak.light // #f9a8d4
flowers.cherryPeak.pale // #fbcfe8
flowers.cherryPeak.falling // #fce7f3Use instead of — the accents version is deprecated.
flowers.wildfloweraccents.flowerflowerstypescript
import { flowers } from '@autumnsgrove/groveengine/ui/nature';
// 草地野花(黄、紫、粉、白)
flowers.wildflower.buttercup // #facc15 - 黄色
flowers.wildflower.daffodil // #fde047 - 浅黄色
flowers.wildflower.crocus // #a78bfa - 紫色番红花
flowers.wildflower.violet // #8b5cf6 - 野生紫罗兰
flowers.wildflower.purple // #a855f7 - 羽扇豆、蓟
flowers.wildflower.lavender // #c4b5fd - 远景花丛
flowers.wildflower.tulipPink // #f9a8d4 - 粉色郁金香
flowers.wildflower.tulipRed // #fb7185 - 红色郁金香
flowers.wildflower.white // #fefefe - 雏菊、延龄草
// 樱花 - 夏季标准配色
flowers.cherry.deep // #db2777
flowers.cherry.standard // #ec4899
flowers.cherry.light // #f472b6
flowers.cherry.pale // #f9a8d4
flowers.cherry.falling // #fbcfe8
// 盛花期樱花 - 鲜艳春季配色
flowers.cherryPeak.deep // #ec4899
flowers.cherryPeak.standard // #f472b6
flowers.cherryPeak.light // #f9a8d4
flowers.cherryPeak.pale // #fbcfe8
flowers.cherryPeak.falling // #fce7f3请使用替代 —— accents版本已被废弃。
flowers.wildfloweraccents.flowerAutumn & Winter Palettes
秋季与冬季调色板
typescript
import { autumn, autumnReds, winter } from '@autumnsgrove/groveengine/ui/nature';
// Autumn - warm fall foliage (dark-to-light for depth)
autumn.rust // #9a3412 - Deep background
autumn.ember // #c2410c - Oak-like
autumn.pumpkin // #ea580c - Maple mid-tones
autumn.amber // #d97706 - Classic fall
autumn.gold // #eab308 - Aspen/birch
autumn.honey // #facc15 - Bright foreground
autumn.straw // #fde047 - Pale dying leaves
// Autumn Reds - cherry/maple fall foliage
autumnReds.crimson // #be123c - Deep maple
autumnReds.scarlet // #e11d48 - Bright cherry
autumnReds.rose // #f43f5e - Light autumn
autumnReds.coral // #fb7185 - Pale accent
// Winter - frost, snow, ice + frosted evergreens
winter.snow, winter.frost, winter.ice, winter.glacier
winter.frostedPine, winter.winterGreen, winter.coldSpruce
winter.winterSky, winter.twilight, winter.overcast
winter.bareBranch, winter.frostedBark, winter.coldWood
winter.hillDeep, winter.hillMid, winter.hillNear, winter.hillFronttypescript
import { autumn, autumnReds, winter } from '@autumnsgrove/groveengine/ui/nature';
// 秋季 - 温暖秋叶色(从深到浅排序以营造层次感)
autumn.rust // #9a3412 - 深背景
autumn.ember // #c2410c - 橡树风格
autumn.pumpkin // #ea580c - 枫树中间色调
autumn.amber // #d97706 - 经典秋季色
autumn.gold // #eab308 - 白杨树/桦树
autumn.honey // #facc15 - 明亮前景色
autumn.straw // #fde047 - 浅枯黄色
// 秋季红色系 - 樱花/枫叶秋叶色
autumnReds.crimson // #be123c - 深红枫叶
autumnReds.scarlet // #e11d48 - 亮樱花红
autumnReds.rose // #f43f5e - 浅秋季红
autumnReds.coral // #fb7185 - 浅强调色
// 冬季 - 霜、雪、冰 + 霜覆盖的常绿树
winter.snow, winter.frost, winter.ice, winter.glacier
winter.frostedPine, winter.winterGreen, winter.coldSpruce
winter.winterSky, winter.twilight, winter.overcast
winter.bareBranch, winter.frostedBark, winter.coldWood
winter.hillDeep, winter.hillMid, winter.hillNear, winter.hillFrontAccent Palettes
强调色调色板
typescript
import { accents, wildflowers } from '@autumnsgrove/groveengine/ui/nature';
// Mushrooms - fairy tale pops of color
accents.mushroom.redCap, accents.mushroom.orangeCap, accents.mushroom.brownCap
accents.mushroom.spots, accents.mushroom.gill
// Firefly - bioluminescence
accents.firefly.glow, accents.firefly.warmGlow, accents.firefly.body
// Berry - rich saturated
accents.berry.ripe, accents.berry.elderberry, accents.berry.red
// Water - cool blue spectrum
accents.water.surface, accents.water.deep, accents.water.shallow, accents.water.lily
// Sky - time of day
accents.sky.dayLight, accents.sky.dayMid, accents.sky.sunset, accents.sky.night, accents.sky.star
// Birds - species-specific colors
accents.bird.cardinalRed, accents.bird.cardinalMask, accents.bird.cardinalBeak
accents.bird.chickadeeCap, accents.bird.chickadeeBody, accents.bird.chickadeeBelly
accents.bird.robinBody, accents.bird.robinBreast, accents.bird.robinBeak
accents.bird.bluebirdBody, accents.bird.bluebirdWing, accents.bird.bluebirdBreast
// NOTE: accents.flower is deprecated - use flowers.wildflower insteadtypescript
import { accents, wildflowers } from '@autumnsgrove/groveengine/ui/nature';
// 蘑菇色 - 童话风格的亮色点缀
accents.mushroom.redCap, accents.mushroom.orangeCap, accents.mushroom.brownCap
accents.mushroom.spots, accents.mushroom.gill
// 萤火虫色 - 生物荧光色
accents.firefly.glow, accents.firefly.warmGlow, accents.firefly.body
// 浆果色 - 浓郁饱和色
accents.berry.ripe, accents.berry.elderberry, accents.berry.red
// 水色 - 冷蓝色系
accents.water.surface, accents.water.deep, accents.water.shallow, accents.water.lily
// 天空色 - 不同时段
accents.sky.dayLight, accents.sky.dayMid, accents.sky.sunset, accents.sky.night, accents.sky.star
// 鸟类色 - 特定鸟类配色
accents.bird.cardinalRed, accents.bird.cardinalMask, accents.bird.cardinalBeak
accents.bird.chickadeeCap, accents.bird.chickadeeBody, accents.bird.chickadeeBelly
accents.bird.robinBody, accents.bird.robinBreast, accents.bird.robinBeak
accents.bird.bluebirdBody, accents.bird.bluebirdWing, accents.bird.bluebirdBreast
// 注意:accents.flower已废弃 - 请使用flowers.wildflower替代Seasonal Helper Functions
季节辅助函数
typescript
import { getSeasonalGreens, getCherryColors, isTreeBare, pickRandom, pickFrom } from '@autumnsgrove/groveengine/ui/nature';
// Get foliage colors mapped to season
const foliage = getSeasonalGreens(season);
// spring → springFoliage colors
// summer → greens
// autumn → autumn palette
// winter → frosted evergreen colors
// Get cherry tree colors by season
const cherryColors = getCherryColors(season);
// spring → cherryBlossomsPeak (vibrant!)
// summer → cherryBlossoms (standard)
// autumn → autumnReds
// winter → null (bare tree)
// Check if deciduous tree is bare
if (isTreeBare('cherry', 'winter')) { /* no foliage */ }
// Random color selection for natural variation
const randomGreen = pickRandom(greens);
const specificGreen = pickFrom(greens, ['grove', 'meadow']);typescript
import { getSeasonalGreens, getCherryColors, isTreeBare, pickRandom, pickFrom } from '@autumnsgrove/groveengine/ui/nature';
// 根据季节获取对应foliage配色
const foliage = getSeasonalGreens(season);
// 春季 → springFoliage配色
// 夏季 → greens配色
// 秋季 → autumn调色板
// 冬季 → 霜覆盖常绿树配色
// 根据季节获取樱花树配色
const cherryColors = getCherryColors(season);
// 春季 → cherryBlossomsPeak(鲜艳版!)
// 夏季 → cherryBlossoms(标准版)
// 秋季 → autumnReds
// 冬季 → null(无叶)
// 判断落叶树是否处于无叶状态
if (isTreeBare('cherry', 'winter')) { /* 无foliage */ }
// 随机选择颜色以营造自然变化
const randomGreen = pickRandom(greens);
const specificGreen = pickFrom(greens, ['grove', 'meadow']);Deprecated Aliases (Still Work)
已废弃别名(仍可使用)
typescript
// These work but will be removed in v1.0:
import { spring, pinks, springBlossoms } from '@autumnsgrove/groveengine/ui/nature';
// spring → use springFoliage, wildflowers, springSky instead
// pinks → use cherryBlossoms instead
// springBlossoms → use cherryBlossomsPeak instead
// accents.flower → use flowers.wildflower insteadtypescript
// 以下别名仍可使用,但将在v1.0版本移除:
import { spring, pinks, springBlossoms } from '@autumnsgrove/groveengine/ui/nature';
// spring → 请使用springFoliage, wildflowers, springSky替代
// pinks → 请使用cherryBlossoms替代
// springBlossoms → 请使用cherryBlossomsPeak替代
// accents.flower → 请使用flowers.wildflower替代Season Mood Summary
季节氛围总结
| Season | Primary Colors | Mood |
|---|---|---|
| Spring | | Renewal, hope |
| Summer | | Growth, warmth |
| Autumn | | Harvest, reflection |
| Winter | | Rest, stillness |
| 季节 | 主色调 | 氛围 |
|---|---|---|
| 春季 | | 新生、希望 |
| 夏季 | | 成长、温暖 |
| 秋季 | | 收获、沉思 |
| 冬季 | | 休憩、宁静 |
Seasonal Weather Effects
季节天气效果
svelte
<!-- Winter: Snowfall -->
{#if isWinter}
<SnowfallLayer count={40} zIndex={5} opacity={{ min: 0.4, max: 0.8 }} spawnDelay={8} />
{/if}
<!-- Spring: Cherry blossom petals -->
{#if isSpring}
<FallingPetalsLayer count={80} zIndex={100} opacity={{ min: 0.5, max: 0.9 }} />
{/if}
<!-- Autumn: Falling leaves (tied to trees) -->
{#if isAutumn}
<FallingLeavesLayer trees={forestTrees} season={$season} minLeavesPerTree={2} maxLeavesPerTree={4} />
{/if}svelte
<!-- 冬季:降雪 -->
{#if isWinter}
<SnowfallLayer count={40} zIndex={5} opacity={{ min: 0.4, max: 0.8 }} spawnDelay={8} />
{/if}
<!-- 春季:樱花花瓣飘落 -->
{#if isSpring}
<FallingPetalsLayer count={80} zIndex={100} opacity={{ min: 0.5, max: 0.9 }} />
{/if}
<!-- 秋季:落叶(与树木关联) -->
{#if isAutumn}
<FallingLeavesLayer trees={forestTrees} season={$season} minLeavesPerTree={2} maxLeavesPerTree={4} />
{/if}Seasonal Background Gradients
季节背景渐变
svelte
<main class="min-h-screen transition-colors duration-1000
{isWinter ? 'bg-gradient-to-b from-slate-200 via-slate-100 to-slate-50 dark:from-slate-900 dark:via-slate-800 dark:to-slate-700' : ''}
{isAutumn ? 'bg-gradient-to-b from-orange-100 via-amber-50 to-yellow-50 dark:from-slate-900 dark:via-amber-950 dark:to-orange-950' : ''}
{isSpring ? 'bg-gradient-to-b from-pink-50 via-sky-50 to-lime-50 dark:from-slate-900 dark:via-pink-950 dark:to-lime-950' : ''}
{/* Summer default */} 'bg-gradient-to-b from-sky-100 via-sky-50 to-emerald-50 dark:from-slate-900 dark:via-slate-800 dark:to-emerald-950'
">svelte
<main class="min-h-screen transition-colors duration-1000
{isWinter ? 'bg-gradient-to-b from-slate-200 via-slate-100 to-slate-50 dark:from-slate-900 dark:via-slate-800 dark:to-slate-700' : ''}
{isAutumn ? 'bg-gradient-to-b from-orange-100 via-amber-50 to-yellow-50 dark:from-slate-900 dark:via-amber-950 dark:to-orange-950' : ''}
{isSpring ? 'bg-gradient-to-b from-pink-50 via-sky-50 to-lime-50 dark:from-slate-900 dark:via-pink-950 dark:to-lime-950' : ''}
{/* 夏季默认 */} 'bg-gradient-to-b from-sky-100 via-sky-50 to-emerald-50 dark:from-slate-900 dark:via-slate-800 dark:to-emerald-950'
">When to Use Seasons
季节主题适用场景
- Roadmap pages — Show progress through seasonal metaphor
- Story/about pages — Create atmosphere and emotional connection
- Interactive demos — Let users toggle seasons (like /forest)
- Help articles — Consider seasonal decor to break up long content
- Anywhere you want magic — Use judgment based on page purpose
- 路线图页面 —— 用季节隐喻展示进度
- 故事/关于页面 —— 营造氛围与情感联结
- 交互式演示 —— 允许用户切换季节(如/forest页面)
- 帮助文章 —— 可添加季节装饰以分割长内容
- 任何需要增添氛围感的场景 —— 根据页面用途合理判断
Randomized Forests
随机森林生成
The forest should feel alive and different every visit.
森林应给人鲜活的感觉,每次访问都略有不同。
Tree Generation Pattern
树木生成模式
typescript
interface GeneratedTree {
id: number;
x: number; // percentage from left (5-93% to avoid edges)
size: number; // base width in pixels
aspectRatio: number; // height = size * aspectRatio (1.0-1.5 range)
treeType: TreeType; // 'logo' | 'pine' | 'cherry' | 'aspen' | 'birch'
opacity: number; // 0.5-0.9 for depth
zIndex: number; // larger trees = higher z-index
}
// Aspect ratio creates natural height variation
const TREE_ASPECT_RATIO_RANGE = { min: 1.0, max: 1.5 };
function generateSectionTrees(count: number): GeneratedTree[] {
const trees: GeneratedTree[] = [];
const usedPositions: number[] = [];
for (let i = 0; i < count; i++) {
// Find non-overlapping position
let x: number;
let attempts = 0;
do {
x = 5 + Math.random() * 88;
attempts++;
} while (usedPositions.some(pos => Math.abs(pos - x) < 8) && attempts < 20);
usedPositions.push(x);
const size = 80 + Math.random() * 80;
const aspectRatio = 1.0 + Math.random() * 0.5;
const opacity = 0.5 + Math.random() * 0.4;
const zIndex = size > 130 ? 3 : size > 100 ? 2 : 1;
trees.push({ id: i, x, size, aspectRatio, treeType: pickRandom(treeTypes), opacity, zIndex });
}
return trees.sort((a, b) => a.x - b.x);
}typescript
interface GeneratedTree {
id: number;
x: number; // 距左侧的百分比(5-93%以避免边缘)
size: number; // 基础宽度(像素)
aspectRatio: number; // 高度 = size * aspectRatio(范围1.0-1.5)
treeType: TreeType; // 'logo' | 'pine' | 'cherry' | 'aspen' | 'birch'
opacity: number; // 0.5-0.9以营造层次感
zIndex: number; // 树木越大,z-index越高
}
// 宽高比营造自然的高度变化
const TREE_ASPECT_RATIO_RANGE = { min: 1.0, max: 1.5 };
function generateSectionTrees(count: number): GeneratedTree[] {
const trees: GeneratedTree[] = [];
const usedPositions: number[] = [];
for (let i = 0; i < count; i++) {
// 寻找不重叠的位置
let x: number;
let attempts = 0;
do {
x = 5 + Math.random() * 88;
attempts++;
} while (usedPositions.some(pos => Math.abs(pos - x) < 8) && attempts < 20);
usedPositions.push(x);
const size = 80 + Math.random() * 80;
const aspectRatio = 1.0 + Math.random() * 0.5;
const opacity = 0.5 + Math.random() * 0.4;
const zIndex = size > 130 ? 3 : size > 100 ? 2 : 1;
trees.push({ id: i, x, size, aspectRatio, treeType: pickRandom(treeTypes), opacity, zIndex });
}
return trees.sort((a, b) => a.x - b.x);
}Regeneration Timing
重新生成时机
- On mount — Trees generate once when page loads
- On resize (significant) — Only if viewport bracket changes dramatically
- Never on scroll — Keep forest stable during reading
- 页面加载时 —— 树木仅在页面首次加载时生成一次
- 大幅窗口调整时 —— 仅当视口尺寸发生显著变化时
- 滚动时绝不生成 —— 阅读过程中保持森林稳定
Rendering Trees
树木渲染
svelte
{#each forestTrees as tree (tree.id)}
<div
class="absolute"
style="
left: {tree.x}%;
bottom: 0;
width: {tree.size}px;
height: {tree.size * tree.aspectRatio}px;
opacity: {tree.opacity};
z-index: {tree.zIndex};
transform: translateX(-50%);
"
>
{#if tree.treeType === 'logo'}
<Logo class="w-full h-full" season={$season} animate />
{:else if tree.treeType === 'pine'}
<TreePine class="w-full h-full" season={$season} animate />
{:else if tree.treeType === 'cherry'}
<TreeCherry class="w-full h-full" season={$season} animate />
{:else if tree.treeType === 'aspen'}
<TreeAspen class="w-full h-full" season={$season} animate />
{:else if tree.treeType === 'birch'}
<TreeBirch class="w-full h-full" season={$season} animate />
{/if}
</div>
{/each}svelte
{#each forestTrees as tree (tree.id)}
<div
class="absolute"
style="
left: {tree.x}%;
bottom: 0;
width: {tree.size}px;
height: {tree.size * tree.aspectRatio}px;
opacity: {tree.opacity};
z-index: {tree.zIndex};
transform: translateX(-50%);
"
>
{#if tree.treeType === 'logo'}
<Logo class="w-full h-full" season={$season} animate />
{:else if tree.treeType === 'pine'}
<TreePine class="w-full h-full" season={$season} animate />
{:else if tree.treeType === 'cherry'}
<TreeCherry class="w-full h-full" season={$season} animate />
{:else if tree.treeType === 'aspen'}
<TreeAspen class="w-full h-full" season={$season} animate />
{:else if tree.treeType === 'birch'}
<TreeBirch class="w-full h-full" season={$season} animate />
{/if}
</div>
{/each}Responsive Density
响应式密度
typescript
function calculateDensity(): number {
const width = window.innerWidth;
if (width < 768) return 1; // Mobile: base count
if (width < 1024) return 1.3; // Tablet
if (width < 1440) return 1.8; // Desktop
if (width < 2560) return 2.5; // Large desktop
return 3.5; // Ultrawide
}typescript
function calculateDensity(): number {
const width = window.innerWidth;
if (width < 768) return 1; // 移动端:基础数量
if (width < 1024) return 1.3; // 平板
if (width < 1440) return 1.8; // 桌面
if (width < 2560) return 2.5; // 大尺寸桌面
return 3.5; // 超宽屏
}Nature Components
自然元素组件
Grove has an extensive library of decorative components. Explore with:
bash
undefinedGrove拥有丰富的装饰组件库,可通过以下命令查看:
bash
undefinedTrees
树木组件
ls landing/src/lib/components/trees/
ls landing/src/lib/components/nature/trees/
ls landing/src/lib/components/trees/
ls landing/src/lib/components/nature/trees/
Weather (seasonal particles)
天气(季节粒子效果)
ls landing/src/lib/components/nature/weather/
ls landing/src/lib/components/nature/weather/
Sky (clouds, stars, moon)
天空(云朵、星星、月亮)
ls landing/src/lib/components/nature/sky/
ls landing/src/lib/components/nature/sky/
Botanical (leaves, petals, vines)
植物(叶子、花瓣、藤蔓)
ls landing/src/lib/components/nature/botanical/
ls landing/src/lib/components/nature/botanical/
Ground (flowers, grass, mushrooms)
地面(花朵、草地、蘑菇)
ls landing/src/lib/components/nature/ground/
ls landing/src/lib/components/nature/ground/
Structural (lattice, lanterns, paths)
结构元素(格子、灯笼、小径)
ls landing/src/lib/components/nature/structural/
ls landing/src/lib/components/nature/structural/
Birds (cardinals, robins, bluebirds)
鸟类(红衣主教鸟、知更鸟、蓝鸲)
ls landing/src/lib/components/nature/creatures/
undefinedls landing/src/lib/components/nature/creatures/
undefinedKey Components
核心组件
| Component | Use | Example Props |
|---|---|---|
| Grove tree, seasonal | |
| Evergreen, stays green in autumn | |
| Blossoms in spring, bare in winter | |
| Deciduous, seasonal colors | |
| Decorative sky element | |
| Winter particles | |
| Spring cherry blossoms | |
| Autumn leaves (tied to trees) | |
| Winter birds | |
| Spring birds | |
| Decorative ivy/vines | varies |
| Warm glow points | varies |
| 组件 | 用途 | 示例属性 |
|---|---|---|
| Grove品牌树,支持季节变化 | |
| 常绿树,秋季仍保持绿色 | |
| 春季开花,冬季落叶 | |
| 落叶树,支持季节配色 | |
| 装饰性天空元素 | |
| 冬季粒子效果 | |
| 春季樱花花瓣飘落 | |
| 秋季落叶(与树木关联) | |
| 冬季鸟类 | |
| 春季鸟类 | |
| 装饰性常春藤/藤蔓 | 多种属性 |
| 暖光装饰点 | 多种属性 |
Birds by Season
季节鸟类组件使用
svelte
<!-- Winter birds -->
{#if isWinter}
<Cardinal facing="right" style="..." />
<Chickadee facing="left" style="..." />
{/if}
<!-- Spring birds -->
{#if isSpring}
<Robin facing="right" style="..." />
<Bluebird facing="left" style="..." />
{/if}svelte
<!-- 冬季鸟类 -->
{#if isWinter}
<Cardinal facing="right" style="..." />
<Chickadee facing="left" style="..." />
{/if}
<!-- 春季鸟类 -->
{#if isSpring}
<Robin facing="right" style="..." />
<Bluebird facing="left" style="..." />
{/if}Midnight Bloom Palette
午夜绽放调色板
For dreamy, far-future, mystical content. The tea shop that exists at the edge of tomorrow.
typescript
import { midnightBloom } from '$lib/components/nature/palette';
// Available colors:
midnightBloom.deepPlum // #581c87 - Night sky depth
midnightBloom.purple // #7c3aed - Soft purple glow
midnightBloom.violet // #8b5cf6 - Lighter accent
midnightBloom.amber // #f59e0b - Lantern warmth
midnightBloom.warmCream // #fef3c7 - Tea steam, page glow
midnightBloom.softGold // #fcd34d - Fairy lights适用于梦幻、远景、神秘类内容。就像存在于未来边缘的深夜茶店。
typescript
import { midnightBloom } from '$lib/components/nature/palette';
// 可用颜色:
midnightBloom.deepPlum // #581c87 - 夜空深邃色
midnightBloom.purple // #7c3aed - 柔和紫色光
midnightBloom.violet // #8b5cf6 - 浅色强调
midnightBloom.amber // #f59e0b - 灯笼暖光
midnightBloom.warmCream // #fef3c7 - 茶蒸汽、页面光晕
midnightBloom.softGold // #fcd34d - fairy lightsMidnight Bloom Styling
午夜绽放风格示例
svelte
<section class="bg-gradient-to-b from-orange-950/50 via-purple-950 to-slate-950">
<!-- Stars -->
<StarCluster count={12} class="absolute top-12 left-[10%]" />
<!-- Moon -->
<Moon phase="waning-crescent" class="absolute top-20 right-[15%] w-16 h-16 opacity-60" />
<!-- Fireflies -->
<Firefly count={8} class="absolute inset-0" />
<!-- Content with purple glass -->
<blockquote class="bg-purple-900/30 backdrop-blur-sm border border-purple-700/30 rounded-lg p-6">
<p class="text-purple-200 italic">Dreamy quote here...</p>
</blockquote>
</section>svelte
<section class="bg-gradient-to-b from-orange-950/50 via-purple-950 to-slate-950">
<!-- 星星 -->
<StarCluster count={12} class="absolute top-12 left-[10%]" />
<!-- 月亮 -->
<Moon phase="waning-crescent" class="absolute top-20 right-[15%] w-16 h-16 opacity-60" />
<!-- 萤火虫 -->
<Firefly count={8} class="absolute inset-0" />
<!-- 带紫色玻璃效果的内容 -->
<blockquote class="bg-purple-900/30 backdrop-blur-sm border border-purple-700/30 rounded-lg p-6">
<p class="text-purple-200 italic">梦幻风格引用...</p>
</blockquote>
</section>Icons: Lucide Only
图标规范:仅使用Lucide
NEVER use emojis. ALWAYS use Lucide icons.
svelte
import { MapPin, Check, Leaf, Trees, Mail } from 'lucide-svelte';
<!-- Good -->
<MapPin class="w-4 h-4" />
<Check class="w-5 h-5 text-green-500" />
<!-- Bad - NEVER do this -->
<!-- ❌ 🌱 📧 ✅ -->绝对禁止使用emoji。必须使用Lucide图标。
svelte
import { MapPin, Check, Leaf, Trees, Mail } from 'lucide-svelte';
<!-- 正确用法 -->
<MapPin class="w-4 h-4" />
<Check class="w-5 h-5 text-green-500" />
<!-- 错误用法 - 绝对禁止 -->
<!-- ❌ 🌱 📧 ✅ -->Standardized Icon Mapping
标准化图标映射
Use these icons consistently across the project:
| Concept | Icon | Notes |
|---|---|---|
| Navigation | ||
| Home | | |
| About | | |
| Vision | | Looking forward |
| Roadmap | | Journey/direction |
| Pricing | | Money/currency |
| Knowledge | | Learning/docs |
| Forest | | Community blogs |
| Blog | | Writing |
| Features | ||
| ||
| Storage | | |
| Theming | | Customization |
| Authentication | | Security |
| Cloud | | Remote/serverless |
| Search | | Code/advanced search |
| Archives | | Backups |
| Upload | | |
| Video | | |
| Comments | | User discussions |
| GitHub | | External links to GitHub |
| States | ||
| Success | | Completed/valid |
| Error | | Failed/close |
| Loading | | With animate-spin |
| Content | ||
| Posts | | Blog posts |
| Tags | | Categorization |
| Growth | | Grove brand, new beginnings |
| Heart | | Love, care |
| External | | Opens new tab |
| Location | | Current position |
| Phases | ||
| Coming Soon | | Something growing |
| Refinement | | Polish, quality |
| The Dream | | Mystical (use sparingly!) |
| Night | | Midnight themes |
| Actions | ||
| Getting Started | | Guidance |
| What's New | | Announcements |
| Next Steps | | Ideas |
项目中请统一使用以下图标:
| 概念 | 图标 | 说明 |
|---|---|---|
| 导航 | ||
| 首页 | | |
| 关于 | | |
| 愿景 | | 展望未来 |
| 路线图 | | 旅程/方向 |
| 定价 | | 货币/支付 |
| 知识库 | | 学习/文档 |
| 森林 | | 社区博客 |
| 博客 | | 写作 |
| 功能 | ||
| 邮件 | | |
| 存储 | | |
| 主题定制 | | 个性化设置 |
| 身份验证 | | 安全 |
| 云服务 | | 远程/无服务器 |
| 搜索 | | 代码/高级搜索 |
| 归档 | | 备份 |
| 上传 | | |
| 视频 | | |
| 评论 | | 用户讨论 |
| GitHub | | 外部GitHub链接 |
| 状态 | ||
| 成功 | | 已完成/有效 |
| 错误 | | 失败/关闭 |
| 加载中 | | 搭配animate-spin动画 |
| 内容 | ||
| 文章 | | 博客文章 |
| 标签 | | 分类 |
| 成长 | | Grove品牌元素,新开始 |
| 喜爱 | | 喜欢/关注 |
| 外部链接 | | 打开新标签页 |
| 位置 | | 当前位置 |
| 阶段 | ||
| 即将推出 | | 成长中 |
| 优化中 | | 打磨、品质提升 |
| 愿景 | | 神秘场景(谨慎使用!) |
| 夜晚 | | 午夜主题 |
| 操作 | ||
| 快速开始 | | 指引 |
| 最新动态 | | 公告 |
| 下一步 | | 想法 |
Icon Mapping Tables in Files
图标映射文件
Create a consistent icon map at the top of each component/page that uses icons:
typescript
// landing/src/lib/utils/icons.ts - Centralized icon registry
import {
Mail, HardDrive, Palette, ShieldCheck, Cloud, SearchCode,
Archive, Upload, MessagesSquare, Github, Check, X, Loader2,
FileText, Tag, Sprout, Heart, ExternalLink, MapPin, // ... etc
} from 'lucide-svelte';
export const featureIcons = {
mail: Mail,
harddrive: HardDrive,
palette: Palette,
shieldcheck: ShieldCheck,
cloud: Cloud,
searchcode: SearchCode,
// ... all mapped icons
} as const;
export const stateIcons = {
success: Check,
error: X,
loading: Loader2,
} as const;Then use in components:
svelte
<script lang="ts">
import { featureIcons } from '$lib/utils/icons';
</script>
{#each features as feature}
<svelte:component this={featureIcons[feature.icon]} class="w-5 h-5" />
{/each}Benefits:
- Single source of truth for all icons
- Prevents undefined icon errors
- Easy to maintain and extend
- Reusable across entire project
在每个使用图标的组件/页面顶部创建统一的图标映射:
typescript
// landing/src/lib/utils/icons.ts - 集中式图标注册表
import {
Mail, HardDrive, Palette, ShieldCheck, Cloud, SearchCode,
Archive, Upload, MessagesSquare, Github, Check, X, Loader2,
FileText, Tag, Sprout, Heart, ExternalLink, MapPin, // ... 其他图标
} from 'lucide-svelte';
export const featureIcons = {
mail: Mail,
harddrive: HardDrive,
palette: Palette,
shieldcheck: ShieldCheck,
cloud: Cloud,
searchcode: SearchCode,
// ... 所有映射图标
} as const;
export const stateIcons = {
success: Check,
error: X,
loading: Loader2,
} as const;然后在组件中使用:
svelte
<script lang="ts">
import { featureIcons } from '$lib/utils/icons';
</script>
{#each features as feature}
<svelte:component this={featureIcons[feature.icon]} class="w-5 h-5" />
{/each}优势:
- 所有图标单一数据源
- 避免未定义图标错误
- 易于维护与扩展
- 全项目可复用
Icon Usage Guidelines
图标使用准则
- Always use icon maps - Never hardcode icon imports in every component
- Avoid overusing Sparkles - Reserve for truly mystical/magical contexts
- Be consistent - Use the same icon for the same concept everywhere
- Semantic meaning - Choose icons that convey meaning, not just decoration
- Export from central utility - Use for all icon sets
landing/src/lib/utils/icons.ts
- 始终使用图标映射 - 切勿在每个组件中硬编码图标导入
- 避免过度使用Sparkles - 仅用于真正神秘/魔幻的场景
- 保持一致性 - 同一概念在所有场景使用相同图标
- 语义化 - 选择能传达含义的图标,而非仅作装饰
- 从公共工具导出 - 所有图标集使用
landing/src/lib/utils/icons.ts
Icon Sizing
图标尺寸规范
svelte
<!-- Inline with text -->
<span class="inline-flex items-center gap-1.5">
<Leaf class="w-4 h-4" /> Feature name
</span>
<!-- Button icon -->
<button class="p-2">
<Menu class="w-5 h-5" />
</button>
<!-- Large decorative -->
<Gem class="w-8 h-8 text-amber-400" />svelte
<!-- 与文本内联 -->
<span class="inline-flex items-center gap-1.5">
<Leaf class="w-4 h-4" /> 功能名称
</span>
<!-- 按钮图标 -->
<button class="p-2">
<Menu class="w-5 h-5" />
</button>
<!-- 大型装饰图标 -->
<Gem class="w-8 h-8 text-amber-400" />Icon Composition (Building Block Pattern)
图标组合(积木式模式)
Philosophy: "The grove doesn't need to be drawn. It just needs to be arranged."
For creating custom logos, illustrations, or decorative elements, compose existing Lucide icons rather than drawing custom SVG from scratch. This ensures visual consistency with the icon system.
设计理念:“森林无需手绘,只需合理排列。”
创建自定义logo、插图或装饰元素时,优先组合现有Lucide图标,而非从头绘制自定义SVG。这可确保与图标系统的视觉一致性。
Why This Pattern?
该模式优势
- Consistency — Icons match the Lucide aesthetic (24x24 grid, 2px strokes, round caps)
- Minimal custom code — Let Lucide do the heavy lifting
- Maintainable — Updating Lucide updates your compositions
- MIT licensed — All paths come from open-source icons
- 一致性 —— 图标匹配Lucide的美学风格(24x24网格、2px描边、圆角端点)
- 减少自定义代码 —— 让Lucide处理复杂部分
- 可维护性 —— Lucide更新时,你的组合图标也会同步更新
- MIT开源许可 —— 所有路径均来自开源图标
How to Extract Lucide Paths
如何提取Lucide图标路径
Lucide icons use a 24×24 viewBox with 2px strokes. Extract paths directly from source:
bash
undefinedLucide图标使用24×24视口与2px描边。直接从源码中提取路径:
bash
undefinedFind icon paths in Lucide source
在Lucide源码中查找图标路径
Look for the <path d="..." /> elements
查找<path d="..." />元素
**Key Lucide icon paths for Grove compositions:**
```typescript
// TreePine - conifer silhouette
const treePine = {
canopy: 'm17 14 3 3.3a1 1 0 0 1-.7 1.7H4.7a1 1 0 0 1-.7-1.7L7 14h-.3a1 1 0 0 1-.7-1.7L9 9h-.2A1 1 0 0 1 8 7.3L12 3l4 4.3a1 1 0 0 1-.8 1.7H15l3 3.3a1 1 0 0 1-.7 1.7H17Z',
trunk: 'M12 22v-3'
};
// TreeDeciduous - deciduous/round tree
const treeDeciduous = {
canopy: 'M8 19a4 4 0 0 1-2.24-7.32A3.5 3.5 0 0 1 9 6.03V6a3 3 0 1 1 6 0v.04a3.5 3.5 0 0 1 3.24 5.65A4 4 0 0 1 16 19Z',
trunk: 'M12 19v3'
};
// Moon - crescent moon
const moon = 'M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401';
// Flame - campfire/hearth
const flame = 'M12 3q1 4 4 6.5t3 5.5a1 1 0 0 1-14 0 5 5 0 0 1 1-3 1 1 0 0 0 5 0c0-2-1.5-3-1.5-5q0-2 2.5-4';
**Grove组合常用的Lucide图标路径:**
```typescript
// TreePine - 针叶树轮廓
const treePine = {
canopy: 'm17 14 3 3.3a1 1 0 0 1-.7 1.7H4.7a1 1 0 0 1-.7-1.7L7 14h-.3a1 1 0 0 1-.7-1.7L9 9h-.2A1 1 0 0 1 8 7.3L12 3l4 4.3a1 1 0 0 1-.8 1.7H15l3 3.3a1 1 0 0 1-.7 1.7H17Z',
trunk: 'M12 22v-3'
};
// TreeDeciduous - 落叶树/圆形树冠
const treeDeciduous = {
canopy: 'M8 19a4 4 0 0 1-2.24-7.32A3.5 3.5 0 0 1 9 6.03V6a3 3 0 1 1 6 0v.04a3.5 3.5 0 0 1 3.24 5.65A4 4 0 0 1 16 19Z',
trunk: 'M12 19v3'
};
// Moon - 新月
const moon = 'M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401';
// Flame - 篝火/壁炉
const flame = 'M12 3q1 4 4 6.5t3 5.5a1 1 0 0 1-14 0 5 5 0 0 1 1-3 1 1 0 0 0 5 0c0-2-1.5-3-1.5-5q0-2 2.5-4';Composing with SVG Transforms
使用SVG变换进行组合
Use to position, scale, and rotate icons:
<g transform="...">svelte
<svg viewBox="0 0 48 32" fill="none">
<!-- Left tree (larger, foreground) -->
<g transform="translate(2, 4) scale(0.85)"
stroke={color} stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d={treePine.canopy} />
<path d={treePine.trunk} />
</g>
<!-- Right tree (smaller, background, tilted) -->
<g transform="translate(20, 8) scale(0.65) rotate(-5, 12, 12)"
stroke={color} stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
opacity="0.7">
<path d={treePine.canopy} />
<path d={treePine.trunk} />
</g>
<!-- Add simple custom elements sparingly -->
<circle cx="30" cy="10" r="1.5" fill={glowColor} opacity="0.8" /> <!-- firefly -->
<path d="M2 28h44" stroke={color} stroke-width="1.5" opacity="0.3" /> <!-- ground -->
</svg>使用来定位、缩放和旋转图标:
<g transform="...">svelte
<svg viewBox="0 0 48 32" fill="none">
<!-- 左侧树木(较大,前景) -->
<g transform="translate(2, 4) scale(0.85)"
stroke={color} stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d={treePine.canopy} />
<path d={treePine.trunk} />
</g>
<!-- 右侧树木(较小,背景,倾斜) -->
<g transform="translate(20, 8) scale(0.65) rotate(-5, 12, 12)"
stroke={color} stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
opacity="0.7">
<path d={treePine.canopy} />
<path d={treePine.trunk} />
</g>
<!-- 谨慎添加简单自定义元素 -->
<circle cx="30" cy="10" r="1.5" fill={glowColor} opacity="0.8" /> <!-- 萤火虫 -->
<path d="M2 28h44" stroke={color} stroke-width="1.5" opacity="0.3" /> <!-- 地面 -->
</svg>Transform Cheatsheet
变换速查表
| Transform | Effect | Example |
|---|---|---|
| Move origin | |
| Uniform size | |
| Rotation around point | |
| Combined | Chain transforms | |
| 变换 | 效果 | 示例 |
|---|---|---|
| 移动原点 | |
| 统一缩放 | |
| 围绕指定点旋转 | |
| 组合变换 | 链式变换 | |
Example: Grove Logo Compositions
示例:Grove Logo组合
See for real implementations:
/landing/src/lib/components/logo-concepts/| Logo | Composition |
|---|---|
| TreePine + TreeDeciduous + glowing circles |
| Two trees angled toward center Flame |
| Two TreePines + Moon + star circles |
| Two TreePines forming archway + Moon |
| TreePines + snow line accents |
实际实现请查看:
/landing/src/lib/components/logo-concepts/| Logo | 组合方式 |
|---|---|
| TreePine + TreeDeciduous + 发光圆点 |
| 两棵树朝向中心Flame |
| 两棵TreePines + Moon + 星星圆点 |
| 两棵TreePines形成拱门 + Moon |
| TreePines + 雪线装饰 |
Guidelines
组合准则
- Use Lucide paths as primary structure — Trees, moon, flame, etc.
- Custom SVG only for simple primitives — circles (fireflies), lines (ground, snow)
- Maintain Lucide styling — 2px strokes, round caps/joins, consistent opacity
- Create depth with opacity/scale — Larger = foreground (opacity 0.9), smaller = background (0.5-0.7)
- Keep viewBox aspect ratios reasonable — 40×32 or 48×32 for horizontal compositions
- 以Lucide路径为核心结构 —— 树木、月亮、火焰等
- 仅为简单基础图形添加自定义SVG —— 圆形(萤火虫)、线条(地面、雪)
- 保持Lucide样式 —— 2px描边、圆角端点/连接、统一透明度
- 用透明度/缩放营造层次感 —— 大图标=前景(透明度0.9),小图标=背景(0.5-0.7)
- 保持合理的视口宽高比 —— 横向组合使用40×32或48×32
When to Use
适用场景
- Logos & branding — Compose icons into unique marks
- Illustrations — Scene building (forest, sky, etc.)
- Custom icons — When Lucide doesn't have exactly what you need
- Seasonal variations — Same composition, different elements (snow, blossoms)
- Logo与品牌标识 —— 将图标组合成独特标志
- 插图 —— 构建场景(森林、天空等)
- 自定义图标 —— 当Lucide没有完全匹配的图标时
- 季节变体 —— 同一组合,不同元素(雪、花)
Mobile Considerations
移动端适配注意事项
Overflow Menu Pattern
溢出菜单模式
Desktop navigation items that don't fit should go to a mobile sheet menu:
svelte
<!-- Mobile menu button (visible md:hidden) -->
<button onclick={() => mobileMenuOpen = true} class="md:hidden p-2">
<Menu class="w-5 h-5" />
</button>
<!-- Sheet menu -->
<MobileMenu bind:open={mobileMenuOpen} onClose={() => mobileMenuOpen = false} />桌面端无法容纳的导航项应放入移动端侧边菜单:
svelte
<!-- 移动端菜单按钮(仅在md:hidden时显示) -->
<button onclick={() => mobileMenuOpen = true} class="md:hidden p-2">
<Menu class="w-5 h-5" />
</button>
<!-- 侧边菜单 -->
<MobileMenu bind:open={mobileMenuOpen} onClose={() => mobileMenuOpen = false} />Decorative Elements on Mobile
移动端装饰元素处理
| Element | Mobile Treatment |
|---|---|
| Trees | Reduce count, simplify (density multiplier = 1) |
| Particles | Reduce count (40→20 snowflakes) |
| Clouds | Hide some, keep 2-3 |
| Complex animations | Reduce or disable |
| Touch targets | Minimum 44x44px |
| 元素 | 移动端处理方式 |
|---|---|
| 树木 | 减少数量,简化样式(密度系数=1) |
| 粒子效果 | 减少数量(如雪花从40→20) |
| 云朵 | 隐藏部分,仅保留2-3个 |
| 复杂动画 | 减少或禁用 |
| 触摸目标 | 最小尺寸44x44px |
Performance Guidelines
性能优化准则
svelte
<!-- Reduce particle counts on mobile -->
<SnowfallLayer count={isLargeScreen ? 100 : 40} ... />
<!-- Skip complex effects for reduced-motion -->
{#if !prefersReducedMotion}
<FallingLeavesLayer ... />
{/if}svelte
<!-- 移动端减少粒子数量 -->
<SnowfallLayer count={isLargeScreen ? 100 : 40} ... />
<!-- 为减少动画偏好用户跳过复杂效果 -->
{#if !prefersReducedMotion}
<FallingLeavesLayer ... />
{/if}When to Use
适用场景
| Pattern | Good For |
|---|---|
| Glassmorphism | Text over backgrounds, navbars, cards, modals |
| Randomized forests | Story pages, about pages, visual sections |
| Seasonal themes | Roadmaps, timelines, emotional storytelling |
| Midnight Bloom | Future features, dreams, mystical content |
| Weather particles | Hero sections, transitions between seasons |
| Birds | Adding life to forest scenes, seasonal indicators |
| 模式 | 适用场景 |
|---|---|
| 玻璃态 | 复杂背景上的文本、导航栏、卡片、模态框 |
| 随机森林 | 故事页面、关于页面、视觉展示区域 |
| 季节主题 | 路线图、时间线、情感化叙事 |
| 午夜绽放 | 未来功能、愿景、神秘内容 |
| 天气粒子 | 首页Hero区域、季节过渡 |
| 鸟类组件 | 为森林场景增添生机、季节指示器 |
When NOT to Use
不适用场景
| Pattern | Avoid When |
|---|---|
| Heavy decoration | Data-dense pages, admin interfaces, forms |
| Particle effects | Performance-critical pages, accessibility concerns |
| Seasonal colors | Brand-critical contexts needing consistent colors |
| Multiple glass layers | Can cause blur performance issues |
| Randomization | Content that needs to match between sessions |
| Complex forests | Mobile-first pages, simple informational content |
| 模式 | 避免场景 |
|---|---|
| 重度装饰 | 数据密集页面、管理后台、表单 |
| 粒子效果 | 性能敏感页面、无障碍需求场景 |
| 季节配色 | 品牌关键场景(需保持配色一致性) |
| 多层玻璃效果 | 可能导致模糊性能问题 |
| 随机化效果 | 需要跨会话保持一致的内容 |
| 复杂森林 | 移动端优先页面、简单信息类内容 |
Reference Pages
参考页面
Study these for implementation patterns:
- — Full randomized forest with all seasons
/forest - — Seasonal sections, progressive decoration, midnight bloom
/roadmap - — Narrative page with glass callouts
/vision
以下页面可作为实现参考:
- —— 完整随机森林,支持所有季节
/forest - —— 季节分块、渐进式装饰、午夜绽放风格
/roadmap - —— 带玻璃态提示框的叙事页面
/vision
OG Images (Social Previews)
OG图片(社交预览)
Grove uses dynamic OG images for social media previews (Discord, Twitter, iMessage, etc.).
Grove为社交媒体预览(Discord、Twitter、iMessage等)使用动态OG图片。
Architecture
架构
OG images are generated by a separate Cloudflare Worker at due to WASM bundling limitations with SvelteKit + Cloudflare Pages.
og.grove.placegrove.place/api/og?title=X
↓ 302 redirect
og.grove.place/?title=X
↓ workers-og
PNG image (1200×630)由于SvelteKit + Cloudflare Pages的WASM打包限制,OG图片由独立的Cloudflare Worker生成,地址为。
og.grove.placegrove.place/api/og?title=X
↓ 302重定向
og.grove.place/?title=X
↓ workers-og生成
PNG图片(1200×630)API
API参数
GET https://og.grove.place/?title=X&subtitle=Y&accent=HEX| Param | Default | Description |
|---|---|---|
| "Grove" | Main title (max 100 chars) |
| "A place to Be." | Subtitle (max 200 chars) |
| "16a34a" | Hex color without # (forest green) |
GET https://og.grove.place/?title=X&subtitle=Y&accent=HEX| 参数 | 默认值 | 说明 |
|---|---|---|
| "Grove" | 主标题(最大100字符) |
| "A place to Be." | 副标题(最大200字符) |
| "16a34a" | 十六进制颜色(无需#,默认森林绿) |
Adding OG to New Pages
为新页面添加OG图片
Use the SEO component which handles OG meta tags:
svelte
<script>
import SEO from '$lib/components/SEO.svelte';
</script>
<SEO
title="Page Title"
description="Page description for search engines"
ogImage="/api/og?title=Page%20Title&subtitle=Custom%20subtitle"
/>使用SEO组件处理OG元标签:
svelte
<script>
import SEO from '$lib/components/SEO.svelte';
</script>
<SEO
title="页面标题"
description="页面搜索引擎描述"
ogImage="/api/og?title=Page%20Title&subtitle=Custom%20subtitle"
/>Files
相关文件
- — Standalone Worker (uses
packages/og-worker/)workers-og - — Proxy to og.grove.place
landing/src/routes/api/og/+server.ts - — Meta tag management
landing/src/lib/components/SEO.svelte
- —— 独立Worker(基于
packages/og-worker/)workers-og - —— 代理到og.grove.place
landing/src/routes/api/og/+server.ts - —— 元标签管理
landing/src/lib/components/SEO.svelte
Integration with Other Skills
与其他技能的集成
When writing text for Grove UI (tooltips, buttons, onboarding, error messages), invoke the grove-documentation skill first. The voice should match the visuals.
Typical flow:
- Design the UI component/page
- Activate for any user-facing text
grove-documentation - Write content following Grove voice principles
- Return to visual implementation
当为Grove UI编写文本(工具提示、按钮、引导流程、错误提示)时,请先调用grove-documentation技能。文本风格应与视觉设计保持一致。
典型流程:
- 设计UI组件/页面
- 为所有面向用户的文本激活技能
grove-documentation - 遵循Grove的语言风格原则编写内容
- 返回视觉实现
Quick Checklist
快速检查清单
Before shipping a Grove page:
- Glass effects used for text readability over busy backgrounds?
- Lucide icons, no emojis?
- Mobile overflow menu for navigation items?
- Decorative elements respect ?
prefers-reduced-motion - Touch targets at least 44x44px?
- Seasonal colors match the page's emotional tone?
- Trees randomized with proper spacing (8% minimum gap)?
- Dark mode supported with appropriate glass variants?
- User-facing text follows Grove voice (see )?
grove-documentation - Grove terminology uses GroveTerm components (not hardcoded)?
- Data-driven content uses syntax with GroveText?
[[term]]
Grove页面上线前请检查:
- 玻璃效果是否用于复杂背景上的文本可读性提升?
- 是否仅使用Lucide图标,未使用emoji?
- 导航项是否使用移动端溢出菜单?
- 装饰元素是否尊重设置?
prefers-reduced-motion - 触摸目标尺寸是否至少为44x44px?
- 季节配色是否匹配页面的情感基调?
- 树木随机生成时是否保持了最小8%的间距?
- 暗色模式是否支持对应的玻璃态变体?
- 面向用户的文本是否遵循Grove语言风格(查看)?
grove-documentation - Grove术语是否使用GroveTerm组件(而非硬编码)?
- 数据驱动型内容是否使用语法搭配GroveText组件?
[[term]]