From fd2e5b093374f539e2955c120261731507a6ac1e Mon Sep 17 00:00:00 2001 From: yiliang114 <1204183885@qq.com> Date: Sun, 23 Nov 2025 15:17:17 +0800 Subject: [PATCH] feat(vscode-ide-companion): improve PermissionDrawer UI with enhanced styling and responsiveness --- .../webview/components/PermissionDrawer.css | 272 ++++++++++++------ .../webview/components/PermissionDrawer.tsx | 1 + 2 files changed, 181 insertions(+), 92 deletions(-) diff --git a/packages/vscode-ide-companion/src/webview/components/PermissionDrawer.css b/packages/vscode-ide-companion/src/webview/components/PermissionDrawer.css index f78223d0..e91684eb 100644 --- a/packages/vscode-ide-companion/src/webview/components/PermissionDrawer.css +++ b/packages/vscode-ide-companion/src/webview/components/PermissionDrawer.css @@ -13,29 +13,35 @@ left: 0; right: 0; bottom: 0; - background-color: rgba(0, 0, 0, 0.4); + background-color: var(--app-modal-background); z-index: 998; animation: fadeIn 0.2s ease-in-out; } /* Drawer container - bottom sheet style */ .permission-drawer { - position: fixed; - left: 0; - right: 0; - bottom: 0; - max-height: 70vh; - background-color: var(--app-primary-background); - border-top: 1px solid var(--app-primary-border-color); - border-top-left-radius: 12px; - border-top-right-radius: 12px; - z-index: 999; display: flex; flex-direction: column; - box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.2); + padding: 8px; + background-color: var(--app-input-secondary-background); + border: 1px solid var(--app-input-border); + border-radius: var(--corner-radius-large); + max-height: 70vh; + outline: 0; + position: relative; + margin-bottom: 6px; + z-index: 999; animation: slideUpFromBottom 0.3s cubic-bezier(0.4, 0, 0.2, 1); } +/* Background layer */ +.permission-drawer-background { + background-color: var(--app-input-background); + border-radius: var(--corner-radius-large); + position: absolute; + inset: 0; +} + @keyframes fadeIn { from { opacity: 0; @@ -60,46 +66,60 @@ display: flex; align-items: center; justify-content: space-between; - padding: 20px 20px 16px; + padding: 28px 28px 24px; border-bottom: 1px solid var(--app-primary-border-color); background-color: var(--app-header-background); - border-top-left-radius: 12px; - border-top-right-radius: 12px; + border-top-left-radius: 20px; + border-top-right-radius: 20px; flex-shrink: 0; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05); } .permission-drawer-title { - font-size: 14px; - font-weight: 600; + font-weight: 700; color: var(--app-primary-foreground); - margin: 0; + margin-bottom: 4px; } .permission-drawer-close { - width: 28px; - height: 28px; + width: 36px; + height: 36px; padding: 0; - background: transparent; - border: none; - border-radius: 4px; + background: var(--app-secondary-background); + border: 1px solid var(--app-transparent-inner-border); + border-radius: 8px; color: var(--app-secondary-foreground); cursor: pointer; display: flex; align-items: center; justify-content: center; - transition: background-color 0.15s, color 0.15s; + transition: all 0.2s ease; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); } .permission-drawer-close:hover { background-color: var(--app-ghost-button-hover-background); color: var(--app-primary-foreground); + transform: scale(1.05); + border-color: var(--app-primary-border-color); + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); +} + +.permission-drawer-close:active { + transform: scale(0.98); } /* Drawer content */ .permission-drawer-content { + font-size: 1.1em; + color: var(--app-primary-foreground); + display: flex; + flex-direction: column; + min-height: 0; + z-index: 1; flex: 1; overflow-y: auto; - padding: 20px; + padding: 0; min-height: 0; } @@ -115,6 +135,16 @@ padding: 0; } +/* Add a subtle border at the top of the card when in drawer */ +.permission-drawer-content .permission-request-card::before { + content: ''; + display: block; + height: 1px; + background: var(--app-primary-border-color); + margin-bottom: 24px; + opacity: 0.5; +} + /* Scrollbar for drawer content */ .permission-drawer-content::-webkit-scrollbar { width: 8px; @@ -137,20 +167,42 @@ .permission-drawer-header::before { content: ''; position: absolute; - top: 8px; + top: 12px; left: 50%; transform: translateX(-50%); - width: 40px; - height: 4px; + width: 48px; + height: 5px; background-color: var(--app-secondary-foreground); - opacity: 0.3; - border-radius: 2px; + opacity: 0.2; + border-radius: 3px; } /* Responsive adjustments */ @media (max-width: 768px) { .permission-drawer { - max-height: 85vh; + max-height: 90vh; + border-top-left-radius: 16px; + border-top-right-radius: 16px; + } + + .permission-drawer-header { + padding: 24px 24px 20px; + border-top-left-radius: 16px; + border-top-right-radius: 16px; + } + + .permission-drawer-header::before { + top: 10px; + width: 40px; + height: 4px; + } + + .permission-drawer-content { + padding: 24px; + } + + .permission-drawer-content::after { + height: 24px; } } @@ -162,6 +214,8 @@ background: var(--app-primary-background); border-radius: 8px; padding: 16px; + border: 1px solid var(--app-primary-border-color); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); } .permission-card-body { @@ -174,11 +228,20 @@ .permission-header { display: flex; align-items: flex-start; - gap: 12px; + gap: 16px; + padding-bottom: 16px; } .permission-icon-wrapper { flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; + width: 40px; + height: 40px; + background: var(--app-secondary-background); + border-radius: 8px; + border: 1px solid var(--app-transparent-inner-border); } .permission-icon { @@ -190,21 +253,21 @@ flex: 1; display: flex; flex-direction: column; - gap: 4px; + gap: 6px; } .permission-title { - font-size: 14px; - font-weight: 500; + font-size: 16px; + font-weight: 600; color: var(--app-primary-foreground); - line-height: 1.5; + line-height: 1.4; word-break: break-word; } .permission-subtitle { - font-size: 12px; + font-size: 13px; color: var(--app-secondary-foreground); - opacity: 0.7; + opacity: 0.8; } /* Command Section - Bash style */ @@ -214,14 +277,15 @@ gap: 8px; background: var(--app-secondary-background); border: 1px solid var(--app-transparent-inner-border); - border-radius: 6px; + border-radius: 8px; overflow: hidden; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05); } .permission-command-header { display: flex; align-items: center; - padding: 8px 12px; + padding: 12px 16px; background: var(--app-secondary-background); border-bottom: 1px solid var(--app-transparent-inner-border); } @@ -229,17 +293,17 @@ .permission-command-status { display: flex; align-items: center; - gap: 6px; + gap: 8px; } .permission-command-dot { color: var(--app-qwen-orange, #ff8c00); - font-size: 8px; + font-size: 10px; line-height: 1; } .permission-command-label { - font-size: 11px; + font-size: 12px; font-weight: 600; color: var(--app-secondary-foreground); text-transform: uppercase; @@ -254,40 +318,40 @@ .permission-command-input-section { display: grid; - grid-template-columns: 32px 1fr; + grid-template-columns: 40px 1fr; align-items: flex-start; - padding: 8px 0; + padding: 12px 0; background: var(--app-primary-background); } .permission-command-io-label { - font-size: 11px; + font-size: 12px; font-weight: 600; color: var(--app-secondary-foreground); - opacity: 0.6; + opacity: 0.7; text-align: right; - padding-right: 12px; - padding-top: 2px; + padding-right: 16px; + padding-top: 4px; } .permission-command-code { font-family: var(--vscode-editor-font-family, 'Monaco', 'Courier New', monospace); - font-size: 12px; + font-size: 13px; line-height: 1.6; color: var(--app-primary-foreground); background: transparent; border: none; - padding: 0 12px 0 0; + padding: 0 16px 0 0; white-space: pre-wrap; word-break: break-word; overflow-wrap: break-word; } .permission-command-description { - font-size: 12px; + font-size: 13px; color: var(--app-secondary-foreground); - opacity: 0.7; - padding: 8px 12px; + opacity: 0.8; + padding: 12px 16px; border-top: 1px solid var(--app-transparent-inner-border); background: var(--app-secondary-background); } @@ -296,29 +360,37 @@ .permission-locations-section { display: flex; flex-direction: column; - gap: 6px; + gap: 8px; } .permission-locations-label { - font-size: 12px; + font-size: 13px; font-weight: 500; color: var(--app-secondary-foreground); - opacity: 0.8; + opacity: 0.9; } .permission-location-item { display: flex; align-items: center; - gap: 6px; - padding: 6px 8px; + gap: 8px; + padding: 8px 12px; background: var(--app-secondary-background); - border-radius: 4px; - font-size: 12px; + border-radius: 6px; + font-size: 13px; + border: 1px solid var(--app-transparent-inner-border); + transition: all 0.15s ease; +} + +.permission-location-item:hover { + background: var(--app-ghost-button-hover-background); + border-color: var(--app-primary-border-color); } .permission-location-icon { - font-size: 14px; + font-size: 16px; flex-shrink: 0; + color: var(--app-qwen-orange, #ff8c00); } .permission-location-path { @@ -328,145 +400,161 @@ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + font-weight: 500; } .permission-location-line { color: var(--app-secondary-foreground); - opacity: 0.6; + opacity: 0.7; font-family: var(--vscode-editor-font-family, 'Monaco', 'Courier New', monospace); + font-weight: 500; } /* Options Section */ .permission-options-section { display: flex; flex-direction: column; - gap: 12px; + gap: 16px; } .permission-options-label { - font-size: 12px; + font-size: 14px; font-weight: 500; color: var(--app-secondary-foreground); - opacity: 0.8; + opacity: 0.9; } .permission-options-list { display: flex; flex-direction: column; - gap: 6px; + gap: 8px; } .permission-option { display: flex; align-items: center; - gap: 8px; - padding: 10px 12px; + gap: 12px; + padding: 12px 16px; background: var(--app-secondary-background); border: 1px solid var(--app-transparent-inner-border); border-radius: 6px; cursor: pointer; - transition: all 0.15s; + transition: all 0.2s ease; } .permission-option:hover { background: var(--app-ghost-button-hover-background); border-color: var(--app-primary-border-color); + transform: translateY(-1px); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); } .permission-option.selected { background: var(--app-qwen-clay-button-orange); border-color: var(--app-qwen-orange, #ff8c00); + box-shadow: 0 2px 6px rgba(255, 140, 0, 0.2); } .permission-radio { - width: 16px; - height: 16px; + width: 18px; + height: 18px; margin: 0; cursor: pointer; + accent-color: var(--app-qwen-orange, #ff8c00); } .permission-option-content { flex: 1; display: flex; align-items: center; - gap: 6px; - font-size: 13px; + gap: 8px; + font-size: 14px; color: var(--app-primary-foreground); + font-weight: 500; } .permission-option-number { display: inline-flex; align-items: center; justify-content: center; - width: 20px; - height: 20px; + width: 24px; + height: 24px; background: var(--app-qwen-orange, #ff8c00); color: var(--app-qwen-ivory, #fff); - border-radius: 4px; - font-size: 11px; + border-radius: 6px; + font-size: 12px; font-weight: 600; flex-shrink: 0; } .permission-always-badge { - font-size: 14px; + font-size: 16px; flex-shrink: 0; + color: #ffd700; } .permission-no-options { - padding: 12px; + padding: 16px; text-align: center; color: var(--app-secondary-foreground); opacity: 0.6; - font-size: 12px; + font-size: 13px; } /* Actions */ .permission-actions { display: flex; justify-content: flex-end; - gap: 8px; - padding-top: 8px; + gap: 12px; + padding-top: 16px; } .permission-confirm-button { - padding: 8px 16px; + padding: 10px 20px; background: var(--app-qwen-orange, #ff8c00); color: var(--app-qwen-ivory, #fff); border: none; border-radius: 6px; - font-size: 13px; + font-size: 14px; font-weight: 500; cursor: pointer; - transition: all 0.15s; + transition: all 0.2s ease; + box-shadow: 0 2px 4px rgba(255, 140, 0, 0.3); } .permission-confirm-button:hover:not(:disabled) { - opacity: 0.9; + background: #e67e00; + transform: translateY(-1px); + box-shadow: 0 4px 8px rgba(255, 140, 0, 0.4); } .permission-confirm-button:disabled { opacity: 0.5; cursor: not-allowed; + transform: none; + box-shadow: none; } /* Success Message */ .permission-success { display: flex; align-items: center; - gap: 8px; - padding: 12px; + gap: 12px; + padding: 16px; background: var(--app-qwen-green, #6BCF7F); color: var(--app-qwen-ivory, #fff); - border-radius: 6px; - font-size: 13px; + border-radius: 8px; + font-size: 14px; + box-shadow: 0 2px 8px rgba(107, 207, 127, 0.3); + animation: fadeIn 0.3s ease-in-out; } .permission-success-icon { - font-size: 16px; + font-size: 20px; flex-shrink: 0; } .permission-success-text { flex: 1; + font-weight: 500; } diff --git a/packages/vscode-ide-companion/src/webview/components/PermissionDrawer.tsx b/packages/vscode-ide-companion/src/webview/components/PermissionDrawer.tsx index 116ceef4..e8227915 100644 --- a/packages/vscode-ide-companion/src/webview/components/PermissionDrawer.tsx +++ b/packages/vscode-ide-companion/src/webview/components/PermissionDrawer.tsx @@ -75,6 +75,7 @@ export const PermissionDrawer: React.FC = ({ {/* Drawer */}
+

Permission Required

{onClose && (