Files
supabase/apps/studio/components/interfaces/Account/AccessTokens/Classic/NewTokenButton.tsx
kemal.earth 8ffdcfc145 feat(studio): scoped pat ui (#38170)
## 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?

Introduces UI for Scoped PAT's.

## Additional context

WIP. Testing endpoints.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Scoped access tokens: create, view, delete, and manage granular
resource/action permissions with custom expiry options and scoped
creation flows.
* New scoped token UI: modal/sheet creation flow, resource access
selectors, permissions editor, and a scoped token list.

* **UI Improvements**
* Tabbed Classic vs Scoped tokens layout, refreshed tokens page,
improved forms, search/filtering, and table tweaks.

* **Bug Fixes / Maintenance**
  * New data hooks and utilities for scoped tokens and token handling.

* **Removed**
  * Legacy account settings layout and legacy token banner.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-02-09 11:32:55 +00:00

68 lines
1.9 KiB
TypeScript

import { ChevronDown } from 'lucide-react'
import { useState } from 'react'
import {
Button,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from 'ui'
import { NewTokenDialog } from './NewTokenDialog'
import { type NewAccessToken } from 'data/access-tokens/access-tokens-create-mutation'
export interface NewAccessTokenButtonProps {
onCreateToken: (token: NewAccessToken) => void
}
export const NewTokenButton = ({ onCreateToken }: NewAccessTokenButtonProps) => {
const [visible, setVisible] = useState(false)
const [tokenScope, setTokenScope] = useState<'V0' | undefined>(undefined)
return (
<>
<div className="flex items-center">
<Button
className="rounded-r-none px-3"
onClick={() => {
setTokenScope(undefined)
setVisible(true)
}}
>
Generate new token
</Button>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
type="primary"
title="Choose token scope"
className="rounded-l-none px-[4px] py-[5px]"
icon={<ChevronDown />}
/>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" side="bottom">
<DropdownMenuItem
key="experimental-token"
onClick={() => {
setTokenScope('V0')
setVisible(true)
}}
>
<div className="space-y-1">
<p className="block text-foreground">Generate token for experimental API</p>
</div>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
<NewTokenDialog
open={visible}
onOpenChange={setVisible}
tokenScope={tokenScope}
onCreateToken={onCreateToken}
/>
</>
)
}