Apply supplied SVG branding and polish device settings
This commit is contained in:
@@ -40,6 +40,7 @@ import { version as appVersion } from '../package.json';
|
||||
import AccountPanel from './AccountPanel.vue';
|
||||
import SendComposer from './SendComposer.vue';
|
||||
import InstallButton from './InstallButton.vue';
|
||||
import LogoMark from './LogoMark.vue';
|
||||
import { createNearbySearch } from './nearbySearch';
|
||||
import { useVisibleViewport } from './viewport';
|
||||
useVisibleViewport();
|
||||
@@ -631,7 +632,7 @@ async function spaceAction(space, action, memberId) {
|
||||
<header class="site-header">
|
||||
<div class="header-brand">
|
||||
<button class="wordmark" @click="tab = 'devices'" aria-label="hop. 홈">
|
||||
hop<span>.</span>
|
||||
<LogoMark />
|
||||
</button>
|
||||
<span class="header-tagline">기기 사이를 가볍게.</span>
|
||||
</div>
|
||||
@@ -1129,7 +1130,7 @@ async function spaceAction(space, action, memberId) {
|
||||
</template>
|
||||
<template v-else-if="modal === 'about'">
|
||||
<div class="service-info">
|
||||
<strong class="service-brand">hop.</strong>
|
||||
<LogoMark class="service-brand" label="hop." />
|
||||
<p class="service-tagline">기기 사이를 가볍게.</p>
|
||||
<div class="service-intro">
|
||||
<p>Android, iOS, macOS, Windows.</p>
|
||||
@@ -1171,17 +1172,28 @@ async function spaceAction(space, action, memberId) {
|
||||
aria-label="기기 이름"
|
||||
maxlength="40"
|
||||
required /></label
|
||||
><button class="button primary" :disabled="busy" aria-label="이름 저장">
|
||||
이름 저장
|
||||
</button>
|
||||
><button class="button primary" :disabled="busy" aria-label="저장">저장</button>
|
||||
</form>
|
||||
<label class="settings-row discovery-setting"
|
||||
><span>다른 기기에서 발견 허용</span
|
||||
><input
|
||||
type="checkbox"
|
||||
:checked="device?.discoverable"
|
||||
:disabled="busy"
|
||||
@change="act(() => patchDevice({ discoverable: $event.target.checked }))" /></label
|
||||
<label class="settings-row discovery-setting">
|
||||
<span>다른 기기에서 발견 허용</span>
|
||||
<span class="relative inline-flex h-6 w-11 shrink-0 items-center">
|
||||
<input
|
||||
class="peer absolute inset-0 m-0 h-full w-full cursor-pointer opacity-0"
|
||||
type="checkbox"
|
||||
role="switch"
|
||||
:checked="device?.discoverable"
|
||||
:disabled="busy"
|
||||
@change="act(() => patchDevice({ discoverable: $event.target.checked }))"
|
||||
/>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="pointer-events-none absolute inset-0 rounded-full bg-[var(--line)] transition-colors motion-reduce:transition-none peer-checked:bg-[var(--ink)] peer-focus-visible:outline-2 peer-focus-visible:outline-offset-4 peer-focus-visible:outline-[var(--ink)] peer-disabled:opacity-50"
|
||||
></span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="pointer-events-none absolute left-0.5 top-0.5 size-5 rounded-full bg-[var(--surface)] shadow-sm transition-transform motion-reduce:transition-none peer-checked:translate-x-5 peer-disabled:opacity-50"
|
||||
></span>
|
||||
</span> </label
|
||||
></template>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
20
apps/web/src/LogoMark.vue
Normal file
20
apps/web/src/LogoMark.vue
Normal file
@@ -0,0 +1,20 @@
|
||||
<script setup>
|
||||
import { useId } from 'vue';
|
||||
import source from '../public/logo.svg?raw';
|
||||
defineProps({ label: String });
|
||||
const instance = useId();
|
||||
// A fixed repository asset, not user/API HTML. Keep each SVG's clip IDs unique.
|
||||
const markup = source
|
||||
.replace(/fill="(?:white|#fff|#ffffff)"/gi, 'fill="currentColor"')
|
||||
.replace(/\bid="([^"]+)"/g, (_, id) => `id="${id}-${instance}"`)
|
||||
.replace(/url\(#([^)]+)\)/g, (_, id) => `url(#${id}-${instance})`);
|
||||
</script>
|
||||
<template>
|
||||
<span
|
||||
class="brand-logo"
|
||||
:role="label ? 'img' : undefined"
|
||||
:aria-label="label"
|
||||
:aria-hidden="label ? undefined : 'true'"
|
||||
v-html="markup"
|
||||
></span>
|
||||
</template>
|
||||
@@ -116,17 +116,14 @@ button:active:not(:disabled) {
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
.wordmark {
|
||||
font-size: 43px;
|
||||
font-weight: 750;
|
||||
letter-spacing: -3.5px;
|
||||
display: block;
|
||||
width: 64px;
|
||||
height: 32px;
|
||||
border: 0;
|
||||
background: none;
|
||||
padding: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
.wordmark span {
|
||||
color: var(--brand);
|
||||
}
|
||||
.desktop-nav {
|
||||
display: flex;
|
||||
gap: 34px;
|
||||
@@ -1257,9 +1254,6 @@ h1 span {
|
||||
height: 80px;
|
||||
gap: 0;
|
||||
}
|
||||
.wordmark {
|
||||
font-size: 37px;
|
||||
}
|
||||
.desktop-nav {
|
||||
display: none;
|
||||
}
|
||||
@@ -2893,9 +2887,6 @@ a.button {
|
||||
.site-header {
|
||||
gap: 18px;
|
||||
}
|
||||
.site-header .wordmark {
|
||||
font-size: 32px;
|
||||
}
|
||||
.header-brand {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
@@ -3035,7 +3026,8 @@ a.button {
|
||||
gap: 10px;
|
||||
}
|
||||
.site-header .wordmark {
|
||||
font-size: 28px;
|
||||
width: 56px;
|
||||
height: 28px;
|
||||
}
|
||||
.device-footer {
|
||||
align-items: flex-start;
|
||||
@@ -3447,8 +3439,9 @@ a.button {
|
||||
font-size: 13px;
|
||||
}
|
||||
.service-brand {
|
||||
font-size: 30px;
|
||||
letter-spacing: -0.07em;
|
||||
display: block;
|
||||
width: 64px;
|
||||
height: 32px;
|
||||
}
|
||||
.service-info p {
|
||||
margin: 0;
|
||||
@@ -3500,3 +3493,48 @@ a.button {
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.brand-logo {
|
||||
display: block;
|
||||
color: var(--ink);
|
||||
}
|
||||
.wordmark .brand-logo {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.brand-logo svg {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.modal .device-settings-form {
|
||||
height: auto;
|
||||
align-items: flex-end;
|
||||
}
|
||||
.modal .device-settings-form input,
|
||||
.modal .device-settings-form .button {
|
||||
height: 44px;
|
||||
min-height: 44px;
|
||||
border-radius: 12px;
|
||||
padding: 8px 12px;
|
||||
}
|
||||
.modal .device-settings-form .button {
|
||||
min-width: 72px;
|
||||
}
|
||||
.modal .device-settings-form input:focus-visible {
|
||||
outline-offset: -2px;
|
||||
}
|
||||
.modal .discovery-setting {
|
||||
border: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.modal .discovery-setting input {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
@media (max-width: 639px) {
|
||||
.modal .device-settings-form {
|
||||
align-items: stretch;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user