feat(ui): updates to design system (#37471)
This commit is contained in:
@@ -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 (
|
||||||
|
|||||||
@@ -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"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user