blob: 95198fabee9c738df891f8dd2496ba5b897aeb44 [file] [log] [blame]
Philip Zeyligere08c7ff2025-06-06 13:22:12 -07001import { css, html, LitElement } from "lit";
2import { customElement, property } from "lit/decorators.js";
3import { ConnectionStatus } from "../data";
4
5@customElement("mobile-title")
6export class MobileTitle extends LitElement {
7 @property({ type: String })
8 connectionStatus: ConnectionStatus = "disconnected";
9
10 @property({ type: Boolean })
11 isThinking = false;
12
13 static styles = css`
14 :host {
15 display: block;
16 background-color: #f8f9fa;
17 border-bottom: 1px solid #e9ecef;
18 padding: 12px 16px;
19 }
20
21 .title-container {
22 display: flex;
23 align-items: center;
24 justify-content: space-between;
25 }
26
27 .title {
28 font-size: 18px;
29 font-weight: 600;
30 color: #212529;
31 margin: 0;
32 }
33
34 .status-indicator {
35 display: flex;
36 align-items: center;
37 gap: 8px;
38 font-size: 14px;
39 }
40
41 .status-dot {
42 width: 8px;
43 height: 8px;
44 border-radius: 50%;
45 flex-shrink: 0;
46 }
47
48 .status-dot.connected {
49 background-color: #28a745;
50 }
51
52 .status-dot.connecting {
53 background-color: #ffc107;
54 animation: pulse 1.5s ease-in-out infinite;
55 }
56
57 .status-dot.disconnected {
58 background-color: #dc3545;
59 }
60
61 .thinking-indicator {
62 display: flex;
63 align-items: center;
64 gap: 6px;
65 color: #6c757d;
66 font-size: 13px;
67 }
68
69 .thinking-dots {
70 display: flex;
71 gap: 2px;
72 }
73
74 .thinking-dot {
75 width: 4px;
76 height: 4px;
77 border-radius: 50%;
78 background-color: #6c757d;
79 animation: thinking 1.4s ease-in-out infinite both;
80 }
81
82 .thinking-dot:nth-child(1) {
83 animation-delay: -0.32s;
84 }
85 .thinking-dot:nth-child(2) {
86 animation-delay: -0.16s;
87 }
88 .thinking-dot:nth-child(3) {
89 animation-delay: 0;
90 }
91
92 @keyframes pulse {
93 0%,
94 100% {
95 opacity: 1;
96 }
97 50% {
98 opacity: 0.5;
99 }
100 }
101
102 @keyframes thinking {
103 0%,
104 80%,
105 100% {
106 transform: scale(0);
107 }
108 40% {
109 transform: scale(1);
110 }
111 }
112 `;
113
114 private getStatusText() {
115 switch (this.connectionStatus) {
116 case "connected":
117 return "Connected";
118 case "connecting":
119 return "Connecting...";
120 case "disconnected":
121 return "Disconnected";
122 default:
123 return "Unknown";
124 }
125 }
126
127 render() {
128 return html`
129 <div class="title-container">
130 <h1 class="title">Sketch</h1>
131
132 <div class="status-indicator">
133 ${this.isThinking
134 ? html`
135 <div class="thinking-indicator">
136 <span>thinking</span>
137 <div class="thinking-dots">
138 <div class="thinking-dot"></div>
139 <div class="thinking-dot"></div>
140 <div class="thinking-dot"></div>
141 </div>
142 </div>
143 `
144 : html`
145 <span class="status-dot ${this.connectionStatus}"></span>
146 <span>${this.getStatusText()}</span>
147 `}
148 </div>
149 </div>
150 `;
151 }
152}