From 85ac7c9a9f0a6c30fa36094818a64b3d935148b1 Mon Sep 17 00:00:00 2001 From: EmNudge <24513691+EmNudge@users.noreply.github.com> Date: Mon, 27 Apr 2026 23:09:37 -0400 Subject: [PATCH] Add design system page and refine UI across the app - Add dev-only /design-system page showcasing all tokens and components - Refine color tokens for better contrast in both light and dark themes - Update form components with softer radius, smoother transitions, and ring-style focus states - Restyle results rows, info panel, command palette, and header with lighter typography - Add backdrop blur and spring animation to Modal - Fix hover/disabled contrast issues across all components --- design-system/index.html | 12 + dist/index.html | 4 +- src/App.vue | 11 +- src/components/CommandPalette.vue | 38 +- src/components/Header.vue | 27 +- src/components/Loader.vue | 8 + src/components/ThemeSwitcher.vue | 10 +- src/components/advanced-search/BoxContent.vue | 17 +- src/components/advanced-search/Button.vue | 20 +- src/components/advanced-search/Dropdown.vue | 10 +- src/components/advanced-search/Input.vue | 5 +- .../advanced-search/NumberInput.vue | 5 +- .../table-container/InfoContainer.vue | 35 +- .../table-container/ResultsContainer.vue | 8 +- src/components/table-container/ResultsRow.vue | 31 +- .../table-container/info-tables/Encoding.vue | 38 +- .../info-tables/HtmlEntities.vue | 13 +- .../info-tables/Properties.vue | 14 +- src/design-system/App.vue | 1356 +++++++++++++++++ src/design-system/main.ts | 5 + src/icons/GitHubIcon.vue | 7 +- src/lib/components/forms/Button.vue | 42 +- src/lib/components/forms/Input.vue | 23 +- src/lib/components/forms/Label.vue | 6 +- src/lib/components/forms/Select.vue | 21 +- src/lib/components/forms/TextArea.vue | 19 +- src/lib/components/overlay/Modal.vue | 18 +- src/styles/base.css | 41 +- src/styles/tokens.css | 17 +- vite.config.ts | 7 + 30 files changed, 1690 insertions(+), 178 deletions(-) create mode 100644 design-system/index.html create mode 100644 src/design-system/App.vue create mode 100644 src/design-system/main.ts diff --git a/design-system/index.html b/design-system/index.html new file mode 100644 index 0000000..7f7c6fb --- /dev/null +++ b/design-system/index.html @@ -0,0 +1,12 @@ + + + + + + Design System - Unicode Lookup + + +
+ + + diff --git a/dist/index.html b/dist/index.html index 7f24ac7..2d8175b 100644 --- a/dist/index.html +++ b/dist/index.html @@ -6,8 +6,8 @@ Unicode Lookup - - + +
diff --git a/src/App.vue b/src/App.vue index 757ac96..87829fd 100644 --- a/src/App.vue +++ b/src/App.vue @@ -47,8 +47,7 @@ onMounted(() => { @@ -71,10 +70,12 @@ main { margin: 0 auto; width: 600px; max-width: 100%; + padding: 0 var(--space-4); } @media (min-width: 640px) { main { max-width: none; + padding: 0; } } .content.middle { @@ -94,4 +95,10 @@ aside div { overflow-y: auto; height: 100vh; } +.no-results { + color: var(--color-text-tertiary); + font-weight: 300; + letter-spacing: -0.01em; + padding: var(--space-4) 0; +} diff --git a/src/components/CommandPalette.vue b/src/components/CommandPalette.vue index 5107da5..d9a20ab 100644 --- a/src/components/CommandPalette.vue +++ b/src/components/CommandPalette.vue @@ -140,33 +140,36 @@ const handleItemHover = (index: number) => { diff --git a/src/components/Header.vue b/src/components/Header.vue index f443021..ca61ed4 100644 --- a/src/components/Header.vue +++ b/src/components/Header.vue @@ -28,12 +28,24 @@ header { display: flex; justify-content: space-between; max-width: 600px; - margin: var(--space-5) auto; - display: flex; - align-items: center; + margin: var(--space-8) auto var(--space-6); + align-items: baseline; } h1 { - font-size: 1.7em; + font-size: 1.5em; + font-weight: 400; + letter-spacing: -0.025em; +} +h3 { + font-weight: 300; + font-size: var(--font-size-sm); + color: var(--color-text-tertiary); + letter-spacing: 0.01em; +} +.text { + display: flex; + align-items: baseline; + gap: var(--space-3); } .buttons { display: flex; @@ -42,15 +54,10 @@ button { cursor: pointer; margin: 0; z-index: 2; - padding: var(--space-3) var(--space-5); + padding: var(--space-2) var(--space-4); } .active { color: var(--hsl-bg); background: var(--hsl); - transition: 0.25s; -} -button:focus { - outline: var(--border-width-2) solid var(--color-border-focus); - outline-offset: var(--border-width-2); } diff --git a/src/components/Loader.vue b/src/components/Loader.vue index 50432a6..891f38a 100644 --- a/src/components/Loader.vue +++ b/src/components/Loader.vue @@ -36,10 +36,18 @@ section { text-align: center; padding-top: var(--space-12); } +h2 { + font-weight: 300; + font-size: var(--font-size-base); + color: var(--color-text-tertiary); + letter-spacing: 0.02em; + margin-bottom: var(--space-4); +} .chars span { display: inline-block; width: var(--space-6); text-align: center; line-height: 1em; + opacity: 0.5; } diff --git a/src/components/ThemeSwitcher.vue b/src/components/ThemeSwitcher.vue index eeb34e7..2789b29 100644 --- a/src/components/ThemeSwitcher.vue +++ b/src/components/ThemeSwitcher.vue @@ -56,10 +56,14 @@ button { margin: 0; background: none; border: none; - padding: 0 10px; - opacity: 0.6; + padding: 0 var(--space-3); + opacity: 0.5; + transition: opacity var(--duration-fast) var(--ease-out); +} +button:hover { + opacity: 0.8; } button:active { - transform: scale(0.9); + transform: scale(0.92); } diff --git a/src/components/advanced-search/BoxContent.vue b/src/components/advanced-search/BoxContent.vue index 83e9d3a..1f9b832 100644 --- a/src/components/advanced-search/BoxContent.vue +++ b/src/components/advanced-search/BoxContent.vue @@ -65,32 +65,37 @@ function handleDataChange(data: any) { diff --git a/src/components/advanced-search/Button.vue b/src/components/advanced-search/Button.vue index bd7f9c9..d9f2456 100644 --- a/src/components/advanced-search/Button.vue +++ b/src/components/advanced-search/Button.vue @@ -27,27 +27,19 @@ const btnClass = computed(() => ["styled", props.disabled && "disabled"].filter( diff --git a/src/components/advanced-search/Dropdown.vue b/src/components/advanced-search/Dropdown.vue index 432bd32..9e324cc 100644 --- a/src/components/advanced-search/Dropdown.vue +++ b/src/components/advanced-search/Dropdown.vue @@ -41,16 +41,12 @@ function handleChange(e: Event) { diff --git a/src/components/advanced-search/Input.vue b/src/components/advanced-search/Input.vue index 6709804..9e83a32 100644 --- a/src/components/advanced-search/Input.vue +++ b/src/components/advanced-search/Input.vue @@ -68,6 +68,9 @@ function handleInput(e: Event) { diff --git a/src/components/advanced-search/NumberInput.vue b/src/components/advanced-search/NumberInput.vue index 71be22d..9954f2d 100644 --- a/src/components/advanced-search/NumberInput.vue +++ b/src/components/advanced-search/NumberInput.vue @@ -95,6 +95,9 @@ function handleInput(e: Event) { diff --git a/src/components/table-container/InfoContainer.vue b/src/components/table-container/InfoContainer.vue index c184f1a..ba6ba96 100644 --- a/src/components/table-container/InfoContainer.vue +++ b/src/components/table-container/InfoContainer.vue @@ -103,38 +103,51 @@ const htmlEntityNames = computed(() => symbolHtmlNamesMap.value.get(props.codepo diff --git a/src/components/table-container/ResultsContainer.vue b/src/components/table-container/ResultsContainer.vue index 29f899e..7abded4 100644 --- a/src/components/table-container/ResultsContainer.vue +++ b/src/components/table-container/ResultsContainer.vue @@ -79,9 +79,11 @@ function handleKeydown(e: KeyboardEvent) { } p { text-align: left; - margin: 0; - opacity: 0.7; - font-size: 0.8rem; + margin: 0 0 var(--space-3); + color: var(--color-text-tertiary); + font-size: var(--font-size-xs); + font-weight: 400; + letter-spacing: 0.02em; } .intersection-observer { height: 5rem; diff --git a/src/components/table-container/ResultsRow.vue b/src/components/table-container/ResultsRow.vue index 6174a68..9b103ed 100644 --- a/src/components/table-container/ResultsRow.vue +++ b/src/components/table-container/ResultsRow.vue @@ -78,8 +78,16 @@ watch( .row { border: 1px solid transparent; width: 100%; - background-color: var(--bg-offset); + background-color: var(--color-bg-offset); position: relative; + border-radius: var(--radius-lg); + margin-bottom: var(--space-1); + transition: + border-color var(--duration-fast) var(--ease-out), + background-color var(--duration-fast) var(--ease-out); +} +.row:hover { + box-shadow: inset 0 0 0 1px var(--color-border); } .row:after { content: attr(data-codepoint); @@ -87,30 +95,39 @@ watch( position: absolute; bottom: 0; right: 0; - padding: 0.5rem; + padding: var(--space-2) var(--space-3); + color: var(--color-text-tertiary); opacity: 0.5; - font-size: 0.8rem; + font-size: var(--font-size-xs); + font-family: var(--font-family-mono); + letter-spacing: 0.02em; } .row.active { - border: var(--border-width-1) solid var(--color-border-focus); + border-color: var(--color-border-focus); + box-shadow: 0 0 0 2px rgba(123, 142, 230, 0.2); } .content { width: 100%; - padding: 0.5rem; + padding: var(--space-3) var(--space-3); display: grid; grid-template-columns: auto 1fr; - gap: 1rem; + gap: var(--space-4); + align-items: center; } .symbol { width: 2rem; text-align: center; + font-size: var(--font-size-lg); } .symbol::before, .symbol::after { content: '"'; + opacity: 0.3; } .name { text-align: left; - opacity: 0.75; + color: var(--color-text-secondary); + font-size: var(--font-size-sm); + letter-spacing: 0.005em; } diff --git a/src/components/table-container/info-tables/Encoding.vue b/src/components/table-container/info-tables/Encoding.vue index 4e0dc7e..2e1cd1b 100644 --- a/src/components/table-container/info-tables/Encoding.vue +++ b/src/components/table-container/info-tables/Encoding.vue @@ -79,40 +79,54 @@ function setEncoding(encoding: EncodingType) { diff --git a/src/components/table-container/info-tables/HtmlEntities.vue b/src/components/table-container/info-tables/HtmlEntities.vue index 4175f28..3970b75 100644 --- a/src/components/table-container/info-tables/HtmlEntities.vue +++ b/src/components/table-container/info-tables/HtmlEntities.vue @@ -37,17 +37,24 @@ const props = defineProps(); diff --git a/src/components/table-container/info-tables/Properties.vue b/src/components/table-container/info-tables/Properties.vue index b045794..06ca358 100644 --- a/src/components/table-container/info-tables/Properties.vue +++ b/src/components/table-container/info-tables/Properties.vue @@ -17,10 +17,11 @@ const props = defineProps(); diff --git a/src/design-system/App.vue b/src/design-system/App.vue new file mode 100644 index 0000000..8b6cd2e --- /dev/null +++ b/src/design-system/App.vue @@ -0,0 +1,1356 @@ + + +