Skip to content

Commit 2395a2c

Browse files
feat: refactor combobox with kobalte (#605)
* feat: refactor combobox with kobalte * feat: fix inlineCombobox list overflow for safari * feat: remove @lion/combobox * feat: improve combobox * Create brave-buses-jog.md
1 parent e4f58de commit 2395a2c

File tree

9 files changed

+260
-546
lines changed

9 files changed

+260
-546
lines changed

.changeset/brave-buses-jog.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@codeimage/app": patch
3+
---
4+
5+
feat: refactor combobox with kobalte

apps/codeimage/package.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,6 @@
7575
"@kobalte/utils": "^0.9.0",
7676
"@kobalte/vanilla-extract": "^0.4.0",
7777
"@lezer/highlight": "^1.1.3",
78-
"@lion/combobox": "^0.11.1",
79-
"@lion/core": "^0.24.0",
80-
"@lion/listbox": "^0.14.1",
8178
"@motionone/solid": "^10.16.2",
8279
"@ngneat/falso": "^6.4.0",
8380
"@solid-aria/button": "^0.1.3",

apps/codeimage/src/components/Terminal/Tabs/Tab/DraggableWindowTab.tsx

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,16 @@ import {exportExclude} from '@core/directives/exportExclude';
33
import {createResizeObserver} from '@solid-primitives/resize-observer';
44
import {createSortable} from '@thisbeyond/solid-dnd';
55
import {assignInlineVars} from '@vanilla-extract/dynamic';
6-
import {createMemo, createSignal, onMount, Show, VoidProps} from 'solid-js';
6+
import {
7+
createMemo,
8+
createSignal,
9+
lazy,
10+
onMount,
11+
Show,
12+
Suspense,
13+
VoidProps,
14+
} from 'solid-js';
715
import {CloseIcon} from '../../../Icons/CloseIcon';
8-
import {TabName} from '../TabName/TabName';
916
import * as styles from './Tab.css';
1017
import {WindowTab, WindowTabContentText} from './WindowTab';
1118

@@ -23,6 +30,8 @@ export interface WindowTabProps {
2330
readonly onClose?: (() => void) | null;
2431
}
2532

33+
const TabName = lazy(() => import('../TabName/TabName'));
34+
2635
export function DraggableWindowTab(props: VoidProps<WindowTabProps>) {
2736
let ref!: HTMLDivElement;
2837
const [width, setWidth] = createSignal<number>(0);
@@ -63,11 +72,13 @@ export function DraggableWindowTab(props: VoidProps<WindowTabProps>) {
6372
}
6473
when={!props.readonlyTab}
6574
>
66-
<TabName
67-
readonly={props.readonlyTab && !props.active}
68-
value={props.tabName ?? ''}
69-
onValueChange={value => props.onTabChange?.(value)}
70-
/>
75+
<Suspense>
76+
<TabName
77+
readonly={props.readonlyTab && !props.active}
78+
value={props.tabName ?? ''}
79+
onValueChange={value => props.onTabChange?.(value)}
80+
/>
81+
</Suspense>
7182
</Show>
7283
}
7384
rightContent={

apps/codeimage/src/components/Terminal/Tabs/Tab/WindowTab.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ export function WindowTab(
5050
>
5151
<Suspense fallback={<Loading size={'sm'} />}>
5252
<Show when={props.tabIcon} keyed>
53-
{icon => <TabIcon size={props.lite ? 'xs' : 'md'} content={icon} />}
53+
{icon => (
54+
<TabIcon delay={0} size={props.lite ? 'xs' : 'md'} content={icon} />
55+
)}
5456
</Show>
5557
<div class={styles.tabTextContent}>{props.content}</div>
5658
</Suspense>
Lines changed: 105 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,126 @@
11
import {themeVars} from '@codeimage/ui';
2-
import {style} from '@vanilla-extract/css';
2+
import {componentStateStyles} from '@kobalte/vanilla-extract';
3+
import {keyframes, style} from '@vanilla-extract/css';
34

4-
export const tabHint = style({
5-
position: 'absolute',
6-
backgroundColor: themeVars.dynamicColors.dialog.panelBackgroundColor,
7-
boxShadow: themeVars.dynamicColors.dialog.panelShadow,
8-
borderRadius: themeVars.borderRadius.lg,
9-
zIndex: themeVars.zIndex['50'],
10-
maxHeight: '250px',
11-
overflowY: 'auto',
12-
left: 0,
13-
transition: 'all 100ms ease-in-out',
5+
const contentShow = keyframes({
6+
from: {
7+
opacity: 0,
8+
transform: 'translateY(-8px)',
9+
},
10+
to: {
11+
opacity: 1,
12+
transform: 'translateY(0)',
13+
},
1414
});
1515

16-
export const tabHintDropdownOption = style({
17-
outline: 'none',
18-
':focus': {
19-
outline: 'none',
16+
const contentHide = keyframes({
17+
from: {
18+
opacity: 1,
19+
transform: 'translateY(0px)',
2020
},
21-
':focus-visible': {
22-
outline: 'none',
21+
to: {
22+
opacity: 0,
23+
transform: 'translateY(-0)',
2324
},
2425
});
2526

26-
export const tabHintDropdownItemContent = style({
27-
height: '32px',
28-
fontWeight: themeVars.fontWeight.normal,
29-
fontSize: themeVars.fontSize.sm,
30-
display: 'flex',
31-
alignItems: 'center',
32-
padding: `0 ${themeVars.spacing['3']}`,
33-
borderBottom: `1px solid ${themeVars.dynamicColors.divider}`,
34-
color: themeVars.dynamicColors.listBox.textColor,
35-
whiteSpace: 'nowrap',
36-
cursor: 'pointer',
37-
vars: {
38-
['--highlight-color']: 'rgb(112, 182, 246, 0.25)',
27+
export const tabHint = style([
28+
{
29+
position: 'absolute',
30+
backgroundColor: themeVars.dynamicColors.dialog.panelBackgroundColor,
31+
boxShadow: themeVars.dynamicColors.dialog.panelShadow,
32+
borderRadius: themeVars.borderRadius.lg,
33+
zIndex: themeVars.zIndex['50'],
34+
maxHeight: '250px',
35+
overflowY: 'auto',
36+
left: 0,
37+
transition: 'all 200ms ease-in-out',
38+
transformOrigin: 'var(--kb-combobox-content-transform-origin)',
39+
animation: `${contentHide} 150ms ease-in forwards`,
3940
},
40-
':hover': {
41-
backgroundColor: themeVars.dynamicColors.listBox.hoverBackgroundColor,
41+
componentStateStyles({
42+
expanded: {
43+
animation: `${contentShow} 150ms ease-out`,
44+
},
45+
}),
46+
]);
47+
48+
export const listbox = style({
49+
display: 'flex',
50+
flexDirection: 'column',
51+
maxHeight: '250px',
52+
overflowY: 'auto',
53+
overflowX: 'hidden',
54+
});
55+
56+
export const tabHintDropdownItemContent = style([
57+
{
58+
height: '34px',
59+
flex: '1 0 34px',
60+
fontWeight: themeVars.fontWeight.normal,
61+
fontSize: themeVars.fontSize.sm,
62+
display: 'flex',
63+
alignItems: 'center',
64+
padding: `0 ${themeVars.spacing['3']}`,
65+
borderBottom: `1px solid ${themeVars.dynamicColors.divider}`,
4266
color: themeVars.dynamicColors.listBox.textColor,
43-
},
44-
selectors: {
45-
['[active] &']: {
46-
backgroundColor: themeVars.dynamicColors.listBox.activeBackgroundColor,
47-
color: themeVars.dynamicColors.listBox.activeTextColor,
67+
whiteSpace: 'nowrap',
68+
cursor: 'pointer',
69+
vars: {
70+
['--highlight-color']: 'rgb(112, 182, 246, 0.25)',
71+
},
72+
':hover': {
73+
backgroundColor: themeVars.dynamicColors.listBox.hoverBackgroundColor,
74+
color: themeVars.dynamicColors.listBox.textColor,
75+
},
76+
selectors: {
77+
['[active] &']: {
78+
backgroundColor: themeVars.dynamicColors.listBox.activeBackgroundColor,
79+
color: themeVars.dynamicColors.listBox.activeTextColor,
80+
},
81+
['[aria-selected=true] &']: {
82+
backgroundColor: themeVars.dynamicColors.listBox.activeBackgroundColor,
83+
color: themeVars.dynamicColors.listBox.activeTextColor,
84+
},
4885
},
49-
['[aria-selected=true] &']: {
86+
},
87+
componentStateStyles({
88+
highlighted: {
5089
backgroundColor: themeVars.dynamicColors.listBox.activeBackgroundColor,
5190
color: themeVars.dynamicColors.listBox.activeTextColor,
5291
},
53-
},
92+
}),
93+
]);
94+
95+
export const tabHintDropdownItemLabel = style({
96+
display: 'flex',
97+
alignItems: 'center',
5498
});
5599

56100
export const tabText = style([
57101
{
58102
display: 'inline-block',
59103
},
60104
]);
105+
106+
export const control = style({});
107+
108+
export const inlineHiddenItem = style({
109+
visibility: 'hidden',
110+
display: 'inline-block',
111+
height: 0,
112+
left: 0,
113+
position: 'absolute',
114+
whiteSpace: 'nowrap',
115+
wordBreak: 'keep-all',
116+
});
117+
118+
export const input = style({
119+
backgroundColor: 'transparent',
120+
color: 'inherit',
121+
appearance: 'none',
122+
outline: 'none',
123+
padding: 0,
124+
margin: 0,
125+
border: 'none',
126+
});

0 commit comments

Comments
 (0)