@nexxtmove/ui 2.5.0 → 2.7.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/dist/components/editor/molecules/EditorBorder/EditorBorder.vue.d.ts +12 -0
- package/dist/components/editor/molecules/EditorColor/_ThemeRoleSwatches.vue.d.ts +16 -0
- package/dist/index.js +1094 -1135
- package/dist/nuxt.js +0 -1
- package/package.json +38 -36
- package/src/attribute-contract.test.ts +151 -0
- package/src/components/atoms/AnimatedNumber/AnimatedNumber.stories.ts +36 -0
- package/src/components/atoms/AnimatedNumber/AnimatedNumber.test.ts +21 -0
- package/src/components/atoms/Avatar/Avatar.stories.ts +122 -0
- package/src/components/atoms/Avatar/Avatar.test.ts +134 -0
- package/src/components/atoms/Button/Button.stories.ts +290 -0
- package/src/components/atoms/Button/Button.test.ts +406 -0
- package/src/components/atoms/Card/Card.stories.ts +45 -0
- package/src/components/atoms/Card/Card.test.ts +46 -0
- package/src/components/atoms/Checkbox/Checkbox.stories.ts +35 -0
- package/src/components/atoms/Checkbox/Checkbox.test.ts +55 -0
- package/src/components/atoms/Chip/Chip.stories.ts +274 -0
- package/src/components/atoms/Chip/Chip.test.ts +230 -0
- package/src/components/atoms/EnergyLabel/EnergyLabel.stories.ts +189 -0
- package/src/components/atoms/EnergyLabel/EnergyLabel.test.ts +100 -0
- package/src/components/atoms/FloatingPanel/FloatingPanel.stories.ts +677 -0
- package/src/components/atoms/FloatingPanel/FloatingPanel.test.ts +864 -0
- package/src/components/atoms/Icon/Icon.stories.ts +63 -0
- package/src/components/atoms/Icon/Icon.test.ts +89 -0
- package/src/components/atoms/Loader/Loader.stories.ts +36 -0
- package/src/components/atoms/Loader/Loader.test.ts +40 -0
- package/src/components/atoms/PickerItem/PickerItem.stories.ts +172 -0
- package/src/components/atoms/PickerItem/PickerItem.test.ts +142 -0
- package/src/components/atoms/PickerPreview/PickerPreview.stories.ts +183 -0
- package/src/components/atoms/PickerPreview/PickerPreview.test.ts +137 -0
- package/src/components/atoms/PresenceIndicator/PresenceIndicator.stories.ts +21 -0
- package/src/components/atoms/PropertyListing/PropertyListing.stories.ts +38 -0
- package/src/components/atoms/PropertyListing/PropertyListing.test.ts +46 -0
- package/src/components/atoms/SelectableOption/SelectableOption.stories.ts +131 -0
- package/src/components/atoms/SelectableOption/SelectableOption.test.ts +96 -0
- package/src/components/atoms/Skeleton/Skeleton.stories.ts +27 -0
- package/src/components/atoms/Skeleton/Skeleton.test.ts +28 -0
- package/src/components/atoms/Slider/Slider.stories.ts +151 -0
- package/src/components/atoms/Slider/Slider.test.ts +191 -0
- package/src/components/atoms/Squircle/Squircle.stories.ts +114 -0
- package/src/components/atoms/Squircle/Squircle.test.ts +70 -0
- package/src/components/atoms/Switch/Switch.stories.ts +91 -0
- package/src/components/atoms/Switch/Switch.test.ts +183 -0
- package/src/components/atoms/Tooltip/Tooltip.stories.ts +158 -0
- package/src/components/atoms/Tooltip/Tooltip.test.ts +134 -0
- package/src/components/editor/atoms/EditorDimensionField/EditorDimensionField.stories.ts +124 -0
- package/src/components/editor/atoms/EditorDimensionField/EditorDimensionField.test.ts +464 -0
- package/src/components/editor/atoms/EditorSettingsBlock/EditorSettingsBlock.stories.ts +266 -0
- package/src/components/editor/atoms/EditorSettingsBlock/EditorSettingsBlock.test.ts +421 -0
- package/src/components/editor/atoms/EditorSettingsGroup/EditorSettingsGroup.stories.ts +365 -0
- package/src/components/editor/atoms/EditorSettingsGroup/EditorSettingsGroup.test.ts +484 -0
- package/src/components/editor/composables/useRadioGrid.test.ts +261 -0
- package/src/components/editor/molecules/EditorAlignItems/EditorAlignItems.stories.ts +73 -0
- package/src/components/editor/molecules/EditorAlignItems/EditorAlignItems.test.ts +189 -0
- package/src/components/editor/molecules/EditorAlignmentGrid/EditorAlignmentGrid.stories.ts +309 -0
- package/src/components/editor/molecules/EditorAlignmentGrid/EditorAlignmentGrid.test.ts +359 -0
- package/src/components/editor/molecules/EditorAnchor/EditorAnchor.stories.ts +138 -0
- package/src/components/editor/molecules/EditorAnchor/EditorAnchor.test.ts +344 -0
- package/src/components/editor/molecules/EditorBackgroundSize/EditorBackgroundSize.stories.ts +87 -0
- package/src/components/editor/molecules/EditorBackgroundSize/EditorBackgroundSize.test.ts +262 -0
- package/src/components/editor/molecules/EditorBlur/EditorBlur.stories.ts +115 -0
- package/src/components/editor/molecules/EditorBlur/EditorBlur.test.ts +243 -0
- package/src/components/editor/molecules/EditorBorder/EditorBorder.stories.ts +187 -0
- package/src/components/editor/molecules/EditorBorder/EditorBorder.test.ts +456 -0
- package/src/components/editor/molecules/EditorBorder/EditorBorder.vue +58 -2
- package/src/components/editor/molecules/EditorColor/EditorColor.stories.ts +563 -0
- package/src/components/editor/molecules/EditorColor/EditorColor.test.ts +689 -0
- package/src/components/editor/molecules/EditorColor/EditorColorGradient.test.ts +793 -0
- package/src/components/editor/molecules/EditorColor/_ColorField.vue +7 -29
- package/src/components/editor/molecules/EditorColor/_ThemeRoleSwatches.vue +57 -0
- package/src/components/editor/molecules/EditorColor/gradientClass.test.ts +303 -0
- package/src/components/editor/molecules/EditorDashPattern/EditorDashPattern.stories.ts +72 -0
- package/src/components/editor/molecules/EditorDashPattern/EditorDashPattern.test.ts +124 -0
- package/src/components/editor/molecules/EditorFlexDirection/EditorFlexDirection.stories.ts +46 -0
- package/src/components/editor/molecules/EditorFlexDirection/EditorFlexDirection.test.ts +97 -0
- package/src/components/editor/molecules/EditorFontSize/EditorFontSize.stories.ts +248 -0
- package/src/components/editor/molecules/EditorFontSize/EditorFontSize.test.ts +288 -0
- package/src/components/editor/molecules/EditorGap/EditorGap.stories.ts +129 -0
- package/src/components/editor/molecules/EditorGap/EditorGap.test.ts +253 -0
- package/src/components/editor/molecules/EditorHeadingType/EditorHeadingType.stories.ts +68 -0
- package/src/components/editor/molecules/EditorHeadingType/EditorHeadingType.test.ts +150 -0
- package/src/components/editor/molecules/EditorJustifyContent/EditorJustifyContent.stories.ts +71 -0
- package/src/components/editor/molecules/EditorJustifyContent/EditorJustifyContent.test.ts +161 -0
- package/src/components/editor/molecules/EditorLetterSpacing/EditorLetterSpacing.stories.ts +204 -0
- package/src/components/editor/molecules/EditorLetterSpacing/EditorLetterSpacing.test.ts +238 -0
- package/src/components/editor/molecules/EditorLineHeight/EditorLineHeight.stories.ts +257 -0
- package/src/components/editor/molecules/EditorLineHeight/EditorLineHeight.test.ts +286 -0
- package/src/components/editor/molecules/EditorLineStyle/EditorLineStyle.stories.ts +135 -0
- package/src/components/editor/molecules/EditorLineStyle/EditorLineStyle.test.ts +230 -0
- package/src/components/editor/molecules/EditorMaxWidth/EditorMaxWidth.stories.ts +154 -0
- package/src/components/editor/molecules/EditorMaxWidth/EditorMaxWidth.test.ts +112 -0
- package/src/components/editor/molecules/EditorOverrideStatus/EditorOverrideStatus.stories.ts +206 -0
- package/src/components/editor/molecules/EditorOverrideStatus/EditorOverrideStatus.test.ts +332 -0
- package/src/components/editor/molecules/EditorPadding/EditorPadding.stories.ts +374 -0
- package/src/components/editor/molecules/EditorPadding/EditorPadding.test.ts +712 -0
- package/src/components/editor/molecules/EditorRadius/EditorRadius.stories.ts +64 -0
- package/src/components/editor/molecules/EditorRadius/EditorRadius.test.ts +137 -0
- package/src/components/editor/molecules/EditorShadow/EditorShadow.stories.ts +103 -0
- package/src/components/editor/molecules/EditorShadow/EditorShadow.test.ts +168 -0
- package/src/components/editor/molecules/EditorSize/EditorSize.stories.ts +84 -0
- package/src/components/editor/molecules/EditorSize/EditorSize.test.ts +253 -0
- package/src/components/editor/molecules/EditorSizeLimit/EditorSizeLimit.stories.ts +49 -0
- package/src/components/editor/molecules/EditorSizeLimit/EditorSizeLimit.test.ts +43 -0
- package/src/components/editor/molecules/EditorTextAlign/EditorTextAlign.stories.ts +69 -0
- package/src/components/editor/molecules/EditorTextAlign/EditorTextAlign.test.ts +155 -0
- package/src/components/molecules/Announcement/Announcement.stories.ts +224 -0
- package/src/components/molecules/Announcement/Announcement.test.ts +161 -0
- package/src/components/molecules/ContactInfoCard/ContactInfoCard.stories.ts +99 -0
- package/src/components/molecules/ContactInfoCard/ContactInfoCard.test.ts +70 -0
- package/src/components/molecules/CustomerJourneyTile/CustomerJourneyTile.stories.ts +148 -0
- package/src/components/molecules/CustomerJourneyTile/CustomerJourneyTile.test.ts +271 -0
- package/src/components/molecules/DoughnutChart/DoughnutChart.stories.ts +45 -0
- package/src/components/molecules/DoughnutChart/DoughnutChart.test.ts +205 -0
- package/src/components/molecules/InfoBlock/InfoBlock.stories.ts +84 -0
- package/src/components/molecules/InfoBlock/InfoBlock.test.ts +101 -0
- package/src/components/molecules/InputField/InputField.stories.ts +117 -0
- package/src/components/molecules/InputField/InputField.test.ts +138 -0
- package/src/components/molecules/InputSelect/InputSelect.stories.ts +116 -0
- package/src/components/molecules/InputSelect/InputSelect.test.ts +127 -0
- package/src/components/molecules/ModalFooter/ModalFooter.stories.ts +204 -0
- package/src/components/molecules/ModalFooter/ModalFooter.test.ts +276 -0
- package/src/components/molecules/PageCard/PageCard.stories.ts +100 -0
- package/src/components/molecules/PageCard/PageCard.test.ts +91 -0
- package/src/components/molecules/PageContainer/PageContainer.stories.ts +90 -0
- package/src/components/molecules/PageContainer/PageContainer.test.ts +50 -0
- package/src/components/molecules/PageMockup/PageMockup.stories.ts +38 -0
- package/src/components/molecules/PageMockup/PageMockup.test.ts +20 -0
- package/src/components/molecules/PageTypeTile/PageTypeTile.stories.ts +63 -0
- package/src/components/molecules/PageTypeTile/PageTypeTile.test.ts +41 -0
- package/src/components/molecules/Pagination/Pagination.stories.ts +72 -0
- package/src/components/molecules/Pagination/Pagination.test.ts +130 -0
- package/src/components/molecules/PickerGroup/PickerGroup.stories.ts +90 -0
- package/src/components/molecules/PickerGroup/PickerGroup.test.ts +145 -0
- package/src/components/molecules/PickerList/PickerList.stories.ts +436 -0
- package/src/components/molecules/PickerList/PickerList.test.ts +870 -0
- package/src/components/molecules/PlaceholderInput/PlaceholderInput.stories.ts +48 -0
- package/src/components/molecules/PlaceholderInput/PlaceholderInput.test.ts +107 -0
- package/src/components/molecules/PropertyCard/PropertyCard.stories.ts +46 -0
- package/src/components/molecules/PropertyCard/PropertyCard.test.ts +59 -0
- package/src/components/molecules/Select/Select.stories.ts +264 -0
- package/src/components/molecules/Select/Select.test.ts +315 -0
- package/src/components/molecules/SidebarMenuItem/SidebarMenuItem.stories.ts +84 -0
- package/src/components/molecules/SidebarMenuItem/SidebarMenuItem.test.ts +103 -0
- package/src/components/molecules/SkeletonPropertyCard/SkeletonPropertyCard.stories.ts +11 -0
- package/src/components/molecules/SkeletonPropertyCard/SkeletonPropertyCard.test.ts +38 -0
- package/src/components/molecules/SocialIcons/SocialIcons.stories.ts +28 -0
- package/src/components/molecules/SocialIcons/SocialIcons.test.ts +58 -0
- package/src/components/molecules/SocialMediaCustomTemplate/SocialMediaCustomTemplate.stories.ts +11 -0
- package/src/components/molecules/SocialMediaCustomTemplate/SocialMediaCustomTemplate.test.ts +116 -0
- package/src/components/molecules/SocialMediaType/SocialMediaType.stories.ts +37 -0
- package/src/components/molecules/SocialMediaType/SocialMediaType.test.ts +126 -0
- package/src/components/molecules/Source/Source.stories.ts +35 -0
- package/src/components/molecules/Source/Source.test.ts +45 -0
- package/src/components/molecules/TabbedContent/TabbedContent.stories.ts +96 -0
- package/src/components/molecules/TabbedContent/TabbedContent.test.ts +109 -0
- package/src/components/molecules/Tabs/Tabs.stories.ts +230 -0
- package/src/components/molecules/Tabs/Tabs.test.ts +280 -0
- package/src/components/molecules/TemplateCard/TemplateCard.stories.ts +327 -0
- package/src/components/molecules/TemplateCard/TemplateCard.test.ts +339 -0
- package/src/components/molecules/Textarea/Textarea.stories.ts +216 -0
- package/src/components/molecules/Textarea/Textarea.test.ts +191 -0
- package/src/components/molecules/TimelineEvent/TimelineEvent.stories.ts +319 -0
- package/src/components/molecules/TimelineEvent/TimelineEvent.test.ts +224 -0
- package/src/components/molecules/TimelineLanes/TimelineLanes.stories.ts +29 -0
- package/src/components/molecules/TimelineLanes/TimelineLanes.test.ts +30 -0
- package/src/components/molecules/Toast/Toast.stories.ts +110 -0
- package/src/components/molecules/Toast/Toast.test.ts +103 -0
- package/src/components/molecules/ToggleGroup/ToggleGroup.stories.ts +297 -0
- package/src/components/molecules/ToggleGroup/ToggleGroup.test.ts +578 -0
- package/src/components/molecules/Tree/Tree.stories.ts +884 -0
- package/src/components/molecules/Tree/Tree.test.ts +1247 -0
- package/src/components/molecules/Tree/tree-drop.test.ts +223 -0
- package/src/components/organisms/Calendar/Calendar.stories.ts +108 -0
- package/src/components/organisms/Calendar/Calendar.test.ts +279 -0
- package/src/components/organisms/Calendar/_CalendarDayView.test.ts +104 -0
- package/src/components/organisms/Calendar/_CalendarHeader.test.ts +86 -0
- package/src/components/organisms/Calendar/_CalendarMonthView.test.ts +52 -0
- package/src/components/organisms/Calendar/_CalendarTimePicker.test.ts +89 -0
- package/src/components/organisms/Calendar/_CalendarYearView.test.ts +56 -0
- package/src/components/organisms/ColorPicker/ColorPicker.stories.ts +229 -0
- package/src/components/organisms/ColorPicker/ColorPicker.test.ts +638 -0
- package/src/components/organisms/ColorPicker/gradient.test.ts +67 -0
- package/src/components/organisms/ColorPicker/gradientGeometry.test.ts +206 -0
- package/src/components/organisms/Combobox/Combobox.stories.ts +234 -0
- package/src/components/organisms/Combobox/Combobox.test.ts +512 -0
- package/src/components/organisms/Combobox/Combobox.vue +1 -1
- package/src/components/organisms/ComboboxPanel/ComboboxPanel.stories.ts +158 -0
- package/src/components/organisms/ComboboxPanel/ComboboxPanel.test.ts +524 -0
- package/src/components/organisms/ComboboxPanel/ComboboxPanel.vue +1 -1
- package/src/components/organisms/CountrySelect/CountrySelect.stories.ts +139 -0
- package/src/components/organisms/CountrySelect/CountrySelect.test.ts +149 -0
- package/src/components/organisms/DatePicker/DatePicker.stories.ts +163 -0
- package/src/components/organisms/DatePicker/DatePicker.test.ts +214 -0
- package/src/components/organisms/DropdownButton/DropdownButton.stories.ts +123 -0
- package/src/components/organisms/DropdownButton/DropdownButton.test.ts +379 -0
- package/src/components/organisms/FontPicker/FontPicker.stories.ts +476 -0
- package/src/components/organisms/FontPicker/FontPicker.test.ts +873 -0
- package/src/components/organisms/Header/Header.stories.ts +75 -0
- package/src/components/organisms/Header/Header.test.ts +233 -0
- package/src/components/organisms/IconPicker/IconPicker.stories.ts +734 -0
- package/src/components/organisms/IconPicker/IconPicker.test.ts +669 -0
- package/src/components/organisms/IconPicker/_IconPickerGrid.test.ts +184 -0
- package/src/components/organisms/IconPicker/_IconPickerRail.test.ts +102 -0
- package/src/components/organisms/IconPicker/useIconPickerNavigation.test.ts +215 -0
- package/src/components/organisms/Modal/Modal.stories.ts +350 -0
- package/src/components/organisms/Modal/Modal.test.ts +275 -0
- package/src/components/organisms/PickerPanel/PickerPanel.stories.ts +452 -0
- package/src/components/organisms/PickerPanel/PickerPanel.test.ts +358 -0
- package/src/components/organisms/ProgressBar/ProgressBar.stories.ts +100 -0
- package/src/components/organisms/ProgressBar/ProgressBar.test.ts +417 -0
- package/src/components/organisms/ReferenceCard/ReferenceCard.stories.ts +191 -0
- package/src/components/organisms/ReferenceCard/ReferenceCard.test.ts +165 -0
- package/src/components/organisms/SocialMediaTemplate/SocialMediaTemplate.stories.ts +65 -0
- package/src/components/organisms/SocialMediaTemplate/SocialMediaTemplate.test.ts +466 -0
- package/src/components/organisms/StepperHeader/StepperHeader.stories.ts +91 -0
- package/src/components/organisms/StepperHeader/StepperHeader.test.ts +279 -0
- package/src/components/organisms/Table/Table.stories.ts +332 -0
- package/src/components/organisms/Table/Table.test.ts +320 -0
- package/src/components/organisms/TimelinePhaseblock/TimelinePhaseblock.stories.ts +198 -0
- package/src/components/organisms/TimelinePhaseblock/TimelinePhaseblock.test.ts +283 -0
- package/src/components/organisms/TimelineTrack/TimelineTrack.stories.ts +120 -0
- package/src/components/organisms/TimelineTrack/TimelineTrack.test.ts +91 -0
- package/src/components/organisms/Toaster/Toaster.stories.ts +51 -0
- package/src/components/organisms/Toaster/Toaster.test.ts +75 -0
- package/src/components/organisms/VideoControls/VideoControls.stories.ts +792 -0
- package/src/components/organisms/VideoControls/VideoControls.test.ts +1056 -0
- package/src/components/organisms/VideoPlayer/VideoPlayer.stories.ts +327 -0
- package/src/components/organisms/VideoPlayer/VideoPlayer.test.ts +439 -0
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
import { expect, userEvent, waitFor, within } from 'storybook/test'
|
|
4
|
+
import EditorPadding from './EditorPadding.vue'
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
title: 'Components/Editor Components/Molecules/Editor Padding',
|
|
8
|
+
component: EditorPadding,
|
|
9
|
+
decorators: [() => ({ template: '<div class="w-100 mx-auto"><story /></div>' })],
|
|
10
|
+
argTypes: {
|
|
11
|
+
label: { control: 'text' },
|
|
12
|
+
},
|
|
13
|
+
} satisfies Meta<typeof EditorPadding>
|
|
14
|
+
|
|
15
|
+
type Story = StoryObj<typeof EditorPadding>
|
|
16
|
+
|
|
17
|
+
/** Shows the class string as-is: it is what the editor puts on the element. */
|
|
18
|
+
const render = (args: Story['args'], initial: string) => ({
|
|
19
|
+
components: { EditorPadding },
|
|
20
|
+
setup() {
|
|
21
|
+
const padding = ref(initial)
|
|
22
|
+
return { args, padding }
|
|
23
|
+
},
|
|
24
|
+
template: `
|
|
25
|
+
<div>
|
|
26
|
+
<EditorPadding v-bind="args" v-model="padding" />
|
|
27
|
+
<p data-testid="padding-class" class="small-normal text-gray-700">{{ padding }}</p>
|
|
28
|
+
</div>
|
|
29
|
+
`,
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
/** The class string the story is bound to, as the readout under the block shows it. */
|
|
33
|
+
const classString = (canvasElement: HTMLElement) =>
|
|
34
|
+
canvasElement.querySelector('[data-testid="padding-class"]')!.textContent
|
|
35
|
+
|
|
36
|
+
/** The fields, in reading order; the two of the collapsed row are in the DOM as well. */
|
|
37
|
+
const fields = (canvas: ReturnType<typeof within>) =>
|
|
38
|
+
canvas.getAllByRole('textbox') as HTMLInputElement[]
|
|
39
|
+
|
|
40
|
+
/** The fields show px while the model stays a Tailwind class: `p-6` reads as 24. */
|
|
41
|
+
export const Default: Story = {
|
|
42
|
+
render: (args) => render(args, 'p-6'),
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Padding that is not set yet: every field falls back to its `0` placeholder. */
|
|
46
|
+
export const Empty: Story = {
|
|
47
|
+
render: (args) => render(args, 'p-0'),
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The tooltip is portalled to the body, so it is looked up outside the canvas,
|
|
52
|
+
* and on reka-ui's own wrapper rather than by role or text: `role="tooltip"`
|
|
53
|
+
* sits on a visually hidden copy that is also `aria-hidden` (so `*ByRole`
|
|
54
|
+
* skips it) while the text itself is in the DOM twice (so `*ByText` finds two).
|
|
55
|
+
* Hover and keyboard focus both have to open it.
|
|
56
|
+
*/
|
|
57
|
+
const expectTooltip = async (text: string, canvas: ReturnType<typeof within>) => {
|
|
58
|
+
const button = canvas.getByRole('button', { name: text })
|
|
59
|
+
|
|
60
|
+
const tooltip = () => document.querySelector('[data-reka-popper-content-wrapper]')
|
|
61
|
+
|
|
62
|
+
expect(button).toHaveAttribute('data-state', 'closed')
|
|
63
|
+
|
|
64
|
+
// Keyboard first, from a state the pointer has not touched yet.
|
|
65
|
+
button.focus()
|
|
66
|
+
await waitFor(() => expect(tooltip()).toHaveTextContent(text))
|
|
67
|
+
expect(button).toHaveAttribute('aria-describedby')
|
|
68
|
+
|
|
69
|
+
button.blur()
|
|
70
|
+
await waitFor(() => expect(button).toHaveAttribute('data-state', 'closed'))
|
|
71
|
+
|
|
72
|
+
await userEvent.hover(button)
|
|
73
|
+
await waitFor(() => expect(tooltip()).toHaveTextContent(text))
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Opening the four fields slides the second row out from behind the first, so
|
|
78
|
+
* the block grows instead of jumping. Both rows keep the same column widths.
|
|
79
|
+
*/
|
|
80
|
+
export const TogglesOpen: Story = {
|
|
81
|
+
render: (args) => render(args, 'p-4'),
|
|
82
|
+
play: async ({ canvasElement }) => {
|
|
83
|
+
const canvas = within(canvasElement)
|
|
84
|
+
const row = canvasElement.querySelector('[data-testid="editor-padding-secondary-row"]')!
|
|
85
|
+
const toggleLine = canvas
|
|
86
|
+
.getByRole('button', { name: 'Padding per zijde' })
|
|
87
|
+
.querySelector('line')!
|
|
88
|
+
const lengthBefore = toggleLine.getAttribute('x1')
|
|
89
|
+
|
|
90
|
+
expect(row.className).toContain('grid-rows-[0fr]')
|
|
91
|
+
expect(row.getAttribute('inert')).not.toBeNull()
|
|
92
|
+
|
|
93
|
+
await expectTooltip('Padding per zijde', canvas)
|
|
94
|
+
|
|
95
|
+
await userEvent.click(canvas.getByRole('button', { name: 'Padding per zijde' }))
|
|
96
|
+
|
|
97
|
+
await waitFor(() => expect(row.className).toContain('grid-rows-[1fr]'))
|
|
98
|
+
expect(row.getAttribute('inert')).toBeNull()
|
|
99
|
+
|
|
100
|
+
// The second row carries its own grid, so its columns are only guaranteed
|
|
101
|
+
// to line up with the first row as long as both use the same template.
|
|
102
|
+
const [first, , third] = fields(canvas)
|
|
103
|
+
expect(third.getBoundingClientRect().width).toBe(first.getBoundingClientRect().width)
|
|
104
|
+
|
|
105
|
+
// The second row is clipped to make the 0fr collapse work, so its fields
|
|
106
|
+
// need room left over for a focus ring inside that clipping box.
|
|
107
|
+
const clip = row.firstElementChild!.getBoundingClientRect()
|
|
108
|
+
const field = third.parentElement!.getBoundingClientRect()
|
|
109
|
+
expect(clip.left).toBeLessThanOrEqual(field.left - 2)
|
|
110
|
+
expect(clip.right).toBeGreaterThanOrEqual(field.right + 2)
|
|
111
|
+
|
|
112
|
+
// The toggle is four-sided in both states, so its lines must not change
|
|
113
|
+
// length when it flips -- only the field icons swap which lines are lit,
|
|
114
|
+
// and they fade rather than cut.
|
|
115
|
+
expect(toggleLine.getAttribute('x1')).toBe(lengthBefore)
|
|
116
|
+
|
|
117
|
+
const fieldLine = first.previousElementSibling!.querySelector('line')!
|
|
118
|
+
expect(getComputedStyle(fieldLine).transitionProperty).toContain('opacity')
|
|
119
|
+
await waitFor(() => expect(getComputedStyle(fieldLine).opacity).toBe('1'))
|
|
120
|
+
},
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* A value that two fields cannot express, so the four fields open on mount.
|
|
125
|
+
* `pt-4 pr-2 pb-4 pl-2` would *not* open them: that is `px-2 py-4`, which the
|
|
126
|
+
* collapsed pair says in full. Reads 16 / 8 / 24 / 8 px.
|
|
127
|
+
*/
|
|
128
|
+
export const Expanded: Story = {
|
|
129
|
+
render: (args) => render(args, 'pt-4 pr-2 pb-6 pl-2'),
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* The widest the fields ever get: three digits and the unit. The story renders
|
|
134
|
+
* at the same width as every other one; the narrow case is measured in the play,
|
|
135
|
+
* because a clipped number is silent -- the value scrolls inside its own box and
|
|
136
|
+
* nothing looks broken.
|
|
137
|
+
*/
|
|
138
|
+
export const MaxValue: Story = {
|
|
139
|
+
render: (args) => render(args, 'p-96'),
|
|
140
|
+
play: async ({ canvasElement }) => {
|
|
141
|
+
const canvas = within(canvasElement)
|
|
142
|
+
const [horizontal, vertical] = fields(canvas)
|
|
143
|
+
|
|
144
|
+
expect(horizontal.value).toBe('384')
|
|
145
|
+
|
|
146
|
+
// Poppins is what the numbers are measured in, and a fallback font is a
|
|
147
|
+
// different width: without this the margin below is measured against
|
|
148
|
+
// whatever happened to be loaded.
|
|
149
|
+
await document.fonts.ready
|
|
150
|
+
|
|
151
|
+
// The decorator is a fixed `w-100`, so narrowing the canvas would change
|
|
152
|
+
// nothing -- the wrapper itself has to shrink. Inline, and put back
|
|
153
|
+
// afterwards, so the story looks like all the others in Storybook.
|
|
154
|
+
const wrapper = canvasElement.firstElementChild as HTMLElement
|
|
155
|
+
const width = wrapper.style.width
|
|
156
|
+
|
|
157
|
+
try {
|
|
158
|
+
// A real editor sidebar column, narrower than the story renders at.
|
|
159
|
+
wrapper.style.width = '256px'
|
|
160
|
+
|
|
161
|
+
const field = horizontal.parentElement!.getBoundingClientRect()
|
|
162
|
+
const unit = horizontal.nextElementSibling!.getBoundingClientRect()
|
|
163
|
+
|
|
164
|
+
// Nothing is clipped. `scrollWidth` bottoms out at the padding box, so it
|
|
165
|
+
// can only prove the absence of overflow, never how much room is left.
|
|
166
|
+
expect(horizontal.scrollWidth).toBeLessThanOrEqual(horizontal.clientWidth)
|
|
167
|
+
|
|
168
|
+
// Room to spare, measured against the text itself: at 0 the next font or
|
|
169
|
+
// the next digit clips the value with no other symptom. The ruler carries
|
|
170
|
+
// the same utilities and sits in the same font context as the input.
|
|
171
|
+
const ruler = document.createElement('span')
|
|
172
|
+
ruler.className = 'small-normal tabular-nums'
|
|
173
|
+
ruler.style.cssText = 'position:absolute;visibility:hidden;white-space:pre'
|
|
174
|
+
ruler.textContent = horizontal.value
|
|
175
|
+
horizontal.parentElement!.append(ruler)
|
|
176
|
+
|
|
177
|
+
const text = ruler.getBoundingClientRect().width
|
|
178
|
+
ruler.remove()
|
|
179
|
+
|
|
180
|
+
// Measured at 6px with Poppins loaded; 4 is the floor worth defending.
|
|
181
|
+
expect(horizontal.clientWidth - text).toBeGreaterThanOrEqual(4)
|
|
182
|
+
|
|
183
|
+
// The unit sits behind the number and inside the field, never clipped by
|
|
184
|
+
// the rounded box or overlapping the value.
|
|
185
|
+
expect(unit.left).toBeGreaterThanOrEqual(horizontal.getBoundingClientRect().right - 1)
|
|
186
|
+
expect(unit.right).toBeLessThanOrEqual(field.right)
|
|
187
|
+
|
|
188
|
+
// Both fields share the 1fr columns, so neither grows with its content.
|
|
189
|
+
expect(vertical.parentElement!.getBoundingClientRect().width).toBe(field.width)
|
|
190
|
+
} finally {
|
|
191
|
+
wrapper.style.width = width
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Closing the four fields is a decision, not just a view change: the two fields
|
|
198
|
+
* that stay on screen are the ones the user can see, so the hidden sides follow
|
|
199
|
+
* them and the value is rewritten at once. Opening is the harmless direction.
|
|
200
|
+
*/
|
|
201
|
+
export const CollapsesToVisibleValues: Story = {
|
|
202
|
+
render: (args) => render(args, 'pt-4 pr-2 pb-6 pl-2'),
|
|
203
|
+
play: async ({ canvasElement }) => {
|
|
204
|
+
const canvas = within(canvasElement)
|
|
205
|
+
|
|
206
|
+
expect(classString(canvasElement)).toBe('pt-4 pr-2 pb-6 pl-2')
|
|
207
|
+
expect(fields(canvas).map((field) => field.value)).toEqual(['16', '8', '24', '8'])
|
|
208
|
+
|
|
209
|
+
await userEvent.click(canvas.getByRole('button', { name: 'Padding per zijde' }))
|
|
210
|
+
|
|
211
|
+
// Onder followed Boven and Links followed Rechts, so the 24 is gone.
|
|
212
|
+
await waitFor(() => expect(classString(canvasElement)).toBe('px-2 py-4'))
|
|
213
|
+
const [horizontal, vertical] = fields(canvas)
|
|
214
|
+
expect(horizontal.value).toBe('8')
|
|
215
|
+
expect(vertical.value).toBe('16')
|
|
216
|
+
|
|
217
|
+
// And opening again only shows what is already there.
|
|
218
|
+
await userEvent.click(canvas.getByRole('button', { name: 'Padding per zijde' }))
|
|
219
|
+
await waitFor(() => expect(fields(canvas)[2].value).toBe('16'))
|
|
220
|
+
expect(classString(canvasElement)).toBe('px-2 py-4')
|
|
221
|
+
},
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Typing is left alone until it is confirmed: the value only snaps to a step on
|
|
226
|
+
* blur or Enter, so a "3" on the way to "30" is not snapped to 4 under the
|
|
227
|
+
* caret. The arrow keys skip that wait -- they step the list itself.
|
|
228
|
+
*/
|
|
229
|
+
export const SnapsOnCommit: Story = {
|
|
230
|
+
render: (args) => render(args, 'p-4'),
|
|
231
|
+
play: async ({ canvasElement }) => {
|
|
232
|
+
const canvas = within(canvasElement)
|
|
233
|
+
const [horizontal] = fields(canvas)
|
|
234
|
+
|
|
235
|
+
// Focus selects the value, so the first digit replaces it instead of
|
|
236
|
+
// landing next to it.
|
|
237
|
+
horizontal.focus()
|
|
238
|
+
expect(horizontal.selectionStart).toBe(0)
|
|
239
|
+
expect(horizontal.selectionEnd).toBe(horizontal.value.length)
|
|
240
|
+
|
|
241
|
+
await userEvent.clear(horizontal)
|
|
242
|
+
await userEvent.type(horizontal, '30')
|
|
243
|
+
|
|
244
|
+
// Mid-edit: the field shows what was typed and the model is untouched.
|
|
245
|
+
expect(horizontal.value).toBe('30')
|
|
246
|
+
expect(classString(canvasElement)).toBe('p-4')
|
|
247
|
+
|
|
248
|
+
// 30 sits between 28 and 32, and the tie-free nearer of the two wins.
|
|
249
|
+
await userEvent.tab()
|
|
250
|
+
await waitFor(() => expect(horizontal.value).toBe('28'))
|
|
251
|
+
expect(classString(canvasElement)).toBe('px-7 py-4')
|
|
252
|
+
|
|
253
|
+
// A tie goes down: 26 is as far from 24 as it is from 28.
|
|
254
|
+
await userEvent.clear(horizontal)
|
|
255
|
+
await userEvent.type(horizontal, '26')
|
|
256
|
+
await userEvent.tab()
|
|
257
|
+
await waitFor(() => expect(horizontal.value).toBe('24'))
|
|
258
|
+
expect(classString(canvasElement)).toBe('px-6 py-4')
|
|
259
|
+
|
|
260
|
+
// Arrows write straight away, no blur needed.
|
|
261
|
+
horizontal.focus()
|
|
262
|
+
await userEvent.keyboard('{ArrowUp}')
|
|
263
|
+
await waitFor(() => expect(horizontal.value).toBe('28'))
|
|
264
|
+
expect(classString(canvasElement)).toBe('px-7 py-4')
|
|
265
|
+
|
|
266
|
+
// Escape is an undo of the typing, not of the value.
|
|
267
|
+
await userEvent.clear(horizontal)
|
|
268
|
+
await userEvent.type(horizontal, '9')
|
|
269
|
+
await userEvent.keyboard('{Escape}')
|
|
270
|
+
await waitFor(() => expect(horizontal.value).toBe('28'))
|
|
271
|
+
expect(classString(canvasElement)).toBe('px-7 py-4')
|
|
272
|
+
},
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Top and bottom only, for an element where horizontal padding has no sensible
|
|
277
|
+
* effect. Collapsed it is one field writing `py-N`; the toggle shows Boven and
|
|
278
|
+
* Onder in the same row, written as `pt-N pb-N`. The incoming `px-6` is not
|
|
279
|
+
* shown and drops out on the first write.
|
|
280
|
+
*/
|
|
281
|
+
export const Vertical: Story = {
|
|
282
|
+
args: { sides: 'vertical', label: 'Witruimte' },
|
|
283
|
+
render: (args) => render(args, 'px-6 py-4'),
|
|
284
|
+
play: async ({ canvasElement }) => {
|
|
285
|
+
const canvas = within(canvasElement)
|
|
286
|
+
|
|
287
|
+
expect(fields(canvas)).toHaveLength(1)
|
|
288
|
+
const [field] = fields(canvas)
|
|
289
|
+
expect(field).toHaveAccessibleName('Verticaal (px)')
|
|
290
|
+
expect(field.value).toBe('16')
|
|
291
|
+
|
|
292
|
+
// The single field spans both field columns, up to the toggle.
|
|
293
|
+
const toggle = canvas.getByRole('button', { name: 'Padding per zijde' })
|
|
294
|
+
const box = field.parentElement!.getBoundingClientRect()
|
|
295
|
+
expect(box.right).toBeLessThan(toggle.getBoundingClientRect().left)
|
|
296
|
+
expect(box.width).toBeGreaterThan(toggle.getBoundingClientRect().width * 2)
|
|
297
|
+
|
|
298
|
+
field.focus()
|
|
299
|
+
await userEvent.keyboard('{ArrowUp}')
|
|
300
|
+
await waitFor(() => expect(classString(canvasElement)).toBe('py-5'))
|
|
301
|
+
|
|
302
|
+
await userEvent.click(toggle)
|
|
303
|
+
await waitFor(() => expect(fields(canvas)).toHaveLength(2))
|
|
304
|
+
const [top, bottom] = fields(canvas)
|
|
305
|
+
expect(top).toHaveAccessibleName('Boven (px)')
|
|
306
|
+
expect(bottom).toHaveAccessibleName('Onder (px)')
|
|
307
|
+
|
|
308
|
+
// Same row: the two fields share a top edge.
|
|
309
|
+
expect(bottom.getBoundingClientRect().top).toBe(top.getBoundingClientRect().top)
|
|
310
|
+
|
|
311
|
+
bottom.focus()
|
|
312
|
+
await userEvent.keyboard('{ArrowUp}')
|
|
313
|
+
await waitFor(() => expect(classString(canvasElement)).toBe('pt-5 pb-6'))
|
|
314
|
+
},
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* The mirror image of `vertical`, for a standing divider in a row: left and
|
|
319
|
+
* right only. Collapsed it is one field writing `px-N`; the toggle shows Links
|
|
320
|
+
* and Rechts in the same row, written as `pl-N pr-N`. The incoming `py-6` is
|
|
321
|
+
* not shown and drops out on the first write.
|
|
322
|
+
*/
|
|
323
|
+
export const Horizontal: Story = {
|
|
324
|
+
args: {
|
|
325
|
+
sides: 'horizontal',
|
|
326
|
+
label: 'Witruimte',
|
|
327
|
+
messages: { horizontal: 'Links en rechts', toggle: 'Links en rechts apart' },
|
|
328
|
+
},
|
|
329
|
+
render: (args) => render(args, 'px-4 py-6'),
|
|
330
|
+
play: async ({ canvasElement }) => {
|
|
331
|
+
const canvas = within(canvasElement)
|
|
332
|
+
|
|
333
|
+
expect(fields(canvas)).toHaveLength(1)
|
|
334
|
+
const [field] = fields(canvas)
|
|
335
|
+
expect(field).toHaveAccessibleName('Links en rechts (px)')
|
|
336
|
+
expect(field.value).toBe('16')
|
|
337
|
+
|
|
338
|
+
field.focus()
|
|
339
|
+
await userEvent.keyboard('{ArrowUp}')
|
|
340
|
+
await waitFor(() => expect(classString(canvasElement)).toBe('px-5'))
|
|
341
|
+
|
|
342
|
+
const toggle = canvas.getByRole('button', { name: 'Links en rechts apart' })
|
|
343
|
+
await userEvent.click(toggle)
|
|
344
|
+
await waitFor(() => expect(fields(canvas)).toHaveLength(2))
|
|
345
|
+
const [left, right] = fields(canvas)
|
|
346
|
+
expect(left).toHaveAccessibleName('Links (px)')
|
|
347
|
+
expect(right).toHaveAccessibleName('Rechts (px)')
|
|
348
|
+
expect(right.getBoundingClientRect().top).toBe(left.getBoundingClientRect().top)
|
|
349
|
+
|
|
350
|
+
right.focus()
|
|
351
|
+
await userEvent.keyboard('{ArrowUp}')
|
|
352
|
+
await waitFor(() => expect(classString(canvasElement)).toBe('pl-5 pr-6'))
|
|
353
|
+
},
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
export const CustomMessages: Story = {
|
|
357
|
+
args: {
|
|
358
|
+
label: 'Padding',
|
|
359
|
+
messages: {
|
|
360
|
+
horizontal: 'Horizontal',
|
|
361
|
+
vertical: 'Vertical',
|
|
362
|
+
top: 'Top',
|
|
363
|
+
right: 'Right',
|
|
364
|
+
bottom: 'Bottom',
|
|
365
|
+
left: 'Left',
|
|
366
|
+
toggle: 'Separate sides',
|
|
367
|
+
unit: 'px',
|
|
368
|
+
},
|
|
369
|
+
},
|
|
370
|
+
render: (args) => render(args, 'p-4'),
|
|
371
|
+
// The tooltip says the same thing as the accessible name, so overriding
|
|
372
|
+
// `toggle` has to move both.
|
|
373
|
+
play: async ({ canvasElement }) => expectTooltip('Separate sides', within(canvasElement)),
|
|
374
|
+
}
|