Refine client setup state and subscription controls

This commit is contained in:
2026-07-11 10:43:28 +03:00
parent 99f7f58fcb
commit e19d33adb9
7 changed files with 266 additions and 13 deletions

View File

@@ -0,0 +1,76 @@
# Motion and interaction
## Motion character
Aim for fluid, slightly viscous motion: noticeable, calm, and complete. Avoid bounce, elastic easing, abrupt unmounts, decorative page choreography, or tiny effects too weak to communicate feedback.
Use exponential ease-out curves such as `cubic-bezier(0.16, 1, 0.3, 1)` for arrivals. Typical timing:
- hover and press: 180-300 ms;
- state color and glow: 600-900 ms;
- content reveal: 600-850 ms;
- numeric tween and progress: about 900 ms;
- copy feedback: about 800 ms;
- server cascade: 620-760 ms per row with 90-110 ms stagger.
## Power state
- Transition gray to green slowly when connecting and green to gray when disconnecting.
- Animate icon color, localized light, and SVG shadow together.
- Let the light expand and brighten on enable, then contract and fade on disable.
- Keep the hit target and all surrounding geometry fixed.
- Use a short press compression, followed by a slower release.
## Changing text and numbers
- Put alternate labels in fixed-size slots.
- Reveal connection title, timer, and hint with opacity plus light blur, never vertical layout movement.
- Do not reanimate the timer every second; animate only its initial appearance.
- Tween numeric traffic values from old to new with `requestAnimationFrame` or an equivalent stable counter.
- Animate progress width concurrently and add a brief glow that fully fades.
- Never translate changing numbers if the user asked for a fluid morph; use numerical interpolation, opacity, color, blur, and light.
## Refresh
- Use a clean, symmetric SVG refresh icon aligned in the same flex row as its label.
- Spin for at least one full cycle. If the request finishes mid-cycle, continue to the next cycle boundary before stopping.
- Update data immediately when it arrives; finishing the icon cycle must not delay the data.
- Manual refresh may replay meaningful data and server transitions.
- Background polling should update quietly and must not repeatedly replay the server cascade.
- On updated traffic, tween the number, advance the bar, and emit a visible but brief green flare.
## Server cascade
- On initial display, reveal rows from top to bottom with a small negative Y offset, opacity, and blur.
- On manual refresh, animate an explicit exit phase first. Fade rows top to bottom, then remount and enter top to bottom.
- Wait for the last exit delay and duration before starting entry.
- Disable pointer interaction during exit.
- Do not replay on ping updates or unrelated renders.
## Subscription input
- Show the public domain while retaining the full URL internally.
- Disable browser autocomplete suggestions and neutralize autofill backgrounds.
- Hide the blinking caret when the paste-first interaction does not need it, while preserving keyboard input and focus outline.
- When an existing subscription is being edited and the field is idle, use the green underline as a five-second timeout indicator: start bright, fade to quiet, then restore display mode.
- Pause the timeout once the user enters content.
- Close and clear unfinished input on outside click or Escape.
## First-run initialization
- With no subscription, show only the centered subscription input. Hide power, proxy controls, usage, and servers.
- After a valid subscription loads, keep the subscription and server list centered. Require an explicit server choice instead of silently selecting the first server.
- On server choice, slide the subscription column to the right while revealing the power column on the viewport's central axis.
- Preserve the chosen server on later visits, but return to first-run initialization after subscription deletion.
- Deleting a subscription must stop the VPN, clear its cached/configured state, and return the UI to the centered input without leaving stale controls visible.
## Copy feedback
- Keep protocol buttons fixed-size and centered.
- Copy the complete protocol URL while showing a shared address separately.
- Overlay green `Copied` feedback in the same fixed box; do not append text or move the label.
- Make feedback appear immediately, hold briefly, and fade fully before restoring the original label. Keep the whole cycle near 800 ms.
## Reduced motion
Under `prefers-reduced-motion: reduce`, remove transitions and keyframe animations while preserving final state, focus, color contrast, copy wording, and all functionality.

View File

@@ -0,0 +1,49 @@
# Visual language
## Scene and character
Design for a macOS user glancing at a small VPN control surface in a quiet desktop environment. The UI should feel soft, precise, dependable, and slightly terminal-like, not like a network administration dashboard.
## Composition
- Make one primary action dominant: the VPN power icon.
- Keep the power control centered on the viewport's vertical axis, not merely centered inside a left column.
- Build the left flow vertically: power icon, stable connection copy, proxy address, copy actions.
- Place subscription identity, usage, expiry, and servers in a compact column to the right.
- Collapse to one centered column on narrow screens.
- Avoid cards and enclosing frames. Use spacing, type, thin rules, and state color for hierarchy.
- Keep server rows vertical and narrow. Underlines should be only slightly wider than the server label and ping.
## Geometry and alignment
- Reserve identical height for mutually exclusive content such as timer versus connection hint.
- Give copy buttons fixed width. Overlay temporary feedback instead of replacing text in normal flow.
- Align icons and labels in the same flex row. Do not position an icon by guessed absolute offsets.
- Preserve a generous invisible hit area around icon-only controls.
- Center proxy address and protocol actions with the power column.
- Treat one-pixel optical misalignment as a defect when controls sit beside uppercase labels.
## Typography
- Prefer the existing JetBrains Mono / SF Mono stack for the client surface.
- Use uppercase, tracked, muted micro-labels for metadata.
- Use stronger weight and size for the subscription domain and connection state.
- Use tabular numerals for timers and changing numeric data.
- Avoid display fonts, oversized headings, and mixed type families.
## Color and light
- Preserve green-tinted dark and light neutrals through the existing OKLCH variables.
- Inactive power stays neutral gray even on hover; active power becomes green.
- Use green for active VPN, selected server underline, progress, copy success, refresh success, and focus.
- Prefer localized `drop-shadow`, `text-shadow`, or a soft radial light layer over filled green containers.
- Let glow support state recognition. Do not leave every element glowing continuously.
## Data presentation
- Show subscription domain, not the credential-like full URL.
- Show used traffic and total limit as the primary statistic.
- Omit upload/download breakdown when provider support is absent or ambiguous.
- Show expiry as both date and remaining days, with correct Russian forms.
- If there is no total, say `без лимита` and omit the progress bar.
- Hide unavailable rows instead of showing empty placeholders or zeros that imply real measurements.