main
html 206 lines 5.85 KB
Raw
1 <script type="module">
2 import { store } from "/plugins/_goal/webui/goal-store.js";
3 </script>
4
5 <div x-data
6 class="goal-strip-root"
7 x-create="$store.goalBar.onMount()"
8 x-destroy="$store.goalBar.cleanup()">
9 <template x-if="$store.goalBar && $store.goalBar.visible">
10 <div class="goal-strip" :class="`is-${$store.goalBar.goal?.status || 'active'}`">
11 <x-icon class="goal-strip-icon" :name="$store.goalBar.statusIcon" aria-hidden="true"></x-icon>
12
13 <template x-if="!$store.goalBar.editing">
14 <div class="goal-strip-copy">
15 <span class="goal-strip-status" x-text="$store.goalBar.statusLabel"></span>
16 <span class="goal-strip-objective" x-text="$store.goalBar.goal?.objective || ''"></span>
17 <span class="goal-strip-time" x-text="`• ${$store.goalBar.elapsedLabel}`"></span>
18 </div>
19 </template>
20
21 <template x-if="$store.goalBar.editing">
22 <div class="goal-strip-edit">
23 <input class="goal-strip-input"
24 type="text"
25 x-model="$store.goalBar.draft"
26 @keydown.enter.prevent="$store.goalBar.saveEdit()"
27 @keydown.escape.prevent="$store.goalBar.cancelEdit()"
28 aria-label="Goal objective" />
29 <button type="button" class="goal-strip-action" title="Save goal" @click="$store.goalBar.saveEdit()" :disabled="$store.goalBar.saving">
30 <x-icon aria-hidden="true" name="check"></x-icon>
31 </button>
32 <button type="button" class="goal-strip-action" title="Cancel" @click="$store.goalBar.cancelEdit()" :disabled="$store.goalBar.saving">
33 <x-icon aria-hidden="true" name="close"></x-icon>
34 </button>
35 </div>
36 </template>
37
38 <div class="goal-strip-actions" x-show="!$store.goalBar.editing">
39 <button type="button" class="goal-strip-action" title="Edit goal" @click="$store.goalBar.startEdit()" :disabled="$store.goalBar.saving">
40 <x-icon aria-hidden="true" name="edit"></x-icon>
41 </button>
42 <button type="button" class="goal-strip-action"
43 :title="$store.goalBar.goal?.status === 'active' ? 'Pause goal' : 'Resume goal'"
44 @click="$store.goalBar.pauseOrResume()"
45 :disabled="$store.goalBar.saving">
46 <x-icon aria-hidden="true" :name="$store.goalBar.goal?.status === 'active' ? 'pause_circle' : 'play_circle'"></x-icon>
47 </button>
48 <button type="button" class="goal-strip-action" title="Delete goal" @click="$confirmClick($event, () => $store.goalBar.deleteGoal())" :disabled="$store.goalBar.saving">
49 <x-icon aria-hidden="true" name="delete"></x-icon>
50 </button>
51 </div>
52 </div>
53 </template>
54 </div>
55
56 <style>
57 #progress-bar-box.has-goal-bar {
58 flex-wrap: wrap;
59 row-gap: var(--spacing-xs);
60 }
61
62 #progress-bar-box.has-goal-bar .goal-strip-root {
63 flex: 0 0 100%;
64 min-width: 0;
65 display: flex;
66 width: 100%;
67 }
68
69 .goal-strip {
70 width: 100%;
71 min-height: 2rem;
72 display: flex;
73 align-items: center;
74 gap: 0.42rem;
75 padding: 0.18rem var(--spacing-sm);
76 color: var(--color-text);
77 background: transparent;
78 border: none;
79 border-radius: 0;
80 box-shadow: none;
81 }
82
83 .goal-strip-icon {
84 flex: 0 0 auto;
85 font-size: 1rem;
86 opacity: 0.75;
87 }
88
89 .goal-strip-copy {
90 min-width: 0;
91 display: flex;
92 align-items: baseline;
93 gap: 0.3rem;
94 flex: 1 1 auto;
95 overflow: hidden;
96 }
97
98 .goal-strip-status {
99 flex: 0 0 auto;
100 font-size: 0.76rem;
101 font-weight: 600;
102 }
103
104 .goal-strip-objective {
105 min-width: 0;
106 overflow: hidden;
107 text-overflow: ellipsis;
108 white-space: nowrap;
109 color: color-mix(in srgb, var(--color-text) 64%, transparent);
110 font-size: 0.76rem;
111 }
112
113 .goal-strip-time {
114 flex: 0 0 auto;
115 color: color-mix(in srgb, var(--color-text) 44%, transparent);
116 font-size: 0.76rem;
117 white-space: nowrap;
118 }
119
120 .goal-strip-actions,
121 .goal-strip-edit {
122 display: flex;
123 align-items: center;
124 gap: 0.18rem;
125 min-width: 0;
126 }
127
128 .goal-strip-edit {
129 flex: 1 1 auto;
130 }
131
132 .goal-strip-input {
133 flex: 1 1 auto;
134 min-width: 8rem;
135 height: 1.55rem;
136 padding: 0 0.35rem;
137 border: 1px solid color-mix(in srgb, var(--color-border) 82%, transparent);
138 border-radius: 6px;
139 background: color-mix(in srgb, var(--color-background) 80%, transparent);
140 color: var(--color-text);
141 font-family: var(--font-family-main, "Rubik", Arial, Helvetica, sans-serif);
142 font-size: 0.76rem;
143 outline: none;
144 }
145
146 .goal-strip-input:focus {
147 border-color: color-mix(in srgb, var(--color-text) 28%, var(--color-border));
148 }
149
150 .goal-strip-action {
151 width: 1.55rem;
152 height: 1.55rem;
153 display: inline-flex;
154 align-items: center;
155 justify-content: center;
156 padding: 0;
157 border: none;
158 border-radius: 6px;
159 background: transparent;
160 color: var(--color-text);
161 opacity: 0.68;
162 cursor: pointer;
163 }
164
165 .goal-strip-action:hover:not(:disabled) {
166 opacity: 1;
167 background: color-mix(in srgb, var(--color-border) 34%, transparent);
168 }
169
170 .goal-strip-action.confirming:not(:disabled) {
171 opacity: 1;
172 color: var(--color-warning, var(--color-text));
173 background: color-mix(in srgb, var(--color-warning, var(--color-text)) 16%, transparent);
174 }
175
176 .goal-strip-action:disabled {
177 opacity: 0.35;
178 cursor: not-allowed;
179 }
180
181 .goal-strip-action .material-symbols-outlined {
182 font-size: 1rem;
183 }
184
185 .goal-strip.is-paused .goal-strip-icon,
186 .goal-strip.is-blocked .goal-strip-icon {
187 color: var(--color-warning, var(--color-text));
188 }
189
190 .goal-strip.is-complete .goal-strip-icon {
191 color: var(--color-success, var(--color-text));
192 }
193
194 @media (max-width: 768px) {
195 .goal-strip {
196 width: 100%;
197 }
198
199 .goal-strip-status,
200 .goal-strip-objective,
201 .goal-strip-time,
202 .goal-strip-input {
203 font-size: 0.72rem;
204 }
205 }
206 </style>