diff --git a/js/app/packages/app/component/UnifiedListView.tsx b/js/app/packages/app/component/UnifiedListView.tsx index ae80eaf0c..f3f8d9ad0 100644 --- a/js/app/packages/app/component/UnifiedListView.tsx +++ b/js/app/packages/app/component/UnifiedListView.tsx @@ -1288,10 +1288,10 @@ export function UnifiedListView(props: UnifiedListViewProps) {
-
-
- - - - - - - - - - - - -
- - +
+ + +
@@ -335,7 +315,7 @@ export function KommandMenuInner(props: { return ( { @@ -343,26 +323,34 @@ export function KommandMenuInner(props: { setCurrentValue(value); }} > -
- +
+ + { + if (val) { + setKonsoleMode('FULL_TEXT_SEARCH'); + } else { + setKonsoleMode('ENTITY_SEARCH'); + } + }} + checked={isFullTextSearch()} + // switchRootClass='subtle' + label="Full Text Search" + size="SM" />
-
+
-
+
{currentKonsoleMode() === 'FULL_TEXT_SEARCH' && cleanQuery().length < 3 ? 'Enter 3 or more characters to search all documents.' @@ -375,7 +363,7 @@ export function KommandMenuInner(props: { {(item, index) => ( diff --git a/js/app/packages/app/component/command/KonsoleFilter.tsx b/js/app/packages/app/component/command/KonsoleFilter.tsx index 1adf5527d..1f6dd87cd 100644 --- a/js/app/packages/app/component/command/KonsoleFilter.tsx +++ b/js/app/packages/app/component/command/KonsoleFilter.tsx @@ -1,12 +1,5 @@ -import { TextButton } from '@core/component/TextButton'; -import { - createEffect, - createSignal, - For, - onCleanup, - onMount, - Show, -} from 'solid-js'; +import { SegmentedControl } from '@core/component/FormControls/SegmentControls'; +import { createMemo, onCleanup, onMount } from 'solid-js'; import { commandCategoryIndex, searchCategories, @@ -15,8 +8,35 @@ import { import { konsoleOpen } from './state'; export function KonsoleFilter() { - const [containerRef, setContainerRef] = createSignal(); - const buttonRefs: HTMLDivElement[] = []; + const visibleCategories = createMemo(() => { + return searchCategories + .listVisible() + .map((category, index) => { + if (searchCategories.isCategoryActive(index)) { + return category.name; + } + return null; + }) + .filter(Boolean) as string[]; + }); + + const selectedCategoryName = createMemo(() => { + const categories = searchCategories.listVisible(); + const index = commandCategoryIndex(); + if (index >= 0 && index < categories.length) { + return categories[index].name; + } + return categories[0]?.name || ''; + }); + + const handleCategoryChange = (categoryName: string) => { + const index = searchCategories + .listVisible() + .findIndex((cat) => cat.name === categoryName); + if (index !== -1) { + setCommandCategoryIndex(index); + } + }; onMount(() => { const down = (e: KeyboardEvent) => { @@ -48,62 +68,14 @@ export function KonsoleFilter() { }); }); - // Scroll selected category into view when selection changes - createEffect(() => { - const container = containerRef(); - const selectedIndex = commandCategoryIndex(); - - if (container && buttonRefs[selectedIndex]) { - const selectedButtonDiv = buttonRefs[selectedIndex]; - - // Use requestAnimationFrame to ensure DOM updates are complete - requestAnimationFrame(() => { - const containerRect = container.getBoundingClientRect(); - const buttonRect = selectedButtonDiv.getBoundingClientRect(); - - const isFullyVisible = - buttonRect.left >= containerRect.left && - buttonRect.right <= containerRect.right; - - if (!isFullyVisible) { - // For rightmost items like "Companies", scroll to show them fully - // Add some padding so the button isn't right at the edge - const scrollLeft = - selectedButtonDiv.offsetLeft - - container.clientWidth + - selectedButtonDiv.offsetWidth + - 8; - container.scrollTo({ - left: Math.max(0, scrollLeft), - behavior: 'smooth', - }); - } - }); - } - }); - return ( -
- - {(item, index) => ( - - { - if (el) buttonRefs[index()] = el; - }} - theme={ - index() === commandCategoryIndex() ? 'accentFill' : 'clear' - } - text={item.name} - onMouseDown={() => setCommandCategoryIndex(index())} - class="flex-shrink-0 h-auto *:h-7 *:px-2" - /> - - )} - +
+
); } diff --git a/js/app/packages/app/component/command/state.ts b/js/app/packages/app/component/command/state.ts index e1c1a0163..5cfd585a2 100644 --- a/js/app/packages/app/component/command/state.ts +++ b/js/app/packages/app/component/command/state.ts @@ -44,7 +44,7 @@ export function cleanQuery(query?: string) { } export const COMMAND_MODES = [ - // { id: 'FULL_TEXT_SEARCH', sigil: '%', label: 'Full Text Search' }, + { id: 'FULL_TEXT_SEARCH', sigil: '%', label: 'Full Text Search' }, // { id: "REGEX_SEARCH", sigil: "/", label: "Regex Search" }, // { id: "RUN_COMMAND", sigil: ">", label: "Run" }, // { id: "TEMP_CHAT", sigil: " ", label: "Temporary Chat" }, diff --git a/js/app/packages/app/index.css b/js/app/packages/app/index.css index 374428de6..ee80d929a 100644 --- a/js/app/packages/app/index.css +++ b/js/app/packages/app/index.css @@ -212,7 +212,7 @@ --color-task: var(--theme-task); --color-task-bg: color-mix(in srgb, var(--color-task), var(--color-panel) 90%); - + /* SCUFFED We probably want to let the theme determine 3 or 4 "extra" hue offsets. Rights now these are only being */ /* used as debug colors and to improve the consistency of markdown block lightness/chroma with themed css */ --color-accent-30: oklch(var(--a0l) var(--a0c) calc(var(--a0h) + 30deg)); @@ -243,6 +243,13 @@ --color-focus: var(--color-accent); } +/* +*{ + scrollbar-width: thin; + scrollbar-color: var(--color-accent); +} +*/ + /* NOTE: We use this as a compile-time css util in this file to be able reuse the * declarations while still being able to override the color. */ @utility util-bracket-bg-image { @@ -320,6 +327,10 @@ } } +@utility hide-scrollbar { + scrollbar-width: none; +} + @utility bracket-* { background-image: conic-gradient(from 90deg at top 1px left 1px, #0000 90deg, var(--color-focus) 0), diff --git a/js/app/packages/block-channel/component/ParticipantManager.tsx b/js/app/packages/block-channel/component/ParticipantManager.tsx index 6d8516d8c..6426310c4 100644 --- a/js/app/packages/block-channel/component/ParticipantManager.tsx +++ b/js/app/packages/block-channel/component/ParticipantManager.tsx @@ -6,6 +6,8 @@ import { useAddParticipantsToChannel, useRemoveParticipantsFromChannel, } from '@block-channel/signal/participants'; +import { ClippedPanel } from '@core/component/ClippedPanel'; +import { IconButton } from '@core/component/IconButton'; import { getDestinationFromOptions } from '@core/component/NewMessage'; import { RecipientSelector } from '@core/component/RecipientSelector'; import { TextButton } from '@core/component/TextButton'; @@ -18,7 +20,7 @@ import { } from '@core/user'; import InvitedIcon from '@icon/regular/paper-plane-tilt.svg'; import UsersIcon from '@icon/regular/users.svg'; -import XIcon from '@icon/regular/x.svg'; +import CloseIcon from '@icon/regular/x.svg'; import { Dialog } from '@kobalte/core/dialog'; import BracketLeft from '@macro-icons/macro-group-bracket-left.svg'; import type { ChannelParticipant } from '@service-comms/generated/models/channelParticipant'; @@ -82,59 +84,56 @@ export function ParticipantManager(props: { participantCount: number }) { - +
- -
- - {title()} - - - - -
- -
-

- Invite Participants -

- - placeholder={'Add participant'} - options={options} - selectedOptions={usersToInvite} - setSelectedOptions={setUsersToInvite} - /> -
+ + +
+ + + + {title()} +
+ +
+ + setSelectedOptions={setUsersToInvite} + selectedOptions={usersToInvite} + placeholder={'Search'} + options={options} + hideBorder + noPadding + />
-
- + -
-

- Participants{' '} - - ({channel?.participants.length}) - -

- -
+
+ +
+
@@ -176,16 +175,16 @@ export function ParticipantList(props: { }); return ( -
+
10}> setSearchQuery(e.currentTarget.value)} /> -
+
0} fallback={} @@ -193,6 +192,7 @@ export function ParticipantList(props: { { - return hovered() || open(); - }; - return ( -
setHovered(true)} - onMouseLeave={() => setHovered(false)} - > -
- -
- -

{idToEmail(props.id)}

-
-

{props.description}

+ +
setHovered(true)} + onMouseLeave={() => setHovered(false)} + > +
+ +
+ +

{idToEmail(props.id)}

+
+

{props.description}

+
+ + +
- } - > - - - - - - - - - - - -
+ ); } diff --git a/js/app/packages/core/component/BozzyBracket.tsx b/js/app/packages/core/component/BozzyBracket.tsx index 11f10fa3a..a820f7643 100644 --- a/js/app/packages/core/component/BozzyBracket.tsx +++ b/js/app/packages/core/component/BozzyBracket.tsx @@ -1,11 +1,11 @@ import { createSignal, type JSX, onMount, type ParentProps } from 'solid-js'; type BozzyBracketProps = { - active: boolean; - class?: string; style?: JSX.CSSProperties; - hover?: boolean; unfocusable?: boolean; + active: boolean; + hover?: boolean; + class?: string; }; /** @@ -29,7 +29,7 @@ export function BozzyBracket(props: ParentProps) { style={props.style} >
setBig(false)); }); } + /* TEST BEFORE REMOVING left-[-1px] top-[-1px] w-[calc(100%+2px)] h-[calc(100%+2px)] */ return (
{ + setScrollHeight(scrollContainerRef.scrollHeight); + setClientHeight(scrollContainerRef.clientHeight); + }); + + function thumbTop() { + const maxScroll = scrollHeight() - clientHeight(); + const maxThumbTop = clientHeight() - thumbSize; + return maxScroll > 0 ? (scrollTop() / maxScroll) * maxThumbTop : 0; + } + + return ( +
+
+ {props.children} +
+ +
+
+
+
+ ); +} diff --git a/js/app/packages/core/component/TopBar/ShareButton.tsx b/js/app/packages/core/component/TopBar/ShareButton.tsx index 7b7a395e7..afe346a08 100644 --- a/js/app/packages/core/component/TopBar/ShareButton.tsx +++ b/js/app/packages/core/component/TopBar/ShareButton.tsx @@ -23,11 +23,11 @@ import { type MaybeResult, } from '@core/util/maybeResult'; import { buildSimpleEntityUrl } from '@core/util/url'; -import EyeSlash from '@icon/bold/eye-slash-bold.svg'; -import GlobeIcon from '@icon/bold/globe-simple-bold.svg'; -import LinkIconBold from '@icon/bold/link-bold.svg'; -import Users from '@icon/bold/users-bold.svg'; +import IconEyeSlash from '@icon/regular/eye-slash.svg'; +import IconGlobe from '@icon/regular/globe.svg'; +import IconLink from '@icon/regular/link.svg'; import User from '@icon/regular/user.svg'; +import IconUsers from '@icon/regular/users.svg'; import { Dialog } from '@kobalte/core/dialog'; import { DropdownMenu } from '@kobalte/core/dropdown-menu'; import { Switch as KobalteSwitch } from '@kobalte/core/switch'; @@ -54,14 +54,12 @@ import { Show, Switch, } from 'solid-js'; -import { Button } from '../FormControls/Button'; import { ForwardToChannel } from '../ForwardToChannel'; import { IconButton } from '../IconButton'; import { DropdownMenuContent, MENU_ITEM_CLASS, MenuItem } from '../Menu'; import { Permissions } from '../SharePermissions'; import { TextButton } from '../TextButton'; import { toast } from '../Toast/Toast'; -import { Tooltip } from '../Tooltip'; import { openLoginModal } from './LoginButton'; false && clickOutside; @@ -533,7 +531,7 @@ export function ShareModal(props: ShareModalProps) { - +
@@ -685,7 +683,7 @@ export function ShareButton(props: ShareButtonProps) { e.stopPropagation(); copyLink(); }, - icon: LinkIconBold, + icon: IconLink, }; }); @@ -700,76 +698,62 @@ export function ShareButton(props: ShareButtonProps) { return 'Just me'; }); + const shareIcon = createMemo(() => { + const accessLevel = shareAccessLevelText(); + if (accessLevel === 'Public') { + return IconGlobe; + } + if (accessLevel === 'Shared') { + return IconUsers; + } + if (accessLevel === 'Just me') { + return IconEyeSlash; + } + return IconGlobe; + }); + return ( <> -
- -
-
-
} - > - - - - -
- - Share -
- + icon={shareIcon()} + theme="clear" + size="sm" + /> + + + );