fix: edit nav UI + extract translations

scarlett
NGPixel 2 weeks ago
parent f985f041d0
commit 8ff4a3e62d
No known key found for this signature in database

@ -1888,9 +1888,9 @@
"editor.redirect.pageTitle": "Redirect Title", "editor.redirect.pageTitle": "Redirect Title",
"editor.redirect.pageTitleHint": "The name this page appears under in navigation and in the file manager.", "editor.redirect.pageTitleHint": "The name this page appears under in navigation and in the file manager.",
"editor.redirect.pickerTitle": "Select Redirection Target", "editor.redirect.pickerTitle": "Select Redirection Target",
"editor.redirect.showInTreeHint": "List this redirection in the site's browse menu. Off keeps it out, which is usually what a doorway left behind for an old path should do. It is listed in the file manager either way.",
"editor.redirect.showInterstitial": "Show Interstitial", "editor.redirect.showInterstitial": "Show Interstitial",
"editor.redirect.showInterstitialHint": "Show a short notice saying where the reader is going before taking them there. Off sends them straight on.", "editor.redirect.showInterstitialHint": "Show a short notice saying where the reader is going before taking them there. Off sends them straight on.",
"editor.redirect.showInTreeHint": "List this redirection in the site's browse menu. Off keeps it out, which is usually what a doorway left behind for an old path should do. It is listed in the file manager either way.",
"editor.redirect.summaryDirect": "Readers arriving at this page are sent to {target} right away.", "editor.redirect.summaryDirect": "Readers arriving at this page are sent to {target} right away.",
"editor.redirect.summaryIncomplete": "This redirection has no target yet, and cannot be saved until it does.", "editor.redirect.summaryIncomplete": "This redirection has no target yet, and cannot be saved until it does.",
"editor.redirect.summaryInterstitial": "Readers arriving at this page are told they are being sent to {target}, then taken there a few seconds later.", "editor.redirect.summaryInterstitial": "Readers arriving at this page are told they are being sent to {target}, then taken there a few seconds later.",
@ -2198,6 +2198,20 @@
"navEdit.label": "Label", "navEdit.label": "Label",
"navEdit.labelHint": "Text to display on the menu item.", "navEdit.labelHint": "Text to display on the menu item.",
"navEdit.link": "Link", "navEdit.link": "Link",
"navEdit.modeHide": "Hide Current + Descendants",
"navEdit.modeHideExact": "Hide Current Only",
"navEdit.modeHideExactHint": "Completely hide the site navigation sidebar only for this path.",
"navEdit.modeHideHint": "Completely hide the site navigation sidebar for this path and all descendants.",
"navEdit.modeInherit": "Inherit",
"navEdit.modeInheritHint": "Use the menu items and settings from the parent path.",
"navEdit.modeOverride": "Override Current + Descendants",
"navEdit.modeOverrideExact": "Override Current Only",
"navEdit.modeOverrideExactHint": "Set menu items and settings only for this path.",
"navEdit.modeOverrideHint": "Set menu items and settings for this path and all descendants.",
"navEdit.modeRootHide": "Hide",
"navEdit.modeRootHideHint": "Completely hide the left sidebar navigation.",
"navEdit.modeRootShow": "Show",
"navEdit.modeRootShowHint": "Show the left sidebar navigation menu items.",
"navEdit.nestItem": "Nest Item", "navEdit.nestItem": "Nest Item",
"navEdit.nestingWarn": "The previous menu item must be a normal link or another nested link. Invalid nested items will be shown in red.", "navEdit.nestingWarn": "The previous menu item must be a normal link or another nested link. Invalid nested items will be shown in red.",
"navEdit.noSelection": "Select a menu item from the left to start editing.", "navEdit.noSelection": "Select a menu item from the left to start editing.",

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="96px" height="96px"><path fill="#199be2" d="M35.983,32.448l-3.536,3.536l7.87,7.87c0.195,0.195,0.512,0.195,0.707,0l2.828-2.828 c0.195-0.195,0.195-0.512,0-0.707L35.983,32.448z"/><radialGradient id="jfxEe3fHLI4QQCvReOTNsa" cx="20.024" cy="505.904" r="19.604" gradientTransform="matrix(1 0 0 -1 0 526)" gradientUnits="userSpaceOnUse"><stop offset=".693" stop-color="#006185"/><stop offset=".921" stop-color="#35c1f1"/></radialGradient><polygon fill="url(#jfxEe3fHLI4QQCvReOTNsa)" points="31.601,28.065 28.065,31.601 32.448,35.983 35.983,32.448"/><linearGradient id="jfxEe3fHLI4QQCvReOTNsb" x1="8.911" x2="31.339" y1="517.089" y2="494.661" gradientTransform="matrix(1 0 0 -1 0 526)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#a3ffff"/><stop offset=".223" stop-color="#9dfbff"/><stop offset=".53" stop-color="#8bf1ff"/><stop offset=".885" stop-color="#6ee0ff"/><stop offset="1" stop-color="#63daff"/></linearGradient><circle cx="20" cy="20" r="16" fill="url(#jfxEe3fHLI4QQCvReOTNsb)"/><linearGradient id="jfxEe3fHLI4QQCvReOTNsc" x1="10" x2="14" y1="20" y2="20" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#3079d6"/><stop offset="1" stop-color="#297cd2"/></linearGradient><circle cx="12" cy="20" r="2" fill="url(#jfxEe3fHLI4QQCvReOTNsc)"/><linearGradient id="jfxEe3fHLI4QQCvReOTNsd" x1="18" x2="22" y1="20" y2="20" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#3079d6"/><stop offset="1" stop-color="#297cd2"/></linearGradient><circle cx="20" cy="20" r="2" fill="url(#jfxEe3fHLI4QQCvReOTNsd)"/><linearGradient id="jfxEe3fHLI4QQCvReOTNse" x1="26" x2="30" y1="20" y2="20" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#3079d6"/><stop offset="1" stop-color="#297cd2"/></linearGradient><circle cx="28" cy="20" r="2" fill="url(#jfxEe3fHLI4QQCvReOTNse)"/></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@ -85,7 +85,7 @@
<div class="searchpanel-header"> <div class="searchpanel-header">
<span>Popular Tags</span> <span>Popular Tags</span>
<w-space /> <w-space />
<w-btn class="acrylic-btn" flat label="View All" rounded size="xs" /> <w-btn class="acrylic-btn" flat label="View All" size="xs" />
</div> </div>
<div class="mb-4 flex flex-wrap gap-1"> <div class="mb-4 flex flex-wrap gap-1">
<w-chip <w-chip
@ -103,17 +103,19 @@
</div> </div>
</template> </template>
<div class="searchpanel-header">Search Operators</div> <div class="searchpanel-header">Search Operators</div>
<div class="searchpanel-tip"> <div class="searchpanel-tips">
<code>!foo</code> or <code>-bar</code> to exclude "foo" and "bar". <div class="searchpanel-tip">
</div> <code>!foo</code> or <code>-bar</code> to exclude "foo" and "bar".
<div class="searchpanel-tip"> </div>
<code>bana*</code> for to match any term starting with "bana" (e.g. banana). <div class="searchpanel-tip">
</div> <code>foo*</code> to match any term starting with "foo".
<div class="searchpanel-tip"> </div>
<code>foo,bar</code> or <code>foo|bar</code> to search for "foo" OR "bar". <div class="searchpanel-tip">
</div> <code>foo,bar</code> or <code>foo|bar</code> to search for "foo" OR "bar".
<div class="searchpanel-tip"> </div>
<code>"foo bar"</code> to match exactly the phrase "foo bar". <div class="searchpanel-tip">
<code>"foo bar"</code> to match exactly the phrase "foo bar".
</div>
</div> </div>
</div> </div>
</div> </div>
@ -270,6 +272,17 @@ defineExpose({ focus })
</script> </script>
<style lang="scss"> <style lang="scss">
/*
Where the operator tips fall back to a single column. This panel's own threshold rather than one of
the app's `--breakpoint-*`: the panel is as wide as the search field, which is whatever the header
has left over after the site title and its buttons -- so it only has room for two columns of tips
on a very wide window. Stated as a `max` value just under 2000px, the way the shared ones are.
*/
$tips-single-column-max: 1999.98px;
/* The gap between a panel title and the rule under it, which the View All button has to cancel. */
$searchpanel-header-gap: 0.15rem;
/* /*
The header search box. The header search box.
@ -402,23 +415,73 @@ defineExpose({ focus })
&-header { &-header {
font-weight: 500; font-weight: 500;
border-bottom: 1px solid rgba(255, 255, 255, 0.2); border-bottom: 1px solid rgba(255, 255, 255, 0.2);
padding: 0 0 0.5rem 0; padding: 0 0 $searchpanel-header-gap 0;
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
display: flex; display: flex;
align-items: center; align-items: center;
/*
View All sits ON the rule rather than above it: it gives back the title's bottom gap and squares
its lower corners, so the button's own edge and the rule read as one line -- a tab on the rule
rather than a pill floating over it. Hence no `rounded` prop on the button either: all four
corners are this rule's to set, and a pill's 28px would fight the two it keeps.
`flex-end` rather than the header's `center` because the negative margin shrinks the button's
outer box -- centred, half of it would be taken up by the centring and the button would come to
rest short of the rule.
*/
.acrylic-btn {
align-self: flex-end;
margin-bottom: -$searchpanel-header-gap;
border-radius: 5px 5px 0 0;
}
} }
&-tip { /*
+ .searchpanel-tip { The separator is a pseudo-element on the grid rather than a border on the right-hand column: with
margin-top: 0.5rem; a row gap between the tips, a per-cell border would come out as one dash per row instead of a
single line down the middle of the gutter.
*/
&-tips {
position: relative;
display: grid;
grid-template-columns: 1fr 1fr;
column-gap: 1.5rem;
row-gap: 0.35rem;
&::before {
content: '';
position: absolute;
top: 0;
bottom: 0;
left: calc(50% - 0.5px);
width: 1px;
background-color: rgba(255, 255, 255, 0.15);
}
/* Below 2000px the tips stack, and the separator has nothing left to separate. */
@media (max-width: $tips-single-column-max) {
grid-template-columns: 1fr;
&::before {
content: none;
}
} }
} }
&-tip {
font-size: 0.75rem;
line-height: 1.4;
}
/*
Colour alone rather than a chip: the tips are one line each and mostly operator, so a filled
background on every other word made the column read as a row of buttons. `primary-lighter` and
not `primary` because the panel is a wash of black in either theme -- the mid-tone is picked to
read on white, and even the heading shade is dim at this size.
*/
code { code {
background-color: rgba(0, 0, 0, 0.7); color: var(--color-primary-lighter);
padding: 2px 8px;
font-weight: 700;
border-radius: 4px;
} }
} }
</style> </style>

@ -9,15 +9,15 @@
<w-item tag="label"> <w-item tag="label">
<w-item-section side><w-radio v-model="state.mode" val="inherit" /></w-item-section> <w-item-section side><w-radio v-model="state.mode" val="inherit" /></w-item-section>
<w-item-section> <w-item-section>
<w-item-label>Show</w-item-label> <w-item-label>{{ t(`navEdit.modeRootShow`) }}</w-item-label>
<w-item-label caption>Show the left sidebar navigaiton menu items.</w-item-label> <w-item-label caption>{{ t(`navEdit.modeRootShowHint`) }}</w-item-label>
</w-item-section> </w-item-section>
</w-item> </w-item>
<w-item tag="label"> <w-item tag="label">
<w-item-section side><w-radio v-model="state.mode" val="hide" /></w-item-section> <w-item-section side><w-radio v-model="state.mode" val="hide" /></w-item-section>
<w-item-section> <w-item-section>
<w-item-label>Hide</w-item-label> <w-item-label>{{ t(`navEdit.modeRootHide`) }}</w-item-label>
<w-item-label caption>Completely hide the left sidebar navigation.</w-item-label> <w-item-label caption>{{ t(`navEdit.modeRootHideHint`) }}</w-item-label>
</w-item-section> </w-item-section>
</w-item> </w-item>
</template> </template>
@ -25,36 +25,36 @@
<w-item tag="label"> <w-item tag="label">
<w-item-section side><w-radio v-model="state.mode" val="inherit" /></w-item-section> <w-item-section side><w-radio v-model="state.mode" val="inherit" /></w-item-section>
<w-item-section> <w-item-section>
<w-item-label>Inherit</w-item-label> <w-item-label>{{ t(`navEdit.modeInherit`) }}</w-item-label>
<w-item-label caption>Use the menu items and settings from the parent path.</w-item-label> <w-item-label caption>{{ t(`navEdit.modeInheritHint`) }}</w-item-label>
</w-item-section> </w-item-section>
</w-item> </w-item>
<w-item tag="label"> <w-item tag="label">
<w-item-section side><w-radio v-model="state.mode" val="override" /></w-item-section> <w-item-section side><w-radio v-model="state.mode" val="override" /></w-item-section>
<w-item-section> <w-item-section>
<w-item-label>Override Current + Descendants</w-item-label> <w-item-label>{{ t(`navEdit.modeOverride`) }}</w-item-label>
<w-item-label caption>Set menu items and settings for this path and all descendants.</w-item-label> <w-item-label caption>{{ t(`navEdit.modeOverrideHint`) }}</w-item-label>
</w-item-section> </w-item-section>
</w-item> </w-item>
<w-item tag="label"> <w-item tag="label">
<w-item-section side><w-radio v-model="state.mode" val="overrideExact" /></w-item-section> <w-item-section side><w-radio v-model="state.mode" val="overrideExact" /></w-item-section>
<w-item-section> <w-item-section>
<w-item-label>Override Current Only</w-item-label> <w-item-label>{{ t(`navEdit.modeOverrideExact`) }}</w-item-label>
<w-item-label caption>Set menu items and settings only for this path.</w-item-label> <w-item-label caption>{{ t(`navEdit.modeOverrideExactHint`) }}</w-item-label>
</w-item-section> </w-item-section>
</w-item> </w-item>
<w-item tag="label"> <w-item tag="label">
<w-item-section side><w-radio v-model="state.mode" val="hide" /></w-item-section> <w-item-section side><w-radio v-model="state.mode" val="hide" /></w-item-section>
<w-item-section> <w-item-section>
<w-item-label>Hide Current + Descendants</w-item-label> <w-item-label>{{ t(`navEdit.modeHide`) }}</w-item-label>
<w-item-label caption>Completely hide the left sidebar navigation for this path and all descendants.</w-item-label> <w-item-label caption>{{ t(`navEdit.modeHideHint`) }}</w-item-label>
</w-item-section> </w-item-section>
</w-item> </w-item>
<w-item tag="label"> <w-item tag="label">
<w-item-section side><w-radio v-model="state.mode" val="hideExact" /></w-item-section> <w-item-section side><w-radio v-model="state.mode" val="hideExact" /></w-item-section>
<w-item-section> <w-item-section>
<w-item-label>Hide Current Only</w-item-label> <w-item-label>{{ t(`navEdit.modeHideExact`) }}</w-item-label>
<w-item-label caption>Completely hide the left sidebar navigation only for this path.</w-item-label> <w-item-label caption>{{ t(`navEdit.modeHideExactHint`) }}</w-item-label>
</w-item-section> </w-item-section>
</w-item> </w-item>
</template> </template>
@ -214,7 +214,7 @@ async function save() {
}).json() }).json()
// -> The API client does not throw on 400, so a refusal comes back as a parsed error // -> The API client does not throw on 400, so a refusal comes back as a parsed error
if (resp?.ok === false) { if (resp?.ok === false) {
throw new Error(resp.message || 'An unexpected error occured.') throw new Error(resp.message || t(`common.error.unexpected`))
} }
notify({ notify({
type: 'positive', type: 'positive',

@ -1,7 +1,7 @@
<template> <template>
<div <div
class="w-bar flex w-full flex-nowrap items-center" class="w-bar flex w-full flex-nowrap items-center"
:class="dense ? 'w-bar--dense' : 'w-bar--standard'"> :class="[dense ? 'w-bar--dense' : 'w-bar--standard', { 'w-bar--flush': flush }]">
<slot /> <slot />
</div> </div>
</template> </template>
@ -13,11 +13,18 @@
* Metrics taken from Quasar's own variables so migrated chrome keeps its exact size: * Metrics taken from Quasar's own variables so migrated chrome keeps its exact size:
* standard height 32px (16px inner font x2), padding 0 12px, font-size 18px, buttons 11px * standard height 32px (16px inner font x2), padding 0 12px, font-size 18px, buttons 11px
* dense height 24px (14px + 10), padding 0 8px, font-size 14px, buttons 8px * dense height 24px (14px + 10), padding 0 8px, font-size 14px, buttons 8px
*
* `flush` drops the side padding, for a bar whose contents are meant to reach its edges -- a single
* full-width button rather than a row of controls inset from the sides.
*/ */
defineProps({ defineProps({
dense: { dense: {
type: Boolean, type: Boolean,
default: false default: false
},
flush: {
type: Boolean,
default: false
} }
}) })
</script> </script>
@ -39,6 +46,12 @@ defineProps({
font-size: 14px; font-size: 14px;
} }
/* -> After the two size rules, so it overrides whichever of them is in play */
.w-bar--flush {
padding-left: 0;
padding-right: 0;
}
/* /*
Quasar sized buttons inside a bar well below the bar's own font size, and spaced them by 2px. Quasar sized buttons inside a bar well below the bar's own font size, and spaced them by 2px.
Reproduced here so a bar full of buttons keeps its compact look. Reproduced here so a bar full of buttons keeps its compact look.

@ -105,6 +105,13 @@
*/ */
--color-primary-light: color-mix(in srgb, var(--color-primary) 60%, white); --color-primary-light: color-mix(in srgb, var(--color-primary) 60%, white);
/*
A step lighter again, for brand-coloured text that is small AND on a dark surface -- the search
panel's operator names. `primary-light` is mixed for headings, which carry their contrast partly
in their weight; the same shade at 12px on black reads as dim rather than as a highlight.
*/
--color-primary-lighter: color-mix(in srgb, var(--color-primary) 35%, white);
/* /*
And the sidebar's colour a shade lighter, for the one control that sits INSIDE that column and has And the sidebar's colour a shade lighter, for the one control that sits INSIDE that column and has
to read as a button against it rather than as a second accent beside it: scroll-to-top, tucked into to read as a button against it rather than as a second accent beside it: scroll-to-top, tucked into

@ -80,7 +80,7 @@
</div> </div>
<nav-sidebar /> <nav-sidebar />
<!-- -> Edit Nav is the whole bar now, so it is also what decides whether there is one --> <!-- -> Edit Nav is the whole bar now, so it is also what decides whether there is one -->
<w-bar v-if="showEditNav" class="sidebar-footerbtns text-white" dense> <w-bar v-if="showEditNav" class="sidebar-footerbtns text-white" dense flush>
<w-btn class="flex-1" icon="la:dharmachakra" label="Edit Nav" flat> <w-btn class="flex-1" icon="la:dharmachakra" label="Edit Nav" flat>
<w-menu ref="navEditMenu" anchor="top left" self="bottom left" :offset="[0, 10]"> <w-menu ref="navEditMenu" anchor="top left" self="bottom left" :offset="[0, 10]">
<nav-edit-menu <nav-edit-menu

Loading…
Cancel
Save