diff --git a/packages/app/src/composer/editor/editor.tsx b/packages/app/src/composer/editor/editor.tsx index 7f66fd9337f..8080d20a524 100644 --- a/packages/app/src/composer/editor/editor.tsx +++ b/packages/app/src/composer/editor/editor.tsx @@ -1433,6 +1433,8 @@ function ComposerEditorAlternateDelivery(props: { controller: ComposerEditorMode const sendIcon = motionTuning.choice("composer.sendIcon", { label: "Send icon", group: "Experiments", + card: "Icons", + order: 3, value: "today", labels: { today: "Today", ios: "iOS", heavy: "Heavier", filled: "Filled" }, }) @@ -1440,6 +1442,8 @@ const sendIcon = motionTuning.choice("composer.sendIcon", { const stopIcon = motionTuning.choice("composer.stopIcon", { label: "Stop icon", group: "Experiments", + card: "Icons", + order: 3, value: "today", labels: { today: "Today", rounded: "Rounded", ios: "iOS", heavy: "Heavier" }, }) @@ -1447,6 +1451,8 @@ const stopIcon = motionTuning.choice("composer.stopIcon", { const roundedStopSize = motionTuning.number("composer.stopIcon.size", { label: "Rounded stop size", group: "Experiments", + card: "Icons", + order: 3, value: 10, min: 6, max: 14, diff --git a/packages/app/src/session/composer/activity-chips.tsx b/packages/app/src/session/composer/activity-chips.tsx index 9910bbc772e..5f9e79638f6 100644 --- a/packages/app/src/session/composer/activity-chips.tsx +++ b/packages/app/src/session/composer/activity-chips.tsx @@ -14,12 +14,14 @@ import "./activity-chips.css" const chip = motionTuning.choice("activity.chip", { label: en["experiment.activityChip"], group: "Experiments", + order: 1, value: "today", labels: { today: en["experiment.activityChip.today"], orb: en["experiment.activityChip.orb"] }, }) const corners = motionTuning.choice("activity.chip.corners", { label: en["experiment.chipCorners"], group: "Experiments", + order: 1, value: "capsule", labels: { capsule: en["experiment.chipCorners.capsule"], composer: en["experiment.chipCorners.composer"] }, }) diff --git a/packages/app/src/session/header/separator.tsx b/packages/app/src/session/header/separator.tsx index c07b8693fb1..652f13e5289 100644 --- a/packages/app/src/session/header/separator.tsx +++ b/packages/app/src/session/header/separator.tsx @@ -3,10 +3,14 @@ import { Match, Switch } from "solid-js" import { createStore } from "solid-js/store" const group = "Experiments" +const card = "Icons" +const order = 3 const glyph = motionTuning.choice("sessionHeader.separator", { - label: "Header separator", + label: "Separator", group, + card, + order, value: "chevron", labels: { divider: "Divider", slash: "Slash", chevron: "Chevron", bold: "Bold chevron", dot: "Dot" }, }) @@ -14,6 +18,8 @@ const glyph = motionTuning.choice("sessionHeader.separator", { const size = motionTuning.number("sessionHeader.separator.size", { label: "Separator size", group, + card, + order, value: 11, min: 6, max: 24, @@ -24,6 +30,8 @@ const size = motionTuning.number("sessionHeader.separator.size", { const weight = motionTuning.number("sessionHeader.separator.weight", { label: "Separator weight", group, + card, + order, value: 1, min: 0.5, max: 3, @@ -34,6 +42,8 @@ const weight = motionTuning.number("sessionHeader.separator.weight", { const opacity = motionTuning.number("sessionHeader.separator.opacity", { label: "Separator opacity", group, + card, + order, value: 1, min: 0.2, max: 1, @@ -43,6 +53,8 @@ const opacity = motionTuning.number("sessionHeader.separator.opacity", { const gap = motionTuning.number("sessionHeader.separator.gap", { label: "Separator gap (ink to ink)", group, + card, + order, value: 10, min: 4, max: 20, diff --git a/packages/app/src/shell/titlebar/sidebar-hover.tsx b/packages/app/src/shell/titlebar/sidebar-hover.tsx index 2a37b8681fa..b3ae1a90be8 100644 --- a/packages/app/src/shell/titlebar/sidebar-hover.tsx +++ b/packages/app/src/shell/titlebar/sidebar-hover.tsx @@ -4,15 +4,19 @@ import { makeEventListener } from "@solid-primitives/event-listener" import { createSignal, onCleanup, onMount, Show } from "solid-js" const choice = motionTuning.choice("sidebar.hover", { - label: "Sidebar hover", + label: "Style", group: "Experiments", + card: "Sidebar hover", + order: 2, value: "today", labels: { today: "Today", glide: "Glide" }, }) const tuning = motionTuning.spring("sidebar.hover.glide", { - label: "Sidebar hover glide", + label: "Glide", group: "Experiments", + card: "Sidebar hover", + order: 2, presets: { snappy: { duration: 0.14, bounce: 0 }, smooth: { duration: 0.2, bounce: 0 }, diff --git a/packages/ui/src/components/spinner.tsx b/packages/ui/src/components/spinner.tsx index c839ce2e203..fe7ff360ef3 100644 --- a/packages/ui/src/components/spinner.tsx +++ b/packages/ui/src/components/spinner.tsx @@ -10,6 +10,7 @@ export type SpinnerVariantName = "today" | keyof typeof spinnerVariants const choice = motionTuning.choice("spinner.variant", { label: "Activity spinner", group: "Experiments", + order: 1, value: "radar", // SAFETY: built from spinnerVariants' own keys, plus "today". labels: Object.fromEntries([ diff --git a/packages/ui/src/data-display/project-avatar/project-avatar.tsx b/packages/ui/src/data-display/project-avatar/project-avatar.tsx index 97861b1979d..f200ec2e662 100644 --- a/packages/ui/src/data-display/project-avatar/project-avatar.tsx +++ b/packages/ui/src/data-display/project-avatar/project-avatar.tsx @@ -24,6 +24,7 @@ export { generateProjectIcon, GENERATED_PROJECT_ICON_STYLE, type GeneratedProjec const avatarChoice = motionTuning.choice("projectAvatar.style", { label: "Project avatars", group: "Experiments", + order: 1, value: "letters", labels: { letters: "Letters", generated: "Generated" }, }) diff --git a/packages/ui/src/motion-tuning-panel.ts b/packages/ui/src/motion-tuning-panel.ts index f785a20ff79..4b961c44a9b 100644 --- a/packages/ui/src/motion-tuning-panel.ts +++ b/packages/ui/src/motion-tuning-panel.ts @@ -31,7 +31,11 @@ export function mountMotionPanel( const { action, choice, defineControls, easing, knob, spring, toggle } = await import("knobs") const field = (item: MotionKnob) => { - const meta = { label: item.label, group: item.group, tab: item.group === global ? undefined : item.group } + const meta = { + label: item.label, + group: item.card ?? item.group, + tab: item.group === global ? undefined : item.group, + } if (item.kind === "spring") return spring(item.initial, meta) @@ -104,7 +108,11 @@ export function mountMotionPanel( ...Object.fromEntries( [...list, ...actions] .filter((item) => item.group !== global) - .toSorted((a, b) => sections.indexOf(a.group) - sections.indexOf(b.group)) + .toSorted( + (a, b) => + sections.indexOf(a.group) - sections.indexOf(b.group) || + ("order" in a ? (a.order ?? 0) : 0) - ("order" in b ? (b.order ?? 0) : 0), + ) .map((item) => "run" in item ? [ diff --git a/packages/ui/src/motion-tuning.ts b/packages/ui/src/motion-tuning.ts index 12446a500c6..9057f501c0f 100644 --- a/packages/ui/src/motion-tuning.ts +++ b/packages/ui/src/motion-tuning.ts @@ -9,6 +9,9 @@ type Knob = { id: string label: string group: string + /** Its own card within the group's tab, such as one experiment among several; `order` places that card. */ + card?: string + order?: number /** Shown only while this holds, e.g. the controls of the option a choice selects. */ when?: () => boolean initial: Value @@ -33,7 +36,7 @@ export type MotionKnob = export type MotionAction = { id: string; label: string; group: string; run: () => void } -type Meta = { label: string; group: string; when?: () => boolean } +type Meta = { label: string; group: string; card?: string; order?: number; when?: () => boolean } // Bumped when knobs are merged or renamed, so values saved for the old ones are dropped. const key = "opencode.motion.v2" @@ -57,6 +60,8 @@ export const motionTuning = { id, label: meta.label, group: meta.group, + card: meta.card, + order: meta.order, when: meta.when, initial, value: { duration: number(`${id}.duration`, initial.duration), bounce: number(`${id}.bounce`, initial.bounce) }, @@ -75,6 +80,8 @@ export const motionTuning = { id, label: meta.label, group: meta.group, + card: meta.card, + order: meta.order, when: meta.when, initial: meta.value, // SAFETY: mapping the four indices of a Bezier yields four numbers. @@ -95,6 +102,8 @@ export const motionTuning = { id, label: meta.label, group: meta.group, + card: meta.card, + order: meta.order, when: meta.when, initial, value: number(id, initial ? 1 : 0) === 1, @@ -108,6 +117,8 @@ export const motionTuning = { id, label: meta.label, group: meta.group, + card: meta.card, + order: meta.order, when: meta.when, initial: meta.value, value: number(id, meta.value ? 1 : 0) === 1, @@ -125,6 +136,8 @@ export const motionTuning = { id, label: meta.label, group: meta.group, + card: meta.card, + order: meta.order, when: meta.when, initial: meta.value, value: options[number(id, options.indexOf(meta.value))] ?? meta.value, @@ -148,6 +161,8 @@ export const motionTuning = { id, label: meta.label, group: meta.group, + card: meta.card, + order: meta.order, when: meta.when, initial: meta.value, value: number(id, meta.value),