feat(ui): updates to design system (#37471)

This commit is contained in:
Aarav Sareen
2026-07-17 15:39:15 +05:30
committed by GitHub
parent d16dad8286
commit 3e2902fa82
7 changed files with 54 additions and 7 deletions
@@ -113,6 +113,29 @@
cursor: not-allowed; cursor: not-allowed;
} }
[data-component="button-v2"][data-variant="warning"] {
background-color: var(--v2-background-bg-button-neutral);
color: var(--v2-state-fg-warning);
box-shadow: var(--v2-elevation-button-neutral);
}
[data-component="button-v2"][data-variant="warning"]:is(:hover, [data-state="hover"]):not(:disabled) {
background-image:
linear-gradient(90deg, var(--v2-overlay-simple-overlay-hover) 0%, var(--v2-overlay-simple-overlay-hover) 100%),
linear-gradient(90deg, var(--v2-background-bg-button-neutral) 0%, var(--v2-background-bg-button-neutral) 100%);
}
[data-component="button-v2"][data-variant="warning"]:is(:active, [data-state="pressed"]):not(:disabled) {
background-image:
linear-gradient(90deg, var(--v2-overlay-simple-overlay-pressed) 0%, var(--v2-overlay-simple-overlay-pressed) 100%),
linear-gradient(90deg, var(--v2-background-bg-button-neutral) 0%, var(--v2-background-bg-button-neutral) 100%);
}
[data-component="button-v2"][data-variant="warning"]:is(:disabled, [data-state="disabled"]) {
opacity: 0.5;
cursor: not-allowed;
}
/* Outline */ /* Outline */
[data-component="button-v2"][data-variant="outline"] { [data-component="button-v2"][data-variant="outline"] {
background-color: transparent; background-color: transparent;
@@ -4,7 +4,7 @@ const docs = `### Overview
Button v2 with visual variants and three sizes. Button v2 with visual variants and three sizes.
### API ### API
- \`variant\`: "neutral" | "danger" | "contrast" | "ghost" | "ghost-muted" | "loading". - \`variant\`: "neutral" | "danger" | "warning" | "contrast" | "ghost" | "ghost-muted" | "loading".
- \`size\`: "small" | "normal" | "large". - \`size\`: "small" | "normal" | "large".
- \`icon\`: Optional icon name. - \`icon\`: Optional icon name.
- Inherits Kobalte Button props and native button attributes. - Inherits Kobalte Button props and native button attributes.
@@ -39,7 +39,7 @@ export default {
}, },
variant: { variant: {
control: "select", control: "select",
options: ["neutral", "danger", "contrast", "ghost", "ghost-muted", "loading"], options: ["neutral", "danger", "warning", "contrast", "ghost", "ghost-muted", "loading"],
}, },
size: { size: {
control: "select", control: "select",
@@ -62,6 +62,7 @@ export const Variants = {
> >
<ButtonV2 variant="neutral">Neutral</ButtonV2> <ButtonV2 variant="neutral">Neutral</ButtonV2>
<ButtonV2 variant="danger">Danger</ButtonV2> <ButtonV2 variant="danger">Danger</ButtonV2>
<ButtonV2 variant="warning">Warning</ButtonV2>
<ButtonV2 variant="contrast">Contrast</ButtonV2> <ButtonV2 variant="contrast">Contrast</ButtonV2>
<ButtonV2 variant="ghost">Ghost</ButtonV2> <ButtonV2 variant="ghost">Ghost</ButtonV2>
<ButtonV2 variant="ghost-muted" icon="edit"> <ButtonV2 variant="ghost-muted" icon="edit">
@@ -117,7 +118,7 @@ export const Icon = {
export const AllStates = { export const AllStates = {
render: () => { render: () => {
const variants = ["neutral", "danger", "contrast", "ghost", "ghost-muted", "loading"] as const const variants = ["neutral", "danger", "warning", "contrast", "ghost", "ghost-muted", "loading"] as const
const states = ["default", "hover", "pressed", "focus", "disabled"] as const const states = ["default", "hover", "pressed", "focus", "disabled"] as const
const toTitleCase = (value: string) => value.charAt(0).toUpperCase() + value.slice(1) const toTitleCase = (value: string) => value.charAt(0).toUpperCase() + value.slice(1)
return ( return (
+1 -1
View File
@@ -7,7 +7,7 @@ export interface ButtonV2Props
extends ComponentProps<typeof Kobalte>, extends ComponentProps<typeof Kobalte>,
Pick<ComponentProps<"button">, "class" | "classList" | "children"> { Pick<ComponentProps<"button">, "class" | "classList" | "children"> {
size?: "small" | "normal" | "large" size?: "small" | "normal" | "large"
variant?: "neutral" | "danger" | "outline" | "contrast" | "ghost" | "ghost-muted" | "loading" variant?: "neutral" | "danger" | "warning" | "outline" | "contrast" | "ghost" | "ghost-muted" | "loading"
icon?: IconProps["name"] icon?: IconProps["name"]
} }
+2 -2
View File
@@ -1,8 +1,8 @@
[data-component="divider-v2"] { [data-component="divider-v2"] {
box-sizing: border-box; box-sizing: border-box;
width: 100%; width: 100%;
height: 0.5px; height: 1px;
margin-block: 0.25px; transform: scaleY(0.5);
border: none; border: none;
background: var(--v2-border-border-strong); background: var(--v2-border-border-strong);
flex: none; flex: none;
@@ -67,9 +67,14 @@
gap: 4px; gap: 4px;
background: var(--v2-background-bg-layer-01); background: var(--v2-background-bg-layer-01);
border-radius: 4px 0 0 4px; border-radius: 4px 0 0 4px;
cursor: default;
transition: background 85ms ease-out; transition: background 85ms ease-out;
} }
[data-component="inline-input-v2"]:where([data-disabled]) [data-slot="inline-input-v2-prefix"] {
cursor: not-allowed;
}
[data-component="inline-input-v2"][data-label-width] [data-slot="inline-input-v2-prefix"] { [data-component="inline-input-v2"][data-label-width] [data-slot="inline-input-v2-prefix"] {
width: var(--inline-input-v2-label-width); width: var(--inline-input-v2-label-width);
min-width: var(--inline-input-v2-label-width); min-width: var(--inline-input-v2-label-width);
@@ -89,6 +94,7 @@
letter-spacing: -0.04px; letter-spacing: -0.04px;
color: var(--v2-text-text-muted); color: var(--v2-text-text-muted);
font-variation-settings: "slnt" 0; font-variation-settings: "slnt" 0;
user-select: none;
} }
[data-component="inline-input-v2"][data-numeric] [data-slot="inline-input-v2-prefix-text"] { [data-component="inline-input-v2"][data-numeric] [data-slot="inline-input-v2-prefix-text"] {
@@ -149,6 +155,7 @@
[data-component="inline-input-v2"] [data-slot="inline-input-v2-input"]::placeholder { [data-component="inline-input-v2"] [data-slot="inline-input-v2-input"]::placeholder {
color: var(--v2-text-text-faint); color: var(--v2-text-text-faint);
user-select: none;
} }
[data-component="inline-input-v2"][data-numeric] [data-slot="inline-input-v2-input"] { [data-component="inline-input-v2"][data-numeric] [data-slot="inline-input-v2-input"] {
@@ -37,6 +37,8 @@ export function InlineInputV2(props: InlineInputV2Props) {
"style", "style",
]) ])
let input: HTMLInputElement | undefined
return ( return (
<div <div
data-component="inline-input-v2" data-component="inline-input-v2"
@@ -59,7 +61,15 @@ export function InlineInputV2(props: InlineInputV2Props) {
: {}), : {}),
}} }}
> >
<div data-slot="inline-input-v2-prefix"> <div
data-slot="inline-input-v2-prefix"
onMouseDown={(event) => {
if (local.disabled || event.button !== 0) return
// Keep focus on the input without using a native <label>, so external labels still work.
event.preventDefault()
input?.focus()
}}
>
<span data-slot="inline-input-v2-prefix-text">{local.prefix}</span> <span data-slot="inline-input-v2-prefix-text">{local.prefix}</span>
</div> </div>
<div data-slot="inline-input-v2-divider" aria-hidden="true" /> <div data-slot="inline-input-v2-divider" aria-hidden="true" />
@@ -67,6 +77,11 @@ export function InlineInputV2(props: InlineInputV2Props) {
<div data-slot="inline-input-v2-value"> <div data-slot="inline-input-v2-value">
<input <input
{...inputProps} {...inputProps}
ref={(el) => {
input = el
const ref = inputProps.ref
if (typeof ref === "function") ref(el)
}}
type={inputProps.type ?? "text"} type={inputProps.type ?? "text"}
disabled={local.disabled} disabled={local.disabled}
aria-invalid={local.invalid ? true : undefined} aria-invalid={local.invalid ? true : undefined}
@@ -98,6 +98,7 @@
[data-component="text-input-v2"] [data-slot="text-input-v2-input"]::placeholder { [data-component="text-input-v2"] [data-slot="text-input-v2-input"]::placeholder {
color: var(--v2-text-text-faint); color: var(--v2-text-text-faint);
user-select: none;
} }
[data-component="text-input-v2"] [data-slot="text-input-v2-input"][type="search"]::-webkit-search-cancel-button { [data-component="text-input-v2"] [data-slot="text-input-v2-input"][type="search"]::-webkit-search-cancel-button {