Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .Jules/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

## [Unreleased]

### Changed
- **Button Focus States:** Added consistent `focus-visible` styles to `Button` component and inline buttons (`Modal`, `Toast`, `Input`) for better keyboard navigation across both Neobrutalism and Glassmorphism themes.
Comment on lines +9 to +10
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add a blank line after the heading to satisfy markdownlint (MD022).

Line 9 should be followed by an empty line before the list item.

🛠️ Proposed fix
 ### Changed
+
 - **Button Focus States:** Added consistent `focus-visible` styles to `Button` component and inline buttons (`Modal`, `Toast`, `Input`) for better keyboard navigation across both Neobrutalism and Glassmorphism themes.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
### Changed
- **Button Focus States:** Added consistent `focus-visible` styles to `Button` component and inline buttons (`Modal`, `Toast`, `Input`) for better keyboard navigation across both Neobrutalism and Glassmorphism themes.
### Changed
- **Button Focus States:** Added consistent `focus-visible` styles to `Button` component and inline buttons (`Modal`, `Toast`, `Input`) for better keyboard navigation across both Neobrutalism and Glassmorphism themes.
🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 9-9: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.Jules/changelog.md around lines 9 - 10, Add a blank line after the "###
Changed" heading so MarkdownLint rule MD022 is satisfied; open the
.Jules/changelog.md content around the "### Changed" heading and insert an empty
line before the list item that begins "- **Button Focus States:** ..." to
separate the heading from the list.


### Added
- **Password Strength Meter:** Added a visual password strength indicator to the signup form.
- **Features:**
Expand Down
3 changes: 2 additions & 1 deletion .Jules/todo.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@

### Web

- [ ] **[style]** Consistent hover/focus states across all buttons
- [x] **[style]** Consistent hover/focus states across all buttons
- Completed: 2026-03-01
- Files: `web/components/ui/Button.tsx`, usage across pages
- Context: Ensure all buttons have proper hover + focus-visible styles
- Impact: Professional feel, keyboard users know where they are
Expand Down
12 changes: 6 additions & 6 deletions web/components/ui/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const Button: React.FC<ButtonProps> = ({
}) => {
const { style } = useTheme();

const baseStyles = "transition-all duration-200 font-bold flex items-center justify-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed";
const baseStyles = "transition-all duration-200 font-bold flex items-center justify-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-offset-white dark:focus-visible:ring-offset-gray-900";

const sizeStyles = {
sm: "px-3 py-1.5 text-sm",
Expand All @@ -31,7 +31,7 @@ export const Button: React.FC<ButtonProps> = ({
let themeStyles = "";

if (style === THEMES.NEOBRUTALISM) {
themeStyles = "border-2 border-black shadow-[4px_4px_0px_0px_rgba(0,0,0,1)] hover:translate-x-[2px] hover:translate-y-[2px] hover:shadow-[2px_2px_0px_0px_rgba(0,0,0,1)] active:translate-x-[4px] active:translate-y-[4px] active:shadow-none rounded-none uppercase tracking-wider font-mono";
themeStyles = "border-2 border-black shadow-[4px_4px_0px_0px_rgba(0,0,0,1)] hover:translate-x-[2px] hover:translate-y-[2px] hover:shadow-[2px_2px_0px_0px_rgba(0,0,0,1)] active:translate-x-[4px] active:translate-y-[4px] active:shadow-none rounded-none uppercase tracking-wider font-mono focus-visible:ring-black dark:focus-visible:ring-white";

if (variant === 'primary') themeStyles += " bg-neo-main text-white";
if (variant === 'secondary') themeStyles += " bg-neo-second text-black";
Expand All @@ -42,10 +42,10 @@ export const Button: React.FC<ButtonProps> = ({
// Glassmorphism
themeStyles = "rounded-xl backdrop-blur-md border border-white/20 shadow-lg hover:shadow-xl active:scale-95";

if (variant === 'primary') themeStyles += " bg-gradient-to-r from-blue-500 to-purple-600 text-white shadow-blue-500/30";
if (variant === 'secondary') themeStyles += " bg-white/10 text-white hover:bg-white/20";
if (variant === 'danger') themeStyles += " bg-gradient-to-r from-red-500 to-pink-600 text-white shadow-red-500/30";
if (variant === 'ghost') themeStyles += " bg-transparent border-none shadow-none hover:bg-white/10 text-current";
if (variant === 'primary') themeStyles += " bg-gradient-to-r from-blue-500 to-purple-600 text-white shadow-blue-500/30 focus-visible:ring-blue-500";
if (variant === 'secondary') themeStyles += " bg-white/10 text-white hover:bg-white/20 focus-visible:ring-white/50";
if (variant === 'danger') themeStyles += " bg-gradient-to-r from-red-500 to-pink-600 text-white shadow-red-500/30 focus-visible:ring-red-500";
if (variant === 'ghost') themeStyles += " bg-transparent border-none shadow-none hover:bg-white/10 text-current focus-visible:ring-gray-400";
}

return (
Expand Down
6 changes: 3 additions & 3 deletions web/components/ui/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ export const Input: React.FC<InputProps> = ({ label, error, className = '', type
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className={`absolute right-3 top-1/2 -translate-y-1/2 p-1 rounded-md transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-offset-1 ${
className={`absolute right-3 top-1/2 -translate-y-1/2 p-1 rounded-md transition-opacity hover:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-offset-white dark:focus-visible:ring-offset-gray-900 ${
style === THEMES.NEOBRUTALISM
? (mode === 'dark' ? 'text-white opacity-80 focus:ring-white' : 'text-black opacity-60 focus:ring-black')
: 'text-white/60 hover:text-white focus:ring-white/50'
? (mode === 'dark' ? 'text-white opacity-80 focus-visible:ring-white' : 'text-black opacity-60 focus-visible:ring-black')
: 'text-white/60 hover:text-white focus-visible:ring-white/50'
}`}
aria-label={showPassword ? "Hide password" : "Show password"}
>
Expand Down
2 changes: 1 addition & 1 deletion web/components/ui/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export const Modal: React.FC<ModalProps> = ({ isOpen, onClose, title, children,
{/* Header */}
<div className={`p-6 flex justify-between items-center ${style === THEMES.NEOBRUTALISM ? 'border-b-2 border-black bg-neo-main text-white' : 'border-b border-white/10 bg-white/5'}`}>
<h3 id={titleId} className={`text-2xl font-bold ${style === THEMES.NEOBRUTALISM ? 'uppercase font-mono tracking-tighter' : ''}`}>{title}</h3>
<button type="button" onClick={onClose} className="hover:rotate-90 transition-transform duration-200" aria-label="Close modal">
<button type="button" onClick={onClose} className="hover:rotate-90 transition-transform duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-black dark:focus-visible:ring-white focus-visible:ring-offset-white dark:focus-visible:ring-offset-gray-900 rounded-sm" aria-label="Close modal">
<X size={24} />
</button>
</div>
Expand Down
2 changes: 1 addition & 1 deletion web/components/ui/Toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const ToastItem: React.FC<{ toast: Toast }> = ({ toast }) => {
<button
type="button"
onClick={() => removeToast(toast.id)}
className="shrink-0 hover:opacity-70 transition-opacity"
className="shrink-0 hover:opacity-70 transition-opacity focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-black dark:focus-visible:ring-white focus-visible:ring-offset-white dark:focus-visible:ring-offset-gray-900 rounded-sm"
aria-label="Close notification"
>
<X className="w-4 h-4" />
Expand Down
Loading