Compare commits

...
2 Commits
Author SHA1 Message Date
rajch_ales 0c5099b48b Standardize left sidebar controls 2026-08-05 17:38:23 +02:00
rajch_ales f4d0b79ed9 Document shared icon placement rules 2026-08-05 17:33:21 +02:00
5 changed files with 22 additions and 7 deletions
+4
View File
@@ -47,6 +47,10 @@ This project replaces the Excel/VBA workflow named `Catalog maker - 20` with a N
- Panel collapse/open controls must use the shared `panel-control-button` style; do not create separate visual variants for `X`, chevrons or future panel toggles. - Panel collapse/open controls must use the shared `panel-control-button` style; do not create separate visual variants for `X`, chevrons or future panel toggles.
- Verify shared panel-control styling through computed browser styles, not only by checking class names. - Verify shared panel-control styling through computed browser styles, not only by checking class names.
- Use Playwright to inspect the rendered result after every visual change at desktop and narrow viewport sizes. - Use Playwright to inspect the rendered result after every visual change at desktop and narrow viewport sizes.
- Every actionable button and selector must use an icon before its text whenever a suitable symbol exists. Reuse the existing symbols from `public/icons.svg`; do not create text-only controls when an appropriate icon exists.
- Button icons must be placed before the label in DOM order, with the icon and label centered together as one group. Keep the control's chevron or disclosure arrow in its own fixed right-side slot so it does not shift the centered label.
- Use one shared icon size, gap, alignment, hover state and disabled state for equivalent controls. Do not mix icon-only, text-only and icon-after-text variants for the same control family.
- Before finishing any UI change, inspect the rendered page with Playwright and verify that icons are visible, precede their labels, remain centered, and do not overlap or drift between controls. Update this file when a new reusable visual rule is discovered.
## TypeScript workflow ## TypeScript workflow
+2
View File
@@ -12,5 +12,7 @@
<symbol id="erase" viewBox="0 0 24 24"><path d="m4 15 8-8a2 2 0 0 1 2.8 0l4.2 4.2a2 2 0 0 1 0 2.8l-5 5H7zM13 19h7" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8"/></symbol> <symbol id="erase" viewBox="0 0 24 24"><path d="m4 15 8-8a2 2 0 0 1 2.8 0l4.2 4.2a2 2 0 0 1 0 2.8l-5 5H7zM13 19h7" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8"/></symbol>
<symbol id="moon" viewBox="0 0 24 24"><path d="M20 15.5A8.5 8.5 0 0 1 8.5 4 8.5 8.5 0 1 0 20 15.5Z" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="1.8"/></symbol> <symbol id="moon" viewBox="0 0 24 24"><path d="M20 15.5A8.5 8.5 0 0 1 8.5 4 8.5 8.5 0 1 0 20 15.5Z" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="1.8"/></symbol>
<symbol id="settings" viewBox="0 0 24 24"><path d="M12 8.5a3.5 3.5 0 1 0 0 7 3.5 3.5 0 0 0 0-7Z" fill="none" stroke="currentColor" stroke-width="1.8"/><path d="m19 13.5 1.2 1-.2 2-1.5.8-.3 1.6-1.8.9-1.4-.7-1.5.7-1.8-.9-.3-1.6-1.5-.8-.2-2 1.2-1-.1-1.5-1.2-1 .2-2 1.5-.8.3-1.6 1.8-.9 1.4.7 1.5-.7 1.8.9.3 1.6 1.5.8.2 2-1.2 1.1.1 1.5Z" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="1.4"/></symbol> <symbol id="settings" viewBox="0 0 24 24"><path d="M12 8.5a3.5 3.5 0 1 0 0 7 3.5 3.5 0 0 0 0-7Z" fill="none" stroke="currentColor" stroke-width="1.8"/><path d="m19 13.5 1.2 1-.2 2-1.5.8-.3 1.6-1.8.9-1.4-.7-1.5.7-1.8-.9-.3-1.6-1.5-.8-.2-2 1.2-1-.1-1.5-1.2-1 .2-2 1.5-.8.3-1.6 1.8-.9 1.4.7 1.5-.7 1.8.9.3 1.6 1.5.8.2 2-1.2 1.1.1 1.5Z" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="1.4"/></symbol>
<symbol id="globe" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9" fill="none" stroke="currentColor" stroke-width="1.8"/><path d="M3 12h18M12 3c2.3 2.4 3.4 5.4 3.4 9S14.3 18.6 12 21M12 3c-2.3 2.4-3.4 5.4-3.4 9S9.7 18.6 12 21" fill="none" stroke="currentColor" stroke-width="1.4"/></symbol>
<symbol id="tag" viewBox="0 0 24 24"><path d="m4 5 8.5-.5L20 12l-8 8-7.5-7.5L4 5Z" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="1.8"/><circle cx="8" cy="8" r="1.2" fill="currentColor"/></symbol>
<symbol id="close" viewBox="0 0 24 24"><path d="m6 6 12 12M18 6 6 18" fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.8"/></symbol> <symbol id="close" viewBox="0 0 24 24"><path d="m6 6 12 12M18 6 6 18" fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.8"/></symbol>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

+3 -1
View File
@@ -57,6 +57,7 @@
</div> </div>
<div class="select-control"> <div class="select-control">
<svg class="sidebar-icon select-icon" aria-hidden="true"><use href="/icons.svg#globe"></use></svg>
<select class="input-like" id="languageSelect" aria-label="Language"> <select class="input-like" id="languageSelect" aria-label="Language">
<option value="">Select language</option> <option value="">Select language</option>
</select> </select>
@@ -65,6 +66,7 @@
<div class="manufacturer-picker" id="manufacturerPicker"> <div class="manufacturer-picker" id="manufacturerPicker">
<button class="manufacturer-trigger" id="manufacturerTrigger" type="button" aria-haspopup="listbox" aria-expanded="false"> <button class="manufacturer-trigger" id="manufacturerTrigger" type="button" aria-haspopup="listbox" aria-expanded="false">
<svg class="sidebar-icon select-icon" aria-hidden="true"><use href="/icons.svg#tag"></use></svg>
<span id="manufacturerValue">Select manufacturer</span> <span id="manufacturerValue">Select manufacturer</span>
<span class="select-chevron picker-chevron" aria-hidden="true"></span> <span class="select-chevron picker-chevron" aria-hidden="true"></span>
</button> </button>
@@ -73,7 +75,7 @@
<div class="manufacturer-options" id="manufacturerOptions" role="listbox"></div> <div class="manufacturer-options" id="manufacturerOptions" role="listbox"></div>
</div> </div>
</div> </div>
<select class="input-like native-manufacturer-select" id="manufacturerSelect" aria-label="Manufacturer"> <select class="input-like native-manufacturer-select" id="manufacturerSelect" aria-label="Manufacturer" hidden>
<option value="">Select manufacturer</option> <option value="">Select manufacturer</option>
</select> </select>
+1 -1
View File
File diff suppressed because one or more lines are too long
+12 -5
View File
@@ -57,13 +57,17 @@
.sidebar-overlay[hidden] { display: none; } .sidebar-overlay[hidden] { display: none; }
.sidebar-drawer[aria-hidden="true"] { @apply -translate-x-full; } .sidebar-drawer[aria-hidden="true"] { @apply -translate-x-full; }
.sidebar-section { @apply border-t border-slate-700 pt-1; } .sidebar-section { @apply border-t border-slate-700 pt-1; }
.drawer-trigger { @apply flex min-h-8 w-full items-center gap-2 rounded border border-slate-700 bg-slate-800 px-2 text-left text-[11px] font-semibold text-slate-100 transition hover:border-slate-500 hover:bg-slate-700; } .drawer-trigger { @apply relative flex min-h-8 w-full items-center justify-center rounded border border-slate-700 bg-slate-800 px-8 text-center text-[11px] font-semibold text-slate-100 transition hover:border-slate-500 hover:bg-slate-700; }
.drawer-trigger .sidebar-icon { @apply absolute left-2; }
.drawer-trigger > span:not(.drawer-chevron) { @apply min-w-0 truncate text-center; }
.drawer-trigger .drawer-chevron { @apply inline-flex h-2 w-2 border-b-2 border-r-2 text-[0px] leading-none; } .drawer-trigger .drawer-chevron { @apply inline-flex h-2 w-2 border-b-2 border-r-2 text-[0px] leading-none; }
.drawer-trigger .drawer-chevron { @apply ml-auto rotate-45 text-slate-300; } .drawer-trigger .drawer-chevron { @apply ml-auto rotate-45 text-slate-300; }
.drawer-trigger[aria-expanded="true"] .drawer-chevron { @apply rotate-[225deg]; } .drawer-trigger[aria-expanded="true"] .drawer-chevron { @apply rotate-[225deg]; }
.parser-drawer[hidden] { display: none; } .parser-drawer[hidden] { display: none; }
.sidebar-icon { @apply inline-flex h-4 w-4 shrink-0 items-center justify-center text-sm leading-none text-slate-300; } .sidebar-icon { @apply inline-flex h-4 w-4 shrink-0 items-center justify-center text-sm leading-none text-slate-300; }
.action-button { @apply flex items-center justify-center gap-1.5; } .action-button { @apply flex items-center justify-center gap-1.5; }
.action-button > .sidebar-icon { @apply shrink-0; }
.action-button > span { @apply min-w-0 truncate text-center; }
.action-button .sidebar-icon { @apply text-slate-400; } .action-button .sidebar-icon { @apply text-slate-400; }
.sidebar-footer { @apply mt-auto grid gap-1 border-t border-slate-700 pt-2; } .sidebar-footer { @apply mt-auto grid gap-1 border-t border-slate-700 pt-2; }
.app-status { @apply rounded border border-slate-700 bg-slate-950 p-1 text-[10px] leading-tight text-slate-100; } .app-status { @apply rounded border border-slate-700 bg-slate-950 p-1 text-[10px] leading-tight text-slate-100; }
@@ -86,14 +90,16 @@
.arrow-button:disabled, .action-button:disabled { @apply cursor-not-allowed opacity-50; } .arrow-button:disabled, .action-button:disabled { @apply cursor-not-allowed opacity-50; }
.input-like { @apply h-7 px-1 text-[11px]; } .input-like { @apply h-7 px-1 text-[11px]; }
.select-control { @apply relative w-full; } .select-control { @apply relative w-full; }
.select-control .input-like { @apply appearance-none pr-7 text-center; } .select-control .input-like { @apply appearance-none pr-7 pl-9 text-center; }
.select-icon { @apply pointer-events-none absolute left-3 top-1/2 z-10 h-4 w-4 -translate-y-1/2 text-slate-300; }
.select-chevron { @apply pointer-events-none absolute right-3 top-1/2 h-2 w-2 -translate-y-1/2 rotate-45 border-b-2 border-r-2 text-slate-200; } .select-chevron { @apply pointer-events-none absolute right-3 top-1/2 h-2 w-2 -translate-y-1/2 rotate-45 border-b-2 border-r-2 text-slate-200; }
.native-manufacturer-select { @apply hidden; } .native-manufacturer-select { @apply hidden; }
.manufacturer-picker { @apply relative; } .manufacturer-picker { @apply relative; }
.manufacturer-trigger { @apply relative flex h-7 w-full items-center justify-center rounded border border-slate-700 bg-slate-800 px-2 text-center text-[11px] text-slate-200 shadow-sm; } .manufacturer-trigger { @apply relative flex h-7 w-full items-center justify-center rounded border border-slate-700 bg-slate-800 px-9 text-center text-[11px] text-slate-200 shadow-sm; }
.manufacturer-trigger .select-icon { @apply left-3; }
.manufacturer-trigger > span:not(.select-chevron) { @apply min-w-0 truncate text-center; }
.manufacturer-trigger:hover { @apply border-slate-500 bg-slate-700; } .manufacturer-trigger:hover { @apply border-slate-500 bg-slate-700; }
.manufacturer-trigger[aria-expanded="true"] { @apply border-catalog-focus ring-2 ring-catalog-focus/25; } .manufacturer-trigger[aria-expanded="true"] { @apply border-catalog-focus ring-2 ring-catalog-focus/25; }
.manufacturer-trigger span:first-child { @apply min-w-0 truncate; }
.manufacturer-trigger .select-chevron { @apply right-3 top-1/2 ml-0 translate-y-[-50%]; } .manufacturer-trigger .select-chevron { @apply right-3 top-1/2 ml-0 translate-y-[-50%]; }
.manufacturer-menu { @apply absolute left-0 right-0 top-full z-50 mt-1 rounded border border-slate-300 bg-white p-1 shadow-xl; } .manufacturer-menu { @apply absolute left-0 right-0 top-full z-50 mt-1 rounded border border-slate-300 bg-white p-1 shadow-xl; }
.manufacturer-menu[hidden] { display: none; } .manufacturer-menu[hidden] { display: none; }
@@ -240,7 +246,8 @@
html:not(.dark) .column-header { @apply border-slate-300 bg-slate-100 text-slate-700; } html:not(.dark) .column-header { @apply border-slate-300 bg-slate-100 text-slate-700; }
html:not(.dark) .sidebar-drawer-title { @apply text-slate-700; } html:not(.dark) .sidebar-drawer-title { @apply text-slate-700; }
html:not(.dark) .drawer-trigger .drawer-chevron, html:not(.dark) .drawer-trigger .drawer-chevron,
html:not(.dark) .select-chevron { @apply text-slate-700; } html:not(.dark) .select-chevron,
html:not(.dark) .select-icon { @apply text-slate-700; }
html:not(.dark) .sidebar-close-button, html:not(.dark) .sidebar-close-button,
html:not(.dark) .sidebar-open-button, html:not(.dark) .sidebar-open-button,
html:not(.dark) .drawer-trigger, html:not(.dark) .drawer-trigger,