@filipgutica/ui 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -0
- package/dist/components/UiAlert.vue.d.ts +18 -0
- package/dist/components/UiBadge.vue.d.ts +18 -0
- package/dist/components/UiButton.vue.d.ts +4 -2
- package/dist/components/UiCheckbox.vue.d.ts +24 -0
- package/dist/components/UiDialog.vue.d.ts +24 -0
- package/dist/components/UiField.vue.d.ts +21 -0
- package/dist/components/UiInput.vue.d.ts +19 -0
- package/dist/components/UiProgress.vue.d.ts +8 -0
- package/dist/components/UiSelect.vue.d.ts +27 -0
- package/dist/components/UiSurface.vue.d.ts +20 -0
- package/dist/components/field-context.d.ts +8 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +291 -11
- package/package.json +11 -3
- package/src/components.css +283 -15
- package/src/theme.css +3 -1
package/README.md
CHANGED
|
@@ -22,6 +22,18 @@ The theme exposes Tailwind utilities such as `bg-ui-bg`, `bg-ui-surface`,
|
|
|
22
22
|
|
|
23
23
|
## Vue components
|
|
24
24
|
|
|
25
|
+
The first application-focused set includes:
|
|
26
|
+
|
|
27
|
+
- `UiButton` with primary, secondary, ghost, danger, and text variants
|
|
28
|
+
- `UiInput`, `UiSelect`, and `UiField` for consistent form controls
|
|
29
|
+
- `UiCheckbox`, `UiBadge`, `UiAlert`, and `UiProgress` for state and feedback
|
|
30
|
+
- `UiSurface` for restrained content grouping
|
|
31
|
+
- `UiDialog`, built on Reka UI, for accessible modal interaction
|
|
32
|
+
|
|
33
|
+
Place `UiInput` or `UiSelect` inside `UiField`. The field supplies the control ID
|
|
34
|
+
and automatically connects its description or error through the corresponding
|
|
35
|
+
ARIA relationship.
|
|
36
|
+
|
|
25
37
|
```vue
|
|
26
38
|
<template>
|
|
27
39
|
<UiButton variant="secondary" size="compact">
|
|
@@ -73,3 +85,14 @@ redistribute theme assets remain responsible for their licenses.
|
|
|
73
85
|
pnpm install
|
|
74
86
|
pnpm verify
|
|
75
87
|
```
|
|
88
|
+
|
|
89
|
+
Commits follow the Conventional Commits format. Releases run from `main`:
|
|
90
|
+
|
|
91
|
+
- `fix:` publishes a patch release
|
|
92
|
+
- `feat:` publishes a minor release
|
|
93
|
+
- a `BREAKING CHANGE:` footer publishes a major release
|
|
94
|
+
|
|
95
|
+
The `release.yml` workflow publishes through npm trusted publishing with GitHub
|
|
96
|
+
OIDC. Configure the npm package's trusted publisher once with user
|
|
97
|
+
`filipgutica`, repository `ui`, and workflow filename `release.yml`; no npm token
|
|
98
|
+
is stored in GitHub.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface UiAlertProps {
|
|
2
|
+
tone?: 'neutral' | 'info' | 'success' | 'warning' | 'danger' | 'error';
|
|
3
|
+
}
|
|
4
|
+
declare var __VLS_8: {};
|
|
5
|
+
type __VLS_Slots = {} & {
|
|
6
|
+
default?: (props: typeof __VLS_8) => any;
|
|
7
|
+
};
|
|
8
|
+
declare const __VLS_base: import("vue").DefineComponent<UiAlertProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<UiAlertProps> & Readonly<{}>, {
|
|
9
|
+
tone: "neutral" | "info" | "success" | "warning" | "danger" | "error";
|
|
10
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
11
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
14
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
15
|
+
new (): {
|
|
16
|
+
$slots: S;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface UiBadgeProps {
|
|
2
|
+
tone?: 'neutral' | 'info' | 'success' | 'warning' | 'danger';
|
|
3
|
+
}
|
|
4
|
+
declare var __VLS_8: {};
|
|
5
|
+
type __VLS_Slots = {} & {
|
|
6
|
+
default?: (props: typeof __VLS_8) => any;
|
|
7
|
+
};
|
|
8
|
+
declare const __VLS_base: import("vue").DefineComponent<UiBadgeProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<UiBadgeProps> & Readonly<{}>, {
|
|
9
|
+
tone: "neutral" | "info" | "success" | "warning" | "danger";
|
|
10
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
11
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
14
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
15
|
+
new (): {
|
|
16
|
+
$slots: S;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export interface UiButtonProps {
|
|
2
2
|
disabled?: boolean;
|
|
3
|
+
loading?: boolean;
|
|
3
4
|
size?: 'default' | 'compact';
|
|
4
5
|
type?: 'button' | 'submit' | 'reset';
|
|
5
|
-
variant?: 'primary' | 'secondary' | 'text';
|
|
6
|
+
variant?: 'primary' | 'secondary' | 'ghost' | 'danger' | 'text';
|
|
6
7
|
}
|
|
7
8
|
declare var __VLS_8: {};
|
|
8
9
|
type __VLS_Slots = {} & {
|
|
@@ -10,9 +11,10 @@ type __VLS_Slots = {} & {
|
|
|
10
11
|
};
|
|
11
12
|
declare const __VLS_base: import("vue").DefineComponent<UiButtonProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<UiButtonProps> & Readonly<{}>, {
|
|
12
13
|
disabled: boolean;
|
|
14
|
+
loading: boolean;
|
|
13
15
|
size: "default" | "compact";
|
|
14
16
|
type: "button" | "submit" | "reset";
|
|
15
|
-
variant: "primary" | "secondary" | "text";
|
|
17
|
+
variant: "primary" | "secondary" | "ghost" | "danger" | "text";
|
|
16
18
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
17
19
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
18
20
|
declare const _default: typeof __VLS_export;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface UiCheckboxProps {
|
|
2
|
+
disabled?: boolean;
|
|
3
|
+
modelValue?: boolean;
|
|
4
|
+
}
|
|
5
|
+
declare var __VLS_15: {};
|
|
6
|
+
type __VLS_Slots = {} & {
|
|
7
|
+
default?: (props: typeof __VLS_15) => any;
|
|
8
|
+
};
|
|
9
|
+
declare const __VLS_base: import("vue").DefineComponent<UiCheckboxProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
10
|
+
"update:modelValue": (value: boolean) => any;
|
|
11
|
+
}, string, import("vue").PublicProps, Readonly<UiCheckboxProps> & Readonly<{
|
|
12
|
+
"onUpdate:modelValue"?: (value: boolean) => any;
|
|
13
|
+
}>, {
|
|
14
|
+
disabled: boolean;
|
|
15
|
+
modelValue: boolean;
|
|
16
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
17
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
18
|
+
declare const _default: typeof __VLS_export;
|
|
19
|
+
export default _default;
|
|
20
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
21
|
+
new (): {
|
|
22
|
+
$slots: S;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface UiDialogProps {
|
|
2
|
+
description?: string;
|
|
3
|
+
open: boolean;
|
|
4
|
+
title: string;
|
|
5
|
+
}
|
|
6
|
+
declare var __VLS_45: {}, __VLS_47: {};
|
|
7
|
+
type __VLS_Slots = {} & {
|
|
8
|
+
default?: (props: typeof __VLS_45) => any;
|
|
9
|
+
} & {
|
|
10
|
+
footer?: (props: typeof __VLS_47) => any;
|
|
11
|
+
};
|
|
12
|
+
declare const __VLS_base: import("vue").DefineComponent<UiDialogProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
13
|
+
"update:open": (value: boolean) => any;
|
|
14
|
+
}, string, import("vue").PublicProps, Readonly<UiDialogProps> & Readonly<{
|
|
15
|
+
"onUpdate:open"?: (value: boolean) => any;
|
|
16
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
17
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
18
|
+
declare const _default: typeof __VLS_export;
|
|
19
|
+
export default _default;
|
|
20
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
21
|
+
new (): {
|
|
22
|
+
$slots: S;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface UiFieldProps {
|
|
2
|
+
controlId: string;
|
|
3
|
+
description?: string;
|
|
4
|
+
error?: string;
|
|
5
|
+
label: string;
|
|
6
|
+
}
|
|
7
|
+
type __VLS_Slots = {
|
|
8
|
+
default(props: {
|
|
9
|
+
descriptionId: string | undefined;
|
|
10
|
+
errorId: string | undefined;
|
|
11
|
+
}): unknown;
|
|
12
|
+
};
|
|
13
|
+
declare const __VLS_base: import("vue").DefineComponent<UiFieldProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<UiFieldProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
14
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
15
|
+
declare const _default: typeof __VLS_export;
|
|
16
|
+
export default _default;
|
|
17
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
18
|
+
new (): {
|
|
19
|
+
$slots: S;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface UiInputProps {
|
|
2
|
+
disabled?: boolean;
|
|
3
|
+
id?: string;
|
|
4
|
+
invalid?: boolean;
|
|
5
|
+
modelValue?: string;
|
|
6
|
+
type?: 'text' | 'search' | 'email' | 'password' | 'url';
|
|
7
|
+
}
|
|
8
|
+
declare const __VLS_export: import("vue").DefineComponent<UiInputProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
9
|
+
"update:modelValue": (value: string) => any;
|
|
10
|
+
}, string, import("vue").PublicProps, Readonly<UiInputProps> & Readonly<{
|
|
11
|
+
"onUpdate:modelValue"?: (value: string) => any;
|
|
12
|
+
}>, {
|
|
13
|
+
disabled: boolean;
|
|
14
|
+
type: "text" | "search" | "email" | "password" | "url";
|
|
15
|
+
modelValue: string;
|
|
16
|
+
invalid: boolean;
|
|
17
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
18
|
+
declare const _default: typeof __VLS_export;
|
|
19
|
+
export default _default;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface UiProgressProps {
|
|
2
|
+
label: string;
|
|
3
|
+
max: number;
|
|
4
|
+
value: number | null;
|
|
5
|
+
}
|
|
6
|
+
declare const __VLS_export: import("vue").DefineComponent<UiProgressProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<UiProgressProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
7
|
+
declare const _default: typeof __VLS_export;
|
|
8
|
+
export default _default;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface UiSelectProps {
|
|
2
|
+
disabled?: boolean;
|
|
3
|
+
id?: string;
|
|
4
|
+
invalid?: boolean;
|
|
5
|
+
modelValue?: string;
|
|
6
|
+
}
|
|
7
|
+
declare var __VLS_10: {};
|
|
8
|
+
type __VLS_Slots = {} & {
|
|
9
|
+
default?: (props: typeof __VLS_10) => any;
|
|
10
|
+
};
|
|
11
|
+
declare const __VLS_base: import("vue").DefineComponent<UiSelectProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
12
|
+
"update:modelValue": (value: string) => any;
|
|
13
|
+
}, string, import("vue").PublicProps, Readonly<UiSelectProps> & Readonly<{
|
|
14
|
+
"onUpdate:modelValue"?: (value: string) => any;
|
|
15
|
+
}>, {
|
|
16
|
+
disabled: boolean;
|
|
17
|
+
modelValue: string;
|
|
18
|
+
invalid: boolean;
|
|
19
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
20
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
21
|
+
declare const _default: typeof __VLS_export;
|
|
22
|
+
export default _default;
|
|
23
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
24
|
+
new (): {
|
|
25
|
+
$slots: S;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface UiSurfaceProps {
|
|
2
|
+
as?: string;
|
|
3
|
+
padding?: 'none' | 'compact' | 'default';
|
|
4
|
+
}
|
|
5
|
+
declare var __VLS_8: {};
|
|
6
|
+
type __VLS_Slots = {} & {
|
|
7
|
+
default?: (props: typeof __VLS_8) => any;
|
|
8
|
+
};
|
|
9
|
+
declare const __VLS_base: import("vue").DefineComponent<UiSurfaceProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<UiSurfaceProps> & Readonly<{}>, {
|
|
10
|
+
as: string;
|
|
11
|
+
padding: "none" | "compact" | "default";
|
|
12
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
13
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
14
|
+
declare const _default: typeof __VLS_export;
|
|
15
|
+
export default _default;
|
|
16
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
17
|
+
new (): {
|
|
18
|
+
$slots: S;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ComputedRef, InjectionKey } from 'vue';
|
|
2
|
+
export interface UiFieldContext {
|
|
3
|
+
controlId: ComputedRef<string>;
|
|
4
|
+
descriptionId: ComputedRef<string | undefined>;
|
|
5
|
+
errorId: ComputedRef<string | undefined>;
|
|
6
|
+
invalid: ComputedRef<boolean>;
|
|
7
|
+
}
|
|
8
|
+
export declare const uiFieldContextKey: InjectionKey<UiFieldContext>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,20 @@
|
|
|
1
1
|
export { default as UiButton } from './components/UiButton.vue';
|
|
2
2
|
export type { UiButtonProps } from './components/UiButton.vue';
|
|
3
|
+
export { default as UiAlert } from './components/UiAlert.vue';
|
|
4
|
+
export type { UiAlertProps } from './components/UiAlert.vue';
|
|
5
|
+
export { default as UiBadge } from './components/UiBadge.vue';
|
|
6
|
+
export type { UiBadgeProps } from './components/UiBadge.vue';
|
|
7
|
+
export { default as UiCheckbox } from './components/UiCheckbox.vue';
|
|
8
|
+
export type { UiCheckboxProps } from './components/UiCheckbox.vue';
|
|
9
|
+
export { default as UiDialog } from './components/UiDialog.vue';
|
|
10
|
+
export type { UiDialogProps } from './components/UiDialog.vue';
|
|
11
|
+
export { default as UiField } from './components/UiField.vue';
|
|
12
|
+
export type { UiFieldProps } from './components/UiField.vue';
|
|
13
|
+
export { default as UiInput } from './components/UiInput.vue';
|
|
14
|
+
export type { UiInputProps } from './components/UiInput.vue';
|
|
15
|
+
export { default as UiProgress } from './components/UiProgress.vue';
|
|
16
|
+
export type { UiProgressProps } from './components/UiProgress.vue';
|
|
17
|
+
export { default as UiSelect } from './components/UiSelect.vue';
|
|
18
|
+
export type { UiSelectProps } from './components/UiSelect.vue';
|
|
19
|
+
export { default as UiSurface } from './components/UiSurface.vue';
|
|
20
|
+
export type { UiSurfaceProps } from './components/UiSurface.vue';
|
package/dist/index.js
CHANGED
|
@@ -1,36 +1,316 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Primitive as
|
|
1
|
+
import { computed as e, createBlock as t, createCommentVNode as n, createElementBlock as r, createElementVNode as i, createTextVNode as a, createVNode as o, defineComponent as s, inject as c, normalizeStyle as l, openBlock as u, provide as d, renderSlot as f, toDisplayString as p, unref as m, withCtx as h } from "vue";
|
|
2
|
+
import { CheckboxIndicator as g, CheckboxRoot as _, DialogClose as v, DialogContent as y, DialogDescription as b, DialogOverlay as x, DialogPortal as S, DialogRoot as C, DialogTitle as w, Primitive as T, ProgressIndicator as E, ProgressRoot as D } from "reka-ui";
|
|
3
3
|
//#endregion
|
|
4
4
|
//#region src/components/UiButton.vue
|
|
5
|
-
var
|
|
5
|
+
var O = /* @__PURE__ */ s({
|
|
6
6
|
__name: "UiButton",
|
|
7
7
|
props: {
|
|
8
8
|
disabled: {
|
|
9
9
|
type: Boolean,
|
|
10
10
|
default: !1
|
|
11
11
|
},
|
|
12
|
+
loading: {
|
|
13
|
+
type: Boolean,
|
|
14
|
+
default: !1
|
|
15
|
+
},
|
|
12
16
|
size: { default: "default" },
|
|
13
17
|
type: { default: "button" },
|
|
14
18
|
variant: { default: "primary" }
|
|
15
19
|
},
|
|
16
|
-
setup(
|
|
17
|
-
return (
|
|
20
|
+
setup(e) {
|
|
21
|
+
return (n, r) => (u(), t(m(T), {
|
|
18
22
|
as: "button",
|
|
19
23
|
class: "fg-button",
|
|
20
|
-
"data-size":
|
|
21
|
-
"data-variant":
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
"data-size": e.size,
|
|
25
|
+
"data-variant": e.variant,
|
|
26
|
+
"aria-busy": e.loading ? "true" : void 0,
|
|
27
|
+
disabled: e.disabled || e.loading,
|
|
28
|
+
type: e.type
|
|
24
29
|
}, {
|
|
25
|
-
default:
|
|
30
|
+
default: h(() => [f(n.$slots, "default")]),
|
|
26
31
|
_: 3
|
|
27
32
|
}, 8, [
|
|
28
33
|
"data-size",
|
|
29
34
|
"data-variant",
|
|
35
|
+
"aria-busy",
|
|
30
36
|
"disabled",
|
|
31
37
|
"type"
|
|
32
38
|
]));
|
|
33
39
|
}
|
|
40
|
+
}), k = /* @__PURE__ */ s({
|
|
41
|
+
__name: "UiAlert",
|
|
42
|
+
props: { tone: { default: "neutral" } },
|
|
43
|
+
setup(e) {
|
|
44
|
+
return (n, r) => (u(), t(m(T), {
|
|
45
|
+
as: "div",
|
|
46
|
+
class: "fg-alert",
|
|
47
|
+
"data-tone": e.tone,
|
|
48
|
+
role: e.tone === "danger" || e.tone === "error" ? "alert" : "status"
|
|
49
|
+
}, {
|
|
50
|
+
default: h(() => [f(n.$slots, "default")]),
|
|
51
|
+
_: 3
|
|
52
|
+
}, 8, ["data-tone", "role"]));
|
|
53
|
+
}
|
|
54
|
+
}), A = /* @__PURE__ */ s({
|
|
55
|
+
__name: "UiBadge",
|
|
56
|
+
props: { tone: { default: "neutral" } },
|
|
57
|
+
setup(e) {
|
|
58
|
+
return (n, r) => (u(), t(m(T), {
|
|
59
|
+
as: "span",
|
|
60
|
+
class: "fg-badge",
|
|
61
|
+
"data-tone": e.tone
|
|
62
|
+
}, {
|
|
63
|
+
default: h(() => [f(n.$slots, "default")]),
|
|
64
|
+
_: 3
|
|
65
|
+
}, 8, ["data-tone"]));
|
|
66
|
+
}
|
|
67
|
+
}), j = ["data-disabled"], M = { class: "fg-checkbox__label" }, N = /* @__PURE__ */ s({
|
|
68
|
+
__name: "UiCheckbox",
|
|
69
|
+
props: {
|
|
70
|
+
disabled: {
|
|
71
|
+
type: Boolean,
|
|
72
|
+
default: !1
|
|
73
|
+
},
|
|
74
|
+
modelValue: {
|
|
75
|
+
type: Boolean,
|
|
76
|
+
default: !1
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
emits: ["update:modelValue"],
|
|
80
|
+
setup(e, { emit: t }) {
|
|
81
|
+
let n = t, s = (e) => {
|
|
82
|
+
n("update:modelValue", e === !0);
|
|
83
|
+
};
|
|
84
|
+
return (t, n) => (u(), r("label", {
|
|
85
|
+
class: "fg-checkbox",
|
|
86
|
+
"data-disabled": e.disabled ? "true" : void 0
|
|
87
|
+
}, [o(m(_), {
|
|
88
|
+
class: "fg-checkbox__control",
|
|
89
|
+
disabled: e.disabled,
|
|
90
|
+
"model-value": e.modelValue,
|
|
91
|
+
"onUpdate:modelValue": s
|
|
92
|
+
}, {
|
|
93
|
+
default: h(() => [o(m(g), { class: "fg-checkbox__indicator" }, {
|
|
94
|
+
default: h(() => [...n[0] ||= [a("✓", -1)]]),
|
|
95
|
+
_: 1
|
|
96
|
+
})]),
|
|
97
|
+
_: 1
|
|
98
|
+
}, 8, ["disabled", "model-value"]), i("span", M, [f(t.$slots, "default")])], 8, j));
|
|
99
|
+
}
|
|
100
|
+
}), P = { class: "fg-dialog__header" }, F = { class: "fg-dialog__body" }, I = {
|
|
101
|
+
key: 0,
|
|
102
|
+
class: "fg-dialog__footer"
|
|
103
|
+
}, L = /* @__PURE__ */ s({
|
|
104
|
+
__name: "UiDialog",
|
|
105
|
+
props: {
|
|
106
|
+
description: {},
|
|
107
|
+
open: { type: Boolean },
|
|
108
|
+
title: {}
|
|
109
|
+
},
|
|
110
|
+
emits: ["update:open"],
|
|
111
|
+
setup(e, { emit: s }) {
|
|
112
|
+
let c = s;
|
|
113
|
+
return (s, l) => (u(), t(m(C), {
|
|
114
|
+
open: e.open,
|
|
115
|
+
"onUpdate:open": l[0] ||= (e) => c("update:open", e)
|
|
116
|
+
}, {
|
|
117
|
+
default: h(() => [o(m(S), null, {
|
|
118
|
+
default: h(() => [o(m(x), { class: "fg-dialog__overlay" }), o(m(y), {
|
|
119
|
+
class: "fg-dialog__content",
|
|
120
|
+
"aria-modal": "true"
|
|
121
|
+
}, {
|
|
122
|
+
default: h(() => [
|
|
123
|
+
i("div", P, [i("div", null, [o(m(w), { class: "fg-dialog__title" }, {
|
|
124
|
+
default: h(() => [a(p(e.title), 1)]),
|
|
125
|
+
_: 1
|
|
126
|
+
}), e.description ? (u(), t(m(b), {
|
|
127
|
+
key: 0,
|
|
128
|
+
class: "fg-dialog__description"
|
|
129
|
+
}, {
|
|
130
|
+
default: h(() => [a(p(e.description), 1)]),
|
|
131
|
+
_: 1
|
|
132
|
+
})) : n("", !0)]), o(m(v), {
|
|
133
|
+
class: "fg-dialog__close",
|
|
134
|
+
"aria-label": "Close dialog"
|
|
135
|
+
}, {
|
|
136
|
+
default: h(() => [...l[1] ||= [a("×", -1)]]),
|
|
137
|
+
_: 1
|
|
138
|
+
})]),
|
|
139
|
+
i("div", F, [f(s.$slots, "default")]),
|
|
140
|
+
s.$slots.footer ? (u(), r("div", I, [f(s.$slots, "footer")])) : n("", !0)
|
|
141
|
+
]),
|
|
142
|
+
_: 3
|
|
143
|
+
})]),
|
|
144
|
+
_: 3
|
|
145
|
+
})]),
|
|
146
|
+
_: 3
|
|
147
|
+
}, 8, ["open"]));
|
|
148
|
+
}
|
|
149
|
+
}), R = Symbol("UiFieldContext"), z = ["data-invalid"], B = ["for"], V = ["id"], H = ["id"], U = /* @__PURE__ */ s({
|
|
150
|
+
__name: "UiField",
|
|
151
|
+
props: {
|
|
152
|
+
controlId: {},
|
|
153
|
+
description: {},
|
|
154
|
+
error: {},
|
|
155
|
+
label: {}
|
|
156
|
+
},
|
|
157
|
+
setup(t) {
|
|
158
|
+
let a = t, o = e(() => a.description && !a.error ? `${a.controlId}-description` : void 0), s = e(() => a.error ? `${a.controlId}-error` : void 0), c = e(() => !!a.error);
|
|
159
|
+
return d(R, {
|
|
160
|
+
controlId: e(() => a.controlId),
|
|
161
|
+
descriptionId: o,
|
|
162
|
+
errorId: s,
|
|
163
|
+
invalid: c
|
|
164
|
+
}), (e, a) => (u(), r("div", {
|
|
165
|
+
class: "fg-field",
|
|
166
|
+
"data-invalid": t.error ? "true" : void 0
|
|
167
|
+
}, [
|
|
168
|
+
i("label", {
|
|
169
|
+
class: "fg-field__label",
|
|
170
|
+
for: t.controlId
|
|
171
|
+
}, p(t.label), 9, B),
|
|
172
|
+
f(e.$slots, "default", {
|
|
173
|
+
descriptionId: o.value,
|
|
174
|
+
errorId: s.value
|
|
175
|
+
}),
|
|
176
|
+
t.description && !t.error ? (u(), r("p", {
|
|
177
|
+
key: 0,
|
|
178
|
+
id: o.value,
|
|
179
|
+
class: "fg-field__description",
|
|
180
|
+
"data-field-description": ""
|
|
181
|
+
}, p(t.description), 9, V)) : n("", !0),
|
|
182
|
+
t.error ? (u(), r("p", {
|
|
183
|
+
key: 1,
|
|
184
|
+
id: s.value,
|
|
185
|
+
class: "fg-field__error",
|
|
186
|
+
"data-field-error": ""
|
|
187
|
+
}, p(t.error), 9, H)) : n("", !0)
|
|
188
|
+
], 8, z));
|
|
189
|
+
}
|
|
190
|
+
}), W = /* @__PURE__ */ s({
|
|
191
|
+
__name: "UiInput",
|
|
192
|
+
props: {
|
|
193
|
+
disabled: {
|
|
194
|
+
type: Boolean,
|
|
195
|
+
default: !1
|
|
196
|
+
},
|
|
197
|
+
id: {},
|
|
198
|
+
invalid: {
|
|
199
|
+
type: Boolean,
|
|
200
|
+
default: !1
|
|
201
|
+
},
|
|
202
|
+
modelValue: { default: "" },
|
|
203
|
+
type: { default: "text" }
|
|
204
|
+
},
|
|
205
|
+
emits: ["update:modelValue"],
|
|
206
|
+
setup(e, { emit: n }) {
|
|
207
|
+
let r = c(R, void 0), i = n, a = (e) => {
|
|
208
|
+
e.currentTarget instanceof HTMLInputElement && i("update:modelValue", e.currentTarget.value);
|
|
209
|
+
};
|
|
210
|
+
return (n, i) => (u(), t(m(T), {
|
|
211
|
+
as: "input",
|
|
212
|
+
class: "fg-input",
|
|
213
|
+
id: e.id ?? m(r)?.controlId.value,
|
|
214
|
+
"aria-describedby": m(r)?.descriptionId.value,
|
|
215
|
+
"aria-errormessage": m(r)?.errorId.value,
|
|
216
|
+
"aria-invalid": e.invalid || m(r)?.invalid.value ? "true" : void 0,
|
|
217
|
+
disabled: e.disabled,
|
|
218
|
+
type: e.type,
|
|
219
|
+
value: e.modelValue,
|
|
220
|
+
onInput: a
|
|
221
|
+
}, null, 8, [
|
|
222
|
+
"id",
|
|
223
|
+
"aria-describedby",
|
|
224
|
+
"aria-errormessage",
|
|
225
|
+
"aria-invalid",
|
|
226
|
+
"disabled",
|
|
227
|
+
"type",
|
|
228
|
+
"value"
|
|
229
|
+
]));
|
|
230
|
+
}
|
|
231
|
+
}), G = /* @__PURE__ */ s({
|
|
232
|
+
__name: "UiProgress",
|
|
233
|
+
props: {
|
|
234
|
+
label: {},
|
|
235
|
+
max: {},
|
|
236
|
+
value: {}
|
|
237
|
+
},
|
|
238
|
+
setup(n) {
|
|
239
|
+
let r = n, i = e(() => r.value === null || r.max <= 0 ? 0 : Math.min(100, Math.max(0, r.value / r.max * 100)));
|
|
240
|
+
return (e, r) => (u(), t(m(D), {
|
|
241
|
+
class: "fg-progress",
|
|
242
|
+
"aria-label": n.label,
|
|
243
|
+
max: n.max,
|
|
244
|
+
"model-value": n.value
|
|
245
|
+
}, {
|
|
246
|
+
default: h(() => [o(m(E), {
|
|
247
|
+
class: "fg-progress__indicator",
|
|
248
|
+
style: l({ transform: `translateX(-${100 - i.value}%)` })
|
|
249
|
+
}, null, 8, ["style"])]),
|
|
250
|
+
_: 1
|
|
251
|
+
}, 8, [
|
|
252
|
+
"aria-label",
|
|
253
|
+
"max",
|
|
254
|
+
"model-value"
|
|
255
|
+
]));
|
|
256
|
+
}
|
|
257
|
+
}), K = /* @__PURE__ */ s({
|
|
258
|
+
__name: "UiSelect",
|
|
259
|
+
props: {
|
|
260
|
+
disabled: {
|
|
261
|
+
type: Boolean,
|
|
262
|
+
default: !1
|
|
263
|
+
},
|
|
264
|
+
id: {},
|
|
265
|
+
invalid: {
|
|
266
|
+
type: Boolean,
|
|
267
|
+
default: !1
|
|
268
|
+
},
|
|
269
|
+
modelValue: { default: "" }
|
|
270
|
+
},
|
|
271
|
+
emits: ["update:modelValue"],
|
|
272
|
+
setup(e, { emit: n }) {
|
|
273
|
+
let r = c(R, void 0), i = n, a = (e) => {
|
|
274
|
+
e.currentTarget instanceof HTMLSelectElement && i("update:modelValue", e.currentTarget.value);
|
|
275
|
+
};
|
|
276
|
+
return (n, i) => (u(), t(m(T), {
|
|
277
|
+
as: "select",
|
|
278
|
+
class: "fg-select",
|
|
279
|
+
id: e.id ?? m(r)?.controlId.value,
|
|
280
|
+
"aria-describedby": m(r)?.descriptionId.value,
|
|
281
|
+
"aria-errormessage": m(r)?.errorId.value,
|
|
282
|
+
"aria-invalid": e.invalid || m(r)?.invalid.value ? "true" : void 0,
|
|
283
|
+
disabled: e.disabled,
|
|
284
|
+
value: e.modelValue,
|
|
285
|
+
onChange: a
|
|
286
|
+
}, {
|
|
287
|
+
default: h(() => [f(n.$slots, "default")]),
|
|
288
|
+
_: 3
|
|
289
|
+
}, 8, [
|
|
290
|
+
"id",
|
|
291
|
+
"aria-describedby",
|
|
292
|
+
"aria-errormessage",
|
|
293
|
+
"aria-invalid",
|
|
294
|
+
"disabled",
|
|
295
|
+
"value"
|
|
296
|
+
]));
|
|
297
|
+
}
|
|
298
|
+
}), q = /* @__PURE__ */ s({
|
|
299
|
+
__name: "UiSurface",
|
|
300
|
+
props: {
|
|
301
|
+
as: { default: "section" },
|
|
302
|
+
padding: { default: "default" }
|
|
303
|
+
},
|
|
304
|
+
setup(e) {
|
|
305
|
+
return (n, r) => (u(), t(m(T), {
|
|
306
|
+
as: e.as,
|
|
307
|
+
class: "fg-surface",
|
|
308
|
+
"data-padding": e.padding
|
|
309
|
+
}, {
|
|
310
|
+
default: h(() => [f(n.$slots, "default")]),
|
|
311
|
+
_: 3
|
|
312
|
+
}, 8, ["as", "data-padding"]));
|
|
313
|
+
}
|
|
34
314
|
});
|
|
35
315
|
//#endregion
|
|
36
|
-
export {
|
|
316
|
+
export { k as UiAlert, A as UiBadge, O as UiButton, N as UiCheckbox, L as UiDialog, U as UiField, W as UiInput, G as UiProgress, K as UiSelect, q as UiSurface };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@filipgutica/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "A compact Vue design system with Tailwind CSS and VS Code theme support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": [
|
|
@@ -32,16 +32,19 @@
|
|
|
32
32
|
"scripts": {
|
|
33
33
|
"build": "vite build && vue-tsc -p tsconfig.build.json --emitDeclarationOnly",
|
|
34
34
|
"prepublishOnly": "pnpm verify",
|
|
35
|
+
"release": "semantic-release",
|
|
36
|
+
"release:dry-run": "semantic-release --dry-run --no-ci",
|
|
35
37
|
"test": "vitest run",
|
|
36
38
|
"typecheck": "vue-tsc -p tsconfig.json --noEmit",
|
|
37
|
-
"verify": "pnpm typecheck && pnpm test && pnpm build && pnpm pack --dry-run"
|
|
39
|
+
"verify": "pnpm typecheck && pnpm test && pnpm build && pnpm pack --dry-run && publint"
|
|
38
40
|
},
|
|
39
41
|
"engines": {
|
|
40
42
|
"node": ">=22.12"
|
|
41
43
|
},
|
|
42
44
|
"packageManager": "pnpm@11.6.0",
|
|
43
45
|
"publishConfig": {
|
|
44
|
-
"access": "public"
|
|
46
|
+
"access": "public",
|
|
47
|
+
"provenance": true
|
|
45
48
|
},
|
|
46
49
|
"license": "MIT",
|
|
47
50
|
"repository": {
|
|
@@ -61,10 +64,15 @@
|
|
|
61
64
|
"vue": ">=3.4.0"
|
|
62
65
|
},
|
|
63
66
|
"devDependencies": {
|
|
67
|
+
"@commitlint/cli": "^21.2.2",
|
|
68
|
+
"@commitlint/config-conventional": "^21.2.2",
|
|
64
69
|
"@types/node": "^26.0.0",
|
|
65
70
|
"@vitejs/plugin-vue": "^6.0.0",
|
|
66
71
|
"@vue/test-utils": "^2.4.6",
|
|
72
|
+
"conventional-changelog-conventionalcommits": "^9.3.1",
|
|
67
73
|
"happy-dom": "^20.12.2",
|
|
74
|
+
"publint": "^0.3.24",
|
|
75
|
+
"semantic-release": "^25.0.9",
|
|
68
76
|
"tailwindcss": "^4.3.3",
|
|
69
77
|
"typescript": "^5.9.3",
|
|
70
78
|
"vite": "^8.2.2",
|
package/src/components.css
CHANGED
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
@layer components {
|
|
2
|
+
.fg-button,
|
|
3
|
+
.fg-input,
|
|
4
|
+
.fg-select,
|
|
5
|
+
.fg-dialog__close {
|
|
6
|
+
min-height: 2.5rem;
|
|
7
|
+
border: 1px solid transparent;
|
|
8
|
+
border-radius: var(--radius-control);
|
|
9
|
+
font: inherit;
|
|
10
|
+
}
|
|
11
|
+
|
|
2
12
|
.fg-button {
|
|
3
13
|
display: inline-flex;
|
|
4
14
|
align-items: center;
|
|
5
15
|
justify-content: center;
|
|
6
16
|
gap: 0.5rem;
|
|
7
|
-
|
|
8
|
-
border-radius: var(--radius-control);
|
|
9
|
-
padding: 0.65rem 0.9rem;
|
|
17
|
+
padding: 0.55rem 0.85rem;
|
|
10
18
|
color: var(--color-button-text);
|
|
11
19
|
background: var(--color-button-bg);
|
|
12
|
-
font:
|
|
13
|
-
|
|
20
|
+
font-weight: 680;
|
|
21
|
+
line-height: 1.25;
|
|
14
22
|
cursor: pointer;
|
|
15
23
|
}
|
|
16
24
|
|
|
@@ -18,29 +26,49 @@
|
|
|
18
26
|
background: var(--color-button-hover);
|
|
19
27
|
}
|
|
20
28
|
|
|
21
|
-
.fg-button:
|
|
22
|
-
|
|
23
|
-
|
|
29
|
+
.fg-button:disabled,
|
|
30
|
+
.fg-input:disabled,
|
|
31
|
+
.fg-select:disabled,
|
|
32
|
+
.fg-checkbox[data-disabled="true"] {
|
|
33
|
+
cursor: not-allowed;
|
|
34
|
+
opacity: 0.58;
|
|
24
35
|
}
|
|
25
36
|
|
|
26
|
-
.fg-button
|
|
37
|
+
.fg-button[aria-busy="true"] {
|
|
27
38
|
cursor: wait;
|
|
28
|
-
opacity: 0.6;
|
|
29
39
|
}
|
|
30
40
|
|
|
31
41
|
.fg-button[data-size="compact"] {
|
|
32
|
-
|
|
33
|
-
|
|
42
|
+
min-height: 2rem;
|
|
43
|
+
padding: 0.35rem 0.6rem;
|
|
44
|
+
font-size: 0.8125rem;
|
|
34
45
|
}
|
|
35
46
|
|
|
36
47
|
.fg-button[data-variant="secondary"] {
|
|
37
48
|
border-color: var(--color-border);
|
|
38
49
|
color: var(--color-text);
|
|
39
|
-
background: var(--color-surface);
|
|
50
|
+
background: var(--color-surface-raised);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.fg-button[data-variant="secondary"]:hover:not(:disabled),
|
|
54
|
+
.fg-button[data-variant="ghost"]:hover:not(:disabled) {
|
|
55
|
+
color: var(--color-text);
|
|
56
|
+
background: var(--color-row-hover);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.fg-button[data-variant="ghost"] {
|
|
60
|
+
color: var(--color-muted);
|
|
61
|
+
background: transparent;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.fg-button[data-variant="danger"] {
|
|
65
|
+
color: var(--color-error);
|
|
66
|
+
background: var(--color-error-surface);
|
|
40
67
|
}
|
|
41
68
|
|
|
42
69
|
.fg-button[data-variant="text"] {
|
|
43
|
-
|
|
70
|
+
min-height: auto;
|
|
71
|
+
padding: 0;
|
|
44
72
|
color: var(--color-link);
|
|
45
73
|
background: transparent;
|
|
46
74
|
text-decoration: underline;
|
|
@@ -52,8 +80,248 @@
|
|
|
52
80
|
background: transparent;
|
|
53
81
|
}
|
|
54
82
|
|
|
55
|
-
|
|
83
|
+
.fg-input,
|
|
84
|
+
.fg-select {
|
|
85
|
+
width: 100%;
|
|
86
|
+
padding: 0.5rem 0.7rem;
|
|
87
|
+
border-color: var(--color-input-border);
|
|
88
|
+
color: var(--color-input-text);
|
|
89
|
+
background: var(--color-input-bg);
|
|
90
|
+
line-height: 1.35;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.fg-input::placeholder {
|
|
94
|
+
color: var(--color-input-placeholder);
|
|
95
|
+
opacity: 1;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.fg-input[aria-invalid="true"],
|
|
99
|
+
.fg-select[aria-invalid="true"] {
|
|
100
|
+
border-color: var(--color-error);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.fg-field {
|
|
104
|
+
display: grid;
|
|
105
|
+
gap: 0.4rem;
|
|
106
|
+
min-width: 0;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.fg-field__label {
|
|
110
|
+
color: var(--color-muted);
|
|
111
|
+
font-size: 0.8125rem;
|
|
112
|
+
font-weight: 680;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.fg-field__description,
|
|
116
|
+
.fg-field__error {
|
|
117
|
+
margin: 0;
|
|
118
|
+
font-size: 0.8125rem;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.fg-field__description { color: var(--color-muted); }
|
|
122
|
+
.fg-field__error { color: var(--color-error); }
|
|
123
|
+
|
|
124
|
+
.fg-checkbox {
|
|
125
|
+
display: inline-flex;
|
|
126
|
+
align-items: flex-start;
|
|
127
|
+
gap: 0.65rem;
|
|
128
|
+
color: var(--color-text);
|
|
129
|
+
cursor: pointer;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.fg-checkbox__control {
|
|
133
|
+
display: inline-grid;
|
|
134
|
+
flex: none;
|
|
135
|
+
width: 1.15rem;
|
|
136
|
+
height: 1.15rem;
|
|
137
|
+
margin-top: 0.1rem;
|
|
138
|
+
place-items: center;
|
|
139
|
+
border: 1px solid var(--color-input-border);
|
|
140
|
+
border-radius: 0.3rem;
|
|
141
|
+
color: var(--color-button-text);
|
|
142
|
+
background: var(--color-input-bg);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.fg-checkbox__control[data-state="checked"] {
|
|
146
|
+
border-color: var(--color-button-bg);
|
|
147
|
+
background: var(--color-button-bg);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.fg-checkbox__indicator {
|
|
151
|
+
font-size: 0.8rem;
|
|
152
|
+
font-weight: 800;
|
|
153
|
+
line-height: 1;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.fg-checkbox__label { line-height: 1.4; }
|
|
157
|
+
|
|
158
|
+
.fg-badge {
|
|
159
|
+
display: inline-flex;
|
|
160
|
+
align-items: center;
|
|
161
|
+
width: fit-content;
|
|
162
|
+
border: 1px solid var(--color-border-subtle);
|
|
163
|
+
border-radius: var(--radius-pill);
|
|
164
|
+
padding: 0.18rem 0.48rem;
|
|
165
|
+
color: var(--color-muted);
|
|
166
|
+
background: var(--color-surface-muted);
|
|
167
|
+
font-size: 0.75rem;
|
|
168
|
+
font-weight: 700;
|
|
169
|
+
line-height: 1.25;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.fg-badge[data-tone="info"] { color: var(--color-info); background: var(--color-info-surface); }
|
|
173
|
+
.fg-badge[data-tone="success"] { color: var(--color-success); background: var(--color-success-surface); }
|
|
174
|
+
.fg-badge[data-tone="warning"] { color: var(--color-warning); background: var(--color-warning-surface); }
|
|
175
|
+
.fg-badge[data-tone="danger"] { color: var(--color-error); background: var(--color-error-surface); }
|
|
176
|
+
|
|
177
|
+
.fg-alert {
|
|
178
|
+
display: flex;
|
|
179
|
+
align-items: flex-start;
|
|
180
|
+
gap: 0.75rem;
|
|
181
|
+
padding: 0.85rem 1rem;
|
|
182
|
+
border: 1px solid var(--color-border-subtle);
|
|
183
|
+
border-radius: var(--radius-control);
|
|
184
|
+
color: var(--color-text);
|
|
185
|
+
background: var(--color-surface);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.fg-alert[data-tone="info"] { background: var(--color-info-surface); }
|
|
189
|
+
.fg-alert[data-tone="success"] { background: var(--color-success-surface); }
|
|
190
|
+
.fg-alert[data-tone="warning"] { background: var(--color-warning-surface); }
|
|
191
|
+
.fg-alert[data-tone="danger"],
|
|
192
|
+
.fg-alert[data-tone="error"] {
|
|
193
|
+
border-color: var(--color-error);
|
|
194
|
+
color: var(--color-error);
|
|
195
|
+
background: var(--color-error-surface);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.fg-surface {
|
|
199
|
+
border: 1px solid var(--color-border-subtle);
|
|
200
|
+
border-radius: var(--radius-panel);
|
|
201
|
+
background: var(--color-surface-raised);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.fg-surface[data-padding="compact"] { padding: 0.85rem; }
|
|
205
|
+
.fg-surface[data-padding="default"] { padding: 1.2rem; }
|
|
206
|
+
|
|
207
|
+
.fg-progress {
|
|
208
|
+
position: relative;
|
|
209
|
+
height: 0.55rem;
|
|
210
|
+
overflow: hidden;
|
|
211
|
+
border-radius: var(--radius-pill);
|
|
212
|
+
background: var(--color-surface-muted);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.fg-progress__indicator {
|
|
216
|
+
width: 100%;
|
|
217
|
+
height: 100%;
|
|
218
|
+
border-radius: inherit;
|
|
219
|
+
background: var(--color-progress);
|
|
220
|
+
transition: transform var(--duration-fast) ease-out;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.fg-dialog__overlay {
|
|
224
|
+
position: fixed;
|
|
225
|
+
inset: 0;
|
|
226
|
+
z-index: 50;
|
|
227
|
+
background: var(--color-overlay);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.fg-dialog__content {
|
|
231
|
+
position: fixed;
|
|
232
|
+
z-index: 51;
|
|
233
|
+
top: 50%;
|
|
234
|
+
left: 50%;
|
|
235
|
+
display: grid;
|
|
236
|
+
width: min(42rem, calc(100vw - 2rem));
|
|
237
|
+
max-height: min(42rem, calc(100vh - 2rem));
|
|
238
|
+
overflow: hidden;
|
|
239
|
+
transform: translate(-50%, -50%);
|
|
240
|
+
border: 1px solid var(--color-border);
|
|
241
|
+
border-radius: var(--radius-panel);
|
|
242
|
+
color: var(--color-text);
|
|
243
|
+
background: var(--color-surface-raised);
|
|
244
|
+
box-shadow: var(--shadow-dialog);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.fg-dialog__header,
|
|
248
|
+
.fg-dialog__footer {
|
|
249
|
+
display: flex;
|
|
250
|
+
align-items: flex-start;
|
|
251
|
+
justify-content: space-between;
|
|
252
|
+
gap: 1rem;
|
|
253
|
+
padding: 1rem 1.2rem;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.fg-dialog__header { border-bottom: 1px solid var(--color-border-subtle); }
|
|
257
|
+
.fg-dialog__footer { justify-content: flex-end; border-top: 1px solid var(--color-border-subtle); }
|
|
258
|
+
|
|
259
|
+
.fg-dialog__title {
|
|
260
|
+
margin: 0;
|
|
261
|
+
font-size: 1.1rem;
|
|
262
|
+
font-weight: 750;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.fg-dialog__description {
|
|
266
|
+
margin: 0.25rem 0 0;
|
|
267
|
+
color: var(--color-muted);
|
|
268
|
+
font-size: 0.875rem;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.fg-dialog__body {
|
|
272
|
+
min-height: 0;
|
|
273
|
+
overflow: auto;
|
|
274
|
+
padding: 1.2rem;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.fg-dialog__close {
|
|
278
|
+
display: inline-grid;
|
|
279
|
+
flex: none;
|
|
280
|
+
width: 2.5rem;
|
|
281
|
+
padding: 0;
|
|
282
|
+
place-items: center;
|
|
283
|
+
color: var(--color-muted);
|
|
284
|
+
background: transparent;
|
|
285
|
+
font-size: 1.35rem;
|
|
286
|
+
cursor: pointer;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.fg-dialog__close:hover { color: var(--color-text); background: var(--color-row-hover); }
|
|
290
|
+
|
|
291
|
+
.fg-button:focus-visible,
|
|
292
|
+
.fg-input:focus-visible,
|
|
293
|
+
.fg-select:focus-visible,
|
|
294
|
+
.fg-checkbox__control:focus-visible,
|
|
295
|
+
.fg-dialog__close:focus-visible,
|
|
296
|
+
.fg-dialog__content:focus-visible {
|
|
297
|
+
outline: 3px solid var(--color-focus);
|
|
298
|
+
outline-offset: 2px;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
:root.high-contrast .fg-button,
|
|
302
|
+
:root.high-contrast .fg-input,
|
|
303
|
+
:root.high-contrast .fg-select,
|
|
304
|
+
:root.high-contrast .fg-checkbox__control,
|
|
305
|
+
:root.high-contrast .fg-alert,
|
|
306
|
+
:root.high-contrast .fg-surface,
|
|
307
|
+
:root.high-contrast .fg-dialog__content {
|
|
56
308
|
border-width: 2px;
|
|
57
309
|
border-color: var(--color-border);
|
|
58
310
|
}
|
|
311
|
+
|
|
312
|
+
@media (max-width: 640px) {
|
|
313
|
+
.fg-dialog__content {
|
|
314
|
+
top: auto;
|
|
315
|
+
bottom: 0;
|
|
316
|
+
left: 0;
|
|
317
|
+
width: 100%;
|
|
318
|
+
max-height: calc(100vh - 1rem);
|
|
319
|
+
transform: none;
|
|
320
|
+
border-radius: var(--radius-panel) var(--radius-panel) 0 0;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
@media (prefers-reduced-motion: reduce) {
|
|
325
|
+
.fg-progress__indicator { transition: none; }
|
|
326
|
+
}
|
|
59
327
|
}
|
package/src/theme.css
CHANGED
|
@@ -37,8 +37,10 @@
|
|
|
37
37
|
--color-success-surface: color-mix(in srgb, var(--color-success) 12%, var(--color-surface));
|
|
38
38
|
--color-info-surface: color-mix(in srgb, var(--color-info) 12%, var(--color-surface));
|
|
39
39
|
--radius-control: 0.55rem;
|
|
40
|
-
--radius-panel: 0.
|
|
40
|
+
--radius-panel: 0.75rem;
|
|
41
|
+
--radius-pill: 999px;
|
|
41
42
|
--duration-fast: 180ms;
|
|
43
|
+
--shadow-dialog: 0 20px 64px rgb(0 0 0 / 24%);
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
:root.dark {
|