From afb2143fe5c59592a376510dd6a4eefe6b498f20 Mon Sep 17 00:00:00 2001 From: Avinash Dwarapu Date: Fri, 21 Feb 2025 17:18:10 +0100 Subject: [PATCH] chore: Add internal drag handle UAP support --- pages/drag-handle/wrapper.page.tsx | 44 ++++ .../components/drag-handle-wrapper/index.tsx | 123 ++++++++++++ .../drag-handle-wrapper/motion.scss | 190 ++++++++++++++++++ .../drag-handle-wrapper/styles.scss | 77 +++++++ style-dictionary/utils/token-names.ts | 6 + style-dictionary/visual-refresh/colors.ts | 6 + 6 files changed, 446 insertions(+) create mode 100644 pages/drag-handle/wrapper.page.tsx create mode 100644 src/internal/components/drag-handle-wrapper/index.tsx create mode 100644 src/internal/components/drag-handle-wrapper/motion.scss create mode 100644 src/internal/components/drag-handle-wrapper/styles.scss diff --git a/pages/drag-handle/wrapper.page.tsx b/pages/drag-handle/wrapper.page.tsx new file mode 100644 index 0000000000..4be5469f72 --- /dev/null +++ b/pages/drag-handle/wrapper.page.tsx @@ -0,0 +1,44 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import React, { useState } from 'react'; + +import Box from '~components/box'; +import Button from '~components/button'; +import DragHandleWrapper from '~components/internal/components/drag-handle-wrapper'; + +import ScreenshotArea from '../utils/screenshot-area'; + +export default function GridPage() { + const [open, setOpen] = useState(false); + + return ( + <> +

Drag handle demo

+ + + console.log(direction)} + onClose={() => setOpen(false)} + > + + )} + + ); +} diff --git a/src/internal/components/drag-handle-wrapper/motion.scss b/src/internal/components/drag-handle-wrapper/motion.scss new file mode 100644 index 0000000000..e000389af9 --- /dev/null +++ b/src/internal/components/drag-handle-wrapper/motion.scss @@ -0,0 +1,190 @@ +/* + Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + SPDX-License-Identifier: Apache-2.0 +*/ +@use '../../styles' as styles; +@use '../../styles/tokens' as awsui; + +.drag-button { + @include styles.with-motion { + @include styles.animation-fade-in; + @include styles.animation-fade-out-0; + } +} + +.drag-button-motion-enter, +.drag-button-motion-entering, +.drag-button-motion-exit, +.drag-button-motion-exiting { + @include styles.with-motion { + pointer-events: none; + } +} + +.drag-button-block-start { + &.drag-button-motion-entering { + @include styles.with-motion { + animation: + slide-up awsui.$motion-duration-fast awsui.$motion-easing-expressive, + awsui-motion-fade-in awsui.$motion-duration-fast awsui.$motion-easing-expressive; + } + } + &.drag-button-motion-exiting { + @include styles.with-motion { + animation: + slide-up-exit awsui.$motion-duration-fast awsui.$motion-easing-expressive, + awsui-motion-fade-out-0 awsui.$motion-duration-fast awsui.$motion-easing-expressive; + } + } +} + +.drag-button-block-end { + &.drag-button-motion-entering { + @include styles.with-motion { + animation: + slide-down awsui.$motion-duration-fast awsui.$motion-easing-expressive, + awsui-motion-fade-in awsui.$motion-duration-fast awsui.$motion-easing-expressive; + } + } + &.drag-button-motion-exiting { + @include styles.with-motion { + animation: + slide-down-exit awsui.$motion-duration-fast awsui.$motion-easing-expressive, + awsui-motion-fade-out-0 awsui.$motion-duration-fast awsui.$motion-easing-expressive; + } + } +} + +.drag-button-inline-start { + &.drag-button-motion-entering { + @include styles.with-motion { + animation: + slide-left awsui.$motion-duration-fast awsui.$motion-easing-expressive, + awsui-motion-fade-in awsui.$motion-duration-fast awsui.$motion-easing-expressive; + } + } + &.drag-button-rtl.drag-button-motion-entering { + @include styles.with-motion { + animation: + slide-right awsui.$motion-duration-fast awsui.$motion-easing-expressive, + awsui-motion-fade-in awsui.$motion-duration-fast awsui.$motion-easing-expressive; + } + } + &.drag-button-motion-exiting { + @include styles.with-motion { + animation: + slide-left-exit awsui.$motion-duration-fast awsui.$motion-easing-expressive, + awsui-motion-fade-out-0 awsui.$motion-duration-fast awsui.$motion-easing-expressive; + } + } + &.drag-button-rtl.drag-button-motion-exiting { + @include styles.with-motion { + animation: + slide-right-exit awsui.$motion-duration-fast awsui.$motion-easing-expressive, + awsui-motion-fade-out-0 awsui.$motion-duration-fast awsui.$motion-easing-expressive; + } + } +} + +.drag-button-inline-end { + &.drag-button-motion-entering { + @include styles.with-motion { + animation: + slide-right awsui.$motion-duration-fast awsui.$motion-easing-expressive, + awsui-motion-fade-in awsui.$motion-duration-fast awsui.$motion-easing-expressive; + } + } + &.drag-button-rtl.drag-button-motion-entering { + @include styles.with-motion { + animation: + slide-left awsui.$motion-duration-fast awsui.$motion-easing-expressive, + awsui-motion-fade-in awsui.$motion-duration-fast awsui.$motion-easing-expressive; + } + } + &.drag-button-motion-exiting { + @include styles.with-motion { + animation: + slide-right-exit awsui.$motion-duration-fast awsui.$motion-easing-expressive, + awsui-motion-fade-out-0 awsui.$motion-duration-fast awsui.$motion-easing-expressive; + } + } + &.drag-button-rtl.drag-button-motion-exiting { + @include styles.with-motion { + animation: + slide-left-exit awsui.$motion-duration-fast awsui.$motion-easing-expressive, + awsui-motion-fade-out-0 awsui.$motion-duration-fast awsui.$motion-easing-expressive; + } + } +} + +@keyframes slide-up { + 0% { + transform: translate(0, 20px); + } + 100% { + transform: translate(0, 0); + } +} + +@keyframes slide-up-exit { + 0% { + transform: translate(0, 0); + } + 100% { + transform: translate(0, 20px); + } +} + +@keyframes slide-down { + 0% { + transform: translate(0, -20px); + } + 100% { + transform: translate(0, 0); + } +} + +@keyframes slide-down-exit { + 0% { + transform: translate(0, 0); + } + 100% { + transform: translate(0, -20px); + } +} + +@keyframes slide-left { + 0% { + transform: translate(20px, 0); + } + 100% { + transform: translate(0, 0); + } +} + +@keyframes slide-left-exit { + 0% { + transform: translate(0, 0); + } + 100% { + transform: translate(20px, 0); + } +} + +@keyframes slide-right { + 0% { + transform: translate(-20px, 0); + } + 100% { + transform: translate(0, 0); + } +} + +@keyframes slide-right-exit { + 0% { + transform: translate(0, 0); + } + 100% { + transform: translate(-20px, 0); + } +} diff --git a/src/internal/components/drag-handle-wrapper/styles.scss b/src/internal/components/drag-handle-wrapper/styles.scss new file mode 100644 index 0000000000..122cceb32d --- /dev/null +++ b/src/internal/components/drag-handle-wrapper/styles.scss @@ -0,0 +1,77 @@ +/* + Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + SPDX-License-Identifier: Apache-2.0 +*/ + +@use '../../styles' as styles; +@use '../../styles/tokens' as awsui; +@use './motion'; + +$drag-button-size: awsui.$space-static-xl; + +.drag-handle-wrapper { + position: relative; +} + +// Prevents accidental click-through on the spaces between the button cluster. +.drag-handle-wrapper-open::before { + content: ''; + position: absolute; + inset: calc(-1 * (#{$drag-button-size} + #{awsui.$space-xs})); +} + +.drag-button { + position: absolute; + border-width: 0; + cursor: pointer; + + inline-size: $drag-button-size; + block-size: $drag-button-size; + padding-block: awsui.$space-xxs; + padding-inline: awsui.$space-xxs; + border-start-start-radius: 50%; + border-start-end-radius: 50%; + border-end-start-radius: 50%; + border-end-end-radius: 50%; + background-color: awsui.$color-background-drag-button-default; + color: awsui.$color-text-drag-button-default; + box-shadow: awsui.$shadow-dropdown; + + &:not(.drag-button-disabled):hover { + background-color: awsui.$color-background-drag-button-hover; + } + + &:not(.drag-button-disabled):active { + background-color: awsui.$color-background-drag-button-active; + } +} + +.drag-button-disabled { + cursor: default; + background-color: awsui.$color-background-drag-button-disabled; + color: awsui.$color-text-drag-button-disabled; +} + +.drag-button-hidden { + display: none; +} + +.drag-button-block-start { + inset-block-start: calc(-1 * (#{$drag-button-size} + #{awsui.$space-xxs})); + inset-inline-start: calc(50% - #{$drag-button-size} / 2); +} + +.drag-button-block-end { + inset-block-end: calc(-1 * (#{$drag-button-size} + #{awsui.$space-xxs})); + inset-inline-start: calc(50% - #{$drag-button-size} / 2); +} + +.drag-button-inline-start { + inset-inline-start: calc(-1 * (#{$drag-button-size} + #{awsui.$space-xxs})); + inset-block-start: calc(50% - #{$drag-button-size} / 2); +} + +.drag-button-inline-end { + inset-inline-end: calc(-1 * (#{$drag-button-size} + #{awsui.$space-xxs})); + inset-block-start: calc(50% - #{$drag-button-size} / 2); +} diff --git a/style-dictionary/utils/token-names.ts b/style-dictionary/utils/token-names.ts index 5309b7baed..277be47125 100644 --- a/style-dictionary/utils/token-names.ts +++ b/style-dictionary/utils/token-names.ts @@ -249,6 +249,10 @@ export type ColorsTokenName = | 'colorBackgroundButtonPrimaryDefault' | 'colorBackgroundButtonPrimaryDisabled' | 'colorBackgroundButtonPrimaryHover' + | 'colorBackgroundDragButtonActive' + | 'colorBackgroundDragButtonDefault' + | 'colorBackgroundDragButtonDisabled' + | 'colorBackgroundDragButtonHover' | 'colorBackgroundCalendarCurrentDate' | 'colorBackgroundCellShaded' | 'colorBackgroundCodeEditorGutterActiveLineDefault' @@ -406,6 +410,8 @@ export type ColorsTokenName = | 'colorTextButtonPrimaryActive' | 'colorTextButtonPrimaryDefault' | 'colorTextButtonPrimaryHover' + | 'colorTextDragButtonDefault' + | 'colorTextDragButtonDisabled' | 'colorTextCalendarDateHover' | 'colorTextCalendarDateSelected' | 'colorTextCalendarMonth' diff --git a/style-dictionary/visual-refresh/colors.ts b/style-dictionary/visual-refresh/colors.ts index bcc48cd216..fe758b3cbe 100644 --- a/style-dictionary/visual-refresh/colors.ts +++ b/style-dictionary/visual-refresh/colors.ts @@ -26,6 +26,12 @@ const tokens: StyleDictionary.ColorsDictionary = { colorBackgroundButtonPrimaryDefault: '{colorBorderButtonNormalDefault}', colorBackgroundButtonPrimaryDisabled: { light: '{colorGrey200}', dark: '{colorGrey700}' }, colorBackgroundButtonPrimaryHover: '{colorBorderButtonNormalHover}', + colorBackgroundDragButtonActive: '{colorGrey700}', + colorBackgroundDragButtonDefault: '{colorGrey600}', + colorBackgroundDragButtonDisabled: { light: '{colorGrey200}', dark: '{colorGrey700}' }, + colorBackgroundDragButtonHover: '{colorGrey650}', + colorTextDragButtonDefault: '{colorWhite}', + colorTextDragButtonDisabled: '{colorTextInteractiveDisabled}', colorBackgroundCalendarCurrentDate: { light: '{colorGrey150}', dark: '{colorGrey650}' }, colorBackgroundCellShaded: { light: '{colorGrey125}', dark: '{colorGrey750}' }, colorBackgroundCodeEditorGutterActiveLineDefault: { light: '{colorGrey550}', dark: '{colorGrey500}' },