Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(webview): finalize v0.4.0 UI #155

Merged
merged 72 commits into from
Sep 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
e670d81
build(webview/stories): setup Storybook
ivangabriele Sep 11, 2024
a0ff838
lint(biome): add .storybook/ in Storybook override
ivangabriele Sep 12, 2024
a2d214f
build(tsconfig): include .storybook/ files in base config
ivangabriele Sep 12, 2024
0f41d8f
build(storybook): add /public static dir
ivangabriele Sep 12, 2024
3e0db59
build(storybook): setup screen & loading-screen story types
ivangabriele Sep 12, 2024
c0ef37e
build(storybook): remove @chromatic-com/storybook & @storybook/addon-…
ivangabriele Sep 13, 2024
41d60d9
refactor(webview): move Loader screen from Layout to App
ivangabriele Sep 13, 2024
f2cdc8e
build(storybook): remove Layout from screen decorator
ivangabriele Sep 13, 2024
50b3dc0
lint(biome): disable useNamingConvention rule for stories
ivangabriele Sep 13, 2024
166e2d4
feat(webview/utils): add waitFor()
ivangabriele Sep 13, 2024
f041fd8
build(vite): disable server HMR overlay
ivangabriele Sep 13, 2024
9e22a45
build(npm): prevent auto-open in storybook command
ivangabriele Sep 13, 2024
674f01b
build(storybook): add custom args store
ivangabriele Sep 13, 2024
9a970fa
build(dev-deps): upgrade storybook from v8.2.9 to v8.3.0
ivangabriele Sep 13, 2024
1971fcf
build(storybook): disable Vite server HMR overlay
ivangabriele Sep 13, 2024
4834cf9
build(vite): enable server HMR overlay
ivangabriele Sep 13, 2024
86d2d2f
feat(webview/screens): finalize Loader screen UI
ivangabriele Sep 13, 2024
081eb84
docs(webview/screens): add Loader screen story
ivangabriele Sep 13, 2024
af744af
refactor(storybook): remove all initialization assets & stories
ivangabriele Sep 13, 2024
22a40cb
feat(webview/layouts): make isLoading prop optional
ivangabriele Sep 13, 2024
5bac8a7
feat(webview/components): add Card
ivangabriele Sep 13, 2024
8dcd54a
style(core): set windows size to 800x496
ivangabriele Sep 13, 2024
4cec5a3
style(webview/layouts): update font & colors
ivangabriele Sep 13, 2024
05204dd
style(webview/layouts): normalize MainMenu size & make buttons transp…
ivangabriele Sep 13, 2024
69f0ee5
style(webview/layouts): normalize Screen padding
ivangabriele Sep 13, 2024
7b54054
build(storybook): align sizes & colors
ivangabriele Sep 13, 2024
bf8560b
docs(webview/modules): add readme
ivangabriele Sep 13, 2024
d6c683a
feat(webview/layouts): remove isLoading prop from Screen
ivangabriele Sep 13, 2024
3789575
style(webview): normalize global style colors
ivangabriele Sep 13, 2024
3ea2aa0
style(webview/layouts): set Screen grid display & template
ivangabriele Sep 13, 2024
be781f4
feat(webview/elements): add CircularSpinner
ivangabriele Sep 13, 2024
115edb5
feat(webview/components): add KeyValueList
ivangabriele Sep 13, 2024
bbe2f09
feat(webview/components): add isLoading prop to Card
ivangabriele Sep 13, 2024
f47bec6
build(storybook): set custom dark & light background colors
ivangabriele Sep 13, 2024
e6004d2
feat(webview/modules): add DaemonClient types
ivangabriele Sep 13, 2024
fae3423
feat(webview/screens): draft next Dashboard component
ivangabriele Sep 13, 2024
3da23a7
docs(webview/screens): add Dashboard screen story
ivangabriele Sep 13, 2024
bc570bf
fix(webview/components): add missing empty interpolation in KeyValueL…
ivangabriele Sep 13, 2024
7f2fb22
fix(webview/elements): add missing styled components prefixes in Circ…
ivangabriele Sep 13, 2024
cb71e4a
feat(webview/screens): remove Cloud
ivangabriele Sep 14, 2024
9295f5d
refactor(webview/layouts): rename Screen to ScreenBox
ivangabriele Sep 14, 2024
881dd79
refactor(webview): rename Page enum to Screen
ivangabriele Sep 14, 2024
e032925
feat(webview): move global style into CSS file
ivangabriele Sep 14, 2024
fa9fc49
test(jest): ignore various patterns
ivangabriele Sep 14, 2024
454e41d
feat(webview/hooks): add useDebouncedMemo()
ivangabriele Sep 14, 2024
6fad226
style(webview/components): remove bottom padding for Card with action…
ivangabriele Sep 14, 2024
57fd180
style(webview): normalize ul margin & padding
ivangabriele Sep 14, 2024
6e07733
feat(webview/components): add LogList
ivangabriele Sep 14, 2024
9c7af51
style(webview): normalize scrollbars colors
ivangabriele Sep 14, 2024
bddc90e
fix(webview): add missing MAX_LOG_LIST_HISTORY constant
ivangabriele Sep 14, 2024
1abf358
fix(webview): add missing Core.Log type
ivangabriele Sep 14, 2024
3a21719
feat(webview/screens): add daemon logs in next Dashboard component
ivangabriele Sep 14, 2024
8fe7266
refactor(webview/core): regroup Core types & constants
ivangabriele Sep 14, 2024
0bf299c
refactor(webview): remove Webview namespace
ivangabriele Sep 14, 2024
82c1482
refactor(webview/elements): rename current ScanningSpinner to LegacyS…
ivangabriele Sep 14, 2024
9f8fe97
build(tsconfig): setup import paths
ivangabriele Sep 14, 2024
62a6ad8
build(vite): add missing tsconfig paths plugin
ivangabriele Sep 14, 2024
bd5a499
feat(webview/elements): add ScanningSpinner
ivangabriele Sep 14, 2024
28d8545
feat(webview/layouts): allow both grid & flex in ScreenBox
ivangabriele Sep 14, 2024
53f240e
style(webview/components): decrease Card background opacity
ivangabriele Sep 14, 2024
8e4e455
refactor(webview/components): split types in Card
ivangabriele Sep 14, 2024
701d0f2
refactor(webview/core): simplify FileExplorerNode type
ivangabriele Sep 14, 2024
8eb3a1c
refactor(webview/components): rename FileExplorer to LegacyFileExplorer
ivangabriele Sep 14, 2024
c8711f8
refactor(webview/core): rename FileExplorerTree type to LegacyFileExp…
ivangabriele Sep 14, 2024
c589629
feat(webview/components): add isDisabled prop to Card action
ivangabriele Sep 15, 2024
0adf46d
feat(webview/core): add new Path type
ivangabriele Sep 15, 2024
0a59dae
style(webview/layouts): make ScreenBox position relative
ivangabriele Sep 15, 2024
4c98229
feat(webview/components): add new FileExplorer
ivangabriele Sep 15, 2024
f426d83
feat(webview/core): add next Scanner state
ivangabriele Sep 15, 2024
fc7ff87
feat(webview/screens): draft next Scanner component
ivangabriele Sep 15, 2024
2c59253
docs(webview/screens): add next Scanner component stories
ivangabriele Sep 15, 2024
e439cc6
build(npm): remove useless tsc run & build tsconfig for build:webview…
ivangabriele Sep 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -193,3 +193,5 @@ cobertura.xml
# Used to build and embed sidecars during the bundling process.
/src-tauri/sidecars/*
!/src-tauri/sidecars/.gitkeep

*storybook.log
79 changes: 79 additions & 0 deletions .storybook/argsStore/ArgsStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import type { ArgStoreKey } from './constants'
import type { Args, ArgsStoreItem, Listener } from './types'

export class ArgsStore {
#store: Map<ArgStoreKey, ArgsStoreItem<Args>>

constructor() {
this.#store = new Map()
}

getArgs<T extends Args>(key: ArgStoreKey): T | undefined {
return this.#store.get(key)?.args as T
}

initArgs<T extends Args>(key: ArgStoreKey, newArgs: T): T {
const storeEntry = this.#store.get(key)
const newListeners = storeEntry?.listeners ?? []

this.#store.set(key, {
args: newArgs,
listeners: newListeners,
})

return newArgs
}

updateArgs<T extends Args>(key: ArgStoreKey, nextlArgsPatch: Partial<T>): void {
const storeEntry = this.#store.get(key)
if (!storeEntry) {
return
}

const nextArgs = { ...storeEntry.args, ...nextlArgsPatch }

this.#store.set(key, {
args: nextArgs,
listeners: storeEntry.listeners,
})
this.#triggerChange(key, nextArgs)
}

addListener<T extends Args>(key: ArgStoreKey, callback: Listener<T>): void {
const storeEntry = this.#store.get(key)
const args = storeEntry?.args
const listeners = storeEntry?.listeners ?? []

const nextListeners = [...listeners, callback]

this.#store.set(key, {
args,
listeners: nextListeners as Listener<Args>[],
})
}

removeListener<T extends Args>(key: ArgStoreKey, callbackToRemove: Listener<T>): void {
const storeEntry = this.#store.get(key)
if (!storeEntry) {
return
}

const updatedListeners = storeEntry.listeners.filter(callback => callback !== callbackToRemove)

this.#store.set(key, {
...storeEntry,
listeners: updatedListeners,
})
}

#triggerChange<T extends Args>(key: ArgStoreKey, updatedArgs: T): void {
const storeEntry = this.#store.get(key)
if (!storeEntry) {
return
}

for (const listener of storeEntry.listeners) {
listener(updatedArgs)
}
}
}
5 changes: 5 additions & 0 deletions .storybook/argsStore/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export enum ArgStoreKey {
DashboardScreenComponent = 'DashboardScreenComponent',
LoaderScreenComponent = 'LoaderScreenComponent',
ScannerScreenComponent = 'ScannerScreenComponent',
}
3 changes: 3 additions & 0 deletions .storybook/argsStore/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { ArgsStore } from './ArgsStore'

export const argsStore = new ArgsStore()
8 changes: 8 additions & 0 deletions .storybook/argsStore/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export interface ArgsStoreItem<T extends Args> {
args: T | undefined
listeners: Listener<T>[]
}

// biome-ignore lint/suspicious/noExplicitAny: Args are generic.
export type Args = Record<string, any>
export type Listener<T extends Args> = (args: T) => void
33 changes: 33 additions & 0 deletions .storybook/argsStore/useArgsStoreArgs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useCallback, useEffect, useState } from 'react'

import { argsStore } from '.'
import type { ArgStoreKey } from './constants'
import type { Args } from './types'

export function useArgsStoreArgs<T extends Args>(
key: ArgStoreKey,
initialArgs: T,
): [T, (nextArgsPatch: Partial<T>) => void] {
const [args, setArgs] = useState<T>(argsStore.initArgs<T>(key, initialArgs))

const updateArgs = useCallback(
(nextArgsPatch: Partial<T>) => {
argsStore.updateArgs<T>(key, nextArgsPatch)
},
[key],
)

useEffect(() => {
const handleArgsChange = (updatedArgs: T) => {
setArgs(updatedArgs)
}

argsStore.addListener<T>(key, handleArgsChange)

return () => {
argsStore.removeListener<T>(key, handleArgsChange)
}
}, [key])

return [args, updateArgs]
}
24 changes: 24 additions & 0 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { StorybookConfig } from '@storybook/react-vite'

const config: StorybookConfig = {
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions'],
framework: {
name: '@storybook/react-vite',
options: {},
},
staticDirs: ['../public'],
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],

async viteFinal(config) {
const { mergeConfig } = await import('vite')

return mergeConfig(config, {
server: {
hmr: {
overlay: false,
},
},
})
},
}
export default config
13 changes: 13 additions & 0 deletions .storybook/preview.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
html {
height: 100%;
}
body {
background-color: #0d1117;
border-radius: unset;
height: 100%;
}

#storybook-root {
display: flex;
height: 100%;
}
54 changes: 54 additions & 0 deletions .storybook/preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import type { Preview } from '@storybook/react'
import { StrictMode } from 'react'
import { ThemeProvider } from 'styled-components'

import { ScreenStoryBox } from './story-components/ScreenStoryBox'

import '@fontsource/poppins/300.css'
import '@fontsource/poppins/400.css'
import '@fontsource/poppins/500.css'
import '@fontsource/reddit-mono/400.css'
import '@fontsource/reddit-mono/600.css'

import '../src/global.css'
import './preview.css'

const preview: Preview = {
decorators: [
(Story, { parameters }) => {
switch (parameters.type) {
case 'screen':
return (
<StrictMode>
<ThemeProvider theme={{}}>
<ScreenStoryBox>
<Story />
</ScreenStoryBox>
</ThemeProvider>
</StrictMode>
)

default:
return <Story />
}
},
],

parameters: {
backgrounds: {
values: [
{ name: 'Dark', value: '#0d1117' },
{ name: 'Light', value: '#f6f8fa' },
],
default: 'Dark',
},
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
}

export default preview
29 changes: 29 additions & 0 deletions .storybook/story-components/ScreenStoryBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { ReactNode } from 'react'
import styled from 'styled-components'

type ScreenStoryBoxProps = Readonly<{
children: ReactNode
}>
export function ScreenStoryBox({ children }: ScreenStoryBoxProps) {
return (
<Box className="Box">
<ScreenBox className="ScreenBox">{children}</ScreenBox>
</Box>
)
}

const Box = styled.div`
align-items: center;
display: flex;
flex-grow: 1;
justify-content: center;
`

const ScreenBox = styled.div`
background: linear-gradient(135deg, #660033 0%, #330a1f 100%);
border-radius: 16px;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.75);
display: flex;
height: 496px;
width: 800px;
`
15 changes: 14 additions & 1 deletion biome.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,18 @@
"noNamespace": "off"
}
}
}
},
"overrides": [
{
"include": ["./.storybook/**/*.ts", "./.storybook/**/*.tsx", "./src/stories/**/*.ts", "./src/stories/**/*.tsx"],
"linter": {
"rules": {
"style": {
"noDefaultExport": "off",
"useNamingConvention": "off"
}
}
}
}
]
}
13 changes: 12 additions & 1 deletion configs/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export default {
/** @type {import('jest').Config} */
const jestConfig = {
clearMocks: true,
collectCoverageFrom: ['<rootDir>/src/{hooks,libs,utils}/**/*.t{s,sx}', '<rootDir>/src/**/utils.t{s,sx}'],
maxWorkers: '50%',
Expand All @@ -7,6 +8,14 @@ export default {
setupFilesAfterEnv: ['<rootDir>/configs/jest.setup.ts'],
testEnvironment: 'jsdom',
testMatch: ['<rootDir>/src/**/*.test.t{s,sx}'],
testPathIgnorePatterns: [
'<rootDir>/.dev/*',
'<rootDir>/.yarn/*',
'<rootDir>/daemon/*',
'<rootDir>/node_modules/*',
'<rootDir>/sidecars/*',
'<rootDir>/src-tauri/*',
],
transform: {
'.*\\.(j|t)sx?$': [
'@swc/jest',
Expand All @@ -23,3 +32,5 @@ export default {
},
transformIgnorePatterns: [],
}

export default jestConfig
Loading
Loading