mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-11-07 20:44:05 +09:00
Merge pull request #251 from webstudio-is/more-asset-redesign
Assets - Fix design of upload button and cog
This commit is contained in:
15 files changed
+208
-24
No files matched your search
+7
-2
@@ -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>
|
||||
);
|
||||
|
||||
+15
-5
@@ -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 />
|
||||
+5
-1
@@ -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
-6
@@ -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>
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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.
|
||||
@@ -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)
|
||||
```
|
||||
@@ -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
|
||||
}
|
||||
@@ -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 };
|
||||
@@ -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: {
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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";
|
||||
@@ -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";
|
||||
@@ -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";
|
||||
Reference in new issue
Block a user