mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
fix: consolidate focus states across inputs (#46588)
## Problem All inputs don't have the same style when focused ## Solution Consolidate focus states across inputs ## How to test Checkout the design system form examples: https://design-system-git-gildasgarcia-depr-354-consoli-0188d7-supabase.vercel.app/design-system/docs/ui-patterns/forms <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Style** * Refined focus-visible ring/outline and ring-offset tokens across buttons, multi-select, radio groups, checkbox, select, and switch for a more consistent accessible experience. * Updated focus-state styling details within the shared Button and related controls (including open-state outline behavior). * **Refactor** * Updated icon upload preview triggers in form examples to use the shared Button component while preserving existing upload behavior and visuals. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
1 parent
c79f8fc2b0
commit
211b99f144
8 files changed
+22
-18
No files matched your search
@@ -327,16 +327,17 @@ export default function FormPatternsPageLayout() {
|
||||
>
|
||||
<FormControl>
|
||||
<div className="flex gap-4 items-center">
|
||||
<button
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
onClick={() => uploadButtonRef.current?.click()}
|
||||
className="flex items-center justify-center h-10 w-10 shrink-0 text-foreground-lighter hover:text-foreground-light overflow-hidden rounded-full bg-cover border hover:border-strong"
|
||||
className="flex items-center justify-center h-10 w-10 shrink-0 overflow-hidden rounded-full"
|
||||
style={{
|
||||
backgroundImage: logoUrl ? `url("${logoUrl}")` : 'none',
|
||||
}}
|
||||
>
|
||||
{!logoUrl && <Upload size={14} />}
|
||||
</button>
|
||||
</Button>
|
||||
<div className="flex gap-2 items-center">
|
||||
<Button
|
||||
variant="default"
|
||||
|
||||
@@ -318,7 +318,7 @@ export default function FormPatternsSidePanel() {
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => uploadButtonRef.current?.click()}
|
||||
className="flex items-center justify-center h-10 w-10 shrink-0 text-foreground-lighter hover:text-foreground-light overflow-hidden rounded-full bg-cover border hover:border-strong"
|
||||
className="flex items-center justify-center h-10 w-10 shrink-0 text-foreground-lighter hover:text-foreground-light overflow-hidden rounded-full bg-cover border hover:border-strong focus-visible:outline-brand-600"
|
||||
style={{
|
||||
backgroundImage: logoUrl ? `url("${logoUrl}")` : 'none',
|
||||
}}
|
||||
@@ -327,7 +327,8 @@ export default function FormPatternsSidePanel() {
|
||||
</button>
|
||||
<div className="flex gap-2 items-center">
|
||||
<Button
|
||||
variant="default"
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="tiny"
|
||||
icon={<Upload size={14} />}
|
||||
onClick={() => uploadButtonRef.current?.click()}
|
||||
|
||||
@@ -8,11 +8,11 @@ import React, { isValidElement, ReactElement, useEffect } from 'react'
|
||||
import {
|
||||
Badge,
|
||||
cn,
|
||||
Command as Command,
|
||||
CommandEmpty as CommandEmpty,
|
||||
CommandInput as CommandInput,
|
||||
CommandItem as CommandItem,
|
||||
CommandList as CommandList,
|
||||
Command,
|
||||
CommandEmpty,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
Popover,
|
||||
PopoverAnchor,
|
||||
PopoverContent,
|
||||
@@ -294,7 +294,7 @@ const MultiSelectorTrigger = React.forwardRef<HTMLButtonElement, MultiSelectorTr
|
||||
'flex w-full min-w-[200px] min-h-[40px] items-center justify-between rounded-md border',
|
||||
'border-alternative bg-control px-3 py-2 text-sm',
|
||||
'ring-offset-background placeholder:text-muted-foreground',
|
||||
'focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2',
|
||||
'focus:outline-hidden focus:ring-2 focus:ring-background-control focus:ring-offset-2 focus-visible:ring-offset-foreground-muted',
|
||||
'disabled:cursor-not-allowed disabled:opacity-50',
|
||||
'hover:border-primary transition-colors duration-200',
|
||||
className
|
||||
|
||||
@@ -46,7 +46,7 @@ const buttonVariants = cva(
|
||||
border-strong hover:border-stronger
|
||||
focus-visible:outline-border-strong
|
||||
data-[state=open]:bg-selection
|
||||
data-[state=open]:outline-brand-600
|
||||
data-[state=open]:outline-border-strong
|
||||
data-[state=open]:border-button-hover
|
||||
`,
|
||||
secondary: `
|
||||
|
||||
@@ -47,6 +47,8 @@ const RadioGroupStackedItem = React.forwardRef<
|
||||
'disabled:opacity-50 disabled:cursor-not-allowed',
|
||||
// Enabled/hover states
|
||||
'enabled:cursor-pointer enabled:hover:bg-surface-300 enabled:hover:border-foreground-muted',
|
||||
// Focus state
|
||||
'focus:ring-background-control focus:border-control focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-background-control focus-visible:ring-offset-2 focus-visible:ring-offset-foreground-muted',
|
||||
// Z-index for interactions
|
||||
'hover:z-1 focus-visible:z-1 data-[state=checked]:z-1',
|
||||
// Checked state
|
||||
@@ -68,7 +70,7 @@ const RadioGroupStackedItem = React.forwardRef<
|
||||
// States
|
||||
'group-data-[state=checked]:border-foreground-muted',
|
||||
'group-focus:border-foreground-muted group-focus:outline-hidden',
|
||||
'group-focus-visible:ring-2 group-focus-visible:ring-ring group-focus-visible:ring-offset-2',
|
||||
'group-focus-visible:ring-2 group-focus-visible:ring-background-control group-focus-visible:ring-offset-2 group-focus-visible:ring-offset-foreground-muted',
|
||||
'group-hover:border-foreground-muted'
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import { Checkbox as CheckboxPrimitive } from 'radix-ui'
|
||||
import { Check } from 'lucide-react'
|
||||
import { Checkbox as CheckboxPrimitive } from 'radix-ui'
|
||||
import * as React from 'react'
|
||||
|
||||
import { cn } from '../../../lib/utils/cn'
|
||||
@@ -16,7 +16,7 @@ const Checkbox = React.forwardRef<
|
||||
'peer flex items-center justify-center h-4 w-4 shrink-0 rounded-sm border border-control bg-control/25 ring-offset-background',
|
||||
'transition-colors duration-150 ease-in-out',
|
||||
'hover:border-strong',
|
||||
'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
|
||||
'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-background-control focus-visible:ring-offset-2 focus-visible:ring-offset-foreground-muted',
|
||||
'disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-foreground data-[state=checked]:text-background',
|
||||
className
|
||||
)}
|
||||
|
||||
@@ -47,7 +47,7 @@ const SelectTrigger = React.forwardRef<
|
||||
<SelectPrimitive.Trigger
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'flex w-full items-center justify-between rounded-md border border-strong hover:border-stronger bg-alternative dark:bg-muted hover:bg-selection text-xs ring-offset-background-control data-[placeholder]:text-foreground-lighter focus:outline-hidden ring-border-control focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 transition-all duration-200',
|
||||
'flex w-full items-center justify-between rounded-md border border-strong hover:border-stronger bg-alternative dark:bg-muted hover:bg-selection text-xs ring-offset-background-control data-[placeholder]:text-foreground-lighter focus:outline-hidden ring-border-control focus:ring-2 focus:ring-background-control focus:ring-offset-2 focus-visible:ring-offset-foreground-muted disabled:cursor-not-allowed disabled:opacity-50 transition-all duration-200',
|
||||
'data-[state=open]:bg-selection data-[state=open]:border-stronger',
|
||||
'gap-2',
|
||||
'[&>span]:truncate text-left', // [kemal] This is to prevent double lines rendering when a string is particularly long.
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
'use client'
|
||||
|
||||
import { Switch as SwitchPrimitives } from 'radix-ui'
|
||||
import { cva, VariantProps } from 'class-variance-authority'
|
||||
import { Switch as SwitchPrimitives } from 'radix-ui'
|
||||
import * as React from 'react'
|
||||
|
||||
import { cn } from '../../../lib/utils/cn'
|
||||
|
||||
const switchRootVariants = cva(
|
||||
'peer inline-flex shrink-0 cursor-pointer items-center rounded-full border transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-brand data-[state=checked]:hover:bg-brand-600/90 data-[state=unchecked]:bg-control data-[state=unchecked]:hover:bg-border',
|
||||
'peer inline-flex shrink-0 cursor-pointer items-center rounded-full border transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-background-control focus-visible:ring-offset-2 focus-visible:ring-offset-foreground-muted disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-brand data-[state=checked]:hover:bg-brand-600/90 data-[state=unchecked]:bg-control data-[state=unchecked]:hover:bg-border',
|
||||
{
|
||||
variants: {
|
||||
size: {
|
||||
|
||||
Reference in new issue
Block a user