UNPKG

svelte-swipeout

Version:

iOS-style swipeable list component for Svelte 5 with delete animations and mobile-optimized touch handling

209 lines (201 loc) 6.19 kB
:root { --swipeout-delete-button-bg-color: #ff3b30; --swipeout-button-text-color: #fff; --swipeout-button-padding-vertical: 0; --swipeout-button-padding-horizontal: 30px; --swipeout-button-font-size: inherit; --swipeout-button-font-weight:inherit; --safe-area-left: 0px; --safe-area-right: 0px; --safe-area-top: 0px; --safe-area-bottom: 0px; --safe-area-outer-left: 0px; --safe-area-outer-right: 0px; --device-pixel-ratio:1; } .swipeout-list{ list-style: none; margin: 0; padding: 0; } .swipeout { cursor: grab; overflow: hidden; transform-style: preserve-3d; /* FIX: Allow vertical scrolling by default on mobile, but only vertical */ /* This prevents horizontal scrolling interference with swipe gestures */ touch-action: pan-y; } /* FIX: Disable all touch actions when actively swiping horizontally */ /* This prevents the page from scrolling vertically while user is swiping horizontally */ .swipeout.swipeout-swiping { touch-action: none; } /* Default: Simple fade only */ .swipeout-deleting { transition: opacity 0.3s ease-out; } .swipeout-deleting-active { opacity: 0; } /* Option: Fade and collapse (add class 'swipeout-delete-collapse' to use) */ .swipeout-delete-collapse .swipeout-deleting { overflow: hidden; transition: height 0.4s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s ease-out, margin 0.4s cubic-bezier(0.4, 0, 0.2, 1), padding 0.4s cubic-bezier(0.4, 0, 0.2, 1); } .swipeout-delete-collapse .swipeout-deleting-active { height: 0 !important; opacity: 0; margin-top: 0 !important; margin-bottom: 0 !important; padding-top: 0 !important; padding-bottom: 0 !important; } /* Option 1: Slide left (add class 'swipeout-delete-slide' to use) */ .swipeout-delete-slide .swipeout-deleting { transition: height 0.3s ease-out, opacity 0.25s ease-out, transform 0.3s ease-out, margin 0.3s ease-out, padding 0.3s ease-out; } .swipeout-delete-slide .swipeout-deleting-active { height: 0 !important; opacity: 0; transform: translateX(-100%); margin-top: 0 !important; margin-bottom: 0 !important; padding-top: 0 !important; padding-bottom: 0 !important; } /* Option 3: Scale and fade (add class 'swipeout-delete-scale' to use) */ .swipeout-delete-scale .swipeout-deleting { transform-origin: center; transition: height 0.3s ease-out 0.1s, opacity 0.2s ease-out, transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), margin 0.3s ease-out 0.1s, padding 0.3s ease-out 0.1s; } .swipeout-delete-scale .swipeout-deleting-active { height: 0 !important; opacity: 0; transform: scale(0); margin-top: 0 !important; margin-bottom: 0 !important; padding-top: 0 !important; padding-bottom: 0 !important; } .swipeout-transitioning .swipeout-actions-left button, .swipeout-transitioning .swipeout-actions-right button, .swipeout-transitioning .swipeout-content, .swipeout-transitioning .swipeout-overswipe { transition-duration: 0.3s; transition-property: transform,left; } .swipeout-content { position: relative; z-index: 10; } .swipeout-overswipe { transition-duration: 0.2s; transition-property: left; } .swipeout-actions-left, .swipeout-actions-right { position: absolute; top: 0; height: 100%; display: flex; direction: ltr; } .swipeout-actions-left > a, .swipeout-actions-left > button, .swipeout-actions-left > div, .swipeout-actions-left > span, .swipeout-actions-right > a, .swipeout-actions-right > button, .swipeout-actions-right > div, .swipeout-actions-right > span { cursor: pointer; color: var(--swipeout-button-text-color); padding: var(--swipeout-button-padding-vertical) var(--swipeout-button-padding-horizontal); display: flex; align-items: center; position: relative; left: 0; font-size: var(--swipeout-button-font-size); font-weight: var(--swipeout-button-font-weight); } /* Button reset styles */ .swipeout-actions-left > button, .swipeout-actions-right > button { border: none; font-family: inherit; text-align: center; appearance: none; -webkit-appearance: none; } .swipeout-actions-left > a:after, .swipeout-actions-left > button:after, .swipeout-actions-left > div:after, .swipeout-actions-left > span:after, .swipeout-actions-right > a:after, .swipeout-actions-right > button:after, .swipeout-actions-right > div:after, .swipeout-actions-right > span:after { content: ""; position: absolute; top: 0; width: 600%; height: 100%; background: inherit; z-index: -1; transform: translate3d(0, 0, 0); pointer-events: none; } .swipeout-actions-left .swipeout-delete, .swipeout-actions-right .swipeout-delete { background: var(--swipeout-delete-button-bg-color); } .swipeout-actions-right { right: 0%; transform: translateX(calc(100% + 1px)); } .swipeout-actions-right > a:after, .swipeout-actions-right > button:after, .swipeout-actions-right > div:after, .swipeout-actions-right > span:after { left: 100%; } .swipeout-actions-right > a:last-child, .swipeout-actions-right > button:last-child, .swipeout-actions-right > div:last-child, .swipeout-actions-right > span:last-child { padding-right: calc( var(--swipeout-button-padding-horizontal) + var(--safe-area-right) ); } .swipeout-actions-left { left: 0%; transform: translateX(calc(-100% - 1px)); } .swipeout-actions-left > a:after, .swipeout-actions-left > button:after, .swipeout-actions-left > div:after, .swipeout-actions-left > span:after { right: 100%; } .swipeout-actions-left > a:first-child, .swipeout-actions-left > button:first-child, .swipeout-actions-left > div:first-child, .swipeout-actions-left > span:first-child { /* padding-left:calc(var(--swipeout-button-padding-horizontal) + var(--safe-area-left)) */ } .swipeout-actions-left [class*="color-"], .swipeout-actions-right [class*="color-"] { --swipeout-button-bg-color: var(--theme-color); }