@umbra.ui/core 0.4.3 → 0.4.5

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.
@@ -1,7 +1,15 @@
1
1
  <script setup lang="ts">
2
2
  import { ChevronRightIcon, CalendarDaysIcon } from "@umbra.ui/icons";
3
3
  // - Imports
4
- import { ref, watch, onMounted, nextTick, computed, onUnmounted } from "vue";
4
+ import {
5
+ ref,
6
+ watch,
7
+ onMounted,
8
+ nextTick,
9
+ computed,
10
+ onUnmounted,
11
+ useSlots,
12
+ } from "vue";
5
13
  import {
6
14
  offset,
7
15
  flip,
@@ -28,10 +36,14 @@ interface Day {
28
36
  // - Props
29
37
  export interface Props {
30
38
  date: Date;
39
+ label?: boolean;
31
40
  }
32
41
  const props = withDefaults(defineProps<Props>(), {
33
42
  date: () => new Date(),
43
+ label: true,
34
44
  });
45
+ const slots = useSlots();
46
+ const hasCustomLabelSlot = computed(() => Boolean(slots.label));
35
47
  // - Emits
36
48
  const emits = defineEmits(["update:date"]);
37
49
  // - State Management
@@ -379,14 +391,19 @@ const handleOverlayClick = () => {
379
391
  <div
380
392
  :class="[
381
393
  $style.button,
382
- showPopover ? $style.button_selected : $style.button_normal,
394
+ !hasCustomLabelSlot &&
395
+ (showPopover ? $style.button_selected : $style.button_normal),
383
396
  ]"
384
397
  @click="togglePopover"
385
398
  ref="button"
399
+ data-date-picker-button
400
+ :data-date-picker-open="showPopover ? 'true' : 'false'"
386
401
  >
387
- <CalendarDaysIcon :size="16" />
388
- <p :class="['callout', $style.button_label]">{{ dateString }}</p>
389
- <p :class="['callout', $style.button_sublabel]">{{ yearString }}</p>
402
+ <slot v-if="label" name="label">
403
+ <CalendarDaysIcon :size="16" />
404
+ <p :class="['callout', $style.button_label]">{{ dateString }}</p>
405
+ <p :class="['callout', $style.button_sublabel]">{{ yearString }}</p>
406
+ </slot>
390
407
  </div>
391
408
 
392
409
  <!-- Teleport the overlay and picker to body -->
@@ -66,11 +66,77 @@ const handleDateChange = (date: Date) => {
66
66
  </style>
67
67
  ```
68
68
 
69
+ ## Custom Label Slot
70
+
71
+ When you provide a custom `label` slot, the default button hover/selected
72
+ styles are disabled so you can fully control the label visuals. The
73
+ DatePicker button exposes a `data-date-picker-button` attribute you can use
74
+ to target hover/open states from your custom label styles.
75
+
76
+ ```vue
77
+ <script setup lang="ts">
78
+ import { ref, computed } from "vue";
79
+ import { DatePicker } from "@umbra-ui/core";
80
+ import { CalendarDaysIcon } from "@umbra-ui/icons";
81
+
82
+ const selectedDate = ref(new Date());
83
+ const formattedDate = computed(() =>
84
+ selectedDate.value.toLocaleDateString("en-US", {
85
+ month: "short",
86
+ day: "numeric",
87
+ })
88
+ );
89
+ </script>
90
+
91
+ <template>
92
+ <DatePicker v-model:date="selectedDate">
93
+ <template #label>
94
+ <span class="date-chip">
95
+ <CalendarDaysIcon :size="14" />
96
+ {{ formattedDate }}
97
+ </span>
98
+ </template>
99
+ </DatePicker>
100
+ </template>
101
+
102
+ <style module>
103
+ .date-chip {
104
+ display: inline-flex;
105
+ align-items: center;
106
+ gap: 0.353rem;
107
+ transition: transform 0.2s ease, opacity 0.2s ease;
108
+ transform: translateY(0);
109
+ opacity: 0.9;
110
+ }
111
+ :global([data-date-picker-button]:hover) .date-chip,
112
+ :global([data-date-picker-button][data-date-picker-open="true"]) .date-chip {
113
+ transform: translateY(-1px);
114
+ opacity: 1;
115
+ }
116
+ </style>
117
+ ```
118
+
119
+ ### Hiding the Label
120
+
121
+ ```vue
122
+ <script setup lang="ts">
123
+ import { ref } from "vue";
124
+ import { DatePicker } from "@umbra-ui/core";
125
+
126
+ const selectedDate = ref(new Date());
127
+ </script>
128
+
129
+ <template>
130
+ <DatePicker v-model:date="selectedDate" :label="false" />
131
+ </template>
132
+ ```
133
+
69
134
  ## Props
70
135
 
71
- | Prop Name | Type | Required | Default | Description |
72
- | --------- | ------ | -------- | ------------ | ----------------------- |
73
- | `date` | `Date` | Yes | `new Date()` | Currently selected date |
136
+ | Prop Name | Type | Required | Default | Description |
137
+ | --------- | --------- | -------- | ------------ | ------------------------------------- |
138
+ | `date` | `Date` | Yes | `new Date()` | Currently selected date |
139
+ | `label` | `boolean` | No | `true` | Show or hide the label content/slot |
74
140
 
75
141
  ## Events
76
142
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umbra.ui/core",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
4
4
  "description": "Core components for Umbra UI",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,7 +1,15 @@
1
1
  <script setup lang="ts">
2
2
  import { ChevronRightIcon, CalendarDaysIcon } from "@umbra.ui/icons";
3
3
  // - Imports
4
- import { ref, watch, onMounted, nextTick, computed, onUnmounted } from "vue";
4
+ import {
5
+ ref,
6
+ watch,
7
+ onMounted,
8
+ nextTick,
9
+ computed,
10
+ onUnmounted,
11
+ useSlots,
12
+ } from "vue";
5
13
  import {
6
14
  offset,
7
15
  flip,
@@ -28,10 +36,14 @@ interface Day {
28
36
  // - Props
29
37
  export interface Props {
30
38
  date: Date;
39
+ label?: boolean;
31
40
  }
32
41
  const props = withDefaults(defineProps<Props>(), {
33
42
  date: () => new Date(),
43
+ label: true,
34
44
  });
45
+ const slots = useSlots();
46
+ const hasCustomLabelSlot = computed(() => Boolean(slots.label));
35
47
  // - Emits
36
48
  const emits = defineEmits(["update:date"]);
37
49
  // - State Management
@@ -379,14 +391,19 @@ const handleOverlayClick = () => {
379
391
  <div
380
392
  :class="[
381
393
  $style.button,
382
- showPopover ? $style.button_selected : $style.button_normal,
394
+ !hasCustomLabelSlot &&
395
+ (showPopover ? $style.button_selected : $style.button_normal),
383
396
  ]"
384
397
  @click="togglePopover"
385
398
  ref="button"
399
+ data-date-picker-button
400
+ :data-date-picker-open="showPopover ? 'true' : 'false'"
386
401
  >
387
- <CalendarDaysIcon :size="16" />
388
- <p :class="['callout', $style.button_label]">{{ dateString }}</p>
389
- <p :class="['callout', $style.button_sublabel]">{{ yearString }}</p>
402
+ <slot v-if="label" name="label">
403
+ <CalendarDaysIcon :size="16" />
404
+ <p :class="['callout', $style.button_label]">{{ dateString }}</p>
405
+ <p :class="['callout', $style.button_sublabel]">{{ yearString }}</p>
406
+ </slot>
390
407
  </div>
391
408
 
392
409
  <!-- Teleport the overlay and picker to body -->
@@ -66,11 +66,77 @@ const handleDateChange = (date: Date) => {
66
66
  </style>
67
67
  ```
68
68
 
69
+ ## Custom Label Slot
70
+
71
+ When you provide a custom `label` slot, the default button hover/selected
72
+ styles are disabled so you can fully control the label visuals. The
73
+ DatePicker button exposes a `data-date-picker-button` attribute you can use
74
+ to target hover/open states from your custom label styles.
75
+
76
+ ```vue
77
+ <script setup lang="ts">
78
+ import { ref, computed } from "vue";
79
+ import { DatePicker } from "@umbra-ui/core";
80
+ import { CalendarDaysIcon } from "@umbra-ui/icons";
81
+
82
+ const selectedDate = ref(new Date());
83
+ const formattedDate = computed(() =>
84
+ selectedDate.value.toLocaleDateString("en-US", {
85
+ month: "short",
86
+ day: "numeric",
87
+ })
88
+ );
89
+ </script>
90
+
91
+ <template>
92
+ <DatePicker v-model:date="selectedDate">
93
+ <template #label>
94
+ <span class="date-chip">
95
+ <CalendarDaysIcon :size="14" />
96
+ {{ formattedDate }}
97
+ </span>
98
+ </template>
99
+ </DatePicker>
100
+ </template>
101
+
102
+ <style module>
103
+ .date-chip {
104
+ display: inline-flex;
105
+ align-items: center;
106
+ gap: 0.353rem;
107
+ transition: transform 0.2s ease, opacity 0.2s ease;
108
+ transform: translateY(0);
109
+ opacity: 0.9;
110
+ }
111
+ :global([data-date-picker-button]:hover) .date-chip,
112
+ :global([data-date-picker-button][data-date-picker-open="true"]) .date-chip {
113
+ transform: translateY(-1px);
114
+ opacity: 1;
115
+ }
116
+ </style>
117
+ ```
118
+
119
+ ### Hiding the Label
120
+
121
+ ```vue
122
+ <script setup lang="ts">
123
+ import { ref } from "vue";
124
+ import { DatePicker } from "@umbra-ui/core";
125
+
126
+ const selectedDate = ref(new Date());
127
+ </script>
128
+
129
+ <template>
130
+ <DatePicker v-model:date="selectedDate" :label="false" />
131
+ </template>
132
+ ```
133
+
69
134
  ## Props
70
135
 
71
- | Prop Name | Type | Required | Default | Description |
72
- | --------- | ------ | -------- | ------------ | ----------------------- |
73
- | `date` | `Date` | Yes | `new Date()` | Currently selected date |
136
+ | Prop Name | Type | Required | Default | Description |
137
+ | --------- | --------- | -------- | ------------ | ------------------------------------- |
138
+ | `date` | `Date` | Yes | `new Date()` | Currently selected date |
139
+ | `label` | `boolean` | No | `true` | Show or hide the label content/slot |
74
140
 
75
141
  ## Events
76
142