mirror of
https://github.com/coder/coder.git
synced 2026-06-05 22:18:20 +00:00
7887cff9d0
Adds the account settings UI for managing user secrets, including the table, add/edit/delete dialog, Storybook coverage, and route/sidebar entry. Also updates the shared `FeatureStageBadge` beta variant with dedicated beta styling, sizing, and label casing for the Secrets page. Stacked on #25370. _This PR was generated by Coder Agents._
442 lines
14 KiB
CSS
442 lines
14 KiB
CSS
/*
|
||
To enable opacity in colors, please use the new HSL format.
|
||
Related issue: https://github.com/shadcn-ui/ui/issues/805#issuecomment-1616021820
|
||
*/
|
||
|
||
@tailwind base;
|
||
@tailwind components;
|
||
@tailwind utilities;
|
||
|
||
@font-face {
|
||
font-family: "seti";
|
||
src: url("/seti.woff") format("woff");
|
||
font-weight: normal;
|
||
font-style: normal;
|
||
font-display: swap;
|
||
}
|
||
|
||
@layer components {
|
||
@media (max-width: 767px) {
|
||
/*
|
||
Full-width mobile dropdowns. We set custom properties on
|
||
`document.documentElement` from the chat input container so
|
||
dropdown positions track the actual input box, not hardcoded
|
||
offsets. Radix popover wrappers are fixed-positioned, so
|
||
bottom offsets are measured from the layout viewport. The
|
||
above-composer max-height also accounts for the visual
|
||
viewport offset so soft-keyboard viewport panning on mobile
|
||
keeps dropdowns inside the visible area:
|
||
|
||
- `--mobile-dropdown-bottom`: distance from the layout
|
||
viewport bottom to the composer's bottom edge. Used by the
|
||
`-bottom` variant; the dropdown's bottom edge sits at the
|
||
composer's bottom edge.
|
||
- `--mobile-dropdown-left` and `--mobile-dropdown-width`:
|
||
composer-aligned horizontal geometry for full-width mobile
|
||
dropdowns.
|
||
- `--mobile-dropdown-above-composer-bottom`: distance from
|
||
the layout viewport bottom to a point just above the
|
||
composer's top edge.
|
||
- `--mobile-dropdown-above-composer-max-height`: maximum
|
||
height the `-above-composer` variant can grow to without
|
||
extending past the visible viewport top.
|
||
*/
|
||
[data-radix-popper-content-wrapper]:has(> .mobile-full-width-dropdown) {
|
||
position: fixed !important;
|
||
left: var(--mobile-dropdown-left, 1rem) !important;
|
||
width: var(--mobile-dropdown-width, calc(100vw - 2rem)) !important;
|
||
min-width: 0 !important;
|
||
transform: none !important;
|
||
bottom: var(--mobile-dropdown-bottom, 5rem) !important;
|
||
top: auto !important;
|
||
}
|
||
[data-radix-popper-content-wrapper]:has(> .mobile-full-width-dropdown-top) {
|
||
bottom: auto !important;
|
||
top: var(--mobile-dropdown-top, 3.5rem) !important;
|
||
}
|
||
[data-radix-popper-content-wrapper]:has(
|
||
> .mobile-full-width-dropdown-top-below-header
|
||
) {
|
||
bottom: auto !important;
|
||
top: 5rem !important;
|
||
}
|
||
[data-radix-popper-content-wrapper]:has(
|
||
> .mobile-full-width-dropdown-above-composer
|
||
) {
|
||
bottom: var(--mobile-dropdown-above-composer-bottom, 9rem) !important;
|
||
top: auto !important;
|
||
max-height: var(
|
||
--mobile-dropdown-above-composer-max-height,
|
||
calc(100vh - var(--mobile-dropdown-above-composer-bottom, 9rem) - 1rem)
|
||
) !important;
|
||
overflow: hidden !important;
|
||
}
|
||
.mobile-full-width-dropdown {
|
||
width: 100% !important;
|
||
min-width: 0 !important;
|
||
max-width: none !important;
|
||
}
|
||
.mobile-full-width-dropdown-above-composer {
|
||
max-height: var(
|
||
--mobile-dropdown-above-composer-max-height,
|
||
calc(100vh - var(--mobile-dropdown-above-composer-bottom, 9rem) - 1rem)
|
||
) !important;
|
||
overflow: hidden !important;
|
||
}
|
||
.mobile-full-width-dropdown-above-composer
|
||
.mobile-full-width-dropdown-scroll-area {
|
||
max-height: calc(
|
||
var(--mobile-dropdown-above-composer-max-height, 18rem) -
|
||
0.5rem
|
||
) !important;
|
||
overflow-y: auto !important;
|
||
overscroll-behavior: contain;
|
||
-webkit-overflow-scrolling: touch;
|
||
}
|
||
}
|
||
}
|
||
|
||
@layer base {
|
||
:root,
|
||
.light {
|
||
--content-primary: 240 10% 4%;
|
||
--content-secondary: 240 5% 34%;
|
||
--content-link: 221 83% 53%;
|
||
--content-invert: 0 0% 98%;
|
||
--content-disabled: 240 5% 65%;
|
||
--content-success: 142 72% 29%;
|
||
--content-warning: 27 96% 61%;
|
||
--content-destructive: 0 84% 60%;
|
||
--surface-primary: 0 0% 100%;
|
||
--surface-secondary: 240 5% 96%;
|
||
--surface-tertiary: 240 6% 90%;
|
||
--surface-quaternary: 240 5% 84%;
|
||
--surface-invert-primary: 240 4% 16%;
|
||
--surface-invert-secondary: 240 5% 26%;
|
||
--surface-destructive: 0 93% 94%;
|
||
--surface-green: 141 79% 85%;
|
||
--surface-grey: 240 5% 96%;
|
||
--surface-orange: 34 100% 92%;
|
||
--surface-sky: 191, 67%, 89%;
|
||
--surface-red: 0 93% 94%;
|
||
--surface-purple: 259, 100%, 95%;
|
||
--surface-magenta: 289 100% 98%;
|
||
--border-purple: 255 92% 76%;
|
||
--border-default: 240 6% 90%;
|
||
--border-success: 142 76% 36%;
|
||
--border-sky: 203 90% 40%;
|
||
--border-green: 138 82% 82%;
|
||
--border-magenta: 295, 68%, 46%;
|
||
--border-warning: 30.66, 97.16%, 72.35%;
|
||
--border-destructive: 0 84% 60%;
|
||
--border-secondary: 240 5% 65%;
|
||
--overlay-default: 240 5% 84% / 80%;
|
||
--radius: 0.5rem;
|
||
--highlight-purple: 271, 61%, 35%;
|
||
--highlight-green: 143 64% 24%;
|
||
--highlight-orange: 30 100% 32%;
|
||
--highlight-sky: 195, 61%, 22%;
|
||
--highlight-red: 0 74% 42%;
|
||
--highlight-magenta: 295, 68%, 40%;
|
||
--syntax-key: 211 95% 33%;
|
||
--syntax-string: 0 77% 36%;
|
||
--syntax-number: 158 88% 28%;
|
||
--syntax-boolean: 240 100% 50%;
|
||
--git-added: 142 72% 29%;
|
||
--git-deleted: 0 74% 42%;
|
||
--git-modified: 17 88% 40%;
|
||
--git-merged: 271 91% 65%;
|
||
--git-added-bright: 142 72% 29%;
|
||
--git-deleted-bright: 0 74% 42%;
|
||
--git-merged-bright: 272 72% 47%;
|
||
--surface-git-added: 141 84% 93%;
|
||
--surface-git-deleted: 0 93% 94%;
|
||
--surface-git-merged: 269 100% 95%;
|
||
--border: 240 5.9% 90%;
|
||
--input: 240 5.9% 90%;
|
||
--ring: 240 10% 3.9%;
|
||
/*
|
||
shadcn-compatible aliases consumed by streamdown and
|
||
internal components (e.g. shimmer). These names are
|
||
intentionally generic so they match shadcn conventions.
|
||
Do NOT rename without updating every consumer.
|
||
*/
|
||
--background: var(--surface-primary);
|
||
--foreground: var(--content-primary);
|
||
--muted: var(--surface-secondary);
|
||
--muted-foreground: var(--content-secondary);
|
||
--primary: var(--content-link);
|
||
--primary-foreground: var(--surface-primary);
|
||
--avatar-lg: 2.5rem;
|
||
--avatar-default: 2rem;
|
||
--avatar-sm: 1.5rem;
|
||
}
|
||
.dark {
|
||
--content-primary: 0 0% 100%;
|
||
--content-secondary: 240 5% 65%;
|
||
--content-link: 213 94% 68%;
|
||
--content-invert: 240 10% 4%;
|
||
--content-disabled: 240 5% 26%;
|
||
--content-success: 142 76% 36%;
|
||
--content-warning: 31 97% 72%;
|
||
--content-destructive: 0 91% 71%;
|
||
--surface-primary: 240 10% 4%;
|
||
--surface-secondary: 240 6% 10%;
|
||
--surface-tertiary: 240 4% 16%;
|
||
--surface-quaternary: 240 5% 26%;
|
||
--surface-invert-primary: 240 6% 90%;
|
||
--surface-invert-secondary: 240 5% 65%;
|
||
--surface-destructive: 0 75% 15%;
|
||
--surface-green: 145 80% 10%;
|
||
--surface-grey: 240 6% 10%;
|
||
--surface-orange: 13 81% 15%;
|
||
--surface-sky: 196, 67%, 12%;
|
||
--surface-red: 0 75% 15%;
|
||
--surface-purple: 268, 68%, 17%;
|
||
--surface-magenta: 291, 74%, 15%;
|
||
--border-purple: 255 92% 76%;
|
||
--border-default: 240 4% 16%;
|
||
--border-success: 142 76% 36%;
|
||
--border-magenta: 292, 100%, 78%;
|
||
--border-warning: 30.66, 97.16%, 72.35%;
|
||
--border-destructive: 0 91% 71%;
|
||
--border-sky: 194 90% 62%;
|
||
--border-green: 143 77% 87%;
|
||
--border-secondary: 240 5% 26%;
|
||
--overlay-default: 240 10% 4% / 80%;
|
||
--highlight-purple: 269, 100%, 74%;
|
||
--highlight-green: 141 79% 85%;
|
||
--highlight-orange: 31 100% 70%;
|
||
--highlight-sky: 188, 75%, 80%;
|
||
--highlight-red: 0 91% 71%;
|
||
--highlight-magenta: 292, 100%, 78%;
|
||
--syntax-key: 201 98% 80%;
|
||
--syntax-string: 18 47% 64%;
|
||
--syntax-number: 100 28% 73%;
|
||
--syntax-boolean: 207 61% 59%;
|
||
--git-added: 142 77% 73%;
|
||
--git-deleted: 0 94% 82%;
|
||
--git-modified: 31 97% 72%;
|
||
--git-merged: 271 91% 65%;
|
||
--git-added-bright: 142 71% 45%;
|
||
--git-deleted-bright: 0 91% 71%;
|
||
--git-merged-bright: 270 95% 75%;
|
||
--surface-git-added: 145 80% 10%;
|
||
--surface-git-deleted: 0 75% 15%;
|
||
--surface-git-merged: 274 87% 21%;
|
||
--border: 240 3.7% 15.9%;
|
||
--input: 240 3.7% 15.9%;
|
||
--ring: 240 4.9% 83.9%;
|
||
/* shadcn-compatible aliases – see :root block for details. */
|
||
--background: var(--surface-primary);
|
||
--foreground: var(--content-primary);
|
||
--muted: var(--surface-secondary);
|
||
--muted-foreground: var(--content-secondary);
|
||
--primary: var(--content-link);
|
||
--primary-foreground: var(--surface-primary);
|
||
}
|
||
/*
|
||
Colorblind-friendly variants. ThemeProvider applies these classes
|
||
alongside the base mode class (`dark` or `light`), so unchanged
|
||
variables cascade from the base mode and each block only overrides
|
||
the semantic colors that shift for colorblind accessibility.
|
||
|
||
Palette rationale:
|
||
- dark-protan-deuter / light-protan-deuter: shift the red/green
|
||
success+error axis onto sky-blue (success) + vermilion/orange
|
||
(destructive). Warning shifts to fuchsia so it does not collide
|
||
with destructive states on the orange axis.
|
||
- dark-tritan / light-tritan: keep destructive states on the
|
||
red/orange axis and shift `success` (and the green-tinted
|
||
diff/git surfaces) onto sky-blue. This matches GitHub
|
||
Primer's tritanopia preset, where diff additions render in
|
||
blue rather than green so the success+destructive pair stays
|
||
consistent with the protan-deuter palette and with other
|
||
tritan-aware tools. Warning still moves from amber to
|
||
fuchsia because amber and sky-blue blur together under
|
||
tritanopia.
|
||
*/
|
||
.light-protan-deuter {
|
||
--content-success: 199 89% 48%;
|
||
--content-warning: 322 81% 43%;
|
||
--content-destructive: 24 95% 53%;
|
||
--surface-destructive: 34 100% 92%;
|
||
--surface-green: 201 94% 86%;
|
||
--surface-orange: 289 100% 98%;
|
||
--surface-red: 34 100% 92%;
|
||
--border-success: 199 89% 48%;
|
||
--border-green: 201 94% 86%;
|
||
--border-warning: 322 81% 60%;
|
||
--border-destructive: 24 95% 53%;
|
||
--highlight-green: 201 94% 36%;
|
||
--highlight-orange: 322 81% 43%;
|
||
--highlight-red: 24 95% 42%;
|
||
--syntax-string: 24 95% 42%;
|
||
--syntax-number: 199 89% 38%;
|
||
--git-added: 199 89% 48%;
|
||
--git-deleted: 24 95% 53%;
|
||
--git-modified: 271 91% 45%;
|
||
--git-added-bright: 199 89% 48%;
|
||
--git-deleted-bright: 24 95% 53%;
|
||
--surface-git-added: 204 94% 94%;
|
||
--surface-git-deleted: 33 100% 93%;
|
||
}
|
||
.dark-protan-deuter {
|
||
--content-success: 199 82% 67%;
|
||
--content-warning: 322 81% 67%;
|
||
--content-destructive: 27 96% 67%;
|
||
--surface-destructive: 17 75% 15%;
|
||
--surface-green: 201 80% 14%;
|
||
--surface-orange: 322 70% 15%;
|
||
--surface-red: 17 75% 15%;
|
||
--border-success: 199 82% 67%;
|
||
--border-warning: 322 81% 67%;
|
||
--border-destructive: 27 96% 67%;
|
||
--border-green: 201 94% 86%;
|
||
--highlight-green: 201 94% 86%;
|
||
--highlight-orange: 322 81% 67%;
|
||
--highlight-red: 27 96% 67%;
|
||
--git-added: 199 82% 67%;
|
||
--git-deleted: 27 96% 67%;
|
||
--git-modified: 271 91% 65%;
|
||
--git-added-bright: 199 89% 48%;
|
||
--git-deleted-bright: 24 95% 53%;
|
||
--surface-git-added: 201 80% 14%;
|
||
--surface-git-deleted: 17 75% 15%;
|
||
}
|
||
.light-tritan {
|
||
--content-success: 199 89% 48%;
|
||
--content-warning: 322 81% 43%;
|
||
--surface-green: 201 94% 86%;
|
||
--surface-orange: 289 100% 98%;
|
||
--border-success: 199 89% 48%;
|
||
--border-green: 201 94% 86%;
|
||
--border-warning: 322 81% 60%;
|
||
--highlight-green: 201 94% 36%;
|
||
--highlight-orange: 322 81% 43%;
|
||
--highlight-magenta: 322, 81%, 43%;
|
||
--syntax-boolean: 322 81% 43%;
|
||
--syntax-number: 199 89% 38%;
|
||
--git-added: 199 89% 48%;
|
||
--git-modified: 322 81% 43%;
|
||
--git-added-bright: 199 89% 48%;
|
||
--surface-git-added: 204 94% 94%;
|
||
}
|
||
.dark-tritan {
|
||
--content-success: 199 82% 67%;
|
||
--content-warning: 322 81% 67%;
|
||
--surface-green: 201 80% 14%;
|
||
--surface-orange: 322 70% 15%;
|
||
--surface-magenta: 322 70% 15%;
|
||
--border-success: 199 82% 67%;
|
||
--border-green: 201 94% 86%;
|
||
--border-magenta: 322 81% 72%;
|
||
--border-warning: 322 81% 67%;
|
||
--highlight-green: 201 94% 86%;
|
||
--highlight-orange: 322 81% 67%;
|
||
--highlight-magenta: 322 81% 72%;
|
||
--syntax-boolean: 322 81% 67%;
|
||
--git-added: 199 82% 67%;
|
||
--git-modified: 322 81% 72%;
|
||
--git-added-bright: 199 89% 48%;
|
||
--surface-git-added: 201 80% 14%;
|
||
}
|
||
}
|
||
|
||
@layer base {
|
||
* {
|
||
@apply border-border;
|
||
}
|
||
|
||
html,
|
||
body,
|
||
#root,
|
||
#storybook-root {
|
||
@apply h-full;
|
||
}
|
||
|
||
button,
|
||
input {
|
||
@apply font-sans;
|
||
}
|
||
|
||
input:-webkit-autofill,
|
||
input:-webkit-autofill:hover,
|
||
input:-webkit-autofill:focus,
|
||
input:-webkit-autofill:active {
|
||
-webkit-box-shadow: 0 0 0 100px hsl(var(--surface-primary)) inset !important;
|
||
-webkit-text-fill-color: hsl(var(--content-primary)) !important;
|
||
caret-color: hsl(var(--content-primary));
|
||
}
|
||
|
||
::placeholder {
|
||
@apply text-content-secondary;
|
||
}
|
||
|
||
fieldset {
|
||
@apply border-none p-0 m-0 w-full;
|
||
}
|
||
|
||
/* Global scrollbar color baseline: surface-quaternary thumb on
|
||
transparent track. scrollbar-color is inherited, so this cascades
|
||
to all scroll containers. We intentionally do NOT set
|
||
scrollbar-width globally because any non-auto value opts out of
|
||
overlay scrollbars on macOS/Chromium, causing a permanent gutter
|
||
on every container (even when content does not overflow). */
|
||
:root {
|
||
scrollbar-color: hsl(var(--surface-quaternary)) transparent;
|
||
}
|
||
|
||
/* Prevent layout shift when modals open by maintaining scrollbar width.
|
||
scrollbar-gutter: stable reserves space for the scrollbar so Radix's
|
||
scroll-bar compensation (margin-right/padding-right) is unnecessary
|
||
and causes double spacing. We zero it out with !important to win
|
||
over Radix's injected !important styles. The @supports guard ensures
|
||
we only do this on browsers that actually support scrollbar-gutter.
|
||
|
||
There’s a related issue on GitHub: Radix UI Primitives Issue #3251
|
||
https://github.com/radix-ui/primitives/issues/3251
|
||
*/
|
||
@supports (scrollbar-gutter: stable) {
|
||
html {
|
||
scrollbar-gutter: stable;
|
||
}
|
||
|
||
html body[data-scroll-locked] {
|
||
--removed-body-scroll-bar-size: 0 !important;
|
||
margin-right: 0 !important;
|
||
overflow-y: scroll !important;
|
||
}
|
||
}
|
||
|
||
/*
|
||
This is a temporary fix for MUI Modals/Popovers until they are removed.
|
||
When html has scrollbar-gutter: stable, the browser reserves space for the scrollbar.
|
||
MUI Modals/Popovers, when locking body scroll, add `overflow: hidden` and `padding-right`
|
||
to the body to compensate for the scrollbar they are hiding. This added padding-right
|
||
conflicts with the already reserved gutter space, causing a layout shift.
|
||
This rule overrides MUI's added padding-right on the body specifically when MUI
|
||
is likely to have set both overflow:hidden and padding-right.
|
||
*/
|
||
body[style*="overflow: hidden"][style*="padding-right"] {
|
||
padding-right: 0px;
|
||
}
|
||
}
|
||
|
||
@layer utilities {
|
||
.text-xs-mono {
|
||
@apply text-xs font-mono font-medium;
|
||
}
|
||
}
|
||
|
||
@media (prefers-reduced-motion: reduce) {
|
||
*,
|
||
*::before,
|
||
*::after {
|
||
animation-duration: 0.01ms !important;
|
||
animation-iteration-count: 1 !important;
|
||
transition-duration: 0.01ms !important;
|
||
scroll-behavior: auto !important;
|
||
}
|
||
}
|