Skip to content

Commit e7c86fe

Browse files
committed
v1.5.1: design polish for popover + Preferences ("crafted Mac utility")
Both surfaces now share a small design system (Sources/WeChatMulti/ DesignSystem.swift): - Brand color tokens: jade, jadeDeep, jadeTint, hoverTint, badgeRed — one source of truth, used by both surfaces. - Motion tokens: hover (140ms easeOut), state (220ms easeInOut), entry (spring 0.42/0.86). Mac-feel timings — responsive, not floaty. - SectionLabel: tracked uppercase header that signals "crafted utility" without shouting. - SettingsCard: subtle elevated container with 0.5pt hairline border using the system control-background color (adapts dark/light). - JadeButtonStyle: themed primary button (available for future use). PreferencesView redesigned: - Hero card with app icon, name, version pill, tagline, and a layered jade-tinted gradient background (linear + radial wash anchored to the icon). Drop shadow under the icon picks up jadeDeep. - Three SettingsCards: Startup, WeChat Source, Clones. Each has a tracked uppercase header label plus tightly-spaced content. - WeChat path now rendered in a subtle monospace panel with a shippingbox glyph and a jade version pill at the row's right edge. - Clone count in a jade monospace pill mirrors the Source version pill. - Sections fade + offset in with staggered spring delays on appear. - Footer: jade-colored repo link + "Crafted for macOS" microcopy. MenuPanelView polished: - Account-count chip in a jade-tinted capsule with monospace digits. - Subtitle ("running" / "not running") in monospace; jadeDeep when running, secondary when stopped. - Status dots gain a glow ring + gradient fill + tiny white speckle highlight for depth (animates on state change with state token). - Hover state on rows uses a left-to-right jade gradient + 0.5pt jade border instead of flat opacity — adds visual interest without noise. - Hover transitions animated through the hover token. - Stale-clone prompt redesigned: orange iconography in a circular background, two-line label, trailing arrow.clockwise icon. - Footer items gain SF Symbol leading icons (plus.circle.fill jade-tinted for "Add account", slider.horizontal.3 for Preferences, power for Quit) plus monospace shortcuts that brighten on hover. Bumped to v1.5.1 / build 10.
1 parent 7ff5622 commit e7c86fe

5 files changed

Lines changed: 538 additions & 185 deletions

File tree

Resources/Info.plist

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121
<key>CFBundlePackageType</key>
2222
<string>APPL</string>
2323
<key>CFBundleShortVersionString</key>
24-
<string>1.5.0</string>
24+
<string>1.5.1</string>
2525
<key>CFBundleVersion</key>
26-
<string>9</string>
26+
<string>10</string>
2727
<key>LSMinimumSystemVersion</key>
2828
<string>13.0</string>
2929
<key>LSUIElement</key>
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import SwiftUI
2+
3+
/// Shared design tokens — colors, typography, motion — used by the popover
4+
/// and the Preferences window so both surfaces feel like one app.
5+
///
6+
/// The aesthetic direction is "crafted Mac utility" (Linear / Things 3 / Tot
7+
/// territory): restrained native-feeling layout with the jade brand color
8+
/// surfacing in the moments where it matters — toggles, links, active state,
9+
/// success indicators — instead of flooding every surface with green.
10+
enum Brand {
11+
// MARK: - Color
12+
13+
/// Primary brand jade (lighter top of the icon gradient).
14+
static let jade = Color(red: 0x1F/255, green: 0xC5/255, blue: 0x6B/255)
15+
/// Darker brand jade (bottom of the icon gradient). Used for hover-deep
16+
/// states and the wordmark in the design's wordmark lockup.
17+
static let jadeDeep = Color(red: 0x07/255, green: 0xA0/255, blue: 0x50/255)
18+
/// Highlight tint for active rows — semantically "this is selected".
19+
static let jadeTint = Color(red: 0x1F/255, green: 0xC5/255, blue: 0x6B/255).opacity(0.14)
20+
/// Stronger hover tint for buttons that aren't account rows.
21+
static let hoverTint = Color.primary.opacity(0.06)
22+
/// Accent red from the design's notification badge — used only for
23+
/// destructive actions and overdue warnings.
24+
static let badgeRed = Color(red: 0xFA/255, green: 0x3E/255, blue: 0x3E/255)
25+
}
26+
27+
/// Motion constants — keep durations tight so the UI feels responsive, not
28+
/// floaty. Mac users expect 120–200ms transitions.
29+
enum Motion {
30+
static let hover = Animation.easeOut(duration: 0.14)
31+
static let state = Animation.easeInOut(duration: 0.22)
32+
static let entry = Animation.spring(response: 0.42, dampingFraction: 0.86)
33+
}
34+
35+
/// Reusable section header — the tracked uppercase label that visually
36+
/// separates groups of settings. Cheap typography trick that signals
37+
/// "this is a crafted utility, not a quick form."
38+
struct SectionLabel: View {
39+
let title: String
40+
var body: some View {
41+
Text(title)
42+
.font(.system(size: 10.5, weight: .semibold, design: .default))
43+
.tracking(0.9)
44+
.textCase(.uppercase)
45+
.foregroundStyle(.secondary)
46+
}
47+
}
48+
49+
/// Card container — subtle elevation behind a group of related rows.
50+
/// Adapts to light/dark via NSColor.controlBackgroundColor.
51+
struct SettingsCard<Content: View>: View {
52+
@ViewBuilder var content: Content
53+
54+
var body: some View {
55+
VStack(alignment: .leading, spacing: 14) {
56+
content
57+
}
58+
.padding(.horizontal, 16)
59+
.padding(.vertical, 14)
60+
.background(
61+
RoundedRectangle(cornerRadius: 10, style: .continuous)
62+
.fill(Color(nsColor: .controlBackgroundColor))
63+
)
64+
.overlay(
65+
RoundedRectangle(cornerRadius: 10, style: .continuous)
66+
.strokeBorder(Color.primary.opacity(0.06), lineWidth: 0.5)
67+
)
68+
}
69+
}
70+
71+
/// Themed primary button — jade fill with a darker pressed state. Used for
72+
/// the rare "main action" inside Preferences (currently unused but available).
73+
struct JadeButtonStyle: ButtonStyle {
74+
func makeBody(configuration: Configuration) -> some View {
75+
configuration.label
76+
.font(.system(size: 12, weight: .semibold))
77+
.foregroundColor(.white)
78+
.padding(.horizontal, 14)
79+
.padding(.vertical, 6)
80+
.background(
81+
RoundedRectangle(cornerRadius: 6, style: .continuous)
82+
.fill(configuration.isPressed ? Brand.jadeDeep : Brand.jade)
83+
)
84+
.opacity(configuration.isPressed ? 0.92 : 1)
85+
}
86+
}

0 commit comments

Comments
 (0)