spagestic commited on
Commit
3d1ce05
·
1 Parent(s): 43b2c38

TODO: fix the double scrollbar

Browse files
Files changed (2) hide show
  1. assets/app.css +197 -141
  2. ui/workspace.py +83 -84
assets/app.css CHANGED
@@ -1,141 +1,197 @@
1
- .borderless-main-workspace {
2
- align-items: stretch;
3
- gap: 12px;
4
- flex: 1 1 auto;
5
- min-height: 0;
6
- }
7
-
8
- .borderless-center-panel,
9
- .borderless-chat-panel {
10
- min-height: 70vh;
11
- }
12
-
13
- .borderless-center-panel {
14
- gap: 8px;
15
- display: flex;
16
- flex-direction: column;
17
- }
18
-
19
- .borderless-chat-panel {
20
- border-left: 1px solid rgba(148, 163, 184, 0.18);
21
- padding-left: 10px;
22
- display: flex;
23
- flex-direction: column;
24
- align-self: stretch;
25
- }
26
-
27
- .borderless-tabs {
28
- display: flex;
29
- flex-direction: column;
30
- flex: 1 1 auto;
31
- min-height: 0;
32
- height: 100%;
33
- overflow: hidden;
34
- }
35
-
36
- .borderless-tabs > .tab-wrapper {
37
- flex-shrink: 0;
38
- }
39
-
40
- .borderless-tabs .tabitem {
41
- flex: 1 1 auto;
42
- min-height: 0;
43
- display: flex;
44
- flex-direction: column;
45
- }
46
-
47
- .borderless-tabs .tabitem.borderless-form-tab {
48
- overflow-y: auto;
49
- overflow-x: hidden;
50
- overscroll-behavior: contain;
51
- }
52
-
53
- .borderless-tabs .tabitem.borderless-chat-tab {
54
- overflow: hidden;
55
- }
56
-
57
- .borderless-tabs .tabitem.borderless-chat-tab > .column {
58
- flex: 1 1 auto;
59
- min-height: 0;
60
- display: flex;
61
- flex-direction: column;
62
- }
63
-
64
- .borderless-chat-panel > :where(.gap, .block, .form, div) {
65
- display: flex;
66
- flex-direction: column;
67
- flex: 1 1 auto;
68
- min-height: 0;
69
- gap: 8px;
70
- }
71
-
72
- .borderless-form-panel {
73
- gap: 8px;
74
- }
75
-
76
- .borderless-form-panel textarea {
77
- overflow: auto;
78
- scrollbar-width: none;
79
- -ms-overflow-style: none;
80
- }
81
-
82
- .borderless-form-panel textarea::-webkit-scrollbar {
83
- display: none;
84
- }
85
-
86
- .borderless-form-hint {
87
- color: #9ca3af;
88
- font-size: 0.9rem;
89
- }
90
-
91
- .borderless-chat-panel .borderless-chat-input textarea {
92
- min-height: 6rem;
93
- resize: none;
94
- }
95
-
96
- .borderless-chat-panel textarea::-webkit-scrollbar {
97
- display: none;
98
- }
99
-
100
- .borderless-chat-panel .borderless-chatbot,
101
- .borderless-chat-panel .chatbot {
102
- flex: 1 1 auto;
103
- min-height: 52vh;
104
- }
105
-
106
- .borderless-chat-panel .chatbot-wrap,
107
- .borderless-chat-panel .bubble-wrap {
108
- flex: 1 1 auto;
109
- min-height: 52vh;
110
- }
111
-
112
- .borderless-hero h2 {
113
- margin-bottom: 0.25rem;
114
- }
115
-
116
- .borderless-hero p {
117
- max-width: 820px;
118
- color: #9ca3af;
119
- }
120
-
121
- .borderless-examples-title {
122
- margin-top: 0.35rem;
123
- font-weight: 600;
124
- }
125
-
126
- .globe-column {
127
- min-height: 70vh;
128
- }
129
-
130
- @media (max-width: 900px) {
131
- .borderless-chat-panel {
132
- border-left: 0;
133
- height: auto;
134
- min-height: 70vh;
135
- padding-left: 0;
136
- }
137
- }
138
-
139
- footer {
140
- opacity: 0.72;
141
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .borderless-main-workspace {
2
+ align-items: stretch;
3
+ gap: 12px;
4
+ flex: 1 1 auto;
5
+ min-height: 0;
6
+ }
7
+
8
+ .borderless-center-panel,
9
+ .borderless-chat-panel {
10
+ min-height: 70vh;
11
+ }
12
+
13
+ .borderless-center-panel {
14
+ gap: 8px;
15
+ display: flex;
16
+ flex-direction: column;
17
+ }
18
+
19
+ .borderless-chat-panel {
20
+ border-left: 1px solid rgba(148, 163, 184, 0.18);
21
+ padding-left: 10px;
22
+ display: flex;
23
+ flex-direction: column;
24
+ align-self: stretch;
25
+ overflow: hidden;
26
+ }
27
+
28
+ .borderless-tabs {
29
+ display: flex;
30
+ flex-direction: column;
31
+ flex: 1 1 auto;
32
+ min-height: 0;
33
+ height: 100%;
34
+ overflow: hidden;
35
+ }
36
+
37
+ .borderless-tabs > .tab-wrapper {
38
+ flex-shrink: 0;
39
+ }
40
+
41
+ .borderless-tabs .tabitem {
42
+ flex: 1 1 auto;
43
+ min-height: 0;
44
+ display: flex;
45
+ flex-direction: column;
46
+ }
47
+
48
+ .borderless-tabs .tabitem.borderless-form-tab {
49
+ overflow-y: auto;
50
+ overflow-x: hidden;
51
+ overscroll-behavior: contain;
52
+ }
53
+
54
+ .borderless-tabs .tabitem.borderless-chat-tab {
55
+ overflow: hidden;
56
+ }
57
+
58
+ .borderless-tabs .tabitem.borderless-chat-tab > .column {
59
+ flex: 1 1 auto;
60
+ min-height: 0;
61
+ display: flex;
62
+ flex-direction: column;
63
+ overflow: hidden;
64
+ background: transparent;
65
+ }
66
+
67
+ .borderless-chat-panel > :where(.gap, .block, .form, div) {
68
+ display: flex;
69
+ flex-direction: column;
70
+ flex: 1 1 auto;
71
+ min-height: 0;
72
+ gap: 8px;
73
+ overflow: hidden;
74
+ }
75
+
76
+ .borderless-form-panel {
77
+ gap: 8px;
78
+ }
79
+
80
+ .borderless-form-panel textarea {
81
+ overflow: auto;
82
+ scrollbar-width: none;
83
+ -ms-overflow-style: none;
84
+ }
85
+
86
+ .borderless-form-panel textarea::-webkit-scrollbar {
87
+ display: none;
88
+ }
89
+
90
+ .borderless-form-hint {
91
+ color: #9ca3af;
92
+ font-size: 0.9rem;
93
+ }
94
+
95
+ .borderless-chat-panel .borderless-chat-input textarea {
96
+ min-height: 4rem;
97
+ resize: none;
98
+ background: transparent;
99
+ }
100
+
101
+ .borderless-chat-panel .borderless-chat-input,
102
+ .borderless-chat-panel .borderless-chat-input :where(.wrap, .input-container) {
103
+ flex: 0 0 auto;
104
+ background: transparent !important;
105
+ scrollbar-width: none;
106
+ -ms-overflow-style: none;
107
+ }
108
+
109
+ .borderless-chat-panel textarea::-webkit-scrollbar {
110
+ display: none;
111
+ }
112
+
113
+ .borderless-chat-panel .borderless-chatbot,
114
+ .borderless-chat-panel .chatbot {
115
+ flex: 1 1 auto;
116
+ min-height: 0;
117
+ overflow: hidden;
118
+ background: transparent !important;
119
+ }
120
+
121
+ .borderless-chat-panel .chatbot-wrap {
122
+ flex: 1 1 auto;
123
+ min-height: 0;
124
+ overflow-y: auto;
125
+ overflow-x: hidden;
126
+ overscroll-behavior: contain;
127
+ scrollbar-gutter: auto;
128
+ scrollbar-width: none;
129
+ -ms-overflow-style: none;
130
+ background: transparent !important;
131
+ }
132
+
133
+ .borderless-chat-panel .borderless-chat-input::-webkit-scrollbar,
134
+ .borderless-chat-panel .chatbot-wrap::-webkit-scrollbar {
135
+ display: none;
136
+ }
137
+
138
+ .borderless-chat-panel .bubble-wrap {
139
+ flex: 0 0 auto;
140
+ min-height: auto;
141
+ margin-block: 0.35rem;
142
+ }
143
+
144
+ .borderless-chat-panel :where(
145
+ .bubble,
146
+ .message,
147
+ .message-wrap,
148
+ .message-content,
149
+ .md,
150
+ .prose
151
+ ) {
152
+ max-height: none !important;
153
+ overflow-y: visible !important;
154
+ scrollbar-width: none;
155
+ }
156
+
157
+ .borderless-chat-panel :where(
158
+ .bubble,
159
+ .message,
160
+ .message-wrap,
161
+ .message-content,
162
+ .md,
163
+ .prose
164
+ )::-webkit-scrollbar {
165
+ display: none;
166
+ }
167
+
168
+ .borderless-hero h2 {
169
+ margin-bottom: 0.25rem;
170
+ }
171
+
172
+ .borderless-hero p {
173
+ max-width: 820px;
174
+ color: #9ca3af;
175
+ }
176
+
177
+ .borderless-examples-title {
178
+ margin-top: 0.35rem;
179
+ font-weight: 600;
180
+ }
181
+
182
+ .globe-column {
183
+ min-height: 70vh;
184
+ }
185
+
186
+ @media (max-width: 900px) {
187
+ .borderless-chat-panel {
188
+ border-left: 0;
189
+ height: auto;
190
+ min-height: 70vh;
191
+ padding-left: 0;
192
+ }
193
+ }
194
+
195
+ footer {
196
+ opacity: 0.72;
197
+ }
ui/workspace.py CHANGED
@@ -1,84 +1,83 @@
1
- # ui/workspace.py
2
- import gradio as gr
3
-
4
- from ui.agent import respond
5
- from ui.agent.system_prompt import BORDERLESS_SYSTEM_PROMPT
6
- from ui.chat.defaults import DEFAULT_MAX_TOKENS, DEFAULT_TEMPERATURE, DEFAULT_TOP_P
7
- from ui.chat.panel import SidebarChatInterface
8
- from ui.globe import render_globe_panel
9
- from ui.globe_commands import empty_globe_state
10
- from ui.intake import render_intake_panel
11
-
12
-
13
- def create_main_workspace(
14
- history_container: gr.Column | None = None,
15
- ) -> gr.ChatInterface:
16
- """
17
- Compose the main workspace: globe panel, intake form tab, and chat tab.
18
- """
19
- globe_state = gr.JSON(value=empty_globe_state(), visible=False, elem_id="globe-state")
20
- chat_input = gr.MultimodalTextbox(
21
- show_label=False,
22
- placeholder="Create a prompt from the form, choose a demo, or type directly...",
23
- file_count="multiple",
24
- sources=["upload"],
25
- lines=3,
26
- max_lines=12,
27
- elem_classes=["borderless-chat-input"],
28
- render=False,
29
- )
30
-
31
- with gr.Row(elem_classes=["borderless-main-workspace"], equal_height=True):
32
- with gr.Column(
33
- scale=7,
34
- min_width=520,
35
- elem_classes=["borderless-center-panel"],
36
- ):
37
- gr.Markdown(
38
- "## Borderless\n"
39
- "Describe your background once. The agent researches official sources, compares realistic pathways, and suggests countries to migrate to.",
40
- elem_classes=["borderless-hero"],
41
- )
42
- globe_column = gr.Column(elem_classes=["globe-column"])
43
- with globe_column:
44
- render_globe_panel(height="70vh")
45
-
46
- with gr.Column(
47
- scale=4,
48
- min_width=360,
49
- elem_classes=["borderless-chat-panel"],
50
- ):
51
- with gr.Tabs(elem_classes=["borderless-tabs"]) as workspace_tabs:
52
- with gr.Tab("Form", elem_classes=["borderless-form-tab"]):
53
- render_intake_panel(chat_input, workspace_tabs)
54
- with gr.Tab("Chat", id="chat", elem_classes=["borderless-chat-tab"]):
55
- chat = SidebarChatInterface(
56
- respond,
57
- multimodal=True,
58
- chatbot=gr.Chatbot(
59
- height="52vh",
60
- show_label=False,
61
- container=False,
62
- elem_classes=["borderless-chatbot"],
63
- ),
64
- textbox=chat_input,
65
- history_container=history_container,
66
- fill_height=True,
67
- additional_inputs=[
68
- gr.State(BORDERLESS_SYSTEM_PROMPT),
69
- gr.State(DEFAULT_MAX_TOKENS),
70
- gr.State(DEFAULT_TEMPERATURE),
71
- gr.State(DEFAULT_TOP_P),
72
- globe_state,
73
- ],
74
- additional_outputs=[globe_state],
75
- )
76
-
77
- globe_state.change(
78
- fn=None,
79
- inputs=[globe_state],
80
- outputs=[],
81
- js="(state) => { window.BorderlessGlobe?.applyState(state); return []; }",
82
- queue=False,
83
- )
84
- return chat
 
1
+ # ui/workspace.py
2
+ import gradio as gr
3
+
4
+ from ui.agent import respond
5
+ from ui.agent.system_prompt import BORDERLESS_SYSTEM_PROMPT
6
+ from ui.chat.defaults import DEFAULT_MAX_TOKENS, DEFAULT_TEMPERATURE, DEFAULT_TOP_P
7
+ from ui.chat.panel import SidebarChatInterface
8
+ from ui.globe import render_globe_panel
9
+ from ui.globe_commands import empty_globe_state
10
+ from ui.intake import render_intake_panel
11
+
12
+
13
+ def create_main_workspace(
14
+ history_container: gr.Column | None = None,
15
+ ) -> gr.ChatInterface:
16
+ """
17
+ Compose the main workspace: globe panel, intake form tab, and chat tab.
18
+ """
19
+ globe_state = gr.JSON(value=empty_globe_state(), visible=False, elem_id="globe-state")
20
+ chat_input = gr.MultimodalTextbox(
21
+ show_label=False,
22
+ placeholder="Create a prompt from the form, choose a demo, or type directly...",
23
+ file_count="multiple",
24
+ sources=["upload"],
25
+ lines=3,
26
+ max_lines=12,
27
+ elem_classes=["borderless-chat-input"],
28
+ render=False,
29
+ )
30
+
31
+ with gr.Row(elem_classes=["borderless-main-workspace"], equal_height=True):
32
+ with gr.Column(
33
+ scale=7,
34
+ min_width=520,
35
+ elem_classes=["borderless-center-panel"],
36
+ ):
37
+ gr.Markdown(
38
+ "## Borderless\n"
39
+ "Describe your background once. The agent researches official sources, compares realistic pathways, and suggests countries to migrate to.",
40
+ elem_classes=["borderless-hero"],
41
+ )
42
+ globe_column = gr.Column(elem_classes=["globe-column"])
43
+ with globe_column:
44
+ render_globe_panel(height="70vh")
45
+
46
+ with gr.Column(
47
+ scale=4,
48
+ min_width=360,
49
+ elem_classes=["borderless-chat-panel"],
50
+ ):
51
+ with gr.Tabs(elem_classes=["borderless-tabs"]) as workspace_tabs:
52
+ with gr.Tab("Form", elem_classes=["borderless-form-tab"]):
53
+ render_intake_panel(chat_input, workspace_tabs)
54
+ with gr.Tab("Chat", id="chat", elem_classes=["borderless-chat-tab"]):
55
+ chat = SidebarChatInterface(
56
+ respond,
57
+ multimodal=True,
58
+ chatbot=gr.Chatbot(
59
+ show_label=False,
60
+ container=False,
61
+ elem_classes=["borderless-chatbot"],
62
+ ),
63
+ textbox=chat_input,
64
+ history_container=history_container,
65
+ fill_height=True,
66
+ additional_inputs=[
67
+ gr.State(BORDERLESS_SYSTEM_PROMPT),
68
+ gr.State(DEFAULT_MAX_TOKENS),
69
+ gr.State(DEFAULT_TEMPERATURE),
70
+ gr.State(DEFAULT_TOP_P),
71
+ globe_state,
72
+ ],
73
+ additional_outputs=[globe_state],
74
+ )
75
+
76
+ globe_state.change(
77
+ fn=None,
78
+ inputs=[globe_state],
79
+ outputs=[],
80
+ js="(state) => { window.BorderlessGlobe?.applyState(state); return []; }",
81
+ queue=False,
82
+ )
83
+ return chat