grove-ui-design

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Grove 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';
ComponentUse CaseBehavior
GroveTerm
Interactive terms with popup definitionsColored underline when ON, click for popup. Shows standard term when OFF.
GroveSwap
Silent text replacementReactively swaps text. No underline, no interaction.
GroveText
Parse
[[term]]
syntax in data strings
Renders
[[bloom|posts]]
as interactive GroveTerm components.
GroveSwapText
Parse
[[term]]
syntax silently
Same parsing, silent swaps (no popups).
GroveIntro
"We call it X" page bannersStandardized 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
    ,
    /garden
    ) regardless of display mode.
  • Brand terms (Grove) and subscription tiers (Seedling/Sapling/Oak/Evergreen) always show as-is.
  • Use
    [[term]]
    syntax
    for data-driven content (FAQ items, pricing fineprint, feature lists).
  • Grove Mode store:
    groveModeStore
    from
    @autumnsgrove/groveengine/ui/stores
    . Toggle lives in the footer.
See
docs/grove-user-identity.md
for the full identity language documentation and
packages/engine/src/lib/ui/components/ui/groveterm/
for component source.

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';
组件使用场景行为
GroveTerm
带弹出式定义的交互式术语开启模式时显示彩色下划线,点击可查看弹窗;关闭模式时显示标准术语。
GroveSwap
静默文本替换响应式替换文本,无下划线,无交互。
GroveText
解析数据字符串中的
[[term]]
语法
[[bloom|posts]]
渲染为交互式GroveTerm组件。
GroveSwapText
静默解析
[[term]]
语法
解析规则相同,但仅做静默替换(无弹窗)。
GroveIntro
页面标题下方的“我们称之为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)始终保持原样显示。
  • 数据驱动型内容使用
    [[term]]
    语法搭配GroveText组件。
  • Grove模式状态管理:从
    @autumnsgrove/groveengine/ui/stores
    导入
    groveModeStore
    ,开关位于页脚。
完整的身份语言文档请查看
docs/grove-user-identity.md
,组件源码请查看
packages/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

玻璃态变体

VariantUse CaseLight ModeDark Mode
surface
Headers, navbars95% white95% slate
tint
Text over backgrounds60% white50% slate
card
Content cards80% white70% slate
accent
Callouts, highlights30% accent20% accent
overlay
Modal backdrops50% black60% black
muted
Subtle backgrounds40% white30% slate
变体使用场景亮色模式暗色模式
surface
页眉、导航栏95% 白色95% 石板灰
tint
背景上的文本容器60% 白色50% 石板灰
card
内容卡片80% 白色70% 石板灰
accent
提示框、高亮区域30% 强调色20% 强调色
overlay
模态框背景50% 黑色60% 黑色
muted
微妙背景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:
@autumnsgrove/groveengine/ui/nature
or
$lib/components/nature/palette
导入路径:
@autumnsgrove/groveengine/ui/nature
$lib/components/nature/palette

Core 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.birchWhite
typescript
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.birchWhite

Spring 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   // #fce7f3
typescript
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   // #fce7f3

Unified Flowers Palette (NEW!)

统一花卉调色板(新增!)

The
flowers
namespace consolidates all flower colors into one organized structure:
typescript
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   // #fce7f3
Use
flowers.wildflower
instead of
accents.flower
— the accents version is deprecated.
flowers
命名空间将所有花卉颜色整合到一个结构化的集合中:
typescript
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
请使用
flowers.wildflower
替代
accents.flower
—— accents版本已被废弃。

Autumn & 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.hillFront
typescript
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.hillFront

Accent 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 instead
typescript
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 instead
typescript
// 以下别名仍可使用,但将在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

季节氛围总结

SeasonPrimary ColorsMood
Spring
springFoliage
,
cherryBlossomsPeak
,
wildflowers
Renewal, hope
Summer
greens
,
cherryBlossoms
Growth, warmth
Autumn
autumn
,
autumnReds
Harvest, reflection
Winter
winter
(frost, snow, frosted pines)
Rest, stillness
季节主色调氛围
春季
springFoliage
,
cherryBlossomsPeak
,
wildflowers
新生、希望
夏季
greens
,
cherryBlossoms
成长、温暖
秋季
autumn
,
autumnReds
收获、沉思
冬季
winter
(霜、雪、霜覆盖松树)
休憩、宁静

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
undefined
Grove拥有丰富的装饰组件库,可通过以下命令查看:
bash
undefined

Trees

树木组件

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/
undefined
ls landing/src/lib/components/nature/creatures/
undefined

Key Components

核心组件

ComponentUseExample Props
Logo
Grove tree, seasonal
season
,
animate
,
breathing
TreePine
Evergreen, stays green in autumn
season
,
animate
TreeCherry
Blossoms in spring, bare in winter
season
,
animate
TreeAspen
/
TreeBirch
Deciduous, seasonal colors
season
,
animate
Cloud
Decorative sky element
variant
,
animate
,
speed
,
direction
SnowfallLayer
Winter particles
count
,
opacity
,
spawnDelay
FallingPetalsLayer
Spring cherry blossoms
count
,
opacity
,
fallDuration
FallingLeavesLayer
Autumn leaves (tied to trees)
trees
,
season
Cardinal
/
Chickadee
Winter birds
facing
Robin
/
Bluebird
Spring birds
facing
Vine
Decorative ivy/vinesvaries
Lantern
Warm glow pointsvaries
组件用途示例属性
Logo
Grove品牌树,支持季节变化
season
,
animate
,
breathing
TreePine
常绿树,秋季仍保持绿色
season
,
animate
TreeCherry
春季开花,冬季落叶
season
,
animate
TreeAspen
/
TreeBirch
落叶树,支持季节配色
season
,
animate
Cloud
装饰性天空元素
variant
,
animate
,
speed
,
direction
SnowfallLayer
冬季粒子效果
count
,
opacity
,
spawnDelay
FallingPetalsLayer
春季樱花花瓣飘落
count
,
opacity
,
fallDuration
FallingLeavesLayer
秋季落叶(与树木关联)
trees
,
season
Cardinal
/
Chickadee
冬季鸟类
facing
Robin
/
Bluebird
春季鸟类
facing
Vine
装饰性常春藤/藤蔓多种属性
Lantern
暖光装饰点多种属性

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 lights

Midnight 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:
ConceptIconNotes
Navigation
Home
Home
About
Info
Vision
Telescope
Looking forward
Roadmap
Map
Journey/direction
Pricing
HandCoins
Money/currency
Knowledge
BookOpen
Learning/docs
Forest
Trees
Community blogs
Blog
PenLine
Writing
Features
Email
Mail
Storage
HardDrive
Theming
Palette
Customization
Authentication
ShieldCheck
Security
Cloud
Cloud
Remote/serverless
Search
SearchCode
Code/advanced search
Archives
Archive
Backups
Upload
Upload
Video
Video
Comments
MessagesSquare
User discussions
GitHub
Github
External links to GitHub
States
Success
Check
Completed/valid
Error
X
Failed/close
Loading
Loader2
With animate-spin
Content
Posts
FileText
Blog posts
Tags
Tag
Categorization
Growth
Sprout
Grove brand, new beginnings
Heart
Heart
Love, care
External
ExternalLink
Opens new tab
Location
MapPin
Current position
Phases
Coming Soon
Seedling
Something growing
Refinement
Gem
Polish, quality
The Dream
Sparkles
Mystical (use sparingly!)
Night
Star
Midnight themes
Actions
Getting Started
Compass
Guidance
What's New
Megaphone
Announcements
Next Steps
Lightbulb
Ideas
项目中请统一使用以下图标:
概念图标说明
导航
首页
Home
关于
Info
愿景
Telescope
展望未来
路线图
Map
旅程/方向
定价
HandCoins
货币/支付
知识库
BookOpen
学习/文档
森林
Trees
社区博客
博客
PenLine
写作
功能
邮件
Mail
存储
HardDrive
主题定制
Palette
个性化设置
身份验证
ShieldCheck
安全
云服务
Cloud
远程/无服务器
搜索
SearchCode
代码/高级搜索
归档
Archive
备份
上传
Upload
视频
Video
评论
MessagesSquare
用户讨论
GitHub
Github
外部GitHub链接
状态
成功
Check
已完成/有效
错误
X
失败/关闭
加载中
Loader2
搭配animate-spin动画
内容
文章
FileText
博客文章
标签
Tag
分类
成长
Sprout
Grove品牌元素,新开始
喜爱
Heart
喜欢/关注
外部链接
ExternalLink
打开新标签页
位置
MapPin
当前位置
阶段
即将推出
Seedling
成长中
优化中
Gem
打磨、品质提升
愿景
Sparkles
神秘场景(谨慎使用!)
夜晚
Star
午夜主题
操作
快速开始
Compass
指引
最新动态
Megaphone
公告
下一步
Lightbulb
想法

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

图标使用准则

  1. Always use icon maps - Never hardcode icon imports in every component
  2. Avoid overusing Sparkles - Reserve for truly mystical/magical contexts
  3. Be consistent - Use the same icon for the same concept everywhere
  4. Semantic meaning - Choose icons that convey meaning, not just decoration
  5. Export from central utility - Use
    landing/src/lib/utils/icons.ts
    for all icon sets
  1. 始终使用图标映射 - 切勿在每个组件中硬编码图标导入
  2. 避免过度使用Sparkles - 仅用于真正神秘/魔幻的场景
  3. 保持一致性 - 同一概念在所有场景使用相同图标
  4. 语义化 - 选择能传达含义的图标,而非仅作装饰
  5. 从公共工具导出 - 所有图标集使用
    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
undefined
Lucide图标使用24×24视口与2px描边。直接从源码中提取路径:
bash
undefined

Find 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
<g transform="...">
to position, scale, and rotate icons:
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

变换速查表

TransformEffectExample
translate(x, y)
Move origin
translate(20, 8)
moves icon right 20, down 8
scale(s)
Uniform size
scale(0.65)
makes icon 65% size
rotate(deg, cx, cy)
Rotation around point
rotate(-5, 12, 12)
tilts 5° around center
CombinedChain transforms
translate(20, 8) scale(0.65) rotate(-5, 12, 12)
变换效果示例
translate(x, y)
移动原点
translate(20, 8)
将图标右移20,下移8
scale(s)
统一缩放
scale(0.65)
将图标缩小至65%
rotate(deg, cx, cy)
围绕指定点旋转
rotate(-5, 12, 12)
围绕中心旋转-5°
组合变换链式变换
translate(20, 8) scale(0.65) rotate(-5, 12, 12)

Example: Grove Logo Compositions

示例:Grove Logo组合

See
/landing/src/lib/components/logo-concepts/
for real implementations:
LogoComposition
LogoFireflyForest
TreePine + TreeDeciduous + glowing circles
LogoGatheringHearth
Two trees angled toward center Flame
LogoStarlightPines
Two TreePines + Moon + star circles
LogoShelter
Two TreePines forming archway + Moon
LogoWinterGrove
TreePines + snow line accents
实际实现请查看
/landing/src/lib/components/logo-concepts/
Logo组合方式
LogoFireflyForest
TreePine + TreeDeciduous + 发光圆点
LogoGatheringHearth
两棵树朝向中心Flame
LogoStarlightPines
两棵TreePines + Moon + 星星圆点
LogoShelter
两棵TreePines形成拱门 + Moon
LogoWinterGrove
TreePines + 雪线装饰

Guidelines

组合准则

  1. Use Lucide paths as primary structure — Trees, moon, flame, etc.
  2. Custom SVG only for simple primitives — circles (fireflies), lines (ground, snow)
  3. Maintain Lucide styling — 2px strokes, round caps/joins, consistent opacity
  4. Create depth with opacity/scale — Larger = foreground (opacity 0.9), smaller = background (0.5-0.7)
  5. Keep viewBox aspect ratios reasonable — 40×32 or 48×32 for horizontal compositions
  1. 以Lucide路径为核心结构 —— 树木、月亮、火焰等
  2. 仅为简单基础图形添加自定义SVG —— 圆形(萤火虫)、线条(地面、雪)
  3. 保持Lucide样式 —— 2px描边、圆角端点/连接、统一透明度
  4. 用透明度/缩放营造层次感 —— 大图标=前景(透明度0.9),小图标=背景(0.5-0.7)
  5. 保持合理的视口宽高比 —— 横向组合使用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

移动端装饰元素处理

ElementMobile Treatment
TreesReduce count, simplify (density multiplier = 1)
ParticlesReduce count (40→20 snowflakes)
CloudsHide some, keep 2-3
Complex animationsReduce or disable
Touch targetsMinimum 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

适用场景

PatternGood For
GlassmorphismText over backgrounds, navbars, cards, modals
Randomized forestsStory pages, about pages, visual sections
Seasonal themesRoadmaps, timelines, emotional storytelling
Midnight BloomFuture features, dreams, mystical content
Weather particlesHero sections, transitions between seasons
BirdsAdding life to forest scenes, seasonal indicators
模式适用场景
玻璃态复杂背景上的文本、导航栏、卡片、模态框
随机森林故事页面、关于页面、视觉展示区域
季节主题路线图、时间线、情感化叙事
午夜绽放未来功能、愿景、神秘内容
天气粒子首页Hero区域、季节过渡
鸟类组件为森林场景增添生机、季节指示器

When NOT to Use

不适用场景

PatternAvoid When
Heavy decorationData-dense pages, admin interfaces, forms
Particle effectsPerformance-critical pages, accessibility concerns
Seasonal colorsBrand-critical contexts needing consistent colors
Multiple glass layersCan cause blur performance issues
RandomizationContent that needs to match between sessions
Complex forestsMobile-first pages, simple informational content

模式避免场景
重度装饰数据密集页面、管理后台、表单
粒子效果性能敏感页面、无障碍需求场景
季节配色品牌关键场景(需保持配色一致性)
多层玻璃效果可能导致模糊性能问题
随机化效果需要跨会话保持一致的内容
复杂森林移动端优先页面、简单信息类内容

Reference Pages

参考页面

Study these for implementation patterns:
  • /forest
    — Full randomized forest with all seasons
  • /roadmap
    — Seasonal sections, progressive decoration, midnight bloom
  • /vision
    — Narrative page with glass callouts

以下页面可作为实现参考:
  • /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
og.grove.place
due to WASM bundling limitations with SvelteKit + Cloudflare Pages.
grove.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.place
grove.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
ParamDefaultDescription
title
"Grove"Main title (max 100 chars)
subtitle
"A place to Be."Subtitle (max 200 chars)
accent
"16a34a"Hex color without # (forest green)
GET https://og.grove.place/?title=X&subtitle=Y&accent=HEX
参数默认值说明
title
"Grove"主标题(最大100字符)
subtitle
"A place to Be."副标题(最大200字符)
accent
"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

相关文件

  • packages/og-worker/
    — Standalone Worker (uses
    workers-og
    )
  • landing/src/routes/api/og/+server.ts
    — Proxy to og.grove.place
  • landing/src/lib/components/SEO.svelte
    — Meta tag management

  • packages/og-worker/
    —— 独立Worker(基于
    workers-og
  • landing/src/routes/api/og/+server.ts
    —— 代理到og.grove.place
  • 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:
  1. Design the UI component/page
  2. Activate
    grove-documentation
    for any user-facing text
  3. Write content following Grove voice principles
  4. Return to visual implementation

当为Grove UI编写文本(工具提示、按钮、引导流程、错误提示)时,请先调用grove-documentation技能。文本风格应与视觉设计保持一致。
典型流程:
  1. 设计UI组件/页面
  2. 为所有面向用户的文本激活
    grove-documentation
    技能
  3. 遵循Grove的语言风格原则编写内容
  4. 返回视觉实现

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
    [[term]]
    syntax with GroveText?
Grove页面上线前请检查:
  • 玻璃效果是否用于复杂背景上的文本可读性提升?
  • 是否仅使用Lucide图标,未使用emoji?
  • 导航项是否使用移动端溢出菜单?
  • 装饰元素是否尊重
    prefers-reduced-motion
    设置?
  • 触摸目标尺寸是否至少为44x44px?
  • 季节配色是否匹配页面的情感基调?
  • 树木随机生成时是否保持了最小8%的间距?
  • 暗色模式是否支持对应的玻璃态变体?
  • 面向用户的文本是否遵循Grove语言风格(查看
    grove-documentation
    )?
  • Grove术语是否使用GroveTerm组件(而非硬编码)?
  • 数据驱动型内容是否使用
    [[term]]
    语法搭配GroveText组件?