diff --git a/packages/design-system/src/components/N8nCard/Card.vue b/packages/design-system/src/components/N8nCard/Card.vue index 17630a4d1e..d7a2893973 100644 --- a/packages/design-system/src/components/N8nCard/Card.vue +++ b/packages/design-system/src/components/N8nCard/Card.vue @@ -34,7 +34,11 @@ const classes = computed(() => ({ -
+
@@ -45,7 +49,7 @@ const classes = computed(() => ({ border-radius: var(--border-radius-large); border: var(--border-base); background-color: var(--color-background-xlight); - padding: var(--spacing-s); + padding: var(--card--padding, var(--spacing-s)); display: flex; flex-direction: row; width: 100%; @@ -101,5 +105,6 @@ const classes = computed(() => ({ display: flex; align-items: center; cursor: default; + width: var(--card--append--width, unset); } diff --git a/packages/design-system/src/composables/useDeviceSupport.test.ts b/packages/design-system/src/composables/useDeviceSupport.test.ts index 0260dcacaf..4cfc5f3533 100644 --- a/packages/design-system/src/composables/useDeviceSupport.test.ts +++ b/packages/design-system/src/composables/useDeviceSupport.test.ts @@ -75,6 +75,38 @@ describe('useDeviceSupport()', () => { }); }); + describe('isMobileDevice', () => { + it('should be true for iOS user agent', () => { + Object.defineProperty(navigator, 'userAgent', { value: 'iphone' }); + const { isMobileDevice } = useDeviceSupport(); + expect(isMobileDevice).toEqual(true); + }); + + it('should be true for Android user agent', () => { + Object.defineProperty(navigator, 'userAgent', { value: 'android' }); + const { isMobileDevice } = useDeviceSupport(); + expect(isMobileDevice).toEqual(true); + }); + + it('should be false for non-mobile user agent', () => { + Object.defineProperty(navigator, 'userAgent', { value: 'windows' }); + const { isMobileDevice } = useDeviceSupport(); + expect(isMobileDevice).toEqual(false); + }); + + it('should be true for iPad user agent', () => { + Object.defineProperty(navigator, 'userAgent', { value: 'ipad' }); + const { isMobileDevice } = useDeviceSupport(); + expect(isMobileDevice).toEqual(true); + }); + + it('should be true for iPod user agent', () => { + Object.defineProperty(navigator, 'userAgent', { value: 'ipod' }); + const { isMobileDevice } = useDeviceSupport(); + expect(isMobileDevice).toEqual(true); + }); + }); + describe('isCtrlKeyPressed()', () => { it('should return true for metaKey press on macOS', () => { Object.defineProperty(navigator, 'userAgent', { value: 'macintosh' }); diff --git a/packages/design-system/src/composables/useDeviceSupport.ts b/packages/design-system/src/composables/useDeviceSupport.ts index 8f713ffd30..6b00999216 100644 --- a/packages/design-system/src/composables/useDeviceSupport.ts +++ b/packages/design-system/src/composables/useDeviceSupport.ts @@ -12,12 +12,16 @@ export function useDeviceSupport() { !window.matchMedia('(any-pointer: fine)').matches, ); const userAgent = ref(navigator.userAgent.toLowerCase()); - const isMacOs = ref( - userAgent.value.includes('macintosh') || + + const isIOs = ref( + userAgent.value.includes('iphone') || userAgent.value.includes('ipad') || - userAgent.value.includes('iphone') || userAgent.value.includes('ipod'), ); + const isAndroidOs = ref(userAgent.value.includes('android')); + const isMacOs = ref(userAgent.value.includes('macintosh') || isIOs.value); + const isMobileDevice = ref(isIOs.value || isAndroidOs.value); + const controlKeyCode = ref(isMacOs.value ? 'Meta' : 'Control'); function isCtrlKeyPressed(e: MouseEvent | KeyboardEvent): boolean { @@ -30,7 +34,10 @@ export function useDeviceSupport() { return { userAgent: userAgent.value, isTouchDevice: isTouchDevice.value, + isAndroidOs: isAndroidOs.value, + isIOs: isIOs.value, isMacOs: isMacOs.value, + isMobileDevice: isMobileDevice.value, controlKeyCode: controlKeyCode.value, isCtrlKeyPressed, }; diff --git a/packages/design-system/src/css/index.scss b/packages/design-system/src/css/index.scss index c37709df1b..98e244f43f 100644 --- a/packages/design-system/src/css/index.scss +++ b/packages/design-system/src/css/index.scss @@ -5,6 +5,7 @@ @use './base.scss'; @use './pagination.scss'; @use './dialog.scss'; +@use './display.scss'; // @use "./autocomplete.scss"; @use './dropdown.scss'; @use './dropdown-menu.scss'; diff --git a/packages/design-system/src/css/mixins/_breakpoints.scss b/packages/design-system/src/css/mixins/_breakpoints.scss new file mode 100644 index 0000000000..405351eb21 --- /dev/null +++ b/packages/design-system/src/css/mixins/_breakpoints.scss @@ -0,0 +1,20 @@ +@use '../common/var'; + +@mixin breakpoint($name) { + @if map-has-key(var.$breakpoints-spec, $name) { + $query: map-get(var.$breakpoints-spec, $name); + $media-query: ''; + + @each $key, $value in $query { + $media-query: '#{$media-query} and (#{$key}: #{$value})'; + } + + $media-query: unquote(str-slice($media-query, 6)); // Remove the initial ' and ' + + @media screen and #{$media-query} { + @content; + } + } @else { + @error "No breakpoint named `#{$name}` found in `$breakpoints-spec`."; + } +} diff --git a/packages/design-system/src/css/mixins/index.scss b/packages/design-system/src/css/mixins/index.scss new file mode 100644 index 0000000000..bda8c57b75 --- /dev/null +++ b/packages/design-system/src/css/mixins/index.scss @@ -0,0 +1,6 @@ +@forward 'breakpoints'; +@forward 'button'; +@forward 'config'; +@forward 'function'; +@forward 'mixins'; +@forward 'utils'; diff --git a/packages/editor-ui/src/App.vue b/packages/editor-ui/src/App.vue index 3bd5a4a82b..04223f8d92 100644 --- a/packages/editor-ui/src/App.vue +++ b/packages/editor-ui/src/App.vue @@ -192,6 +192,8 @@ watch(defaultLocale, (newLocale) => { .header { grid-area: header; z-index: var(--z-index-app-header); + min-width: 0; + min-height: 0; } .sidebar { diff --git a/packages/editor-ui/src/components/CredentialCard.vue b/packages/editor-ui/src/components/CredentialCard.vue index d82c67d83e..db40f0d274 100644 --- a/packages/editor-ui/src/components/CredentialCard.vue +++ b/packages/editor-ui/src/components/CredentialCard.vue @@ -162,6 +162,7 @@ function moveResource() {