diff --git a/CHANGELOG.md b/CHANGELOG.md
index e4296f7cc7..306be29e6e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,11 @@
## [Unreleased][unreleased]
+### Changed
+- ContextMenuItem now can render icons
+- use our own ContextMenu for AttachmentMenu
+- replace BlueprintJS Button, Icon, Radio, RadioGroup, Collapse with our implementation
+
## [v1.45.0] - 2024-05-24
diff --git a/images/icons/chats.svg b/images/icons/chats.svg
new file mode 100644
index 0000000000..d8e68a62c1
--- /dev/null
+++ b/images/icons/chats.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/images/icons/chevron-left.svg b/images/icons/chevron-left.svg
new file mode 100644
index 0000000000..2d083eb3ee
--- /dev/null
+++ b/images/icons/chevron-left.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/images/icons/chevron-right.svg b/images/icons/chevron-right.svg
new file mode 100644
index 0000000000..e59de717e9
--- /dev/null
+++ b/images/icons/chevron-right.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/images/icons/map.svg b/images/icons/map.svg
new file mode 100644
index 0000000000..5330ab1fd5
--- /dev/null
+++ b/images/icons/map.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/images/icons/paperclip.svg b/images/icons/paperclip.svg
new file mode 100644
index 0000000000..e415fd48b6
--- /dev/null
+++ b/images/icons/paperclip.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/images/icons/phone.svg b/images/icons/phone.svg
new file mode 100644
index 0000000000..64b4220d94
--- /dev/null
+++ b/images/icons/phone.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/images/icons/upload-file.svg b/images/icons/upload-file.svg
new file mode 100644
index 0000000000..f60a62cce2
--- /dev/null
+++ b/images/icons/upload-file.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/scss/_global.scss b/scss/_global.scss
index 3428c6e265..2f628161e3 100644
--- a/scss/_global.scss
+++ b/scss/_global.scss
@@ -40,7 +40,6 @@ h3,
h4,
h5,
p,
-.bp4-button,
button > span,
label {
user-select: none;
diff --git a/scss/components/_radios.scss b/scss/components/_radios.scss
index e15b6e5cf4..1731051bd2 100644
--- a/scss/components/_radios.scss
+++ b/scss/components/_radios.scss
@@ -15,7 +15,7 @@
width: 36px;
}
& > label {
- padding-left: 4px;
+ padding-left: 7px;
padding-right: 4px;
height: 36px;
display: inline-flex;
diff --git a/scss/composer/_composer.scss b/scss/composer/_composer.scss
index 4e8ab70b37..1bd207ba85 100644
--- a/scss/composer/_composer.scss
+++ b/scss/composer/_composer.scss
@@ -60,19 +60,20 @@
display: flex;
align-items: flex-end;
- .attachment-button,
- .emoji-button {
- .bp4-button.bp4-minimal {
- width: 40px;
- height: 40px;
+ .attachment-button {
+ width: 40px;
+ height: 40px;
- &:hover {
- background: none;
- cursor: pointer;
- }
- &:focus {
- outline: none;
- }
+ background: none;
+ box-shadow: none;
+ border: none;
+
+ &:hover {
+ background: none;
+ cursor: pointer;
+ }
+ &:focus {
+ outline: none;
}
}
diff --git a/scss/main_screen/_navbar_wrapper.scss b/scss/main_screen/_navbar_wrapper.scss
index 4dda818c0a..e5369e9153 100644
--- a/scss/main_screen/_navbar_wrapper.scss
+++ b/scss/main_screen/_navbar_wrapper.scss
@@ -44,12 +44,15 @@
margin-left: auto;
margin-right: 15px;
display: flex;
+ }
- .bp4-button {
- margin: 0px;
- position: relative;
- height: 50px;
- border-radius: 0px;
+ .navbar-button {
+ padding: 0;
+ width: 40px;
+ height: 50px;
+ border-radius: 0;
+ &:hover {
+ background-color: var(--navBarButtonHover);
}
}
@@ -66,7 +69,6 @@
}
#three-dot-menu-button {
- width: 40px;
height: 40px;
border-radius: 100%;
}
diff --git a/scss/misc/_context_menu.scss b/scss/misc/_context_menu.scss
index ad8c1eff91..93ddc87324 100644
--- a/scss/misc/_context_menu.scss
+++ b/scss/misc/_context_menu.scss
@@ -19,8 +19,8 @@
// position is determined in code
position: fixed;
pointer-events: auto;
- background-color: var(--bp4MenuBg);
- color: var(--bp4MenuText);
+ background-color: var(--bgPrimary);
+ color: var(--textPrimary);
border-radius: 3px;
overflow: hidden;
@@ -36,14 +36,20 @@
white-space: nowrap;
display: flex;
align-items: center;
- justify-content: space-between;
+ justify-content: flex-start;
+
+ & .left-icon {
+ background-color: var(--iconBackground);
+ margin: 0 5px 0 0;
+ }
& .right-icon {
width: 18px;
height: 18px;
+ margin-left: auto;
@include color-svg(
'../images/icons/navigate_next.svg',
- var(--bp4MenuText),
+ var(--textPrimary),
100%
);
transform: translate(11px, -0.07em);
diff --git a/src/renderer/components/Button/index.tsx b/src/renderer/components/Button/index.tsx
index 70240e86d0..ca358758ab 100644
--- a/src/renderer/components/Button/index.tsx
+++ b/src/renderer/components/Button/index.tsx
@@ -7,6 +7,7 @@ type Props = React.PropsWithChildren<{
'aria-label'?: string
className?: string
disabled?: boolean
+ active?: boolean
id?: string
onClick: any
type?: 'primary' | 'secondary' | 'danger'
@@ -15,6 +16,7 @@ type Props = React.PropsWithChildren<{
export default function Button({
children,
disabled = false,
+ active = false,
id,
onClick,
type,
@@ -27,6 +29,7 @@ export default function Button({
role='button'
className={classNames(
styles.button,
+ active && styles.active,
type && styles[type],
props.className
)}
diff --git a/src/renderer/components/Button/style.module.scss b/src/renderer/components/Button/style.module.scss
index 33c72a376b..de14827b5b 100644
--- a/src/renderer/components/Button/style.module.scss
+++ b/src/renderer/components/Button/style.module.scss
@@ -12,6 +12,11 @@
padding: 12px 15px;
text-align: center;
text-transform: uppercase;
+ user-select: none;
+
+ & > span {
+ user-select: none;
+ }
&:hover {
background-color: var(--buttonHover);
@@ -31,6 +36,10 @@
color: var(--buttonDangerText);
}
+ &.active {
+ background-color: var(--navBarButtonActive);
+ }
+
&:disabled {
background-color: var(--buttonDisabledBackground);
color: var(--buttonDisabledText);
diff --git a/src/renderer/components/Collapse/index.tsx b/src/renderer/components/Collapse/index.tsx
new file mode 100644
index 0000000000..000e391223
--- /dev/null
+++ b/src/renderer/components/Collapse/index.tsx
@@ -0,0 +1,49 @@
+import React, { useLayoutEffect, useRef } from 'react'
+
+type Props = {
+ className?: string
+ isOpen: boolean
+ children: any
+}
+
+export default function Collapse({
+ className,
+ children,
+ isOpen = false,
+}: Props) {
+ const content = useRef(null)
+ const wrapper = useRef(null)
+
+ useLayoutEffect(() => {
+ if (!content.current || !wrapper.current) {
+ return
+ }
+ const bounds = content.current.getBoundingClientRect()
+
+ const maxHeight = isOpen ? `${bounds?.height}px` : '0px'
+ const translateY = isOpen ? 0 : `-${bounds?.height}px`
+
+ wrapper.current.style.height = maxHeight
+
+ content.current.style.transform = `translate(0px, ${translateY})`
+ })
+ return (
+
+ )
+}
diff --git a/src/renderer/components/ContextMenu.tsx b/src/renderer/components/ContextMenu.tsx
index e86dff14ce..32553a8466 100644
--- a/src/renderer/components/ContextMenu.tsx
+++ b/src/renderer/components/ContextMenu.tsx
@@ -6,15 +6,19 @@ import React, {
useCallback,
} from 'react'
import classNames from 'classnames'
+import Icon from './Icon'
+import type { IconName } from './Icon'
import useContextMenu from '../hooks/useContextMenu'
type ContextMenuItemActionable = {
+ icon?: IconName
action: (event: React.MouseEvent) => void
subitems?: never
}
type ContextMenuItemExpandable = {
+ icon?: IconName
action?: never
subitems: (ContextMenuItem | undefined)[]
}
@@ -344,6 +348,7 @@ export function ContextMenu(props: {
key={index}
{...(item.subitems && { 'data-expandable-index': index })}
>
+ {item.icon && }
{item.label}
{item.subitems && }
diff --git a/src/renderer/components/Icon/index.tsx b/src/renderer/components/Icon/index.tsx
index 577ad81b68..7b68980163 100644
--- a/src/renderer/components/Icon/index.tsx
+++ b/src/renderer/components/Icon/index.tsx
@@ -8,6 +8,9 @@ export type IconName =
| 'audio-muted'
| 'bell'
| 'brightness-6'
+ | 'chats'
+ | 'chevron-left'
+ | 'chevron-right'
| 'code-tags'
| 'cross'
| 'devices'
@@ -17,27 +20,51 @@ export type IconName =
| 'info'
| 'lead-pencil'
| 'list'
+ | 'map'
+ | 'media'
+ | 'minus'
| 'more'
| 'open_in_new'
+ | 'paperclip'
| 'person'
| 'person-filled'
+ | 'phone'
| 'qr'
| 'question_mark'
| 'reaction'
| 'settings'
| 'swap_vert'
+ | 'tint'
+ | 'undo'
+ | 'upload-file'
type Props = {
className?: string
+ onClick?: (ev: Event | React.SyntheticEvent) => void
icon: IconName
+ coloring?: string
size?: number
+ rotation?: number
}
-export default function Icon({ size = 20, icon, className }: Props) {
+export default function Icon({
+ coloring = 'primary',
+ size = 20,
+ rotation = 0,
+ icon,
+ className,
+ onClick,
+}: Props) {
return (
{i !== 8 && i !== 2 && i !== 5 && (
-
+
)}
diff --git a/src/renderer/components/LoginForm.tsx b/src/renderer/components/LoginForm.tsx
index 8b86faed49..3e7b03b29a 100644
--- a/src/renderer/components/LoginForm.tsx
+++ b/src/renderer/components/LoginForm.tsx
@@ -2,7 +2,6 @@
import { C, DcEventType } from '@deltachat/jsonrpc-client'
import React, { useEffect, useRef, useState } from 'react'
-import { Collapse } from '@blueprintjs/core'
import { useDebouncedCallback } from 'use-debounce/lib'
import {
@@ -24,6 +23,7 @@ import Dialog, {
FooterActionButton,
FooterActions,
} from './Dialog'
+import Collapse from './Collapse'
import { I18nContext } from '../contexts/I18nContext'
import useTranslationFunction from '../hooks/useTranslationFunction'
import { getDeviceChatId, saveLastChatId } from '../backend/chat'
diff --git a/src/renderer/components/SearchInput/styles.module.scss b/src/renderer/components/SearchInput/styles.module.scss
index be46dbb802..4dd554e248 100644
--- a/src/renderer/components/SearchInput/styles.module.scss
+++ b/src/renderer/components/SearchInput/styles.module.scss
@@ -1,4 +1,3 @@
-$backgroundColorHover: rgba(143, 153, 168, 0.15);
$borderRadius: 10px;
$closeButtonSize: 30px;
@@ -38,7 +37,7 @@ $closeButtonSize: 30px;
min-width: $closeButtonSize;
&:hover {
- background-color: $backgroundColorHover;
+ background-color: var(--navBarButtonHover);
}
}
diff --git a/src/renderer/components/Settings/Appearance.tsx b/src/renderer/components/Settings/Appearance.tsx
index 8103cb509d..b1223bb9ce 100644
--- a/src/renderer/components/Settings/Appearance.tsx
+++ b/src/renderer/components/Settings/Appearance.tsx
@@ -1,6 +1,5 @@
import { join } from 'path'
import React, { useEffect, useState } from 'react'
-import { Icon } from '@blueprintjs/core'
import { ThemeManager } from '../../ThemeManager'
import { runtime } from '../../runtime'
@@ -21,6 +20,7 @@ import { DialogContent } from '../Dialog'
import useTranslationFunction from '../../hooks/useTranslationFunction'
import useDialog from '../../hooks/dialog/useDialog'
import { LastUsedSlot, rememberLastUsedPath } from '../../utils/lastUsedPaths'
+import Icon from '../Icon'
const log = getLogger('renderer/settings/appearance')
diff --git a/src/renderer/components/SmallSelectDialog.tsx b/src/renderer/components/SmallSelectDialog.tsx
index cda653dc01..a3ec9a9e62 100644
--- a/src/renderer/components/SmallSelectDialog.tsx
+++ b/src/renderer/components/SmallSelectDialog.tsx
@@ -1,5 +1,4 @@
import React, { useState } from 'react'
-import { RadioGroup, Radio } from '@blueprintjs/core'
import Dialog, {
DialogBody,
@@ -8,6 +7,8 @@ import Dialog, {
DialogHeader,
FooterActions,
} from './Dialog'
+import Radio from './Radio'
+import RadioGroup from './RadioGroup'
import FooterActionButton from './Dialog/FooterActionButton'
import useTranslationFunction from '../hooks/useTranslationFunction'
@@ -38,10 +39,9 @@ export default function SmallSelectDialog({
const [actualSelectedValue, setActualSelectedValue] =
useState(selectedValue)
- const onChange = (event: React.FormEvent) => {
- const actualSelectedValue = String(event.currentTarget.value)
- setActualSelectedValue(actualSelectedValue)
- onSelect && onSelect(actualSelectedValue)
+ const onChange = (value: string) => {
+ setActualSelectedValue(value)
+ onSelect && onSelect(value)
}
const saveAndClose = () => {
@@ -49,12 +49,17 @@ export default function SmallSelectDialog({
onClose()
}
+ // FIXME(maxph): get a name for RadioGroup
return (