make simulated window controls perfect

This commit is contained in:
maxichrome 2022-05-23 04:30:38 -05:00
parent 3eb81490ab
commit 56e95305df
No known key found for this signature in database
GPG key ID: DDC459310E98B6AB
6 changed files with 68 additions and 50 deletions

View file

@ -1,6 +1,6 @@
{
"extends": "./base.tsconfig.json",
"compilerOptions": {
"types": ["vite-plugin-svgr/client"]
"types": ["vite-plugin-svgr/client", "vite/client"]
}
}

View file

@ -1,4 +1,4 @@
<svg width="124" height="124" viewBox="0 0 124 124" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="25.6391" y="87.1574" width="87" height="14.1887" transform="rotate(-45 25.6391 87.1574)" fill="#7E0508"/>
<rect x="26.5762" y="34.9421" width="13.7508" height="87" transform="rotate(-45 26.5762 34.9421)" fill="#7E0508"/>
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.05806 8.94194C3.30214 9.18602 3.69786 9.18602 3.94194 8.94194L8.94194 3.94194C9.18602 3.69786 9.18602 3.30214 8.94194 3.05806C8.69786 2.81398 8.30214 2.81398 8.05806 3.05806L3.05806 8.05806C2.81398 8.30214 2.81398 8.69786 3.05806 8.94194Z" fill="#691109"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.94194 8.94194C8.69786 9.18602 8.30214 9.18602 8.05806 8.94194L3.05806 3.94194C2.81398 3.69786 2.81398 3.30214 3.05806 3.05806C3.30214 2.81398 3.69786 2.81398 3.94194 3.05806L8.94194 8.05806C9.18602 8.30214 9.18602 8.69786 8.94194 8.94194Z" fill="#691109"/>
</svg>

Before

Width:  |  Height:  |  Size: 337 B

After

Width:  |  Height:  |  Size: 721 B

View file

@ -1,4 +1,4 @@
<svg width="143" height="143" viewBox="0 0 143 143" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M108.242 32.8833C108.797 32.8817 109.247 33.3317 109.245 33.8862L109.092 87.5891C109.09 88.4786 108.014 88.9223 107.385 88.2933L53.8351 34.7432C53.2061 34.1142 53.6499 33.0387 54.5394 33.0361L108.242 32.8833Z" fill="#0B650D"/>
<path d="M33.8862 109.245C33.3317 109.247 32.8818 108.797 32.8833 108.242L33.0361 54.5394C33.0387 53.6499 34.1142 53.2061 34.7432 53.8351L88.2934 107.385C88.9223 108.014 88.4786 109.09 87.5891 109.092L33.8862 109.245Z" fill="#0B650D"/>
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9 8C9 8.55228 8.55228 9 8 9H4.5L9 4.5V8Z" fill="#286017"/>
<path d="M3 4C3 3.44772 3.44772 3 4 3L7.5 3L3 7.5L3 4Z" fill="#286017"/>
</svg>

Before

Width:  |  Height:  |  Size: 579 B

After

Width:  |  Height:  |  Size: 245 B

View file

@ -1,3 +1,3 @@
<svg width="87" height="16" viewBox="0 0 87 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M87 0H0V16H87V0Z" fill="#985712"/>
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.75 6C9.75 5.58579 9.41421 5.25 9 5.25H3C2.58579 5.25 2.25 5.58579 2.25 6C2.25 6.41421 2.58579 6.75 3 6.75H9C9.41421 6.75 9.75 6.41421 9.75 6Z" fill="#8E591D"/>
</svg>

Before

Width:  |  Height:  |  Size: 147 B

After

Width:  |  Height:  |  Size: 315 B

View file

@ -1,10 +1,11 @@
import { LockClosedIcon } from '@heroicons/react/outline';
import { CogIcon, EyeOffIcon, PlusIcon, ServerIcon } from '@heroicons/react/solid';
import { CogIcon, EyeOffIcon, PlusIcon } from '@heroicons/react/solid';
import { useBridgeCommand, useBridgeQuery } from '@sd/client';
import { Button, Dropdown } from '@sd/ui';
import clsx from 'clsx';
import { CirclesFour, Code, EjectSimple, MonitorPlay, Planet } from 'phosphor-react';
import React, { useContext, useEffect, useState } from 'react';
import { CirclesFour, Code, Planet } from 'phosphor-react';
import React, { useContext } from 'react';
import { useParams } from 'react-router';
import { NavLink, NavLinkProps } from 'react-router-dom';
import { AppPropsContext } from '../../App';
@ -49,7 +50,7 @@ export const MacWindowControlsSpace: React.FC<{
const { children } = props;
return (
<div data-tauri-drag-region className="h-7">
<div data-tauri-drag-region className="h-7 flex-shrink-0">
{children}
</div>
);
@ -72,6 +73,7 @@ export function MacWindowControls() {
export const Sidebar: React.FC<SidebarProps> = (props) => {
const experimental = useStore((state) => state.experimental);
const params = useParams();
const appPropsContext = useContext(AppPropsContext);
const { data: locations } = useBridgeQuery('SysGetLocations');
@ -89,7 +91,10 @@ export const Sidebar: React.FC<SidebarProps> = (props) => {
return (
<div className="flex flex-col flex-grow-0 flex-shrink-0 w-48 min-h-full px-3 overflow-x-hidden overflow-y-scroll border-r border-gray-100 no-scrollbar bg-gray-50 dark:bg-gray-850 dark:border-gray-600">
{appPropsContext?.platform === 'browser' ? <MacWindowControls /> : null}
{appPropsContext?.platform === 'browser' &&
window.location.search.includes('showControls') ? (
<MacWindowControls />
) : null}
{appPropsContext?.platform === 'macOS' ? <MacWindowControlsSpace /> : null}
<Dropdown

View file

@ -1,9 +1,9 @@
import clsx from 'clsx';
import React from 'react';
import React, { useEffect } from 'react';
import { ReactComponent as Close } from '../../assets/svg/macos_close.svg';
import { ReactComponent as Fullscreen } from '../../assets/svg/macos_fullscreen.svg';
import { ReactComponent as Minimize } from '../../assets/svg/macos_minimize.svg';
import closeIconPath from '../../assets/svg/macos_close.svg';
import fullscreenIconPath from '../../assets/svg/macos_fullscreen.svg';
import minimizeIconPath from '../../assets/svg/macos_minimize.svg';
import { useFocusState } from '../../hooks/useFocusState';
import { DefaultProps } from '../primitive/types';
@ -13,52 +13,65 @@ export interface TrafficLightsProps extends DefaultProps {
onFullscreen?: () => void;
}
export const TrafficLights: React.FC<TrafficLightsProps> = (props) => {
export const MacTrafficLights: React.FC<TrafficLightsProps> = (props) => {
const [focused] = useFocusState();
return (
<div
data-tauri-drag-region
className={clsx('flex flex-row space-x-2 px-2 group', props.className)}
className={clsx('flex flex-row space-x-[8px] group', props.className)}
>
<Light mode="close" action={props.onClose} focused={focused} />
<Light mode="minimize" action={props.onMinimize} focused={focused} />
<Light mode="fullscreen" action={props.onFullscreen} focused={focused} />
<TrafficLight type="close" onClick={props.onClose} colorful={focused} />
<TrafficLight type="minimize" onClick={props.onMinimize} colorful={focused} />
<TrafficLight type="fullscreen" onClick={props.onFullscreen} colorful={focused} />
</div>
);
};
interface LightProps {
mode: 'close' | 'minimize' | 'fullscreen';
focused: boolean;
action?: () => void;
interface TrafficLightProps {
type: 'close' | 'minimize' | 'fullscreen';
colorful: boolean;
onClick?: React.HTMLAttributes<HTMLDivElement>['onClick'];
}
const Light: React.FC<LightProps> = (props) => {
const TrafficLight: React.FC<TrafficLightProps> = (props) => {
const { onClick = () => undefined, colorful = false, type } = props;
const iconPath = React.useRef<string>(closeIconPath);
useEffect(() => {
switch (type) {
case 'close':
iconPath.current = closeIconPath;
break;
case 'minimize':
iconPath.current = minimizeIconPath;
break;
case 'fullscreen':
iconPath.current = fullscreenIconPath;
break;
}
}, [type]);
return (
<div
onClick={props.action}
className={clsx('w-[13px] h-[13px] rounded-full bg-gray-500', {
'!bg-red-400 active:!bg-red-300': props.mode == 'close' && props.focused,
'!bg-green-400 active:!bg-green-300': props.mode == 'fullscreen' && props.focused,
'!bg-yellow-400 active:!bg-yellow-300': props.mode == 'minimize' && props.focused
})}
>
{(() => {
switch (props.mode) {
case 'close':
return (
<Close className=" w-[13px] -mt-[1px] h-[15px] opacity-0 group-hover:opacity-100" />
);
case 'minimize':
return (
<Minimize className="ml-[2px] w-[9px] -mt-[1px] h-[15px] opacity-0 group-hover:opacity-100" />
);
case 'fullscreen':
return (
<Fullscreen className="ml-[1px] w-[11px] -mt-[1px] h-[15px] opacity-0 group-hover:opacity-100" />
);
onClick={onClick}
className={clsx(
'rounded-full box-border w-[12px] h-[12px] border-[0.5px] border-transparent bg-[#CDCED0] dark:bg-[#2B2C2F] flex justify-center items-center',
{
'border-red-900 !bg-[#EC6A5E] active:hover:!bg-red-700 dark:active:hover:!bg-red-400':
type === 'close' && colorful,
'border-yellow-900 !bg-[#F4BE4F] active:hover:!bg-yellow-600 dark:active:hover:!bg-yellow-200':
type === 'minimize' && colorful,
'border-green-900 !bg-[#61C253] active:hover:!bg-green-700 dark:active:hover:!bg-green-300':
type === 'fullscreen' && colorful
}
})()}
)}
>
{colorful && (
<img
src={iconPath.current}
className="opacity-0 group-hover:opacity-100 group-active:opacity-100 pointer-events-none"
/>
)}
</div>
);
};