feat(ui): standardize responsive control sizing (#3563)
This commit is contained in:
@@ -23,6 +23,11 @@ import { SettingsPromptEditor } from "@/components/settings/settings-prompt-edit
|
||||
import type { ScriptPlaceholder } from "@/components/settings/profile-edit/script-editor-completions";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
import type { TFunction } from "i18next";
|
||||
import { controlSizingClassName } from "@kandev/ui/control-sizing";
|
||||
import {
|
||||
settingsActionClassName,
|
||||
settingsControlClassName,
|
||||
} from "@/components/settings/settings-control";
|
||||
|
||||
// A function, not a const: `description` is copy, and a module-scope `t()` call
|
||||
// would freeze at the boot locale (see docs/i18n.md). `key` is the substitution
|
||||
@@ -72,7 +77,7 @@ function PresetIconSelect({
|
||||
return (
|
||||
<Select value={value} onValueChange={onChange}>
|
||||
<SelectTrigger
|
||||
className="!h-8 py-0.5 text-sm cursor-pointer"
|
||||
className={settingsControlClassName("py-0.5 text-sm cursor-pointer")}
|
||||
aria-label={t("github:icon")}
|
||||
data-settings-dirty={isDirty}
|
||||
>
|
||||
@@ -131,7 +136,7 @@ function PresetRow({
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<span className="text-[10px] text-muted-foreground">{t("github:label")}</span>
|
||||
<Input
|
||||
className="h-8 w-40"
|
||||
className={settingsControlClassName("w-40")}
|
||||
value={preset.label}
|
||||
data-settings-dirty={preset.label !== baseline?.label}
|
||||
placeholder={t("github:label")}
|
||||
@@ -141,7 +146,7 @@ function PresetRow({
|
||||
<div className="flex flex-col gap-0.5 flex-1">
|
||||
<span className="text-[10px] text-muted-foreground">{t("github:hint")}</span>
|
||||
<Input
|
||||
className="h-8"
|
||||
className={settingsControlClassName()}
|
||||
value={preset.hint}
|
||||
data-settings-dirty={preset.hint !== baseline?.hint}
|
||||
placeholder={t("github:hintOptional")}
|
||||
@@ -150,8 +155,7 @@ function PresetRow({
|
||||
</div>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="h-8 cursor-pointer text-xs"
|
||||
className={settingsActionClassName("cursor-pointer")}
|
||||
onClick={onToggle}
|
||||
>
|
||||
{expanded ? t("github:hidePrompt") : t("github:editPrompt")}
|
||||
@@ -159,7 +163,7 @@ function PresetRow({
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-8 w-8 cursor-pointer text-destructive"
|
||||
className={controlSizingClassName("icon", "cursor-pointer text-destructive")}
|
||||
onClick={onRemove}
|
||||
aria-label={t("github:remove")}
|
||||
>
|
||||
@@ -256,7 +260,7 @@ function PresetEditor({
|
||||
onRemove={() => remove(index)}
|
||||
/>
|
||||
))}
|
||||
<Button size="sm" variant="outline" onClick={add} className="cursor-pointer">
|
||||
<Button variant="outline" onClick={add} className={settingsActionClassName("cursor-pointer")}>
|
||||
<IconPlus className="h-3.5 w-3.5 mr-1" />
|
||||
{addLabel}
|
||||
</Button>
|
||||
@@ -385,11 +389,10 @@ export function ActionPresetsSection({ workspaceId }: { workspaceId: string }) {
|
||||
action={
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={reset}
|
||||
disabled={loading}
|
||||
className="cursor-pointer"
|
||||
className={settingsActionClassName("cursor-pointer")}
|
||||
>
|
||||
<IconRefresh className="h-3.5 w-3.5 mr-1" />
|
||||
{t("common:reset")}
|
||||
|
||||
@@ -21,6 +21,11 @@ import {
|
||||
ISSUE_PRESETS as BUILTIN_ISSUE_PRESETS,
|
||||
} from "@/components/github/my-github/search-bar";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { controlSizingClassName } from "@kandev/ui/control-sizing";
|
||||
import {
|
||||
settingsActionClassName,
|
||||
settingsControlClassName,
|
||||
} from "@/components/settings/settings-control";
|
||||
|
||||
// `label` is PERSISTED as part of `StoredQueryPreset` (github_default_query_presets)
|
||||
// and is editable in the row below, so it must stay locale-neutral — see
|
||||
@@ -56,7 +61,7 @@ function QueryRow({
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<span className="text-[10px] text-muted-foreground">{t("github:label")}</span>
|
||||
<Input
|
||||
className="h-8 w-36"
|
||||
className={settingsControlClassName("w-36")}
|
||||
value={preset.label}
|
||||
data-settings-dirty={preset.label !== baseline?.label}
|
||||
placeholder={t("github:label")}
|
||||
@@ -66,7 +71,7 @@ function QueryRow({
|
||||
<div className="flex flex-col gap-0.5 flex-1">
|
||||
<span className="text-[10px] text-muted-foreground">{t("github:query")}</span>
|
||||
<Input
|
||||
className="h-8 font-mono text-xs"
|
||||
className={settingsControlClassName("font-mono text-xs")}
|
||||
value={preset.filter}
|
||||
data-settings-dirty={preset.filter !== baseline?.filter}
|
||||
placeholder={t("github:queryExample", { query: "review-requested:@me is:open" })}
|
||||
@@ -80,7 +85,7 @@ function QueryRow({
|
||||
onValueChange={(v) => onPatch({ group: v as "inbox" | "created" })}
|
||||
>
|
||||
<SelectTrigger
|
||||
className="h-8 w-28 cursor-pointer"
|
||||
className={settingsControlClassName("w-28 cursor-pointer")}
|
||||
data-settings-dirty={preset.group !== baseline?.group}
|
||||
>
|
||||
<SelectValue />
|
||||
@@ -98,7 +103,7 @@ function QueryRow({
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-8 w-8 cursor-pointer text-destructive mt-3.5"
|
||||
className={controlSizingClassName("icon", "cursor-pointer text-destructive mt-3.5")}
|
||||
onClick={onRemove}
|
||||
aria-label={t("github:remove")}
|
||||
>
|
||||
@@ -142,7 +147,7 @@ function QueryEditor({
|
||||
onRemove={() => remove(index)}
|
||||
/>
|
||||
))}
|
||||
<Button size="sm" variant="outline" onClick={add} className="cursor-pointer">
|
||||
<Button variant="outline" onClick={add} className={settingsActionClassName("cursor-pointer")}>
|
||||
<IconPlus className="h-3.5 w-3.5 mr-1" />
|
||||
{addLabel}
|
||||
</Button>
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
} from "@kandev/ui/drawer";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@kandev/ui/tooltip";
|
||||
import { useTouchDrawer } from "@/hooks/use-compact-task-chrome";
|
||||
import { controlSizingClassName } from "@kandev/ui/control-sizing";
|
||||
|
||||
export function GitHubAccessHelp({
|
||||
label,
|
||||
@@ -40,7 +41,7 @@ export function GitHubAccessHelp({
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-11 w-11 shrink-0 cursor-pointer text-muted-foreground sm:h-6 sm:w-6"
|
||||
className={controlSizingClassName("icon", "shrink-0 cursor-pointer text-muted-foreground")}
|
||||
aria-haspopup={usesTouchDrawer ? "dialog" : undefined}
|
||||
aria-expanded={usesTouchDrawer ? open : undefined}
|
||||
aria-label={label}
|
||||
|
||||
@@ -91,17 +91,17 @@ export function GitHubAppConnectionPanel({ workspaceId }: { workspaceId: string
|
||||
<Button
|
||||
disabled={selectedRegistration?.status !== "active" || registrations.mutating}
|
||||
onClick={() => void install()}
|
||||
className="h-11 cursor-pointer"
|
||||
className="cursor-pointer"
|
||||
data-testid="github-app-install-button"
|
||||
>
|
||||
{registrations.mutating && <Spinner className="mr-2 h-4 w-4" />}
|
||||
{t("github:installForThisWorkspace")}
|
||||
<IconExternalLink className="ml-2 h-4 w-4" />
|
||||
</Button>
|
||||
<Button variant="outline" className="h-11 cursor-pointer" onClick={() => setView("import")}>
|
||||
<Button variant="outline" className="cursor-pointer" onClick={() => setView("import")}>
|
||||
<IconPlus className="mr-2 h-4 w-4" /> {t("github:addExistingApp")}
|
||||
</Button>
|
||||
<Button variant="outline" className="h-11 cursor-pointer" onClick={() => setView("create")}>
|
||||
<Button variant="outline" className="cursor-pointer" onClick={() => setView("create")}>
|
||||
<IconPlus className="mr-2 h-4 w-4" /> {t("github:createNewApp")}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -131,7 +131,7 @@ function useAppRegistrationSelection(workspaceId: string, registrations: Registr
|
||||
function BackButton({ onClick }: { onClick: () => void }) {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Button variant="ghost" className="h-11 cursor-pointer px-2" onClick={onClick}>
|
||||
<Button variant="ghost" className="cursor-pointer px-2" onClick={onClick}>
|
||||
{t("github:backToRegisteredApps")}
|
||||
</Button>
|
||||
);
|
||||
|
||||
@@ -120,13 +120,13 @@ function ManifestHandoff({
|
||||
</div>
|
||||
<div className="flex flex-col gap-2 sm:flex-row">
|
||||
<Button
|
||||
className="h-11 cursor-pointer"
|
||||
className="cursor-pointer"
|
||||
onClick={() => submitManifestToGitHub(handoff.registration_url, handoff.manifest)}
|
||||
>
|
||||
{t("github:continueOnGithub")}
|
||||
<IconExternalLink className="ml-2 h-4 w-4" />
|
||||
</Button>
|
||||
<Button variant="outline" className="h-11 cursor-pointer" onClick={onEdit}>
|
||||
<Button variant="outline" className="cursor-pointer" onClick={onEdit}>
|
||||
{t("github:editDetails")}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -163,14 +163,12 @@ function CreateAppFields(props: CreateFieldsProps) {
|
||||
<div className="grid gap-3 sm:grid-cols-2">
|
||||
<Field label={t("github:nameInKandev")} error={props.errors.displayName}>
|
||||
<Input
|
||||
className="h-11"
|
||||
value={props.displayName}
|
||||
onChange={(event) => props.onDisplayName(event.target.value)}
|
||||
/>
|
||||
</Field>
|
||||
<Field label={t("github:githubOwnerLogin")} error={props.errors.ownerLogin}>
|
||||
<Input
|
||||
className="h-11"
|
||||
value={props.ownerLogin}
|
||||
onChange={(event) => props.onOwnerLogin(event.target.value)}
|
||||
/>
|
||||
@@ -190,7 +188,6 @@ function CreateAppFields(props: CreateFieldsProps) {
|
||||
</RadioGroup>
|
||||
<Field label={t("github:publicKandevUrl")} error={props.errors.publicBaseUrl}>
|
||||
<Input
|
||||
className="h-11"
|
||||
type="url"
|
||||
placeholder="https://kandev.example.com"
|
||||
value={props.publicBaseUrl}
|
||||
@@ -200,7 +197,7 @@ function CreateAppFields(props: CreateFieldsProps) {
|
||||
<p className="text-xs text-muted-foreground">{t("github:githubMustReachThisHttpsOrigin")}</p>
|
||||
<GitHubAppVisibilityField value={props.visibility} onChange={props.onVisibility} />
|
||||
<div className="flex flex-col gap-2 sm:flex-row">
|
||||
<Button type="submit" disabled={props.mutating} className="h-11 cursor-pointer">
|
||||
<Button type="submit" disabled={props.mutating} className="cursor-pointer">
|
||||
{props.mutating && <Spinner className="mr-2 h-4 w-4" />}
|
||||
{t("github:prepareAppOnGithub")}
|
||||
<IconExternalLink className="ml-2 h-4 w-4" />
|
||||
|
||||
@@ -37,24 +37,15 @@ export function GitHubAppImportIdentityFields({
|
||||
<div className="grid gap-3 sm:grid-cols-2">
|
||||
<Field label={t("github:nameInKandev")} error={errors.displayName}>
|
||||
<Input
|
||||
className="h-11"
|
||||
value={values.displayName}
|
||||
onChange={(e) => update("displayName", e.target.value)}
|
||||
/>
|
||||
</Field>
|
||||
<Field label={t("github:githubAppSlug")} error={errors.slug}>
|
||||
<Input
|
||||
className="h-11"
|
||||
value={values.slug}
|
||||
onChange={(e) => update("slug", e.target.value)}
|
||||
/>
|
||||
<Input value={values.slug} onChange={(e) => update("slug", e.target.value)} />
|
||||
</Field>
|
||||
<Field label={t("github:githubOwnerLogin")} error={errors.ownerLogin}>
|
||||
<Input
|
||||
className="h-11"
|
||||
value={values.ownerLogin}
|
||||
onChange={(e) => update("ownerLogin", e.target.value)}
|
||||
/>
|
||||
<Input value={values.ownerLogin} onChange={(e) => update("ownerLogin", e.target.value)} />
|
||||
</Field>
|
||||
</div>
|
||||
<RadioGroup
|
||||
@@ -96,7 +87,6 @@ export function GitHubAppImportSecretFields({
|
||||
{(Object.keys(labels) as (keyof typeof labels)[]).map((name) => (
|
||||
<Field key={name} label={labels[name]} error={errors[name]}>
|
||||
<Input
|
||||
className="h-11"
|
||||
type={name.includes("Secret") || name === "webhookSecret" ? "password" : "text"}
|
||||
autoComplete="off"
|
||||
value={values[name]}
|
||||
|
||||
@@ -149,14 +149,13 @@ function PrepareImportForm(props: {
|
||||
</div>
|
||||
<Field label={t("github:publicKandevUrl")} error={props.error}>
|
||||
<Input
|
||||
className="h-11"
|
||||
type="url"
|
||||
placeholder="https://kandev.example.com"
|
||||
value={props.publicBaseUrl}
|
||||
onChange={(event) => props.onPublicBaseUrl(event.target.value)}
|
||||
/>
|
||||
</Field>
|
||||
<Button type="submit" disabled={props.mutating} className="h-11 cursor-pointer">
|
||||
<Button type="submit" disabled={props.mutating} className="cursor-pointer">
|
||||
{props.mutating && <Spinner className="mr-2 h-4 w-4" />}
|
||||
{t("github:generateSetupInstructions")}
|
||||
</Button>
|
||||
@@ -193,14 +192,14 @@ function PreparedImportForm(props: PreparedImportProps) {
|
||||
update={props.update}
|
||||
/>
|
||||
<div className="flex flex-col gap-2 sm:flex-row">
|
||||
<Button type="submit" disabled={props.mutating} className="h-11 cursor-pointer">
|
||||
<Button type="submit" disabled={props.mutating} className="cursor-pointer">
|
||||
{props.mutating && <Spinner className="mr-2 h-4 w-4" />}
|
||||
{t("github:verifyAndImportApp")}
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
className="h-11 cursor-pointer"
|
||||
className="cursor-pointer"
|
||||
onClick={props.onStartOver}
|
||||
>
|
||||
{t("github:startOver")}
|
||||
|
||||
@@ -67,7 +67,7 @@ export function GitHubAppImportGuide({
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-11 w-11 shrink-0 cursor-pointer"
|
||||
className="shrink-0 cursor-pointer"
|
||||
aria-label={t("github:copy", { label })}
|
||||
onClick={() => void copyValue(value)}
|
||||
>
|
||||
@@ -84,14 +84,14 @@ export function GitHubAppImportGuide({
|
||||
</div>
|
||||
<div className="flex flex-col gap-2 sm:flex-row">
|
||||
{settingsUrl ? (
|
||||
<Button asChild variant="outline" className="h-11 cursor-pointer">
|
||||
<Button asChild variant="outline" className="cursor-pointer">
|
||||
<a href={settingsUrl} target="_blank" rel="noreferrer">
|
||||
{t("github:openGithubAppSettings")}
|
||||
<IconExternalLink className="ml-2 h-4 w-4" />
|
||||
</a>
|
||||
</Button>
|
||||
) : (
|
||||
<Button type="button" variant="outline" className="h-11" disabled>
|
||||
<Button type="button" variant="outline" disabled>
|
||||
{t("github:openGithubAppSettings")}
|
||||
<IconExternalLink className="ml-2 h-4 w-4" />
|
||||
</Button>
|
||||
|
||||
@@ -42,7 +42,7 @@ export function GitHubAppPolicyDialog({
|
||||
return (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline" className="h-11 cursor-pointer">
|
||||
<Button variant="outline" className="cursor-pointer">
|
||||
<IconShieldCheck className="mr-2 h-4 w-4" />
|
||||
{t("github:reviewPermissions")}
|
||||
</Button>
|
||||
|
||||
@@ -113,7 +113,7 @@ export function GitHubCLIForm({
|
||||
onValueChange={setSelected}
|
||||
disabled={disabled || loading || !accounts.length}
|
||||
>
|
||||
<SelectTrigger id="github-cli-account" className="min-h-11 min-w-0 flex-1">
|
||||
<SelectTrigger id="github-cli-account" className="min-w-0 sm:flex-1">
|
||||
<SelectValue placeholder={accountPlaceholder(t, loading, loadError)} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
|
||||
@@ -25,6 +25,7 @@ import type { GitHubStatus } from "@/lib/types/github";
|
||||
import type { GitHubAutomationMethod } from "./github-auth-method-list";
|
||||
import { GitHubConnectionSettingsForm } from "./github-connection-settings-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { controlSizingClassName } from "@kandev/ui/control-sizing";
|
||||
|
||||
function methodForStatus(status: GitHubStatus): GitHubAutomationMethod {
|
||||
if (status.automation?.source === "github_app_installation") return "app";
|
||||
@@ -65,7 +66,10 @@ export function GitHubConnectionDialog({
|
||||
[status],
|
||||
);
|
||||
const trigger = (
|
||||
<Button variant={connected ? "outline" : "default"} className="h-11 cursor-pointer">
|
||||
<Button
|
||||
variant={connected ? "outline" : "default"}
|
||||
className={controlSizingClassName("standard", "cursor-pointer")}
|
||||
>
|
||||
<IconPlug className="mr-2 h-4 w-4" />
|
||||
{connected ? t("github:changeConnection") : t("github:connectGithub")}
|
||||
</Button>
|
||||
|
||||
@@ -284,7 +284,7 @@ export function GitHubConnectionSettingsForm(props: SettingsFormProps) {
|
||||
type="button"
|
||||
disabled={!canSave}
|
||||
onClick={save}
|
||||
className="h-11 w-full cursor-pointer sm:w-auto"
|
||||
className="w-full cursor-pointer sm:w-auto"
|
||||
data-dialog-default-action
|
||||
>
|
||||
{saving && <Spinner className="mr-2 h-4 w-4" />}
|
||||
|
||||
@@ -42,13 +42,13 @@ export function GitHubPATForm({
|
||||
placeholder="ghp_xxxxxxxxxxxx"
|
||||
autoComplete="off"
|
||||
disabled={disabled}
|
||||
className={settingsCredentialClassName("h-11 pr-11")}
|
||||
className={settingsCredentialClassName("pr-11")}
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="absolute right-0 top-0 h-11 w-11 cursor-pointer"
|
||||
className="absolute right-0 top-0 cursor-pointer"
|
||||
onClick={() => setVisible((current) => !current)}
|
||||
disabled={disabled}
|
||||
aria-label={visible ? t("github:hideToken") : t("github:showToken")}
|
||||
|
||||
@@ -47,7 +47,7 @@ export function GitHubPermissionsDialog({ status }: { status: GitHubStatus }) {
|
||||
return (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline" className="h-11 cursor-pointer">
|
||||
<Button variant="outline" className="cursor-pointer">
|
||||
{missingCount > 0 ? (
|
||||
<IconAlertTriangle className="mr-2 h-4 w-4 text-amber-500" />
|
||||
) : (
|
||||
|
||||
@@ -33,6 +33,7 @@ import type {
|
||||
} from "@/lib/types/github";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { t as translate } from "@/lib/i18n";
|
||||
import { controlSizingClassName } from "@kandev/ui/control-sizing";
|
||||
|
||||
function splitCSV(value: string): string[] {
|
||||
return value
|
||||
@@ -86,7 +87,7 @@ function RepositoryScopeHelp() {
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-11 w-11 cursor-pointer text-muted-foreground sm:h-7 sm:w-7"
|
||||
className={controlSizingClassName("icon", "cursor-pointer text-muted-foreground")}
|
||||
aria-haspopup="dialog"
|
||||
aria-expanded={open}
|
||||
aria-label={t("github:explainRepositoryScope")}
|
||||
|
||||
@@ -39,6 +39,7 @@ import { GitHubRateLimitDisplay } from "./github-rate-limit";
|
||||
import { GitHubTaskAccessSummary } from "./github-task-credentials-section";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import type { TFunction } from "i18next";
|
||||
import { controlSizingClassName } from "@kandev/ui/control-sizing";
|
||||
|
||||
// Keyed by the wire enum, which is never translated; only the label is copy.
|
||||
// Catalog keys rather than `t()` calls because this is module scope — a `t()`
|
||||
@@ -237,7 +238,7 @@ function AutomationActions({
|
||||
onClick={onRefresh}
|
||||
disabled={refreshing}
|
||||
aria-busy={refreshing}
|
||||
className="h-11 w-11 cursor-pointer"
|
||||
className={controlSizingClassName("icon", "cursor-pointer")}
|
||||
aria-label={t("github:refreshGithubConnection")}
|
||||
>
|
||||
<IconRefresh className={`h-4 w-4 ${refreshing ? "animate-spin" : ""}`} />
|
||||
@@ -247,7 +248,7 @@ function AutomationActions({
|
||||
variant="outline"
|
||||
onClick={onDisconnect}
|
||||
disabled={busy}
|
||||
className="h-11 cursor-pointer text-destructive"
|
||||
className="cursor-pointer text-destructive"
|
||||
>
|
||||
<IconTrash className="mr-2 h-4 w-4" />
|
||||
{t("github:disconnect")}
|
||||
@@ -357,7 +358,7 @@ function PersonalIdentityActions({
|
||||
return (
|
||||
<div className="flex flex-col gap-2 sm:flex-row">
|
||||
{status.app_available && status.automation?.source === "github_app_installation" && (
|
||||
<Button disabled={busy} onClick={onConnect} className="h-11 cursor-pointer">
|
||||
<Button disabled={busy} onClick={onConnect} className="cursor-pointer">
|
||||
<IconBrandGithub className="mr-2 h-4 w-4" />
|
||||
{status.personal ? t("github:reconnectIdentity") : t("github:connectIdentity")}
|
||||
<IconExternalLink className="ml-2 h-4 w-4" />
|
||||
@@ -368,7 +369,7 @@ function PersonalIdentityActions({
|
||||
variant="outline"
|
||||
onClick={onDisconnect}
|
||||
disabled={busy}
|
||||
className="h-11 cursor-pointer text-destructive"
|
||||
className="cursor-pointer text-destructive"
|
||||
>
|
||||
<IconTrash className="mr-2 h-4 w-4" />
|
||||
{t("github:disconnect")}
|
||||
|
||||
@@ -41,7 +41,7 @@ function StartTaskMenu({
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button size="sm" variant="outline" className="h-7 gap-1 cursor-pointer">
|
||||
<Button size="sm" variant="outline" className="gap-1 cursor-pointer">
|
||||
<IconPlus className="h-3.5 w-3.5" />
|
||||
{t("github:task")}
|
||||
<IconChevronDown className="h-3 w-3" />
|
||||
|
||||
@@ -51,7 +51,7 @@ export function ListToolbar({
|
||||
onRepoFilterChange={onRepoFilterChange}
|
||||
repoOptions={repoOptions}
|
||||
ariaLabel={t("github:filterGithubResultsByRepository")}
|
||||
triggerClassName="h-8 w-full border border-input bg-background px-2 py-1.5 text-xs/relaxed hover:bg-secondary/50 md:w-[220px]"
|
||||
triggerClassName="w-full border border-input bg-background px-2 text-xs/relaxed hover:bg-secondary/50 md:w-[220px]"
|
||||
className="md:min-w-[360px]"
|
||||
testId="github-repo-filter-trigger"
|
||||
dropdownTestId="github-repo-filter-dropdown"
|
||||
|
||||
@@ -96,7 +96,7 @@ function SavePresetForm({
|
||||
onRepoFilterChange={setDefaultRepoFilter}
|
||||
repoOptions={repoOptions}
|
||||
ariaLabel={t("github:defaultRepository")}
|
||||
triggerClassName="h-11 border border-input bg-background px-3 py-2 text-sm hover:bg-secondary/50 md:h-9 md:py-1.5"
|
||||
triggerClassName="border border-input bg-background px-3 text-sm hover:bg-secondary/50"
|
||||
testId="github-save-query-repo-trigger"
|
||||
dropdownTestId="github-save-query-repo-dropdown"
|
||||
/>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useTranslation } from "react-i18next";
|
||||
import { setPanelTitle } from "@/lib/layout/panel-portal-manager";
|
||||
import { IconCheck } from "@tabler/icons-react";
|
||||
import { Button } from "@kandev/ui/button";
|
||||
import { controlSizingClassName } from "@kandev/ui/control-sizing";
|
||||
import { useAppStore } from "@/components/state-provider";
|
||||
import {
|
||||
ChangeRequestDetail,
|
||||
@@ -230,8 +231,10 @@ function ApproveButton({
|
||||
return (
|
||||
<Button
|
||||
data-testid="pr-approve-button"
|
||||
size="sm"
|
||||
className="cursor-pointer gap-1.5 border-0 bg-green-600 text-white hover:bg-green-700 dark:bg-green-600 dark:hover:bg-green-500"
|
||||
className={controlSizingClassName(
|
||||
"standard",
|
||||
"cursor-pointer gap-1.5 border-0 bg-green-600 text-white hover:bg-green-700 dark:bg-green-600 dark:hover:bg-green-500",
|
||||
)}
|
||||
onClick={handleApprove}
|
||||
disabled={submitting}
|
||||
>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { useState } from "react";
|
||||
import { IconChevronDown, IconGitMerge } from "@tabler/icons-react";
|
||||
import { Button } from "@kandev/ui/button";
|
||||
import { controlSizingClassName } from "@kandev/ui/control-sizing";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
@@ -213,8 +214,10 @@ function MergeButtonShell({
|
||||
const primaryBtn = (
|
||||
<Button
|
||||
data-testid="pr-merge-button"
|
||||
size="sm"
|
||||
className={`min-h-11 cursor-pointer gap-1.5 border-0 bg-green-600 text-white hover:bg-green-700 dark:bg-green-600 dark:hover:bg-green-500 ${showDropdown ? "rounded-r-none" : ""}`}
|
||||
className={controlSizingClassName(
|
||||
"standard",
|
||||
`cursor-pointer gap-1.5 border-0 bg-green-600 text-white hover:bg-green-700 dark:bg-green-600 dark:hover:bg-green-500 ${showDropdown ? "rounded-r-none" : ""}`,
|
||||
)}
|
||||
onClick={onPrimaryClick}
|
||||
disabled={disabled}
|
||||
>
|
||||
|
||||
@@ -62,7 +62,9 @@ describe("ReviewsSection re-request action", () => {
|
||||
|
||||
const action = screen.getByRole("button", { name: "Re-request review from octocat" });
|
||||
expect(action).toHaveProperty("disabled", true);
|
||||
expect(action.className).toContain("min-h-11");
|
||||
expect(action.className).toContain("h-7");
|
||||
expect(action.className).toContain("max-md:h-11");
|
||||
expect(action.className).toContain("[@media(pointer:coarse)]:h-11");
|
||||
fireEvent.click(action);
|
||||
expect(onReRequest).not.toHaveBeenCalled();
|
||||
});
|
||||
@@ -86,7 +88,8 @@ describe("ReviewsSection re-request action", () => {
|
||||
name: `Re-request review from ${longLogin}`,
|
||||
});
|
||||
const author = screen.getByRole("link", { name: longLogin });
|
||||
expect(action.className).toContain("min-h-11");
|
||||
expect(action.className).toContain("max-md:h-11");
|
||||
expect(action.className).toContain("[@media(pointer:coarse)]:h-11");
|
||||
expect(action.parentElement?.className).toContain("basis-full");
|
||||
expect(author.className).toContain("inline-block");
|
||||
expect(author.className).toContain("max-w-full");
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Button } from "@kandev/ui/button";
|
||||
import type { PRReview, RequestedReviewer } from "@/lib/types/github";
|
||||
import { CollapsibleSection, FeedbackItemRow } from "./pr-shared";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { controlSizingClassName } from "@kandev/ui/control-sizing";
|
||||
|
||||
function ReviewStateIcon({ state }: { state: string }) {
|
||||
if (state === "APPROVED") return <IconCheck className="h-3.5 w-3.5 text-green-500 shrink-0" />;
|
||||
@@ -157,9 +158,11 @@ function SubmittedReviewRow({
|
||||
<div className="basis-full w-full sm:basis-auto sm:w-auto">
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
variant="outline"
|
||||
className="h-8 min-h-11 w-full max-w-full sm:w-auto sm:min-h-0 shrink-0 cursor-pointer px-2 text-[10px] [@media(pointer:coarse)]:min-h-11"
|
||||
className={controlSizingClassName(
|
||||
"standard",
|
||||
"w-full max-w-full shrink-0 cursor-pointer px-2 text-[10px] sm:w-auto",
|
||||
)}
|
||||
data-testid={`pr-rerequest-review-${normalizeLogin(review.author)}`}
|
||||
aria-label={t("github:reRequestReviewFrom", { author: review.author })}
|
||||
onClick={() => onReRequest(review.author)}
|
||||
|
||||
Reference in New Issue
Block a user