Skip to content

Feature 5: Stat Modifier Buttons #130

@aphexlog

Description

@aphexlog

Description

Add increment/decrement buttons next to each stat to allow manual adjustments (for leveling up, items, etc.).

Priority

P1 (High) - Core character progression mechanic

Estimated Effort

3 days

Dependencies

Acceptance Criteria

  • +/- buttons appear next to each stat
  • Clicking updates stat immediately (optimistic)
  • Stats bounded (1-20 for D&D)
  • Visual feedback on hover/click
  • Changes persisted to database
  • Undo button available for 5 seconds
  • Mobile-friendly button size

Implementation Details

New Component: src/components/StatModifier.tsx

interface StatModifierProps {
  label: string;
  value: number;
  min?: number;
  max?: number;
  onUpdate: (newValue: number) => Promise<void>;
}

export const StatModifier = ({ label, value, min = 1, max = 20, onUpdate }: StatModifierProps) => {
  const [isPending, setIsPending] = useState(false);
  
  const handleChange = async (delta: number) => {
    const newValue = Math.max(min, Math.min(max, value + delta));
    if (newValue === value) return;
    
    setIsPending(true);
    try {
      await onUpdate(newValue);
    } finally {
      setIsPending(false);
    }
  };

  return (
    <div className="flex items-center justify-between gap-2 bg-brand-surface-hover rounded-lg p-2">
      <div className="text-xs text-brand-text-secondary uppercase">{label}</div>
      <div className="flex items-center gap-2">
        <button
          onClick={() => handleChange(-1)}
          disabled={value <= min || isPending}
          className="w-6 h-6 rounded bg-brand-surface-tertiary hover:bg-brand-accent-primary disabled:opacity-30"
        >
          
        </button>
        <div className="text-lg font-bold text-brand-text-primary w-8 text-center">
          {value}
        </div>
        <button
          onClick={() => handleChange(1)}
          disabled={value >= max || isPending}
          className="w-6 h-6 rounded bg-brand-surface-tertiary hover:bg-brand-accent-primary disabled:opacity-30"
        >
          +
        </button>
      </div>
    </div>
  );
};

Testing

  • Click + → stat increases
  • Click − → stat decreases
  • Bounded by min/max values
  • Optimistic update shows immediately
  • Database sync completes in background
  • Error triggers rollback
  • Mobile buttons easy to tap

Related Documentation

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1: HighHigh priority - core functionalitycharacter-sheetCharacter sheet featuresenhancementNew feature or requestgame-masterGame Master mode features

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions