@livestorm/ui-vue 3.0.0 → 4.0.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 +3 -3
- package/components-vite.js +2 -2
- package/dist/UiButton-uyW8EHRJ.mjs +602 -0
- package/dist/UiTimelineItem-EiOEi1yF.mjs +7293 -0
- package/dist/UiTooltip-DZcPD6_N.mjs +158 -0
- package/dist/a11y-CaZxRWzo.mjs +6 -0
- package/dist/breakpoints.mjs +4 -9
- package/dist/bus.mjs +5 -5
- package/dist/components.mjs +236 -231
- package/dist/i18n-B8QOMuFD.mjs +46 -0
- package/dist/index.mjs +4 -91
- package/dist/integrations.mjs +3 -14
- package/dist/layouts.mjs +228 -236
- package/dist/responsive.mjs +31 -36
- package/dist/slot.mjs +11 -17
- package/dist/toastDSV2-D3xDZPe5.mjs +105 -0
- package/dist/types/index.d.ts +19 -1
- package/dist/types/src/components/Toast/ToastMessage.vue.d.ts +17 -7
- package/dist/types/src/components/Toast/toastDSV2.d.ts +89 -64
- package/dist/types/src/components/UiActionBar/types.d.ts +2 -0
- package/dist/types/src/components/UiAvatar/UiAvatar.vue.d.ts +4 -2
- package/dist/types/src/components/UiAvatarList/UiAvatarList.vue.d.ts +3 -2
- package/dist/types/src/components/UiBanner/UiBanner.vue.d.ts +13 -1
- package/dist/types/src/components/UiButton/UiButton.vue.d.ts +95 -35
- package/dist/types/src/components/UiButtonGroup/UiButtonGroup.vue.d.ts +8 -2
- package/dist/types/src/components/UiButtonGroup/types.d.ts +4 -0
- package/dist/types/src/components/UiChoice/UiChoice.vue.d.ts +71 -0
- package/dist/types/src/components/UiChoice/index.d.ts +2 -0
- package/dist/types/src/components/UiChoice/types.d.ts +7 -0
- package/dist/types/src/components/UiColorField/UiColorField.vue.d.ts +1 -1
- package/dist/types/src/components/UiColorPicker/UiColorPicker.vue.d.ts +2 -2
- package/dist/types/src/components/UiCombobox/UiCombobox.types.d.ts +47 -0
- package/dist/types/src/components/UiCombobox/UiCombobox.vue.d.ts +40 -0
- package/dist/types/src/components/UiCombobox/index.d.ts +2 -0
- package/dist/types/src/components/UiDataTable/UiDataTable.types.d.ts +46 -0
- package/dist/types/src/components/UiDataTable/UiDataTable.vue.d.ts +136 -0
- package/dist/types/src/components/UiDataTable/index.d.ts +5 -0
- package/dist/types/src/components/UiDrawer/UiDrawer.vue.d.ts +28 -0
- package/dist/types/src/components/UiDrawer/UiDrawerContent.vue.d.ts +18 -0
- package/dist/types/src/components/UiDrawer/UiDrawerTrigger.vue.d.ts +14 -0
- package/dist/types/src/components/UiDropdown/DropdownItemCheckbox.vue.d.ts +3 -0
- package/dist/types/src/components/UiDropdown/UiDropdownContent.vue.d.ts +10 -0
- package/dist/types/src/components/UiDropdown/UiDropdownGroup.vue.d.ts +17 -0
- package/dist/types/src/components/UiDropdown/UiDropdownItem.vue.d.ts +8 -5
- package/dist/types/src/components/UiDropdown/UiDropdownTrigger.vue.d.ts +21 -5
- package/dist/types/src/components/UiDropdown/index.d.ts +1 -0
- package/dist/types/src/components/UiEmojiPickerList/UiEmojiPickerList.vue.d.ts +22 -0
- package/dist/types/src/components/UiEmptyState/UiEmptyState.vue.d.ts +8 -3
- package/dist/types/src/components/UiFieldWrapper/UiFieldWrapper.vue.d.ts +2 -2
- package/dist/types/src/components/UiInputCheckbox/CheckboxGlyph.vue.d.ts +17 -0
- package/dist/types/src/components/UiInputCheckbox/UiInputCheckbox.vue.d.ts +35 -4
- package/dist/types/src/components/UiInputRadio/RadioGlyph.vue.d.ts +19 -0
- package/dist/types/src/components/UiInputRadio/UiInputRadio.vue.d.ts +21 -8
- package/dist/types/src/components/UiInputRadio/UiInputRadioGroup.vue.d.ts +6 -1
- package/dist/types/src/components/UiInputRadio/types.d.ts +1 -1
- package/dist/types/src/components/UiInputSelect/UiInputSelect.vue.d.ts +5 -5
- package/dist/types/src/components/UiInputTextarea/UiInputTextarea.vue.d.ts +5 -5
- package/dist/types/src/components/UiListItem/UiListItem.vue.d.ts +18 -4
- package/dist/types/src/components/UiLoader/UiSpinnerIcon.vue.d.ts +3 -0
- package/dist/types/src/components/UiMenu/UiMenuContent.vue.d.ts +15 -2
- package/dist/types/src/components/UiMenu/UiMenuItem.vue.d.ts +9 -3
- package/dist/types/src/components/UiNestedOptions/UiNestedOptions.vue.d.ts +13 -0
- package/dist/types/src/components/UiPage/UiPage.vue.d.ts +79 -15
- package/dist/types/src/components/UiPagination/UiPagination.vue.d.ts +36 -0
- package/dist/types/src/components/UiPagination/index.d.ts +2 -0
- package/dist/types/src/components/UiPagination/types.d.ts +4 -0
- package/dist/types/src/components/UiPane/UiPane.vue.d.ts +22 -0
- package/dist/types/src/components/UiPane/UiPaneContent.vue.d.ts +75 -0
- package/dist/types/src/components/UiPane/UiPaneTrigger.vue.d.ts +14 -0
- package/dist/types/src/components/UiPane/index.d.ts +5 -0
- package/dist/types/src/components/UiRating/UiRating.vue.d.ts +62 -0
- package/dist/types/src/components/UiRating/types.d.ts +1 -0
- package/dist/types/src/components/UiRoomButton/UiRoomButton.vue.d.ts +5 -3
- package/dist/types/src/components/UiRoomCountdown/UiRoomCountdown.vue.d.ts +32 -0
- package/dist/types/src/components/UiShell/UiShell.vue.d.ts +3 -0
- package/dist/types/src/components/UiSideMenu/UiSideMenu.vue.d.ts +22 -1
- package/dist/types/src/components/UiSideMenu/UiSideMenuItemContent.vue.d.ts +2 -2
- package/dist/types/src/components/UiSwitch/UiSwitch.vue.d.ts +10 -5
- package/dist/types/src/components/UiTable/UiTable.vue.d.ts +13 -4
- package/dist/types/src/components/UiTable/UiTableActionsCell.vue.d.ts +49 -0
- package/dist/types/src/components/UiTable/UiTableActionsHeaderCell.vue.d.ts +3 -0
- package/dist/types/src/components/UiTable/UiTableBody.vue.d.ts +11 -1
- package/dist/types/src/components/UiTable/UiTableCell.vue.d.ts +16 -1
- package/dist/types/src/components/UiTable/UiTableHeaderCell.vue.d.ts +31 -2
- package/dist/types/src/components/UiTable/UiTableRow.vue.d.ts +32 -2
- package/dist/types/src/components/UiTable/context.d.ts +3 -0
- package/dist/types/src/components/UiTable/index.d.ts +4 -0
- package/dist/types/src/components/UiTabs/UiTabs.vue.d.ts +3 -0
- package/dist/types/src/components/UiTag/UiTag.types.d.ts +25 -0
- package/dist/types/src/components/UiTag/UiTag.vue.d.ts +5 -26
- package/dist/types/src/components/UiTag/index.d.ts +2 -1
- package/dist/types/src/components/UiTextField/UiTextField.vue.d.ts +10 -5
- package/dist/types/src/components/UiTooltip/UiTooltipProvider.vue.d.ts +1 -0
- package/dist/types/src/components/UiTooltip/UiTooltipTrigger.vue.d.ts +2 -2
- package/dist/types/src/composables/storedThemingApplies.d.ts +17 -0
- package/dist/types/src/composables/useButtonStyles.d.ts +1 -0
- package/dist/types/src/composables/useChoiceboxSurface.d.ts +11 -0
- package/dist/types/src/composables/useContentMode.d.ts +7 -9
- package/dist/types/src/composables/useControlModes.d.ts +7 -0
- package/dist/types/src/composables/useControlShape.d.ts +24 -0
- package/dist/types/src/composables/useFieldFocusEvents.d.ts +12 -0
- package/dist/types/src/composables/useIconSize.d.ts +2 -0
- package/dist/types/src/composables/usePullGesture.d.ts +42 -0
- package/dist/types/src/composables/useThemeAndModes.d.ts +4 -0
- package/dist/types/src/theming/colorScale.d.ts +165 -0
- package/dist/types/src/theming/legacyColorScale.d.ts +27 -0
- package/dist/types/src/theming/presetColors.d.ts +11 -0
- package/dist/types/src/theming/primitiveTokens.d.ts +2 -0
- package/dist/types/src/utils/effectiveOpacity.d.ts +2 -0
- package/dist/types/src/utils/numbers.d.ts +1 -2
- package/dist/types/src/utils/tokenColor.d.ts +2 -0
- package/dist/ui-vue.css +2 -1
- package/dist/utils.mjs +165 -194
- package/index.d.ts +18 -0
- package/index.js +36 -0
- package/package.json +26 -21
- package/src/components/Toast/LayoutToasts.vue +19 -11
- package/src/components/Toast/ToastMessage.vue +125 -68
- package/src/components/Toast/toastDSV2.ts +238 -67
- package/src/components/UiActionBar/UiActionBar.vue +4 -3
- package/src/components/UiActionBar/UiActionBarItem.vue +9 -6
- package/src/components/UiActionBar/types.ts +13 -0
- package/src/components/UiAvatar/UiAvatar.vue +8 -2
- package/src/components/UiAvatarList/UiAvatarList.vue +51 -20
- package/src/components/UiBadge/UiBadge.vue +1 -1
- package/src/components/UiBanner/UiBanner.vue +71 -21
- package/src/components/UiBreadcrumb/UiBreadcrumb.vue +1 -1
- package/src/components/UiButton/UiButton.vue +92 -25
- package/src/components/UiButtonGroup/UiButtonGroup.vue +21 -17
- package/src/components/UiButtonGroup/UiButtonGroupItem.vue +33 -15
- package/src/components/UiButtonGroup/types.ts +19 -0
- package/src/components/UiCard/UiCard.vue +20 -23
- package/src/components/UiChoice/UiChoice.vue +187 -0
- package/src/components/UiChoice/index.ts +2 -0
- package/src/components/UiChoice/types.ts +11 -0
- package/src/components/UiColorField/UiColorField.vue +2 -2
- package/src/components/UiColorPicker/UiColorPicker.vue +11 -8
- package/src/components/UiCombobox/UiCombobox.types.ts +52 -0
- package/src/components/UiCombobox/UiCombobox.vue +296 -0
- package/src/components/UiCombobox/index.ts +2 -0
- package/src/components/UiDataTable/UiDataTable.types.ts +47 -0
- package/src/components/UiDataTable/UiDataTable.vue +422 -0
- package/src/components/UiDataTable/index.ts +12 -0
- package/src/components/UiDialog/UiDialogContent.vue +22 -7
- package/src/components/UiDrawer/UiDrawer.vue +16 -0
- package/src/components/UiDrawer/UiDrawerContent.vue +42 -0
- package/src/components/UiDrawer/UiDrawerTrigger.vue +17 -0
- package/src/components/UiDropdown/DropdownItemCheckbox.vue +10 -0
- package/src/components/UiDropdown/UiDropdownContent.vue +32 -21
- package/src/components/UiDropdown/UiDropdownGroup.vue +23 -0
- package/src/components/UiDropdown/UiDropdownItem.vue +38 -18
- package/src/components/UiDropdown/UiDropdownSeparator.vue +1 -1
- package/src/components/UiDropdown/UiDropdownTrigger.vue +138 -43
- package/src/components/UiDropdown/index.ts +1 -0
- package/src/components/UiEmojiPickerList/UiEmojiPickerList.vue +122 -0
- package/src/components/UiEmptyState/UiEmptyState.vue +16 -4
- package/src/components/UiFieldWrapper/UiFieldWrapper.vue +9 -3
- package/src/components/UiHorizontalSeparator/UiHorizontalSeparator.vue +2 -2
- package/src/components/UiInputCheckbox/CheckboxGlyph.vue +78 -0
- package/src/components/UiInputCheckbox/UiInputCheckbox.vue +213 -177
- package/src/components/UiInputEmoji/UiInputEmoji.vue +18 -95
- package/src/components/UiInputRadio/RadioGlyph.vue +45 -0
- package/src/components/UiInputRadio/UiInputRadio.vue +177 -169
- package/src/components/UiInputRadio/UiInputRadioGroup.vue +15 -5
- package/src/components/UiInputRadio/types.ts +1 -2
- package/src/components/UiInputSelect/UiInputSelect.vue +9 -7
- package/src/components/UiInputTextarea/UiInputTextarea.vue +20 -35
- package/src/components/UiLabel/UiLabel.vue +1 -1
- package/src/components/UiListItem/UiListItem.vue +55 -9
- package/src/components/UiLoader/UiLoader.vue +4 -20
- package/src/components/UiLoader/UiSpinnerIcon.vue +21 -0
- package/src/components/UiMenu/UiMenuContent.vue +24 -3
- package/src/components/UiMenu/UiMenuGroup.vue +1 -1
- package/src/components/UiMenu/UiMenuItem.vue +14 -3
- package/src/components/UiMenu/UiMenuSubContent.vue +1 -1
- package/src/components/UiMenu/UiMenuSubTrigger.vue +1 -1
- package/src/components/UiNestedOptions/UiNestedOptions.vue +6 -0
- package/src/components/UiPage/UiPage.vue +190 -32
- package/src/components/UiPagination/UiPagination.vue +99 -0
- package/src/components/UiPagination/index.ts +2 -0
- package/src/components/UiPagination/types.ts +28 -0
- package/src/components/UiPane/UiPane.vue +20 -0
- package/src/components/UiPane/UiPaneContent.vue +232 -0
- package/src/components/UiPane/UiPaneTrigger.vue +14 -0
- package/src/components/UiPane/index.ts +12 -0
- package/src/components/UiPopover/UiPopoverContent.vue +21 -1
- package/src/components/UiProgress/UiProgress.vue +2 -2
- package/src/components/UiRating/UiRating.vue +258 -0
- package/src/components/UiRating/types.ts +1 -0
- package/src/components/UiRoomButton/UiRoomButton.vue +10 -41
- package/src/components/UiRoomCountdown/UiRoomCountdown.vue +376 -0
- package/src/components/UiShell/UiShell.vue +9 -3
- package/src/components/UiSideMenu/UiSideMenu.vue +155 -18
- package/src/components/UiSideMenu/UiSideMenuItemContent.vue +20 -16
- package/src/components/UiStepper/UiStepper.vue +3 -16
- package/src/components/UiStepper/UiStepperDescription.vue +1 -13
- package/src/components/UiStepper/UiStepperIndicator.vue +11 -48
- package/src/components/UiStepper/UiStepperItem.vue +1 -8
- package/src/components/UiStepper/UiStepperSeparator.vue +5 -16
- package/src/components/UiStepper/UiStepperTitle.vue +1 -10
- package/src/components/UiSwitch/UiSwitch.vue +44 -28
- package/src/components/UiTable/UiTable.vue +98 -8
- package/src/components/UiTable/UiTableActionsCell.vue +135 -0
- package/src/components/UiTable/UiTableActionsHeaderCell.vue +19 -0
- package/src/components/UiTable/UiTableBody.vue +16 -1
- package/src/components/UiTable/UiTableCell.vue +33 -16
- package/src/components/UiTable/UiTableHeader.vue +6 -5
- package/src/components/UiTable/UiTableHeaderCell.vue +61 -9
- package/src/components/UiTable/UiTableRow.vue +46 -10
- package/src/components/UiTable/context.ts +5 -0
- package/src/components/UiTable/index.ts +4 -0
- package/src/components/UiTabs/UiTabs.vue +56 -61
- package/src/components/UiTag/UiTag.types.ts +28 -0
- package/src/components/UiTag/UiTag.vue +24 -42
- package/src/components/UiTag/index.ts +2 -0
- package/src/components/UiTextField/UiTextField.vue +21 -36
- package/src/components/UiTooltip/UiTooltipContent.vue +1 -1
- package/src/components/UiTooltip/UiTooltipProvider.vue +3 -0
- package/src/components/UiTooltip/UiTooltipTrigger.vue +16 -1
- package/src/composables/storedThemingApplies.ts +19 -0
- package/src/composables/useButtonStyles.ts +9 -13
- package/src/composables/useChoiceboxSurface.ts +36 -0
- package/src/composables/useContentMode.ts +29 -16
- package/src/composables/useControlModes.ts +11 -0
- package/src/composables/useControlShape.ts +34 -0
- package/src/composables/useFieldFocusEvents.ts +30 -0
- package/src/composables/useIconSize.ts +15 -0
- package/src/composables/usePullGesture.ts +142 -0
- package/src/composables/useThemeAndModes.ts +28 -1
- package/src/css/body.css +16 -1
- package/src/css/fonts.css +39 -5
- package/src/global.d.ts +36 -0
- package/src/theming/colorScale.ts +173 -0
- package/src/theming/legacyColorScale.ts +58 -0
- package/src/theming/presetColors.ts +33 -0
- package/src/theming/primitiveTokens.ts +71 -0
- package/src/utils/effectiveOpacity.ts +8 -0
- package/src/utils/i18n.ts +6 -0
- package/src/utils/numbers.ts +1 -1
- package/src/utils/responsive.d.ts +14 -0
- package/src/utils/tokenColor.ts +9 -0
- package/dist/UiTimelineItem.vue_vue_type_style_index_0_lang-LpdvGf5X.mjs +0 -6093
- package/dist/a11y-BhF_nl7L.mjs +0 -159
- package/dist/i18n-Cktw9hIu.mjs +0 -49
- package/dist/toastDSV2-wMh-UMzW.mjs +0 -74
- package/dist/types/src/components/UiAvatar/index.d.ts +0 -1
- package/dist/types/src/components/UiAvatarList/index.d.ts +0 -1
- package/dist/types/src/components/UiBadge/index.d.ts +0 -1
- package/dist/types/src/components/UiBanner/index.d.ts +0 -2
- package/dist/types/src/components/UiButtonGroup/index.d.ts +0 -3
- package/dist/types/src/components/UiCarousel/index.d.ts +0 -2
- package/dist/types/src/components/UiColorField/index.d.ts +0 -2
- package/dist/types/src/components/UiDialog/MarketplaceHeaderExample.vue.d.ts +0 -28
- package/dist/types/src/components/UiDialog/index.d.ts +0 -7
- package/dist/types/src/components/UiFieldWrapper/index.d.ts +0 -1
- package/dist/types/src/components/UiInputCheckbox/index.d.ts +0 -2
- package/dist/types/src/components/UiInputEmoji/index.d.ts +0 -1
- package/dist/types/src/components/UiInputRadio/index.d.ts +0 -3
- package/dist/types/src/components/UiInputSelect/index.d.ts +0 -2
- package/dist/types/src/components/UiInputTextarea/index.d.ts +0 -2
- package/dist/types/src/components/UiMenu/index.d.ts +0 -10
- package/dist/types/src/components/UiProgress/index.d.ts +0 -2
- package/dist/types/src/components/UiSwitch/index.d.ts +0 -2
- package/dist/types/src/components/UiTabs/index.d.ts +0 -2
- package/dist/types/src/components/UiTimeline/index.d.ts +0 -2
- package/dist/types/src/components/UiTooltip/index.d.ts +0 -4
- package/dist/types/src/mixins/DynamicAction.d.ts +0 -30
- package/dist/useThemeAndModes-BzYwSOEv.mjs +0 -108
- package/src/components/UiAvatar/index.js +0 -1
- package/src/components/UiAvatarList/index.js +0 -1
- package/src/components/UiBadge/index.ts +0 -2
- package/src/components/UiBanner/index.ts +0 -2
- package/src/components/UiButtonGroup/index.ts +0 -3
- package/src/components/UiCarousel/index.ts +0 -2
- package/src/components/UiColorField/index.ts +0 -2
- package/src/components/UiDialog/MarketplaceHeaderExample.vue +0 -217
- package/src/components/UiDialog/index.ts +0 -18
- package/src/components/UiFieldWrapper/index.ts +0 -1
- package/src/components/UiInputCheckbox/index.ts +0 -2
- package/src/components/UiInputEmoji/index.ts +0 -1
- package/src/components/UiInputRadio/index.ts +0 -3
- package/src/components/UiInputSelect/index.ts +0 -2
- package/src/components/UiInputTextarea/index.ts +0 -2
- package/src/components/UiMenu/index.ts +0 -10
- package/src/components/UiProgress/index.ts +0 -2
- package/src/components/UiSwitch/index.ts +0 -2
- package/src/components/UiTabs/index.ts +0 -5
- package/src/components/UiTag/index.js +0 -1
- package/src/components/UiTimeline/index.ts +0 -2
- package/src/components/UiTooltip/index.js +0 -4
- package/src/mixins/DynamicAction.js +0 -61
|
@@ -5,7 +5,7 @@ const props = defineProps<{
|
|
|
5
5
|
</script>
|
|
6
6
|
|
|
7
7
|
<template>
|
|
8
|
-
<div class="separator text-content-legends-medium-md">
|
|
8
|
+
<div class="separator text-content-legends-medium-md uppercase">
|
|
9
9
|
<p
|
|
10
10
|
class="w-full"
|
|
11
11
|
v-text="props.label"
|
|
@@ -23,6 +23,6 @@ const props = defineProps<{
|
|
|
23
23
|
.separator::before,
|
|
24
24
|
.separator::after {
|
|
25
25
|
content: '';
|
|
26
|
-
@apply border-t border-
|
|
26
|
+
@apply border-t border-container-border h-0 w-full;
|
|
27
27
|
}
|
|
28
28
|
</style>
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import type { CheckboxSize } from './types'
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
checked?: boolean
|
|
7
|
+
indeterminate?: boolean
|
|
8
|
+
error?: boolean
|
|
9
|
+
disabled?: boolean
|
|
10
|
+
size?: CheckboxSize
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
14
|
+
checked: false,
|
|
15
|
+
indeterminate: false,
|
|
16
|
+
error: false,
|
|
17
|
+
disabled: false,
|
|
18
|
+
size: 'md',
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const checkedFillClass = computed(() => {
|
|
22
|
+
if (props.error) {
|
|
23
|
+
return 'bg-actions-danger-idle'
|
|
24
|
+
}
|
|
25
|
+
return props.disabled ? 'bg-surface-neutral-alpha-600' : 'bg-actions-primary-idle'
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const boxClasses = computed(() => {
|
|
29
|
+
const classes = [
|
|
30
|
+
'relative shrink-0 grid place-content-center',
|
|
31
|
+
props.disabled ? 'cursor-not-allowed' : 'cursor-pointer',
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
const sizeClasses = {
|
|
35
|
+
sm: 'size-unit-0-75rem rounded-4',
|
|
36
|
+
md: 'size-check-sm rounded-check',
|
|
37
|
+
lg: 'size-check-md rounded-check',
|
|
38
|
+
}
|
|
39
|
+
classes.push(sizeClasses[props.size])
|
|
40
|
+
|
|
41
|
+
// Checked is a plain fill, neutral once disabled; unchecked is a denser fill than the
|
|
42
|
+
// fields, which once disabled falls back to the field fill with an outline
|
|
43
|
+
if (props.checked || props.indeterminate) {
|
|
44
|
+
classes.push('border-none', checkedFillClass.value)
|
|
45
|
+
} else if (props.disabled && !props.error) {
|
|
46
|
+
classes.push('bg-control-field-bg border border-control-disabled-border')
|
|
47
|
+
} else {
|
|
48
|
+
classes.push('bg-control-check-bg border', props.error ? 'border-control-error-border' : 'border-control-field-border')
|
|
49
|
+
if (!props.disabled) {
|
|
50
|
+
classes.push('group-hover/option:bg-control-check-bg-hover')
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return classes
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
const iconClasses = computed(() => {
|
|
58
|
+
const sizeClasses = {
|
|
59
|
+
sm: 'size-2',
|
|
60
|
+
md: 'size-2.5',
|
|
61
|
+
lg: 'size-3',
|
|
62
|
+
}
|
|
63
|
+
return ['block relative z-1 text-actions-neutral-invert-idle', sizeClasses[props.size], props.indeterminate ? 'i-ph-minus' : 'i-ls-checkbox-check']
|
|
64
|
+
})
|
|
65
|
+
</script>
|
|
66
|
+
|
|
67
|
+
<template>
|
|
68
|
+
<span
|
|
69
|
+
:class="boxClasses"
|
|
70
|
+
aria-hidden="true"
|
|
71
|
+
data-testid="ui-checkbox-box"
|
|
72
|
+
>
|
|
73
|
+
<span
|
|
74
|
+
v-if="checked || indeterminate"
|
|
75
|
+
:class="iconClasses"
|
|
76
|
+
/>
|
|
77
|
+
</span>
|
|
78
|
+
</template>
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed, ref, watch, nextTick } from 'vue'
|
|
2
|
+
import { computed, inject, ref, useSlots, watch, nextTick } from 'vue'
|
|
3
3
|
import { Label, useId } from 'reka-ui'
|
|
4
4
|
import type { CheckboxSize } from './types'
|
|
5
5
|
import UiTooltip from '../UiTooltip/UiTooltip.vue'
|
|
6
|
+
import CheckboxGlyph from './CheckboxGlyph.vue'
|
|
7
|
+
import { CHOICE_ROW_KEY } from '../UiChoice/types'
|
|
8
|
+
import type { ControlPosition } from '../UiChoice/types'
|
|
6
9
|
|
|
7
10
|
interface UiInputCheckboxProps {
|
|
8
11
|
/**
|
|
@@ -45,6 +48,11 @@ interface UiInputCheckboxProps {
|
|
|
45
48
|
* Info tooltip for the label
|
|
46
49
|
*/
|
|
47
50
|
labelInfo?: string
|
|
51
|
+
/**
|
|
52
|
+
* Icon class rendered between the checkbox and the text (e.g. `i-ph-bell`).
|
|
53
|
+
* In vertical orientation it sits above the text instead.
|
|
54
|
+
*/
|
|
55
|
+
icon?: string
|
|
48
56
|
/**
|
|
49
57
|
* Description text below the label
|
|
50
58
|
*/
|
|
@@ -66,6 +74,10 @@ interface UiInputCheckboxProps {
|
|
|
66
74
|
* @default 'md'
|
|
67
75
|
*/
|
|
68
76
|
size?: CheckboxSize
|
|
77
|
+
/**
|
|
78
|
+
* Accessible name for the input, for checkboxes rendered without a label
|
|
79
|
+
*/
|
|
80
|
+
ariaLabel?: string
|
|
69
81
|
/**
|
|
70
82
|
* Layout orientation
|
|
71
83
|
* @default 'horizontal'
|
|
@@ -76,6 +88,17 @@ interface UiInputCheckboxProps {
|
|
|
76
88
|
* @default false
|
|
77
89
|
*/
|
|
78
90
|
showBg?: boolean
|
|
91
|
+
/**
|
|
92
|
+
* Whether the checkbox stretches to fill its container instead of
|
|
93
|
+
* shrink-wrapping its content
|
|
94
|
+
* @default false
|
|
95
|
+
*/
|
|
96
|
+
fullWidth?: boolean
|
|
97
|
+
/**
|
|
98
|
+
* Which side of the text the checkbox sits on, in horizontal orientation
|
|
99
|
+
* @default 'start'
|
|
100
|
+
*/
|
|
101
|
+
controlPosition?: ControlPosition
|
|
79
102
|
}
|
|
80
103
|
|
|
81
104
|
const props = withDefaults(defineProps<UiInputCheckboxProps>(), {
|
|
@@ -83,9 +106,13 @@ const props = withDefaults(defineProps<UiInputCheckboxProps>(), {
|
|
|
83
106
|
indeterminate: false,
|
|
84
107
|
error: false,
|
|
85
108
|
required: false,
|
|
109
|
+
icon: undefined,
|
|
86
110
|
size: 'md',
|
|
87
111
|
checked: undefined,
|
|
88
112
|
orientation: 'horizontal',
|
|
113
|
+
ariaLabel: undefined,
|
|
114
|
+
fullWidth: false,
|
|
115
|
+
controlPosition: 'start',
|
|
89
116
|
})
|
|
90
117
|
|
|
91
118
|
const emit = defineEmits<{
|
|
@@ -93,17 +120,23 @@ const emit = defineEmits<{
|
|
|
93
120
|
'change': [event: Event]
|
|
94
121
|
'focus': [event: FocusEvent]
|
|
95
122
|
'blur': [event: FocusEvent]
|
|
123
|
+
'tooltip-clicked': []
|
|
96
124
|
}>()
|
|
97
125
|
|
|
126
|
+
const slots = useSlots()
|
|
127
|
+
const inChoiceRow = inject(CHOICE_ROW_KEY, false)
|
|
128
|
+
|
|
98
129
|
const checkboxRef = ref<HTMLInputElement | null>(null)
|
|
99
130
|
|
|
100
|
-
function triggerCheckbox () {
|
|
101
|
-
|
|
131
|
+
function triggerCheckbox (event: Event) {
|
|
132
|
+
// A click on the input itself bubbles up to this same handler; without the target
|
|
133
|
+
// check we'd re-click it and immediately toggle it back.
|
|
134
|
+
if (!props.disabled && event.target !== checkboxRef.value) {
|
|
102
135
|
checkboxRef.value?.click()
|
|
103
136
|
}
|
|
104
137
|
}
|
|
105
|
-
const
|
|
106
|
-
const inputId =
|
|
138
|
+
const generatedId = useId()
|
|
139
|
+
const inputId = computed(() => props.id ?? generatedId)
|
|
107
140
|
|
|
108
141
|
// Determine if checkbox is checked
|
|
109
142
|
const isChecked = computed(() => {
|
|
@@ -130,82 +163,68 @@ const isChecked = computed(() => {
|
|
|
130
163
|
return false
|
|
131
164
|
})
|
|
132
165
|
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
'relative shrink-0 grid place-content-center',
|
|
137
|
-
'border rounded-sm transition-colors',
|
|
138
|
-
'focus:outline-hidden',
|
|
139
|
-
]
|
|
140
|
-
|
|
141
|
-
baseClasses.push(props.disabled ? 'cursor-not-allowed' : 'cursor-pointer')
|
|
142
|
-
|
|
143
|
-
// Size classes
|
|
144
|
-
const sizeClasses = {
|
|
145
|
-
sm: 'w-3.5 h-3.5',
|
|
146
|
-
md: 'w-4 h-4',
|
|
147
|
-
lg: 'w-5 h-5',
|
|
148
|
-
}
|
|
166
|
+
const hasText = computed(() => !!(props.label || slots.label || props.labelInfo || props.description))
|
|
167
|
+
const hasContent = computed(() => hasText.value || !!(props.icon || slots.icon))
|
|
168
|
+
const isOptionRow = computed(() => props.orientation === 'horizontal' && !props.showBg && hasContent.value)
|
|
149
169
|
|
|
150
|
-
|
|
170
|
+
const controlAtEnd = computed(() => props.orientation === 'horizontal' && props.controlPosition === 'end')
|
|
151
171
|
|
|
152
|
-
|
|
172
|
+
// The showBg tile and the UiChoice row tint their text with the selection.
|
|
173
|
+
// Disabled, a UiChoice row recedes whole, while elsewhere the selection stays legible in neutral.
|
|
174
|
+
const tone = computed(() => {
|
|
153
175
|
if (props.error) {
|
|
154
|
-
|
|
155
|
-
if (isChecked.value || props.indeterminate) {
|
|
156
|
-
baseClasses.push('bg-actions-danger-idle')
|
|
157
|
-
} else {
|
|
158
|
-
baseClasses.push('bg-surface-neutral-bg-main')
|
|
159
|
-
}
|
|
160
|
-
} else if (isChecked.value || props.indeterminate) {
|
|
161
|
-
baseClasses.push('bg-actions-primary-idle border-borders-primary-default')
|
|
162
|
-
} else {
|
|
163
|
-
baseClasses.push('bg-surface-neutral-bg-main border-borders-neutral-strong')
|
|
176
|
+
return 'danger'
|
|
164
177
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
baseClasses.push('ring')
|
|
168
|
-
if (isChecked.value && !props.error) {
|
|
169
|
-
baseClasses.push('ring-borders-primary-strong')
|
|
170
|
-
} else if (props.error) {
|
|
171
|
-
baseClasses.push('ring-borders-danger-strong')
|
|
172
|
-
} else {
|
|
173
|
-
baseClasses.push('ring-2 ring-inset ring-focus-ring')
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
return baseClasses
|
|
178
|
-
})
|
|
179
|
-
|
|
180
|
-
const iconClasses = computed(() => {
|
|
181
|
-
const baseClasses = ['transition-opacity']
|
|
182
|
-
|
|
183
|
-
// Size classes for icon
|
|
184
|
-
const sizeClasses = {
|
|
185
|
-
sm: 'size-2.5',
|
|
186
|
-
md: 'size-3',
|
|
187
|
-
lg: 'size-3.5',
|
|
178
|
+
if (props.disabled) {
|
|
179
|
+
return (isChecked.value || props.indeterminate) && !inChoiceRow ? 'neutral' : 'disabled'
|
|
188
180
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
// Icon type and color based on state
|
|
193
|
-
if (props.indeterminate) {
|
|
194
|
-
baseClasses.push('i-ph-minus text-actions-neutral-invert-idle opacity-100')
|
|
195
|
-
} else if (isChecked.value) {
|
|
196
|
-
// Checked: always visible with light color on primary/error background
|
|
197
|
-
baseClasses.push('i-ls-checkbox-check text-actions-neutral-invert-idle opacity-100')
|
|
198
|
-
} else if (props.error) {
|
|
199
|
-
// Unchecked + error: show on hover only with danger color
|
|
200
|
-
baseClasses.push('i-ls-checkbox-check text-actions-danger-idle opacity-0 group-hover:opacity-50')
|
|
201
|
-
} else {
|
|
202
|
-
// Unchecked + no error: show on hover only with neutral color
|
|
203
|
-
baseClasses.push('i-ls-checkbox-check text-actions-neutral-idle opacity-0 group-hover:opacity-50')
|
|
181
|
+
if (isChecked.value && inChoiceRow) {
|
|
182
|
+
return 'selected'
|
|
204
183
|
}
|
|
205
|
-
|
|
206
|
-
return baseClasses
|
|
184
|
+
return isChecked.value && props.showBg ? 'primary' : 'neutral'
|
|
207
185
|
})
|
|
208
186
|
|
|
187
|
+
const glyphProps = computed(() => ({
|
|
188
|
+
checked: isChecked.value,
|
|
189
|
+
indeterminate: props.indeterminate,
|
|
190
|
+
error: props.error,
|
|
191
|
+
disabled: props.disabled,
|
|
192
|
+
size: props.size,
|
|
193
|
+
}))
|
|
194
|
+
|
|
195
|
+
const hoverOverlayClasses = computed(() => ({
|
|
196
|
+
'bg-actions-neutral-hover-overlay': !isChecked.value && !props.indeterminate && !props.error,
|
|
197
|
+
'bg-actions-danger-hover-overlay': props.error,
|
|
198
|
+
'bg-actions-primary-hover-overlay': (isChecked.value || props.indeterminate) && !props.error,
|
|
199
|
+
}))
|
|
200
|
+
|
|
201
|
+
// Shared text-colour state used by the label and its icon
|
|
202
|
+
const stateTextClasses = computed(() => ({
|
|
203
|
+
'text-text-neutral-base': tone.value === 'neutral',
|
|
204
|
+
'text-text-neutral-tertiary': tone.value === 'disabled',
|
|
205
|
+
'text-text-danger-base': tone.value === 'danger',
|
|
206
|
+
'text-text-primary-base': tone.value === 'primary',
|
|
207
|
+
'text-text-primary-title': tone.value === 'selected',
|
|
208
|
+
}))
|
|
209
|
+
|
|
210
|
+
// Same tertiary tones as the UiInputRadio info icon
|
|
211
|
+
const infoIconClasses = computed(() => ({
|
|
212
|
+
'text-text-neutral-tertiary': tone.value === 'neutral' || tone.value === 'disabled',
|
|
213
|
+
'text-text-danger-tertiary': tone.value === 'danger',
|
|
214
|
+
'text-text-primary-tertiary': tone.value === 'primary' || tone.value === 'selected',
|
|
215
|
+
}))
|
|
216
|
+
|
|
217
|
+
const descriptionClasses = computed(() => ({
|
|
218
|
+
'text-center': props.orientation === 'vertical',
|
|
219
|
+
'text-text-neutral-secondary': tone.value === 'neutral',
|
|
220
|
+
'text-text-neutral-tertiary': tone.value === 'disabled',
|
|
221
|
+
'text-text-danger-tertiary': tone.value === 'danger',
|
|
222
|
+
'text-text-primary-tertiary': tone.value === 'primary',
|
|
223
|
+
'text-text-primary-base': tone.value === 'selected',
|
|
224
|
+
'cursor-not-allowed': props.disabled,
|
|
225
|
+
'cursor-pointer': !props.disabled,
|
|
226
|
+
}))
|
|
227
|
+
|
|
209
228
|
const displayMessage = computed(() => {
|
|
210
229
|
if (props.error && props.errorMessage) {
|
|
211
230
|
return props.errorMessage
|
|
@@ -213,12 +232,19 @@ const displayMessage = computed(() => {
|
|
|
213
232
|
return undefined
|
|
214
233
|
})
|
|
215
234
|
|
|
235
|
+
const descriptionId = computed(() => props.description ? `${inputId.value}-description` : undefined)
|
|
236
|
+
|
|
237
|
+
const ariaDescribedby = computed(() => {
|
|
238
|
+
const ids = [descriptionId.value, displayMessage.value ? `${inputId.value}-message` : undefined].filter(Boolean)
|
|
239
|
+
return ids.length ? ids.join(' ') : undefined
|
|
240
|
+
})
|
|
241
|
+
|
|
216
242
|
// for error/helper message
|
|
217
243
|
const displayMessageClasses = computed(() => {
|
|
218
|
-
const baseClasses = ['text-content-legends-bold-md mt-1']
|
|
244
|
+
const baseClasses = ['flex items-center gap-1 text-content-legends-bold-md mt-1']
|
|
219
245
|
|
|
220
246
|
if (props.error) {
|
|
221
|
-
baseClasses.push('text-text-danger-
|
|
247
|
+
baseClasses.push('text-text-danger-body')
|
|
222
248
|
} else {
|
|
223
249
|
baseClasses.push('text-text-neutral-secondary')
|
|
224
250
|
}
|
|
@@ -227,29 +253,37 @@ const displayMessageClasses = computed(() => {
|
|
|
227
253
|
})
|
|
228
254
|
|
|
229
255
|
const innerWrapperClasses = computed(() => {
|
|
230
|
-
const classes: string[] = ['group relative
|
|
256
|
+
const classes: string[] = ['group/option relative flex flex-col'];
|
|
231
257
|
|
|
232
258
|
if (props.orientation === 'vertical') {
|
|
233
259
|
classes.push('items-center');
|
|
234
260
|
}
|
|
235
261
|
|
|
236
|
-
|
|
237
|
-
|
|
262
|
+
// The row bleeds around the option without taking layout space and carries the
|
|
263
|
+
// focus ring; hover shows on the glyph only. Inside UiChoice the choice draws the row.
|
|
264
|
+
if (inChoiceRow) {
|
|
265
|
+
classes.push('rounded-field-md')
|
|
266
|
+
} else if (isOptionRow.value && !props.showBg) {
|
|
267
|
+
classes.push('isolate before:absolute before:-inset-x-3 before:-inset-y-2 before:-z-10 before:rounded-field-md before:pointer-events-none has-[input:focus-visible]:before:focus-ring')
|
|
238
268
|
} else {
|
|
239
|
-
classes.push('
|
|
269
|
+
classes.push('rounded-field-md has-[input:focus-visible]:focus-ring')
|
|
240
270
|
}
|
|
241
271
|
|
|
272
|
+
classes.push(props.disabled ? 'hover:cursor-not-allowed' : 'hover:cursor-pointer')
|
|
273
|
+
|
|
242
274
|
if (props.showBg) {
|
|
243
275
|
classes.push('p-2 ring-inset');
|
|
244
|
-
if (isChecked.value && !props.error) {
|
|
276
|
+
if (isChecked.value && !props.error && props.disabled) {
|
|
277
|
+
classes.push('bg-control-field-bg ring-1 ring-borders-neutral-strong');
|
|
278
|
+
} else if (isChecked.value && !props.error) {
|
|
245
279
|
// checked
|
|
246
|
-
classes.push('bg-actions-primary-idle-alpha-light ring-2 ring-
|
|
280
|
+
classes.push('bg-actions-primary-idle-alpha-light ring-2 ring-actions-primary-idle');
|
|
247
281
|
} else if (!isChecked.value && !props.error) {
|
|
248
282
|
// idle
|
|
249
283
|
classes.push('bg-surface-neutral-alpha-100 ring-transparent');
|
|
250
284
|
} else if (isChecked.value && props.error) {
|
|
251
285
|
// error + checked
|
|
252
|
-
classes.push('bg-actions-danger-idle-alpha-light ring-2 ring-
|
|
286
|
+
classes.push('bg-actions-danger-idle-alpha-light ring-2 ring-actions-danger-idle');
|
|
253
287
|
} else {
|
|
254
288
|
// error + unchecked
|
|
255
289
|
classes.push('bg-actions-danger-idle-alpha-light')
|
|
@@ -297,12 +331,10 @@ function handleChange (event: Event) {
|
|
|
297
331
|
}
|
|
298
332
|
|
|
299
333
|
function handleFocus(event: FocusEvent) {
|
|
300
|
-
isFocused.value = true
|
|
301
334
|
emit('focus', event)
|
|
302
335
|
}
|
|
303
336
|
|
|
304
337
|
function handleBlur (event: FocusEvent) {
|
|
305
|
-
isFocused.value = false
|
|
306
338
|
emit('blur', event)
|
|
307
339
|
}
|
|
308
340
|
|
|
@@ -322,9 +354,14 @@ defineExpose({
|
|
|
322
354
|
</script>
|
|
323
355
|
|
|
324
356
|
<template>
|
|
325
|
-
<div
|
|
357
|
+
<div
|
|
358
|
+
class="ui-input-checkbox-wrapper"
|
|
359
|
+
data-testid="ui-input-checkbox"
|
|
360
|
+
:class="fullWidth ? 'w-full' : 'w-fit'"
|
|
361
|
+
>
|
|
326
362
|
<div
|
|
327
363
|
:class="innerWrapperClasses"
|
|
364
|
+
data-testid="ui-input-checkbox-row"
|
|
328
365
|
@click="triggerCheckbox"
|
|
329
366
|
>
|
|
330
367
|
<input
|
|
@@ -335,94 +372,108 @@ defineExpose({
|
|
|
335
372
|
:name="name"
|
|
336
373
|
type="checkbox"
|
|
337
374
|
class="absolute opacity-0 pointer-events-none"
|
|
375
|
+
:aria-label="ariaLabel"
|
|
338
376
|
:aria-invalid="error"
|
|
339
|
-
:aria-describedby="
|
|
377
|
+
:aria-describedby="ariaDescribedby"
|
|
340
378
|
@change="handleChange"
|
|
341
379
|
@focus="handleFocus"
|
|
342
380
|
@blur="handleBlur"
|
|
343
381
|
>
|
|
344
382
|
|
|
383
|
+
<!-- Icon - vertical only, stacked above the text -->
|
|
384
|
+
<span
|
|
385
|
+
v-if="(icon || $slots.icon) && orientation === 'vertical'"
|
|
386
|
+
class="flex items-center justify-center shrink-0 mb-2"
|
|
387
|
+
data-testid="ui-input-checkbox-icon"
|
|
388
|
+
>
|
|
389
|
+
<slot name="icon">
|
|
390
|
+
<span
|
|
391
|
+
class="size-4"
|
|
392
|
+
:class="[icon, stateTextClasses]"
|
|
393
|
+
/>
|
|
394
|
+
</slot>
|
|
395
|
+
</span>
|
|
396
|
+
|
|
345
397
|
<!-- First row (contains checkbox for horizontal orientation) -->
|
|
346
398
|
<div
|
|
347
|
-
class="flex
|
|
348
|
-
:class="
|
|
399
|
+
class="flex"
|
|
400
|
+
:class="orientation === 'vertical' ? 'items-center justify-center' : 'items-start'"
|
|
349
401
|
>
|
|
350
402
|
<!-- Checkbox - horizontal only -->
|
|
351
403
|
<label
|
|
352
404
|
v-if="orientation === 'horizontal'"
|
|
353
|
-
class="flex
|
|
354
|
-
:class="
|
|
405
|
+
class="flex size-5 items-center shrink-0"
|
|
406
|
+
:class="[
|
|
407
|
+
disabled ? 'cursor-not-allowed' : 'cursor-pointer',
|
|
408
|
+
controlAtEnd
|
|
409
|
+
? ['justify-end', { 'order-last': hasContent, 'ms-3': hasContent && !inChoiceRow, 'ms-5': hasContent && inChoiceRow }]
|
|
410
|
+
: ['justify-start', { 'me-2': hasContent && showBg, 'me-1': hasContent && !showBg && !inChoiceRow, 'me-3': hasContent && !showBg && inChoiceRow }],
|
|
411
|
+
]"
|
|
355
412
|
>
|
|
356
|
-
<
|
|
357
|
-
:class="checkboxClasses"
|
|
358
|
-
aria-hidden="true"
|
|
359
|
-
>
|
|
360
|
-
<span
|
|
361
|
-
:class="iconClasses"
|
|
362
|
-
class="block relative z-1"
|
|
363
|
-
>
|
|
364
|
-
<div
|
|
365
|
-
class="absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none"
|
|
366
|
-
:class="{
|
|
367
|
-
'bg-actions-neutral-hover-overlay': !isChecked && !error,
|
|
368
|
-
'bg-actions-danger-hover-overlay': error,
|
|
369
|
-
'bg-actions-primary-hover-overlay': isChecked && !error,
|
|
370
|
-
}"
|
|
371
|
-
/>
|
|
372
|
-
</span>
|
|
373
|
-
</span>
|
|
413
|
+
<CheckboxGlyph v-bind="glyphProps" />
|
|
374
414
|
</label>
|
|
375
415
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
'text-text-danger-base': error,
|
|
382
|
-
'text-text-primary-base': isChecked && !error,
|
|
383
|
-
'cursor-not-allowed': disabled,
|
|
384
|
-
'cursor-pointer': !disabled,
|
|
385
|
-
}"
|
|
386
|
-
@click.stop
|
|
416
|
+
<!-- Icon - horizontal only, between the checkbox and the text -->
|
|
417
|
+
<span
|
|
418
|
+
v-if="(icon || $slots.icon) && orientation === 'horizontal'"
|
|
419
|
+
class="flex items-center justify-center shrink-0 me-2 min-h-5"
|
|
420
|
+
data-testid="ui-input-checkbox-icon"
|
|
387
421
|
>
|
|
388
|
-
<slot name="
|
|
389
|
-
|
|
422
|
+
<slot name="icon">
|
|
423
|
+
<span
|
|
424
|
+
class="size-4"
|
|
425
|
+
:class="[icon, stateTextClasses]"
|
|
426
|
+
/>
|
|
390
427
|
</slot>
|
|
391
|
-
</
|
|
428
|
+
</span>
|
|
392
429
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
:
|
|
430
|
+
<div
|
|
431
|
+
v-if="hasText"
|
|
432
|
+
class="flex flex-col min-w-0"
|
|
433
|
+
:class="{ 'items-center': orientation === 'vertical', 'gap-0.5': !showBg && !inChoiceRow, 'gap-1': inChoiceRow, 'flex-1': controlAtEnd }"
|
|
434
|
+
data-testid="ui-input-checkbox-text"
|
|
397
435
|
>
|
|
398
|
-
<
|
|
399
|
-
|
|
400
|
-
:
|
|
401
|
-
|
|
402
|
-
'
|
|
403
|
-
'
|
|
404
|
-
}"
|
|
436
|
+
<Label
|
|
437
|
+
v-if="label || $slots.label || labelInfo"
|
|
438
|
+
:for="inputId"
|
|
439
|
+
:class="[stateTextClasses, inChoiceRow ? 'text-content-text-md-medium' : 'text-content-text-md-regular', {
|
|
440
|
+
'cursor-not-allowed': disabled,
|
|
441
|
+
'cursor-pointer': !disabled,
|
|
442
|
+
}]"
|
|
443
|
+
@click.stop
|
|
405
444
|
>
|
|
406
|
-
<
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
</div>
|
|
445
|
+
<slot name="label">
|
|
446
|
+
{{ label }}{{ required ? '*' : '' }}
|
|
447
|
+
</slot>
|
|
410
448
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
449
|
+
<!-- icon: inline so it wraps with the text instead of centering against the whole label block,
|
|
450
|
+
and the word joiner keeps it on the line of the last word.
|
|
451
|
+
-translate-y-px because the icon aligns with the text so that its visually centered -->
|
|
452
|
+
<span
|
|
453
|
+
v-if="labelInfo"
|
|
454
|
+
class="whitespace-nowrap before:content-['\2060']"
|
|
455
|
+
><UiTooltip :content="labelInfo">
|
|
456
|
+
<span
|
|
457
|
+
class="inline-flex items-center justify-center size-4 ms-2 align-middle -translate-y-px cursor-help shrink-0"
|
|
458
|
+
:class="infoIconClasses"
|
|
459
|
+
data-testid="open-tooltip"
|
|
460
|
+
@click.stop.prevent="emit('tooltip-clicked')"
|
|
461
|
+
>
|
|
462
|
+
<span class="i-ph-info-fill size-4" />
|
|
463
|
+
</span>
|
|
464
|
+
</UiTooltip></span>
|
|
465
|
+
</Label>
|
|
466
|
+
|
|
467
|
+
<span
|
|
468
|
+
v-if="description"
|
|
469
|
+
:id="descriptionId"
|
|
470
|
+
class="text-content-text-md-regular"
|
|
471
|
+
:class="descriptionClasses"
|
|
472
|
+
>
|
|
473
|
+
{{ description }}
|
|
474
|
+
</span>
|
|
475
|
+
</div>
|
|
476
|
+
</div>
|
|
426
477
|
|
|
427
478
|
<!-- Checkbox - vertical only -->
|
|
428
479
|
<label
|
|
@@ -430,34 +481,13 @@ defineExpose({
|
|
|
430
481
|
class="flex justify-center mt-2"
|
|
431
482
|
:class="disabled ? 'cursor-not-allowed' : 'cursor-pointer'"
|
|
432
483
|
>
|
|
433
|
-
<
|
|
434
|
-
:class="checkboxClasses"
|
|
435
|
-
aria-hidden="true"
|
|
436
|
-
>
|
|
437
|
-
<span
|
|
438
|
-
:class="iconClasses"
|
|
439
|
-
class="block relative z-1"
|
|
440
|
-
>
|
|
441
|
-
<div
|
|
442
|
-
class="absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none"
|
|
443
|
-
:class="{
|
|
444
|
-
'bg-actions-neutral-hover-overlay': !isChecked && !error,
|
|
445
|
-
'bg-actions-danger-hover-overlay': error,
|
|
446
|
-
'bg-actions-primary-hover-overlay': isChecked && !error,
|
|
447
|
-
}"
|
|
448
|
-
/>
|
|
449
|
-
</span>
|
|
450
|
-
</span>
|
|
484
|
+
<CheckboxGlyph v-bind="glyphProps" />
|
|
451
485
|
</label>
|
|
452
486
|
|
|
453
487
|
<div
|
|
454
|
-
v-if="showBg"
|
|
455
|
-
class="absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none rounded-
|
|
456
|
-
:class="
|
|
457
|
-
'bg-actions-neutral-hover-overlay': !isChecked && !error,
|
|
458
|
-
'bg-actions-danger-hover-overlay': error,
|
|
459
|
-
'bg-actions-primary-hover-overlay': isChecked && !error,
|
|
460
|
-
}"
|
|
488
|
+
v-if="showBg && !disabled"
|
|
489
|
+
class="absolute inset-0 opacity-0 group-hover/option:opacity-100 transition-opacity pointer-events-none rounded-[inherit]"
|
|
490
|
+
:class="hoverOverlayClasses"
|
|
461
491
|
/>
|
|
462
492
|
</div>
|
|
463
493
|
|
|
@@ -467,6 +497,12 @@ defineExpose({
|
|
|
467
497
|
:id="`${inputId}-message`"
|
|
468
498
|
:class="displayMessageClasses"
|
|
469
499
|
>
|
|
500
|
+
<span
|
|
501
|
+
v-if="error"
|
|
502
|
+
class="i-ph-warning-circle size-4 shrink-0"
|
|
503
|
+
data-testid="ui-input-checkbox-error-icon"
|
|
504
|
+
aria-hidden="true"
|
|
505
|
+
/>
|
|
470
506
|
{{ displayMessage }}
|
|
471
507
|
</p>
|
|
472
508
|
</div>
|