@@ -28,10 +28,7 @@ struct ChatWindowView: View {
2828 }
2929 ) { viewStore in
3030 VStack ( spacing: 0 ) {
31- RoundedRectangle ( cornerRadius: 2 )
32- . fill ( . tertiary)
33- . frame ( width: 120 , height: 4 )
34- . frame ( height: 16 )
31+ ChatTitleBar ( store: store)
3532
3633 Divider ( )
3734
@@ -43,23 +40,6 @@ struct ChatWindowView: View {
4340 ChatTabContainer ( store: store)
4441 . frame ( maxWidth: . infinity, maxHeight: . infinity)
4542 }
46- . background {
47- Button ( action: {
48- viewStore. send ( . hideButtonClicked)
49- } ) {
50- EmptyView ( )
51- }
52- . opacity ( 0 )
53- . keyboardShortcut ( " M " , modifiers: [ . command] )
54-
55- Button ( action: {
56- viewStore. send ( . closeActiveTabClicked)
57- } ) {
58- EmptyView ( )
59- }
60- . opacity ( 0 )
61- . keyboardShortcut ( " W " , modifiers: [ . command] )
62- }
6343 . background ( . regularMaterial)
6444 . xcodeStyleFrame ( )
6545 . opacity ( viewStore. state. isPanelDisplayed ? 1 : 0 )
@@ -69,6 +49,88 @@ struct ChatWindowView: View {
6949 }
7050}
7151
52+ struct ChatTitleBar : View {
53+ let store : StoreOf < ChatPanelFeature >
54+ @State var isHovering = false
55+
56+ var body : some View {
57+ HStack ( spacing: 4 ) {
58+ Button ( action: {
59+ store. send ( . hideButtonClicked)
60+ } ) {
61+ Circle ( )
62+ . fill ( Color ( nsColor: . systemRed) )
63+ . frame ( width: 10 , height: 10 )
64+ . overlay {
65+ Circle ( ) . strokeBorder ( . secondary. opacity ( 0.3 ) , lineWidth: 1 )
66+ }
67+ . overlay {
68+ if isHovering {
69+ Image ( systemName: " xmark " )
70+ . resizable ( )
71+ . foregroundStyle ( . secondary)
72+ . font ( Font . title. weight ( . heavy) )
73+ . frame ( width: 5 , height: 5 )
74+ }
75+ }
76+ }
77+
78+ WithViewStore ( store, observe: { $0. chatPanelInASeparateWindow } ) { viewStore in
79+ if viewStore. state {
80+ Button ( action: {
81+ store. send ( . attachChatPanel)
82+ } ) {
83+ Circle ( )
84+ . fill ( . indigo)
85+ . frame ( width: 10 , height: 10 )
86+ . overlay {
87+ Circle ( ) . strokeBorder ( . secondary. opacity ( 0.3 ) , lineWidth: 1 )
88+ }
89+ . overlay {
90+ if isHovering {
91+ Image ( systemName: " pin " )
92+ . resizable ( )
93+ . foregroundStyle ( . secondary)
94+ . font ( Font . title. weight ( . heavy) )
95+ . frame ( width: 5 , height: 5 )
96+ }
97+ }
98+ }
99+ }
100+ }
101+
102+ Button ( action: {
103+ store. send ( . closeActiveTabClicked)
104+ } ) {
105+ EmptyView ( )
106+ }
107+ . opacity ( 0 )
108+ . keyboardShortcut ( " W " , modifiers: [ . command] )
109+
110+ Spacer ( )
111+ }
112+ . buttonStyle ( . plain)
113+ . overlay {
114+ RoundedRectangle ( cornerRadius: 2 )
115+ . fill ( . tertiary)
116+ . frame ( width: 120 , height: 4 )
117+ . background {
118+ if isHovering {
119+ RoundedRectangle ( cornerRadius: 6 )
120+ . fill ( . tertiary. opacity ( 0.3 ) )
121+ . frame ( width: 128 , height: 12 )
122+ }
123+ }
124+ }
125+ . padding ( . horizontal, 6 )
126+ . frame ( maxWidth: . infinity)
127+ . frame ( height: 16 )
128+ . onHover ( perform: { hovering in
129+ isHovering = hovering
130+ } )
131+ }
132+ }
133+
72134private extension View {
73135 func hideScrollIndicator( ) -> some View {
74136 if #available( macOS 13 . 0 , * ) {
0 commit comments