mirror of
https://seed.radicle.dev/rad:z4D5UCArafTzTQpDZNQRuqswh3ury.git
synced 2026-11-12 14:50:37 +08:00
Redesign the entire app with a new UI kit. Typography, colors, icons, avatars, and border radii have all been updated for a more polished, consistent appearance that matches our other products like radicle-explorer. - Replace blockies-based avatars with a new DID-based avatar system - Move Settings and Create Issue into fullscreen modals - Change the default theme to follow the system theme - Remove window decorations on macOS for a cleaner, more native feel - Update the app icon - Fix popovers and tooltips Navigation: - Rewrite app navigation and layouts - Add a sidebar that gives you access to all your repos - Change the startup screen to open directly to the notification inbox - Add a getting started guide shown to new users on first launch Settings: - Add a setting to disable the notification badge - Add a code font setting Bug fixes: - Fix reactions and edits incorrectly targeting the root comment instead of the intended reply - Restrict issue/patch state, labels and assignees to delegates only
180 lines
4.5 KiB
Svelte
180 lines
4.5 KiB
Svelte
<script lang="ts">
|
|
import type { Snippet } from "svelte";
|
|
|
|
type Variant = "secondary" | "ghost" | "naked" | "outline";
|
|
|
|
interface Props {
|
|
id?: string;
|
|
children: Snippet;
|
|
variant?: Variant;
|
|
onclick?: (e: MouseEvent) => void;
|
|
disabled?: boolean;
|
|
active?: boolean;
|
|
flatLeft?: boolean;
|
|
flatRight?: boolean;
|
|
title?: string;
|
|
styleHeight?: "2rem" | "2.5rem";
|
|
styleWidth?: string;
|
|
styleJustifyContent?: string;
|
|
stylePadding?: string;
|
|
keyShortcuts?: string;
|
|
}
|
|
|
|
const {
|
|
id,
|
|
children,
|
|
variant = "ghost",
|
|
onclick = undefined,
|
|
disabled = false,
|
|
active = false,
|
|
flatLeft = false,
|
|
flatRight = false,
|
|
title,
|
|
styleHeight = "2rem",
|
|
styleWidth = undefined,
|
|
styleJustifyContent = undefined,
|
|
stylePadding = "0 0.5rem",
|
|
keyShortcuts,
|
|
}: Props = $props();
|
|
|
|
const fills: Record<Variant, string> = {
|
|
secondary: "var(--color-surface-brand-secondary)",
|
|
ghost: "var(--color-surface-subtle)",
|
|
naked: "transparent",
|
|
outline: "transparent",
|
|
};
|
|
const fillsHover: Record<Variant, string> = {
|
|
secondary: "var(--color-surface-brand-secondary)",
|
|
ghost: "var(--color-surface-mid)",
|
|
naked: "var(--color-surface-subtle)",
|
|
outline: "var(--color-surface-subtle)",
|
|
};
|
|
const fillsActive: Record<Variant, string> = {
|
|
secondary: "var(--color-surface-brand-primary)",
|
|
ghost: "var(--color-surface-strong)",
|
|
naked: "var(--color-surface-strong)",
|
|
outline: "var(--color-surface-strong)",
|
|
};
|
|
const colors: Record<Variant, string> = {
|
|
secondary: "var(--color-text-on-brand)",
|
|
ghost: "var(--color-text-primary)",
|
|
naked: "inherit",
|
|
outline: "inherit",
|
|
};
|
|
const colorsHover: Record<Variant, string> = {
|
|
secondary: "var(--color-text-on-brand)",
|
|
ghost: "var(--color-text-primary)",
|
|
naked: "inherit",
|
|
outline: "var(--color-text-primary)",
|
|
};
|
|
const colorsActive: Record<Variant, string> = {
|
|
secondary: "var(--color-text-on-brand)",
|
|
ghost: "var(--color-text-primary)",
|
|
naked: "inherit",
|
|
outline: "var(--color-text-primary)",
|
|
};
|
|
</script>
|
|
|
|
<style>
|
|
.button {
|
|
white-space: nowrap;
|
|
|
|
-webkit-touch-callout: none;
|
|
-webkit-user-select: none;
|
|
user-select: none;
|
|
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
border-radius: var(--border-radius-sm);
|
|
border: none;
|
|
background-color: var(--color-fill);
|
|
color: var(--color-text);
|
|
transition: background-color 0.1s ease;
|
|
}
|
|
|
|
.button:hover:not(.disabled) {
|
|
background-color: var(--color-fill-hover);
|
|
color: var(--color-text-hover);
|
|
}
|
|
|
|
.button.active:not(.disabled),
|
|
.button:active:not(.disabled) {
|
|
background-color: var(--color-fill-active);
|
|
color: var(--color-text-active);
|
|
}
|
|
|
|
.button.disabled {
|
|
cursor: default;
|
|
color: var(--color-text-disabled);
|
|
}
|
|
|
|
.button.secondary.disabled,
|
|
.button.ghost.disabled {
|
|
background-color: var(--color-surface-subtle);
|
|
}
|
|
|
|
.button.naked.disabled {
|
|
cursor: inherit;
|
|
}
|
|
|
|
.button.outline {
|
|
border: 1px solid var(--color-fill);
|
|
}
|
|
|
|
.button.outline.active:not(.disabled),
|
|
.button.outline:active:not(.disabled) {
|
|
border-color: var(--color-fill-active);
|
|
}
|
|
|
|
.button.outline.disabled {
|
|
border-color: var(--color-border-subtle);
|
|
}
|
|
|
|
.button.flat-left {
|
|
border-top-left-radius: 0;
|
|
border-bottom-left-radius: 0;
|
|
}
|
|
|
|
.button.flat-right {
|
|
border-top-right-radius: 0;
|
|
border-bottom-right-radius: 0;
|
|
}
|
|
</style>
|
|
|
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
<div
|
|
{id}
|
|
class="button txt-body-m-medium"
|
|
class:secondary={variant === "secondary"}
|
|
class:ghost={variant === "ghost"}
|
|
class:naked={variant === "naked"}
|
|
class:outline={variant === "outline"}
|
|
class:disabled
|
|
class:active
|
|
class:flat-left={flatLeft}
|
|
class:flat-right={flatRight}
|
|
style:cursor={disabled
|
|
? variant === "naked"
|
|
? "inherit"
|
|
: "default"
|
|
: "pointer"}
|
|
style:height={styleHeight}
|
|
style:width={styleWidth}
|
|
style:padding={stylePadding}
|
|
style:justify-content={styleJustifyContent ??
|
|
(styleWidth ? "center" : undefined)}
|
|
style:--color-fill={fills[variant]}
|
|
style:--color-fill-hover={fillsHover[variant]}
|
|
style:--color-fill-active={fillsActive[variant]}
|
|
style:--color-text={colors[variant]}
|
|
style:--color-text-hover={colorsHover[variant]}
|
|
style:--color-text-active={colorsActive[variant]}
|
|
aria-keyshortcuts={keyShortcuts}
|
|
onclick={!disabled ? onclick : undefined}
|
|
role="button"
|
|
tabindex="0"
|
|
{title}>
|
|
{@render children()}
|
|
</div>
|