File size: 3,475 Bytes
cd8bd0a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
"use client";

import type { ProviderDisplayMode } from "../providerPageStorage";

type ProviderMessageTranslator = ((key: string, values?: Record<string, unknown>) => string) & {
  has?: (key: string) => boolean;
};

function providerText(
  t: ProviderMessageTranslator,
  key: string,
  fallback: string,
  values?: Record<string, unknown>
): string {
  if (typeof t.has === "function" && t.has(key)) {
    return t(key, values);
  }
  if (values) {
    return Object.entries(values).reduce(
      (acc, [name, value]) => acc.replaceAll(`{${name}}`, String(value)),
      fallback
    );
  }
  return fallback;
}

interface ProviderDisplayModeControlProps {
  disabledConfigured: boolean;
  mode: ProviderDisplayMode;
  onChange(mode: ProviderDisplayMode): void;
  t: ProviderMessageTranslator;
}

export default function ProviderDisplayModeControl({
  disabledConfigured,
  mode,
  onChange,
  t,
}: ProviderDisplayModeControlProps) {
  const options: Array<{
    mode: ProviderDisplayMode;
    label: string;
    icon: string;
    disabled?: boolean;
    title: string;
  }> = [
    {
      mode: "all",
      label: providerText(t, "providerDisplayModeAll", "All"),
      icon: "view_module",
      title: providerText(
        t,
        "providerDisplayModeAllDesc",
        "Show every provider in grouped sections."
      ),
    },
    {
      mode: "configured",
      label: providerText(t, "providerDisplayModeConfigured", "Configured"),
      icon: "check_circle",
      disabled: disabledConfigured,
      title: providerText(
        t,
        "providerDisplayModeConfiguredDesc",
        "Show providers with saved connections."
      ),
    },
    {
      mode: "compact",
      label: providerText(t, "providerDisplayModeCompact", "Compact"),
      icon: "view_agenda",
      title: providerText(
        t,
        "providerDisplayModeCompactDesc",
        "Show configured and no-auth providers once in a single flat list."
      ),
    },
  ];

  return (
    <div
      className="flex items-center rounded-lg border border-border bg-bg-subtle p-0.5"
      role="radiogroup"
      aria-label={providerText(t, "providerDisplayMode", "Provider display mode")}
      data-testid="provider-display-mode-control"
    >
      {options.map((option) => {
        const isActive = mode === option.mode;
        return (
          <label
            key={option.mode}
            title={option.title}
            data-testid={`provider-display-mode-${option.mode}`}
            data-active={isActive ? "true" : "false"}
            className={`inline-flex h-7 items-center gap-1.5 rounded-md px-2.5 text-xs font-medium transition-colors ${
              isActive
                ? "bg-bg-primary text-text-main shadow-sm"
                : "text-text-muted hover:bg-bg-primary/70 hover:text-text-main"
            } ${option.disabled ? "cursor-not-allowed opacity-50" : ""}`}
          >
            <input
              type="radio"
              name="provider-display-mode"
              value={option.mode}
              checked={isActive}
              disabled={option.disabled}
              onChange={() => onChange(option.mode)}
              className="sr-only"
              aria-label={option.title}
            />
            <span className="material-symbols-outlined text-[14px]" aria-hidden="true">
              {option.icon}
            </span>
            <span>{option.label}</span>
          </label>
        );
      })}
    </div>
  );
}