diff --git a/resources/js/packages/ui/src/Project/ProjectEditBillableSection.vue b/resources/js/packages/ui/src/Project/ProjectEditBillableSection.vue
index c24015c3..02d35adb 100644
--- a/resources/js/packages/ui/src/Project/ProjectEditBillableSection.vue
+++ b/resources/js/packages/ui/src/Project/ProjectEditBillableSection.vue
@@ -1,5 +1,5 @@
+
+
+
+
+
+
diff --git a/resources/js/packages/ui/src/field/FieldContent.vue b/resources/js/packages/ui/src/field/FieldContent.vue
new file mode 100644
index 00000000..7b2c025a
--- /dev/null
+++ b/resources/js/packages/ui/src/field/FieldContent.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
diff --git a/resources/js/packages/ui/src/field/FieldDescription.vue b/resources/js/packages/ui/src/field/FieldDescription.vue
new file mode 100644
index 00000000..a1f67b4b
--- /dev/null
+++ b/resources/js/packages/ui/src/field/FieldDescription.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
diff --git a/resources/js/packages/ui/src/field/FieldError.vue b/resources/js/packages/ui/src/field/FieldError.vue
new file mode 100644
index 00000000..ca9521ab
--- /dev/null
+++ b/resources/js/packages/ui/src/field/FieldError.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+ {{ content }}
+
+
+
+ -
+ {{ error?.message }}
+
+
+
+
diff --git a/resources/js/packages/ui/src/field/FieldGroup.vue b/resources/js/packages/ui/src/field/FieldGroup.vue
new file mode 100644
index 00000000..4781e63c
--- /dev/null
+++ b/resources/js/packages/ui/src/field/FieldGroup.vue
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/resources/js/packages/ui/src/field/FieldLabel.vue b/resources/js/packages/ui/src/field/FieldLabel.vue
new file mode 100644
index 00000000..391c4793
--- /dev/null
+++ b/resources/js/packages/ui/src/field/FieldLabel.vue
@@ -0,0 +1,24 @@
+
+
+
+
+
diff --git a/resources/js/packages/ui/src/field/FieldLegend.vue b/resources/js/packages/ui/src/field/FieldLegend.vue
new file mode 100644
index 00000000..167b9560
--- /dev/null
+++ b/resources/js/packages/ui/src/field/FieldLegend.vue
@@ -0,0 +1,25 @@
+
+
+
+
+
diff --git a/resources/js/packages/ui/src/field/FieldSeparator.vue b/resources/js/packages/ui/src/field/FieldSeparator.vue
new file mode 100644
index 00000000..b2156b70
--- /dev/null
+++ b/resources/js/packages/ui/src/field/FieldSeparator.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/js/packages/ui/src/field/FieldSet.vue b/resources/js/packages/ui/src/field/FieldSet.vue
new file mode 100644
index 00000000..6332d4c7
--- /dev/null
+++ b/resources/js/packages/ui/src/field/FieldSet.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
diff --git a/resources/js/packages/ui/src/field/FieldTitle.vue b/resources/js/packages/ui/src/field/FieldTitle.vue
new file mode 100644
index 00000000..b7981e49
--- /dev/null
+++ b/resources/js/packages/ui/src/field/FieldTitle.vue
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/resources/js/packages/ui/src/field/index.ts b/resources/js/packages/ui/src/field/index.ts
new file mode 100644
index 00000000..b12b74ba
--- /dev/null
+++ b/resources/js/packages/ui/src/field/index.ts
@@ -0,0 +1,39 @@
+import type { VariantProps } from 'class-variance-authority';
+import { cva } from 'class-variance-authority';
+
+export const fieldVariants = cva(
+ 'group/field flex w-full gap-3 data-[invalid=true]:text-destructive',
+ {
+ variants: {
+ orientation: {
+ vertical: ['flex-col [&>*]:w-full [&>.sr-only]:w-auto'],
+ horizontal: [
+ 'flex-row items-center',
+ '[&>[data-slot=field-label]]:flex-auto',
+ 'has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px',
+ ],
+ responsive: [
+ 'flex-col [&>*]:w-full [&>.sr-only]:w-auto @md/field-group:flex-row @md/field-group:items-center @md/field-group:[&>*]:w-auto',
+ '@md/field-group:[&>[data-slot=field-label]]:flex-auto',
+ '@md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px',
+ ],
+ },
+ },
+ defaultVariants: {
+ orientation: 'vertical',
+ },
+ }
+);
+
+export type FieldVariants = VariantProps
;
+
+export { default as Field } from './Field.vue';
+export { default as FieldContent } from './FieldContent.vue';
+export { default as FieldDescription } from './FieldDescription.vue';
+export { default as FieldError } from './FieldError.vue';
+export { default as FieldGroup } from './FieldGroup.vue';
+export { default as FieldLabel } from './FieldLabel.vue';
+export { default as FieldLegend } from './FieldLegend.vue';
+export { default as FieldSeparator } from './FieldSeparator.vue';
+export { default as FieldSet } from './FieldSet.vue';
+export { default as FieldTitle } from './FieldTitle.vue';
diff --git a/resources/js/packages/ui/src/index.ts b/resources/js/packages/ui/src/index.ts
index 469e1564..c465887b 100644
--- a/resources/js/packages/ui/src/index.ts
+++ b/resources/js/packages/ui/src/index.ts
@@ -43,6 +43,21 @@ import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from './
import { Popover, PopoverContent, PopoverTrigger, PopoverAnchor } from './popover/index';
import { RangeCalendar } from './range-calendar/index';
import { CommandPalette } from './CommandPalette/index';
+import { Separator } from './separator/index';
+import {
+ Field,
+ FieldContent,
+ FieldDescription,
+ FieldError,
+ FieldGroup,
+ FieldLabel,
+ FieldLegend,
+ FieldSeparator,
+ FieldSet,
+ FieldTitle,
+ fieldVariants,
+} from './field/index';
+export type { FieldVariants } from './field/index';
export type { ActivityPeriod } from './FullCalendar/idleStatusPlugin';
export type {
CommandPaletteCommand,
@@ -93,4 +108,16 @@ export {
PopoverAnchor,
RangeCalendar,
CommandPalette,
+ Separator,
+ Field,
+ FieldContent,
+ FieldDescription,
+ FieldError,
+ FieldGroup,
+ FieldLabel,
+ FieldLegend,
+ FieldSeparator,
+ FieldSet,
+ FieldTitle,
+ fieldVariants,
};
diff --git a/resources/js/packages/ui/src/separator/Separator.vue b/resources/js/packages/ui/src/separator/Separator.vue
new file mode 100644
index 00000000..1e23e3fc
--- /dev/null
+++ b/resources/js/packages/ui/src/separator/Separator.vue
@@ -0,0 +1,26 @@
+
+
+
+
+
diff --git a/resources/js/packages/ui/src/separator/index.ts b/resources/js/packages/ui/src/separator/index.ts
new file mode 100644
index 00000000..3cb07b01
--- /dev/null
+++ b/resources/js/packages/ui/src/separator/index.ts
@@ -0,0 +1 @@
+export { default as Separator } from './Separator.vue';
diff --git a/resources/js/utils/useAggregatedTimeEntriesQuery.ts b/resources/js/utils/useAggregatedTimeEntriesQuery.ts
index 0fc50bea..72bc9a57 100644
--- a/resources/js/utils/useAggregatedTimeEntriesQuery.ts
+++ b/resources/js/utils/useAggregatedTimeEntriesQuery.ts
@@ -26,6 +26,7 @@ export function useAggregatedTimeEntriesQuery(
queries: unref(filterParams),
}),
enabled: computed(() => !!getCurrentOrganizationId()),
+ placeholderData: (previousData) => previousData,
staleTime: 1000 * 30,
});