Merge pull request #251 from webstudio-is/more-asset-redesign

Assets - Fix design of upload button and cog
This commit is contained in:
Oleg Isonen authored and GitHub committed 2022-09-06 20:57:41 +02:00
commit b7d5239c5e
15 files changed
+208 -24

No files matched your search

@@ -1,8 +1,9 @@
import { Form, useSubmit } from "@remix-run/react";
import ObjectID from "bson-objectid";
import { ChangeEvent, useRef } from "react";
import { Button } from "@webstudio-is/design-system";
import { Button, Flex, Text } from "@webstudio-is/design-system";
import { BaseAsset } from "./types";
import { UploadIcon } from "@webstudio-is/icons";
const readImages = async (fileList: FileList): Promise<BaseAsset[]> => {
const images = [];
@@ -61,8 +62,12 @@ export const AddAnAssetForm = ({
variant="blue"
type="button"
onClick={() => inputRef?.current?.click()}
size={2}
>
Upload Image
<Flex align="center" gap={1}>
<UploadIcon />
<Text>Upload</Text>
</Flex>
</Button>
</Form>
);
@@ -1,12 +1,19 @@
import { useState } from "react";
import { Button, Tooltip } from "@webstudio-is/design-system";
import { GearIcon } from "@webstudio-is/icons";
import { GearIcon, gearIconCssVars } from "@webstudio-is/icons";
import { AssetInfo } from "./asset-info";
import { PANEL_WIDTH } from "~/designer/shared/constants";
import { cssVars } from "@webstudio-is/css-vars";
import { BaseAsset } from "./types";
export const AssetTooltip = ({
const triggerVisibilityVar = cssVars.define("trigger-visibility");
export const assetInfoTriggerCssVars = ({ show }: { show: boolean }) => ({
[triggerVisibilityVar]: show ? "visible" : "hidden",
});
export const AssetInfoTrigger = ({
asset,
onDelete,
}: {
@@ -15,7 +22,6 @@ export const AssetTooltip = ({
}) => {
const [isTooltipOpen, setTooltipOpen] = useState(false);
const closeTooltip = () => setTooltipOpen(false);
return (
<Tooltip
open={isTooltipOpen}
@@ -41,13 +47,17 @@ export const AssetTooltip = ({
title="Options"
onClick={() => setTooltipOpen(true)}
css={{
opacity: 0,
visibility: cssVars.use(triggerVisibilityVar, "hidden"),
position: "absolute",
color: "$slate11",
top: "$1",
right: "$1",
cursor: "pointer",
color: "$hiContrast",
transition: "opacity 100ms ease",
"&:hover": {
color: "$hiContrast",
},
...gearIconCssVars({ fill: "$colors$loContrast" }),
}}
>
<GearIcon />
@@ -56,7 +56,11 @@ export const TabContent = ({
onSetActiveTab("none");
}}
/>
<Flex gap="3" direction="column" css={{ padding: "$1" }}>
<Flex
gap="3"
direction="column"
css={{ padding: "$1", paddingTop: "$2" }}
>
<Flex justify="end">
<AddAnAssetForm onSubmit={onUploadAsset} />
</Flex>
@@ -3,7 +3,7 @@ import { Box } from "@webstudio-is/design-system";
import placeholderImage from "~/shared/images/image-placeholder.svg";
import brokenImage from "~/shared/images/broken-image-placeholder.svg";
import { UploadingAnimation } from "./uploading-animation";
import { AssetTooltip } from "./asset-tooltip";
import { AssetInfoTrigger, assetInfoTriggerCssVars } from "./asset-info-tigger";
import { BaseAsset } from "./types";
const useImageWithFallback = ({
@@ -67,15 +67,12 @@ export const AssetThumbnail = (asset: BaseAsset) => {
alignItems: "center",
padding: "0 $2",
position: "relative",
"&:hover button": {
opacity: 1,
},
"&:hover": assetInfoTriggerCssVars({ show: true }),
}}
>
<Thumbnail path={path} status={status} />
{isUploadedAsset && (
<AssetTooltip asset={asset} onDelete={() => setIsDeleting(true)} />
<AssetInfoTrigger asset={asset} onDelete={() => setIsDeleting(true)} />
)}
{(isUploading || isDeleting) && <UploadingAnimation />}
</Box>
+1
View File
@@ -31,6 +31,7 @@
"@webstudio-is/icons": "*",
"@webstudio-is/prisma-client": "*",
"@webstudio-is/react-sdk": "*",
"@webstudio-is/css-vars": "*",
"bson-objectid": "^2.0.2",
"camelcase": "^6.3.0",
"debug": "^4.3.4",
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Webstudio
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+13
View File
@@ -0,0 +1,13 @@
# CSS Vars utils
This package helps you create uniquely named css variables as well as use them.
## Example
```ts
import { cssVars } from "css-vars";
const myVariable = cssVars.define("my-variable"); // --my-variable-0
cssVars.use(myVariable, "fallback"); // var(--my-variable-0, fallback)
```
+29
View File
@@ -0,0 +1,29 @@
{
"name": "@webstudio-is/css-vars",
"version": "0.1.0",
"description": "CSS vars utility",
"author": "Webstudio <github@webstudio.is>",
"homepage": "https://webstudio.is",
"scripts": {
"typecheck": "tsc --noEmit",
"checks": "yarn typecheck && yarn lint",
"dev": "tsup src/index.ts --format esm,cjs --watch --out-dir=lib",
"build": "rm -fr lib && tsc",
"lint": "eslint ./src --ext .ts,.tsx --max-warnings 0"
},
"dependencies": {},
"devDependencies": {
"@webstudio-is/jest-config": "*",
"tsup": "^6.1.3",
"typescript": "^4.6.2"
},
"main": "lib/index.js",
"types": "lib/index.d.ts",
"files": [
"lib/*",
"README.md",
"!*.test.*"
],
"license": "MIT",
"private": false
}
+21
View File
@@ -0,0 +1,21 @@
let counter = -1;
const define = <Name extends string>(name: Name) => {
return `--${name}-${++counter}` as const;
};
type Cast<T1, T2> = T1 extends T2 ? T1 : T2;
type Join<T extends readonly string[], D extends string> = T extends []
? ""
: T extends [string]
? T[0]
: T extends [string, ...infer Rest]
? `${T[0]}${D}${Join<Cast<Rest, string[]>, D>}`
: never;
const use = <Args extends string[]>(...args: Args) => {
return `var(${args.join(", ") as Join<Args, ", ">})` as const;
};
export const cssVars = { define, use };
+12
View File
@@ -0,0 +1,12 @@
// Extends can't use node's resolution rn https://github.com/dividab/tsconfig-paths/issues/209#issuecomment-1177261091
{
"extends": "../../node_modules/@webstudio-is/tsconfig/base.json",
"include": ["./src/**/*.ts"],
"compilerOptions": {
"module": "commonjs",
"target": "ES2020",
"strict": true,
"baseUrl": ".",
"outDir": "./lib"
}
}
@@ -7,6 +7,7 @@ export const Button = styled("button", {
boxSizing: "border-box",
border: "none",
userSelect: "none",
transition: "all 200ms ease-out",
"&::before": {
boxSizing: "border-box",
},
@@ -83,24 +84,24 @@ export const Button = styled("button", {
},
},
blue: {
backgroundColor: "$blue2",
boxShadow: "inset 0 0 0 1px $colors$blue7",
color: "$blue11",
backgroundColor: "$blue10",
color: "$loContrast",
"@hover": {
"&:hover": {
boxShadow: "inset 0 0 0 1px $colors$blue8",
backgroundColor: "$loContrast",
color: "$blue10",
boxShadow: "inset 0 0 0 1.5px $colors$blue10",
},
},
"&:active": {
backgroundColor: "$blue3",
boxShadow: "inset 0 0 0 1px $colors$blue8",
boxShadow: "inset 0 0 0 1.5px $colors$blue8",
},
"&:focus": {
boxShadow: "inset 0 0 0 1px $colors$blue8, 0 0 0 1px $colors$blue8",
boxShadow:
"inset 0 0 0 1.5px $colors$blue8, 0 0 0 1.5px $colors$blue8",
},
'&[data-state="open"]': {
backgroundColor: "$blue4",
boxShadow: "inset 0 0 0 1px $colors$blue8",
boxShadow: "inset 0 0 0 1.5px $colors$blue8",
},
},
green: {
+2 -1
View File
@@ -20,7 +20,8 @@
"react-dom": "^17.0.2"
},
"dependencies": {
"@radix-ui/react-icons": "^1.1.0"
"@radix-ui/react-icons": "^1.1.0",
"@webstudio-is/css-vars": "*"
},
"main": "lib/index.js",
"types": "lib/index.d.ts",
+43
View File
@@ -0,0 +1,43 @@
import { cssVars } from "@webstudio-is/css-vars";
import * as React from "react";
import { IconProps } from "./types";
const fillVar = cssVars.define("fill");
export const gearIconCssVars = ({ fill }: { fill: string }) => ({
[fillVar]: fill,
});
export const GearIcon = React.forwardRef<SVGSVGElement, IconProps>(
({ color = "currentColor", ...props }, forwardedRef) => {
return (
<svg
width={16}
height={16}
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
ref={forwardedRef}
>
<path
d="M9.117 2.878c-.284-1.17-1.95-1.17-2.234 0a1.149 1.149 0 01-1.714.71c-1.03-.627-2.207.551-1.58 1.58a1.15 1.15 0 01-.711 1.715c-1.17.284-1.17 1.95 0 2.234a1.15 1.15 0 01.71 1.714c-.627 1.03.551 2.207 1.58 1.58a1.148 1.148 0 011.715.711c.284 1.17 1.95 1.17 2.234 0a1.15 1.15 0 011.714-.71c1.03.627 2.207-.551 1.58-1.58a1.148 1.148 0 01.711-1.715c1.17-.284 1.17-1.95 0-2.234a1.15 1.15 0 01-.71-1.714c.627-1.03-.551-2.207-1.58-1.58a1.15 1.15 0 01-1.715-.711z"
stroke={color}
strokeWidth={1.25}
strokeLinecap="round"
strokeLinejoin="round"
style={{ fill: cssVars.use(fillVar, "none") }}
/>
<circle
cx={8}
cy={7.99988}
r={1.875}
stroke={color}
strokeWidth={1.25}
/>
</svg>
);
}
);
GearIcon.displayName = "GearIcon";
+2
View File
@@ -14,3 +14,5 @@ export { AspectRatioIcon } from "./aspect-ratio";
export * from "./cloud";
export { TrashIcon } from "./trash";
export { SizeIcon } from "./size";
export { UploadIcon } from "./upload";
export { GearIcon, gearIconCssVars } from "./gear";
+24
View File
@@ -0,0 +1,24 @@
import * as React from "react";
import { IconProps } from "./types";
export const UploadIcon = React.forwardRef<SVGSVGElement, IconProps>(
({ color = "currentColor", ...props }, forwardedRef) => {
return (
<svg
width="16"
height="16"
viewBox="0 0 16 16"
xmlns="http://www.w3.org/2000/svg"
{...props}
ref={forwardedRef}
>
<path
d="M9.758 8.442a.625.625 0 10.884-.884l-.884.884zM8 5.8l.442-.442a.625.625 0 00-.884 0L8 5.8zM5.358 7.558a.625.625 0 10.884.884l-.884-.884zM7.375 10.2a.625.625 0 101.25 0h-1.25zm5.5-2.2A4.875 4.875 0 018 12.875v1.25A6.125 6.125 0 0014.125 8h-1.25zM8 12.875A4.875 4.875 0 013.125 8h-1.25A6.125 6.125 0 008 14.125v-1.25zM3.125 8A4.875 4.875 0 018 3.125v-1.25A6.125 6.125 0 001.875 8h1.25zM8 3.125A4.875 4.875 0 0112.875 8h1.25A6.125 6.125 0 008 1.875v1.25zm2.642 4.433l-2.2-2.2-.884.884 2.2 2.2.884-.884zm-3.084-2.2l-2.2 2.2.884.884 2.2-2.2-.884-.884zM8.625 10.2V5.8h-1.25v4.4h1.25z"
fill={color}
/>
</svg>
);
}
);
UploadIcon.displayName = "UploadIcon";