Redesign SearchableTextBlock UI — stronger visual hierarchy
Green gradient header, white card with shadow, left-border accent on open accordion items, hover-visible copy button in summary row, lighter dividers. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -159,45 +159,43 @@
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="searchable-text flex flex-col gap-0 border border-stein-200 bg-stein-50 {layoutClasses} {className}"
|
||||
class="searchable-text flex flex-col gap-0 border border-stein-200 bg-white shadow-sm overflow-hidden {layoutClasses} {className}"
|
||||
data-block="SearchableText" data-block-type="searchable_text"
|
||||
data-block-slug={block._slug}
|
||||
>
|
||||
<div class="p-4 md:p-6">
|
||||
{#if block.title}
|
||||
<h2 class="text-xl md:text-2xl font-bold text-stein-900 mb-2">
|
||||
{block.title}
|
||||
</h2>
|
||||
{/if}
|
||||
{#if descriptionHtml}
|
||||
<div class="markdown text-stein-600 max-w-none prose prose-zinc prose-sm">
|
||||
{@html descriptionHtml}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if block.title || descriptionHtml}
|
||||
<div class="px-4 md:px-6 py-5 bg-gradient-to-br from-wald-700 to-wald-800">
|
||||
{#if block.title}
|
||||
<h2 class="text-xl md:text-2xl font-bold text-white mb-1">
|
||||
{block.title}
|
||||
</h2>
|
||||
{/if}
|
||||
{#if descriptionHtml}
|
||||
<div class="markdown text-wald-100 max-w-none prose prose-sm prose-invert">
|
||||
{@html descriptionHtml}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<header
|
||||
class="sticky top-14 z-10 px-4 md:px-6 py-3 border-b border-stein-200 bg-stein-0/95 backdrop-blur-sm md:static md:bg-stein-100 md:backdrop-blur-none shadow-sm md:shadow-none"
|
||||
class="sticky top-14 z-10 px-4 md:px-6 py-3 border-b border-stein-200 bg-white/95 backdrop-blur-sm shadow-sm"
|
||||
>
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="relative flex items-center gap-2">
|
||||
<Tooltip content={helpTooltipText} placement="top">
|
||||
<button
|
||||
type="button"
|
||||
class="shrink-0 p-1.5 rounded-xs text-himmel-500 hover:text-himmel-700 hover:bg-himmel-50 transition-colors focus:outline-none focus:ring-2 focus:ring-wald-500 focus:ring-offset-1"
|
||||
class="shrink-0 p-1.5 rounded-xs text-stein-400 hover:text-wald-600 hover:bg-wald-50 transition-colors focus:outline-none focus:ring-2 focus:ring-wald-500 focus:ring-offset-1"
|
||||
aria-label={t(T.searchable_text_help_aria)}
|
||||
>
|
||||
<Icon
|
||||
icon="mdi:help-circle-outline"
|
||||
class="size-5"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<Icon icon="mdi:help-circle-outline" class="size-5" aria-hidden="true" />
|
||||
</button>
|
||||
</Tooltip>
|
||||
<input
|
||||
type="search"
|
||||
placeholder={t(T.searchable_text_placeholder)}
|
||||
class="w-full text-sm px-4 py-2.5 pr-10 border border-stein-200 rounded-xs focus:outline-none focus:ring-2 focus:ring-wald-500 focus:border-wald-400 bg-stein-0 text-stein-900 placeholder:text-stein-400"
|
||||
class="w-full text-sm px-4 py-2.5 pr-10 border border-stein-200 rounded-xs focus:outline-none focus:ring-2 focus:ring-wald-500 focus:border-wald-400 bg-white text-stein-900 placeholder:text-stein-400"
|
||||
bind:value={searchQuery}
|
||||
oninput={(e) => (searchQuery = (e.target as HTMLInputElement).value)}
|
||||
aria-label={t(T.searchable_text_search_aria)}
|
||||
@@ -205,7 +203,7 @@
|
||||
{#if searchQuery}
|
||||
<button
|
||||
type="button"
|
||||
class="absolute right-9 top-1/2 -translate-y-1/2 p-1.5 rounded-xs hover:bg-stein-200 text-stein-500 hover:text-stein-700 transition-colors"
|
||||
class="absolute right-9 top-1/2 -translate-y-1/2 p-1.5 rounded-xs hover:bg-stein-100 text-stein-400 hover:text-stein-700 transition-colors"
|
||||
onclick={() => (searchQuery = "")}
|
||||
aria-label={t(T.searchable_text_clear_search)}
|
||||
>
|
||||
@@ -219,8 +217,8 @@
|
||||
/>
|
||||
</div>
|
||||
{#if allTags.length > 0}
|
||||
<div class="overflow-x-auto -mx-1 px-1 pt-2 pb-2">
|
||||
<div class="flex gap-2 flex-wrap min-w-max md:flex-wrap md:w-auto">
|
||||
<div class="overflow-x-auto -mx-1 px-1 pt-1 pb-1">
|
||||
<div class="flex gap-1.5 flex-wrap">
|
||||
<Tag
|
||||
label={t(T.searchable_text_tag_all)}
|
||||
variant={selectedTag === "all" ? "green" : "white"}
|
||||
@@ -242,7 +240,7 @@
|
||||
</header>
|
||||
|
||||
<div
|
||||
class="text-xs text-stein-600 px-4 md:px-6 py-2.5 bg-stein-100 border-b border-stein-200"
|
||||
class="text-xs text-stein-500 px-4 md:px-6 py-2 bg-stein-50 border-b border-stein-100"
|
||||
aria-live="polite"
|
||||
>
|
||||
{#if visibleFragments.length === 0}
|
||||
@@ -259,11 +257,11 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-0 bg-stein-100">
|
||||
<div class="flex flex-col divide-y divide-stein-100">
|
||||
{#each visibleFragments as fragment, i}
|
||||
<details class="group border-b border-stein-200 last:border-b-0">
|
||||
<details class="group border-l-4 border-l-transparent open:border-l-wald-500 transition-colors bg-white open:bg-wald-50/30">
|
||||
<summary
|
||||
class="cursor-pointer list-none px-4 md:px-6 py-3.5 bg-stein-50 hover:bg-wald-50 text-sm font-medium text-stein-800 flex flex-col gap-1.5 transition-colors"
|
||||
class="cursor-pointer list-none px-4 md:px-6 py-3.5 hover:bg-wald-50/60 text-sm font-medium text-stein-800 flex flex-col gap-1.5 transition-colors"
|
||||
>
|
||||
<div class="flex items-start gap-2 min-w-0">
|
||||
<div class="grow min-w-0">
|
||||
@@ -272,11 +270,29 @@
|
||||
searchQuery.trim(),
|
||||
)}
|
||||
</div>
|
||||
<Icon
|
||||
icon="mdi:chevron-down"
|
||||
class="shrink-0 text-stein-500 group-open:rotate-180 transition-transform"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<div class="shrink-0 flex items-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
class="opacity-0 group-hover:opacity-100 inline-flex items-center gap-1 px-2 py-1 text-xs font-normal rounded-xs border border-stein-200 bg-white text-stein-600 hover:bg-wald-50 hover:border-wald-300 hover:text-wald-800 transition-all"
|
||||
onclick={(e) => {
|
||||
e.preventDefault();
|
||||
copyFragmentContent(fragment, i);
|
||||
}}
|
||||
aria-label={t(T.searchable_text_copy_aria)}
|
||||
tabindex="-1"
|
||||
>
|
||||
{#if copiedIndex === i}
|
||||
<Icon icon="mdi:check" class="size-3.5 text-wald-600" aria-hidden="true" />
|
||||
{:else}
|
||||
<Icon icon="mdi:content-copy" class="size-3.5" aria-hidden="true" />
|
||||
{/if}
|
||||
</button>
|
||||
<Icon
|
||||
icon="mdi:chevron-down"
|
||||
class="text-stein-400 group-open:rotate-180 transition-transform size-5"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{#if fragment.tags.length > 0}
|
||||
<span class="flex flex-wrap gap-1">
|
||||
@@ -284,13 +300,11 @@
|
||||
</span>
|
||||
{/if}
|
||||
</summary>
|
||||
<div
|
||||
class="px-4 md:px-6 py-4 bg-stein-0 markdown prose prose-zinc prose-sm max-w-none text-xs"
|
||||
>
|
||||
<div class="px-4 md:px-6 py-4 bg-white border-t border-stein-100 markdown prose prose-zinc prose-sm max-w-none text-xs">
|
||||
<div class="flex justify-end mb-3 -mt-1">
|
||||
<button
|
||||
type="button"
|
||||
class="inline-flex items-center gap-1.5 px-2.5 py-1.5 text-xs font-medium rounded-xs border border-stein-200 bg-stein-50 text-stein-700 hover:bg-wald-50 hover:border-wald-200 hover:text-wald-800 transition-colors"
|
||||
class="inline-flex items-center gap-1.5 px-2.5 py-1.5 text-xs font-medium rounded-xs border border-stein-200 bg-stein-50 text-stein-700 hover:bg-wald-50 hover:border-wald-300 hover:text-wald-800 transition-colors"
|
||||
onclick={(e) => {
|
||||
e.preventDefault();
|
||||
copyFragmentContent(fragment, i);
|
||||
@@ -298,18 +312,10 @@
|
||||
aria-label={t(T.searchable_text_copy_aria)}
|
||||
>
|
||||
{#if copiedIndex === i}
|
||||
<Icon
|
||||
icon="mdi:check"
|
||||
class="size-4 text-wald-600"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<Icon icon="mdi:check" class="size-4 text-wald-600" aria-hidden="true" />
|
||||
<span>{t(T.searchable_text_copied)}</span>
|
||||
{:else}
|
||||
<Icon
|
||||
icon="mdi:content-copy"
|
||||
class="size-4"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<Icon icon="mdi:content-copy" class="size-4" aria-hidden="true" />
|
||||
<span>{t(T.searchable_text_copy_button)}</span>
|
||||
{/if}
|
||||
</button>
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
"rss": {
|
||||
"body": "<path fill=\"currentColor\" d=\"M6.18 15.64a2.18 2.18 0 0 1 2.18 2.18C8.36 19 7.38 20 6.18 20C5 20 4 19 4 17.82a2.18 2.18 0 0 1 2.18-2.18M4 4.44A15.56 15.56 0 0 1 19.56 20h-2.83A12.73 12.73 0 0 0 4 7.27zm0 5.66a9.9 9.9 0 0 1 9.9 9.9h-2.83A7.07 7.07 0 0 0 4 12.93z\"/>"
|
||||
},
|
||||
"chevron-left": {
|
||||
"body": "<path fill=\"currentColor\" d=\"M15.41 16.58L10.83 12l4.58-4.59L14 6l-6 6l6 6z\"/>"
|
||||
},
|
||||
"pencil-outline": {
|
||||
"body": "<path fill=\"currentColor\" d=\"m14.06 9l.94.94L5.92 19H5v-.92zm3.6-6c-.25 0-.51.1-.7.29l-1.83 1.83l3.75 3.75l1.83-1.83c.39-.39.39-1.04 0-1.41l-2.34-2.34c-.2-.2-.45-.29-.71-.29m-3.6 3.19L3 17.25V21h3.75L17.81 9.94z\"/>"
|
||||
},
|
||||
@@ -57,9 +60,6 @@
|
||||
"menu": {
|
||||
"body": "<path fill=\"currentColor\" d=\"M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z\"/>"
|
||||
},
|
||||
"chevron-left": {
|
||||
"body": "<path fill=\"currentColor\" d=\"M15.41 16.58L10.83 12l4.58-4.59L14 6l-6 6l6 6z\"/>"
|
||||
},
|
||||
"comment-outline": {
|
||||
"body": "<path fill=\"currentColor\" d=\"M9 22a1 1 0 0 1-1-1v-3H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2h-6.1l-3.7 3.71c-.2.19-.45.29-.7.29zm1-6v3.08L13.08 16H20V4H4v12z\"/>"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user