diff --git a/apps/web/src/components/affine/create-workspace-modal/index.tsx b/apps/web/src/components/affine/create-workspace-modal/index.tsx index cad003ef75..e92222f286 100644 --- a/apps/web/src/components/affine/create-workspace-modal/index.tsx +++ b/apps/web/src/components/affine/create-workspace-modal/index.tsx @@ -74,7 +74,7 @@ const NameWorkspaceContent = ({ data-testid="create-workspace-input" onKeyDown={handleKeyDown} placeholder={t['Set a Workspace name']()} - maxLength={15} // TODO: the max workspace name length? + maxLength={64} minLength={0} onChange={value => { setWorkspaceName(value); diff --git a/apps/web/src/components/affine/workspace-setting-detail/panel/general/index.tsx b/apps/web/src/components/affine/workspace-setting-detail/panel/general/index.tsx index 0c76ca79c4..ce2a311039 100644 --- a/apps/web/src/components/affine/workspace-setting-detail/panel/general/index.tsx +++ b/apps/web/src/components/affine/workspace-setting-detail/panel/general/index.tsx @@ -137,7 +137,7 @@ export const GeneralPanel: React.FC = ({ value={input} data-testid="workspace-name-input" placeholder={t['Workspace Name']()} - maxLength={50} + maxLength={64} minLength={0} onChange={newName => { setInput(newName); diff --git a/packages/component/src/components/app-sidebar/add-page-button/index.css.ts b/packages/component/src/components/app-sidebar/add-page-button/index.css.ts index f3f1c08a97..c7bde86623 100644 --- a/packages/component/src/components/app-sidebar/add-page-button/index.css.ts +++ b/packages/component/src/components/app-sidebar/add-page-button/index.css.ts @@ -8,15 +8,11 @@ export const root = style({ border: '1px solid var(--affine-black-10)', fontSize: 'var(--affine-font-sm)', width: '100%', + position: 'relative', height: '52px', userSelect: 'none', cursor: 'pointer', padding: '0 24px', - selectors: { - '&:hover': { - background: 'var(--affine-hover-color)', - }, - }, }); export const icon = style({ diff --git a/packages/component/src/components/app-sidebar/add-page-button/index.tsx b/packages/component/src/components/app-sidebar/add-page-button/index.tsx index 49bda1f2be..d6f2216295 100644 --- a/packages/component/src/components/app-sidebar/add-page-button/index.tsx +++ b/packages/component/src/components/app-sidebar/add-page-button/index.tsx @@ -1,7 +1,9 @@ import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { PlusIcon } from '@blocksuite/icons'; import clsx from 'clsx'; +import type React from 'react'; +import { Spotlight } from '../spolight'; import * as styles from './index.css'; interface AddPageButtonProps { @@ -26,6 +28,7 @@ export function AddPageButton({ onClick={onClick} > {t['New Page']()} + ); } diff --git a/packages/component/src/components/app-sidebar/menu-item/index.css.ts b/packages/component/src/components/app-sidebar/menu-item/index.css.ts index 6b20819288..3b6d784f28 100644 --- a/packages/component/src/components/app-sidebar/menu-item/index.css.ts +++ b/packages/component/src/components/app-sidebar/menu-item/index.css.ts @@ -22,6 +22,11 @@ export const root = style({ color: 'var(--affine-text-secondary-color)', pointerEvents: 'none', }, + '&[data-active="true"]:hover': { + background: + // make this a variable? + 'linear-gradient(0deg, rgba(0, 0, 0, 0.04), rgba(0, 0, 0, 0.04)), rgba(0, 0, 0, 0.04);', + }, }, }); @@ -34,7 +39,7 @@ export const content = style({ export const icon = style({ marginRight: '14px', color: 'var(--affine-icon-color)', - fontSize: '18px', + fontSize: '20px', }); export const spacer = style({ diff --git a/packages/component/src/components/app-sidebar/quick-search-input/index.css.ts b/packages/component/src/components/app-sidebar/quick-search-input/index.css.ts index a816b5d67b..458738da29 100644 --- a/packages/component/src/components/app-sidebar/quick-search-input/index.css.ts +++ b/packages/component/src/components/app-sidebar/quick-search-input/index.css.ts @@ -13,16 +13,13 @@ export const root = style({ cursor: 'pointer', padding: '0 12px', margin: '12px 0', - selectors: { - '&:hover': { - background: 'var(--affine-hover-color)', - }, - }, + position: 'relative', }); export const icon = style({ marginRight: '14px', color: 'var(--affine-icon-color)', + fontSize: '20px', }); export const spacer = style({ diff --git a/packages/component/src/components/app-sidebar/quick-search-input/index.tsx b/packages/component/src/components/app-sidebar/quick-search-input/index.tsx index e1a67507dd..11974d77cc 100644 --- a/packages/component/src/components/app-sidebar/quick-search-input/index.tsx +++ b/packages/component/src/components/app-sidebar/quick-search-input/index.tsx @@ -3,6 +3,7 @@ import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { SearchIcon } from '@blocksuite/icons'; import clsx from 'clsx'; +import { Spotlight } from '../spolight'; import * as styles from './index.css'; interface QuickSearchInputProps extends React.HTMLAttributes { @@ -27,6 +28,7 @@ export function QuickSearchInput({ onClick, ...props }: QuickSearchInputProps) {
{isMac ? ' ⌘ + K' : ' Ctrl + K'}
+ ); } diff --git a/packages/component/src/components/app-sidebar/spolight/index.css.ts b/packages/component/src/components/app-sidebar/spolight/index.css.ts new file mode 100644 index 0000000000..0125a9ea22 --- /dev/null +++ b/packages/component/src/components/app-sidebar/spolight/index.css.ts @@ -0,0 +1,24 @@ +import { createVar, style } from '@vanilla-extract/css'; + +export const spotlightX = createVar(); +export const spotlightY = createVar(); +export const spotlightOpacity = createVar(); +export const spotlightSize = createVar(); + +export const spotlight = style({ + vars: { + [spotlightX]: '0px', + [spotlightY]: '0px', + [spotlightOpacity]: '0', + [spotlightSize]: '64px', + }, + position: 'absolute', + background: `radial-gradient(${spotlightSize} circle at ${spotlightX} ${spotlightY}, var(--affine-text-primary-color), transparent)`, + inset: '0px', + pointerEvents: 'none', + willChange: 'background', + opacity: spotlightOpacity, + zIndex: 1, + transition: 'all 0.2s', + borderRadius: 'inherit', +}); diff --git a/packages/component/src/components/app-sidebar/spolight/index.tsx b/packages/component/src/components/app-sidebar/spolight/index.tsx new file mode 100644 index 0000000000..c8817006ba --- /dev/null +++ b/packages/component/src/components/app-sidebar/spolight/index.tsx @@ -0,0 +1,49 @@ +import { assignInlineVars } from '@vanilla-extract/dynamic'; +import { useTheme } from 'next-themes'; +import React, { useEffect, useRef } from 'react'; + +import * as styles from './index.css'; + +function useMouseOffset() { + const [offset, setOffset] = React.useState<{ x: number; y: number }>(); + const [outside, setOutside] = React.useState(true); + const ref = useRef(null); + + useEffect(() => { + if (ref.current && ref.current.parentElement) { + const el = ref.current.parentElement; + const bound = el.getBoundingClientRect(); + + // debounce? + const onMouseMove = (e: MouseEvent) => { + setOffset({ x: e.clientX - bound.x, y: e.clientY - bound.y }); + setOutside(false); + }; + + const onMouseLeave = () => { + setOutside(true); + }; + el.addEventListener('mousemove', onMouseMove); + el.addEventListener('mouseleave', onMouseLeave); + return () => { + el.removeEventListener('mousemove', onMouseMove); + el.removeEventListener('mouseleave', onMouseLeave); + }; + } + }, []); + + return [offset, outside, ref] as const; +} + +export function Spotlight() { + const [offset, outside, ref] = useMouseOffset(); + const { theme } = useTheme(); + const isDark = theme === 'dark'; + const offsetVars = assignInlineVars({ + [styles.spotlightX]: (offset?.x ?? 0) + 'px', + [styles.spotlightY]: (offset?.y ?? 0) + 'px', + [styles.spotlightOpacity]: outside ? '0' : isDark ? '.1' : '0.07', + }); + + return
; +} diff --git a/packages/i18n/src/resources/en.json b/packages/i18n/src/resources/en.json index d5c4b993c6..0218ffeeab 100644 --- a/packages/i18n/src/resources/en.json +++ b/packages/i18n/src/resources/en.json @@ -4,7 +4,7 @@ "It takes up little space on your device": "It takes up little space on your device.", "AFFiNE Cloud": "AFFiNE Cloud", "Members": "Members", - "Add to favorites": "Add to favorites", + "Add to favorites": "Add to favourites", "It takes up more space on your device": "It takes up more space on your device.", "Export AFFiNE backup file": "Export AFFiNE backup file", "Saved then enable AFFiNE Cloud": "All changes are saved locally, click to enable AFFiNE Cloud.", @@ -26,7 +26,7 @@ "Expand sidebar": "Expand sidebar", "Paper": "Paper", "Edgeless": "Edgeless", - "Added to Favorites": "Added to Favorites", + "Added to Favorites": "Added to Favourites", "Convert to ": "Convert to ", "Page": "Page", "Export": "Export", @@ -41,7 +41,7 @@ "Delete page?": "Delete page?", "Delete permanently?": "Delete permanently?", "will be moved to Trash": "{{title}} will be moved to Trash", - "Favorite": "Favorite", + "Favorite": "Favourite", "Moved to Trash": "Moved to Trash", "Permanently deleted": "Permanently deleted", "restored": "{{title}} restored", @@ -61,7 +61,7 @@ "Strikethrough": "Strikethrough", "Inline code": "Inline code", "Code block": "Code block", - "Favorited": "Favorited", + "Favorited": "Favourited", "Body text": "Body text", "Heading": "Heading {{number}}", "Increase indent": "Increase indent", @@ -153,7 +153,7 @@ "core": "core", "all": "all", "Data sync mode": "Data sync mode", - "Favorites": "Favorites", + "Favorites": "Favourites", "Check Our Docs": "Check Our Docs", "Get in touch! Join our communities": "Get in touch! Join our communities.", "Download data": "Download {{CoreOrAll}} data", @@ -186,7 +186,7 @@ "Sign out": "Sign out", "All data has been stored in the cloud": "All data has been stored in the cloud. ", "Download all data": "Download all data", - "emptyFavorite": "Click Add to Favorites and the page will appear here.", + "emptyFavorite": "Click Add to Favourites and the page will appear here.", "Edit": "Edit", "Sign out description": "Signing out will cause the unsynchronised content to be lost.", "Retain cached cloud data": "Retain cached cloud data",