mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 09:55:06 +03:00
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Improving accessibility by adding `aria-label` and associating the switches with their labels in database section. Adding `Tooltip` for icon only buttons. ## What is the current behavior? `Switch` components are not connected with their labels, `aria-label` and some `Tooltip` are missing. ## What is the new behavior? Icon-only buttons have now buttons and `aria-label` have been added. `Switch` components are connected to their labels. ## Additional context No visual changes have been made. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Accessibility Improvements** - Added descriptive labels and tooltips to database management actions, including remove, delete, and “More options” controls. - Improved screen reader support for function editor maximize/minimize controls, privilege switches, publication switches, and column actions. - Connected privilege labels with their corresponding controls for clearer navigation. - Clarified permission-related messaging when deleting columns. - Reduced duplicate announcements from tooltips and accessible descriptions. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Gildas Garcia <1122076+djhi@users.noreply.github.com>
121 lines
3.7 KiB
TypeScript
121 lines
3.7 KiB
TypeScript
import { Label, Switch } from 'ui'
|
|
|
|
import {
|
|
ALL_PRIVILEGE_TYPES,
|
|
COLUMN_PRIVILEGE_TYPES,
|
|
TABLE_PRIVILEGE_TYPES,
|
|
} from './Privileges.constants'
|
|
import { usePrivilegesState } from './Privileges.utils'
|
|
import Table from '@/components/to-be-cleaned/Table'
|
|
import type { ColumnPrivilege } from '@/data/privileges/column-privileges-query'
|
|
|
|
export interface PrivilegesTableProps extends Pick<
|
|
ReturnType<typeof usePrivilegesState>,
|
|
'tableCheckedStates' | 'columnCheckedStates' | 'toggleTablePrivilege' | 'toggleColumnPrivilege'
|
|
> {
|
|
columnPrivileges: ColumnPrivilege[]
|
|
disabled: boolean
|
|
isApplyingChanges?: boolean
|
|
}
|
|
|
|
const PrivilegesTable = ({
|
|
columnPrivileges,
|
|
tableCheckedStates,
|
|
columnCheckedStates,
|
|
toggleTablePrivilege,
|
|
toggleColumnPrivilege,
|
|
disabled,
|
|
isApplyingChanges = false,
|
|
}: PrivilegesTableProps) => {
|
|
const handleClickColumnName = (columnId: string) => {
|
|
const hasAllPrivileges = COLUMN_PRIVILEGE_TYPES.every(
|
|
(privilege) => columnCheckedStates[columnId][privilege]
|
|
)
|
|
const privilegesToToggle = COLUMN_PRIVILEGE_TYPES.filter((privilege) =>
|
|
hasAllPrivileges
|
|
? columnCheckedStates[columnId][privilege]
|
|
: !columnCheckedStates[columnId][privilege]
|
|
)
|
|
|
|
privilegesToToggle.forEach((privilege) => {
|
|
toggleColumnPrivilege(columnId, privilege)
|
|
})
|
|
}
|
|
|
|
return (
|
|
<Table
|
|
className="table-fixed mb-4"
|
|
head={[
|
|
<Table.th key="header-column">
|
|
<span>Column</span>
|
|
</Table.th>,
|
|
...ALL_PRIVILEGE_TYPES.map((privilege) => {
|
|
const checked = tableCheckedStates[privilege]
|
|
const switchThId = `privilege-th-${privilege}`
|
|
|
|
return (
|
|
<Table.th key={`header-${privilege}`}>
|
|
<div className="inline-flex items-center gap-2">
|
|
<Label htmlFor={switchThId}>
|
|
{privilege.charAt(0) + privilege.slice(1).toLowerCase()}
|
|
</Label>
|
|
|
|
<Switch
|
|
id={switchThId}
|
|
checked={checked}
|
|
onCheckedChange={() => {
|
|
toggleTablePrivilege(privilege)
|
|
}}
|
|
disabled={disabled || isApplyingChanges}
|
|
/>
|
|
</div>
|
|
</Table.th>
|
|
)
|
|
}),
|
|
]}
|
|
body={columnPrivileges.map((column) => (
|
|
<Table.tr key={column.column_id}>
|
|
<Table.td>
|
|
<button
|
|
tabIndex={0}
|
|
onClick={() => handleClickColumnName(column.column_id)}
|
|
className="block w-full truncate text-left text-foreground"
|
|
>
|
|
{column.column_name}
|
|
</button>
|
|
</Table.td>
|
|
{COLUMN_PRIVILEGE_TYPES.map((privilege) => {
|
|
const checked = columnCheckedStates[column.column_id][privilege]
|
|
|
|
return (
|
|
<Table.td key={privilege}>
|
|
{COLUMN_PRIVILEGE_TYPES.includes(privilege as any) && (
|
|
<div className="ml-5 inline-flex">
|
|
<Switch
|
|
aria-label={`${privilege} privilege for ${column.column_name}`}
|
|
checked={checked}
|
|
onCheckedChange={() => {
|
|
toggleColumnPrivilege(column.column_id, privilege)
|
|
}}
|
|
disabled={disabled || isApplyingChanges}
|
|
/>
|
|
</div>
|
|
)}
|
|
</Table.td>
|
|
)
|
|
})}
|
|
{TABLE_PRIVILEGE_TYPES.map((privilege) => {
|
|
return (
|
|
<Table.td key={privilege}>
|
|
<span className="ml-5 text-xs text-foreground-lighter">N/A</span>
|
|
</Table.td>
|
|
)
|
|
})}
|
|
</Table.tr>
|
|
))}
|
|
/>
|
|
)
|
|
}
|
|
|
|
export default PrivilegesTable
|