feat: enforce tighter character limits for site, funnel, and monitor names to improve UI consistency and usability
This commit is contained in:
@@ -20,6 +20,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||
- **Graceful error recovery.** If a page crashes, you now see a friendly error screen with a "Try again" button instead of a blank white page. Each section of the app has its own error message so you know exactly what went wrong.
|
||||
- **Security headers.** All pages now include clickjacking protection, MIME-sniffing prevention, a strict referrer policy, and HSTS. Browser APIs like camera and microphone are explicitly disabled.
|
||||
- **Better form experience.** Forms now auto-focus the first field when they open, text inputs enforce character limits with a visible counter when you're close, and the settings page warns you before navigating away with unsaved changes.
|
||||
- **Tighter name limits.** Site, funnel, and monitor names are now capped at 100 characters instead of 255 — long enough for any real name, short enough to not break the UI.
|
||||
|
||||
## [0.10.0-alpha] - 2026-02-21
|
||||
|
||||
|
||||
@@ -122,10 +122,10 @@ export default function CreateFunnelPage() {
|
||||
placeholder="e.g. Signup Flow"
|
||||
autoFocus
|
||||
required
|
||||
maxLength={255}
|
||||
maxLength={100}
|
||||
/>
|
||||
{name.length > 200 && (
|
||||
<span className={`text-xs tabular-nums mt-1 ${name.length > 240 ? 'text-amber-500' : 'text-neutral-400'}`}>{name.length}/255</span>
|
||||
{name.length > 80 && (
|
||||
<span className={`text-xs tabular-nums mt-1 ${name.length > 90 ? 'text-amber-500' : 'text-neutral-400'}`}>{name.length}/100</span>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
|
||||
@@ -501,14 +501,14 @@ export default function SiteSettingsPage() {
|
||||
type="text"
|
||||
id="name"
|
||||
required
|
||||
maxLength={255}
|
||||
maxLength={100}
|
||||
value={formData.name}
|
||||
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
|
||||
className="w-full px-4 py-2 border border-neutral-200 dark:border-neutral-800 rounded-lg bg-neutral-50/50 dark:bg-neutral-900/50 focus:bg-white dark:focus:bg-neutral-900
|
||||
focus:border-brand-orange focus:ring-4 focus:ring-brand-orange/10 outline-none transition-all duration-200 dark:text-white"
|
||||
/>
|
||||
{formData.name.length > 200 && (
|
||||
<span className={`text-xs tabular-nums ${formData.name.length > 240 ? 'text-amber-500' : 'text-neutral-400'}`}>{formData.name.length}/255</span>
|
||||
{formData.name.length > 80 && (
|
||||
<span className={`text-xs tabular-nums ${formData.name.length > 90 ? 'text-amber-500' : 'text-neutral-400'}`}>{formData.name.length}/100</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -938,11 +938,11 @@ function MonitorForm({
|
||||
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
|
||||
placeholder="e.g. API, Website, CDN"
|
||||
autoFocus
|
||||
maxLength={255}
|
||||
maxLength={100}
|
||||
className="w-full px-3 py-2 rounded-lg border border-neutral-300 dark:border-neutral-600 bg-white dark:bg-neutral-800 text-neutral-900 dark:text-white placeholder-neutral-400 focus:outline-none focus:ring-2 focus:ring-brand-orange focus:border-transparent text-sm"
|
||||
/>
|
||||
{formData.name.length > 200 && (
|
||||
<span className={`text-xs tabular-nums mt-1 ${formData.name.length > 240 ? 'text-amber-500' : 'text-neutral-400'}`}>{formData.name.length}/255</span>
|
||||
{formData.name.length > 80 && (
|
||||
<span className={`text-xs tabular-nums mt-1 ${formData.name.length > 90 ? 'text-amber-500' : 'text-neutral-400'}`}>{formData.name.length}/100</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -192,7 +192,7 @@ export default function NewSitePage() {
|
||||
id="name"
|
||||
required
|
||||
autoFocus
|
||||
maxLength={255}
|
||||
maxLength={100}
|
||||
value={formData.name}
|
||||
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
|
||||
placeholder="My Website"
|
||||
|
||||
Reference in New Issue
Block a user