From 91363a2825b5681b94e945d217811ddd2ac84f46 Mon Sep 17 00:00:00 2001 From: Sanne de Vries <65487235+sanne-san@users.noreply.github.com> Date: Tue, 28 Oct 2025 03:28:15 -0500 Subject: [PATCH] Improve dark mode (#5819) * Improve dark mode - Switch from `slate` to `zinc` for the gray color palette - Darken overall dark mode UI - Switch from `green` to `emerald` for the green color palette - Update a few previously missed instances of title case to sentence case - Consolidate button styles and change naming from `bright` to `secondary` - Update button disabled styles - Fix tooltip not adjusting to content width - Update graph tooltip layout and typography - Add transition effects to hover states - Reduce footer logo size * Fix oversights - Update funnel graph colors - Update graph grid colors - Improve focus styles - Improve disabled input styles * Fix more oversights in relation to dashboard filtering - Improve consistency of input, button, combobox and modal components in relation to settings area - Fix segment tooltip color * Fix search input style in funnel and segments dropdowns * Add white background to favicon images in dark mode - The GitHub and ChatGPT favicons are hard to see in dark mode, so we add a white background to them. * Fix tooltip color to fit all backgrounds in dark mode * Fix tests * Fixed more tests * Extract SourceFavicon component to eliminate favicon duplication * Fix regression on installation page after rebase * Fix formatting issues * Fix favicon test failure in CI by reading placeholder icon at compile time * Undo previous commit --- assets/css/app.css | 79 +++++++----- assets/css/chartjs.css | 10 -- assets/js/dashboard/components/combobox.js | 12 +- .../components/filter-operator-selector.js | 2 +- assets/js/dashboard/components/notice.js | 17 +-- assets/js/dashboard/components/popover.tsx | 11 +- .../js/dashboard/components/search-input.tsx | 2 +- assets/js/dashboard/components/tabs.tsx | 7 +- assets/js/dashboard/extra/funnel.js | 14 +-- assets/js/dashboard/index.tsx | 2 +- assets/js/dashboard/keybinding.tsx | 2 +- assets/js/dashboard/nav-menu/filters-bar.tsx | 4 +- .../nav-menu/nav-menu-components.tsx | 2 +- .../query-periods/move-period-arrows.tsx | 28 +++-- assets/js/dashboard/nav-menu/top-bar.tsx | 2 +- .../js/dashboard/segments/segment-modals.tsx | 30 +++-- assets/js/dashboard/stats/behaviours/index.js | 2 +- assets/js/dashboard/stats/behaviours/props.js | 2 +- .../js/dashboard/stats/graph/graph-tooltip.js | 40 +++--- assets/js/dashboard/stats/graph/line-graph.js | 9 +- assets/js/dashboard/stats/graph/top-stats.js | 4 +- .../js/dashboard/stats/graph/visitor-graph.js | 2 +- assets/js/dashboard/stats/locations/map.tsx | 16 +-- .../stats/modals/breakdown-table.tsx | 2 +- .../js/dashboard/stats/modals/filter-modal.js | 2 +- assets/js/dashboard/stats/modals/modal.js | 2 +- .../stats/modals/referrer-drilldown.js | 8 +- assets/js/dashboard/stats/modals/sources.js | 8 +- assets/js/dashboard/stats/more-link.js | 2 +- .../dashboard/stats/sources/referrer-list.js | 9 +- .../stats/sources/source-favicon.tsx | 26 ++++ .../js/dashboard/stats/sources/source-list.js | 9 +- assets/js/dashboard/util/tooltip.tsx | 2 +- .../customer_support/team/components/audit.ex | 6 +- .../team/components/billing.ex | 2 +- .../live/funnel_settings/form.ex | 10 +- .../live/funnel_settings/list.ex | 2 +- .../components/billing/billing.ex | 6 +- .../components/billing/plan_box.ex | 10 +- lib/plausible_web/components/flow_progress.ex | 8 +- lib/plausible_web/components/generic.ex | 60 ++++----- lib/plausible_web/components/layout.ex | 6 +- lib/plausible_web/components/two_factor.ex | 2 +- lib/plausible_web/live/choose_plan.ex | 23 +++- .../live/components/combo_box.ex | 6 +- lib/plausible_web/live/components/form.ex | 10 +- lib/plausible_web/live/components/modal.ex | 2 +- .../live/components/verification.ex | 2 +- lib/plausible_web/live/csv_import.ex | 6 +- lib/plausible_web/live/goal_settings/form.ex | 115 ++++++++---------- lib/plausible_web/live/goal_settings/list.ex | 10 +- .../live/imports_exports_settings.ex | 2 +- lib/plausible_web/live/installation.ex | 19 ++- .../live/installation/instructions.ex | 18 +-- .../live/plugins/api/token_form.ex | 11 +- lib/plausible_web/live/props_settings/form.ex | 6 +- lib/plausible_web/live/props_settings/list.ex | 2 +- .../live/shields/country_rules.ex | 6 +- .../live/shields/hostname_rules.ex | 6 +- lib/plausible_web/live/shields/ip_rules.ex | 8 +- lib/plausible_web/live/shields/page_rules.ex | 6 +- lib/plausible_web/live/sites.ex | 30 ++--- lib/plausible_web/live/team_management.ex | 6 +- .../templates/error/404_error.html.heex | 2 +- .../google_analytics/confirm.html.heex | 2 +- .../templates/layout/_footer.html.heex | 4 +- .../templates/layout/_header.html.heex | 12 +- .../templates/layout/app.html.heex | 2 +- .../templates/layout/settings.html.heex | 2 +- .../templates/layout/site_settings.html.heex | 2 +- .../templates/settings/invoices.html.heex | 7 +- .../templates/settings/subscription.html.heex | 4 +- .../membership/invite_member_form.html.heex | 13 +- .../templates/site/new.html.heex | 2 +- .../templates/site/new_shared_link.html.heex | 2 +- .../site/settings_email_reports.html.heex | 2 +- .../templates/site/settings_general.html.heex | 2 +- .../site/settings_integrations.html.heex | 2 +- .../templates/site/settings_people.html.heex | 6 +- .../templates/site/settings_props.html.heex | 4 +- .../site/settings_visibility.html.heex | 4 +- priv/globe_favicon.svg | 8 +- priv/link_favicon.svg | 2 +- storybook/button.story.exs | 6 +- .../controllers/site_controller_test.exs | 2 +- .../live/goal_settings/form_test.exs | 4 +- .../live/props_settings_test.exs | 4 +- 87 files changed, 472 insertions(+), 403 deletions(-) delete mode 100644 assets/css/chartjs.css create mode 100644 assets/js/dashboard/stats/sources/source-favicon.tsx diff --git a/assets/css/app.css b/assets/css/app.css index 8628eb16aa..f5f64fe524 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -4,7 +4,6 @@ @import './loader.css' layer(components); @import './tooltip.css' layer(components); @import './flatpickr-colors.css' layer(components); -@import './chartjs.css' layer(components); @plugin "@tailwindcss/forms"; @@ -28,6 +27,24 @@ [role='button']:not(:disabled) { cursor: pointer; } + + *:focus-visible { + @apply ring-2 ring-indigo-500 ring-offset-2 dark:ring-offset-gray-900 outline-none; + } +} + +@layer components { + /* Replace Tailwind form plugin's focus with focus-visible */ + [type='checkbox']:focus, + [type='radio']:focus { + outline: none; + box-shadow: none; + } + + [type='checkbox']:focus-visible, + [type='radio']:focus-visible { + @apply ring-2 ring-indigo-500 ring-offset-2 outline-none; + } } @theme { @@ -45,28 +62,40 @@ --color-yellow-800: var(--color-amber-800); --color-yellow-900: var(--color-amber-900); --color-yellow-950: var(--color-amber-950); + --color-green-50: var(--color-emerald-50); + --color-green-100: var(--color-emerald-100); + --color-green-200: var(--color-emerald-200); + --color-green-300: var(--color-emerald-300); + --color-green-400: var(--color-emerald-400); + --color-green-500: var(--color-emerald-500); + --color-green-600: var(--color-emerald-600); + --color-green-700: var(--color-emerald-700); + --color-green-800: var(--color-emerald-800); + --color-green-900: var(--color-emerald-900); + --color-green-950: var(--color-emerald-950); /* gray: colors.slate - Map gray to slate colors */ - --color-gray-50: var(--color-slate-50); - --color-gray-100: var(--color-slate-100); - --color-gray-200: var(--color-slate-200); - --color-gray-300: var(--color-slate-300); - --color-gray-400: var(--color-slate-400); - --color-gray-500: var(--color-slate-500); - --color-gray-600: var(--color-slate-600); - --color-gray-700: var(--color-slate-700); - --color-gray-800: var(--color-slate-800); - --color-gray-900: var(--color-slate-900); + --color-gray-50: var(--color-zinc-50); + --color-gray-100: var(--color-zinc-100); + --color-gray-200: var(--color-zinc-200); + --color-gray-300: var(--color-zinc-300); + --color-gray-400: var(--color-zinc-400); + --color-gray-500: var(--color-zinc-500); + --color-gray-600: var(--color-zinc-600); + --color-gray-700: var(--color-zinc-700); + --color-gray-800: var(--color-zinc-800); + --color-gray-900: var(--color-zinc-900); + --color-gray-950: var(--color-zinc-950); /* Custom gray shades from config (override some slate values) */ - --color-gray-150: rgb(234 238 244); - --color-gray-825: rgb(37 47 63); - --color-gray-850: rgb(26 32 44); - --color-gray-950: rgb(13 18 30); + --color-gray-150: rgb(236 236 238); + --color-gray-750: rgb(50 50 54); + --color-gray-825: rgb(35 35 38); + --color-gray-850: rgb(34 34 38); /* Set v3 default ring behavior */ - --default-ring-width: 3px; - --default-ring-color: var(--color-blue-500); + --default-ring-width: 2px; + --default-ring-color: var(--color-indigo-500); } @media print { @@ -91,7 +120,7 @@ } .button { - @apply inline-flex justify-center px-3.5 py-2 text-sm font-medium text-white bg-indigo-600 border border-transparent rounded-md leading-5 transition hover:bg-indigo-700 focus:outline-hidden focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500; + @apply inline-flex justify-center px-3.5 py-2 text-sm font-medium text-white bg-indigo-600 border border-transparent rounded-md leading-5 transition hover:bg-indigo-700; } .button[disabled] { @@ -264,15 +293,15 @@ blockquote { } .table-striped tbody tr:nth-child(odd) { - background-color: #f1f5f8; + background-color: var(--color-gray-100); } .dark .table-striped tbody tr:nth-child(odd) { - background-color: rgb(37 47 63); + background-color: var(--color-gray-800); } .dark .table-striped tbody tr:nth-child(even) { - background-color: rgb(26 32 44); + background-color: var(--color-gray-900); } .fade-enter { @@ -298,10 +327,6 @@ blockquote { background-color: inherit; } -.dark .fullwidth-shadow::before { - box-shadow: 0 4px 2px -2px rgb(200 200 200 / 10%); -} - iframe[hidden] { display: none; } @@ -316,10 +341,6 @@ iframe[hidden] { .date-option-group { } /* stylelint-enable */ -.popper-tooltip { - background-color: rgba(25 30 56); -} - .tooltip-arrow, .tooltip-arrow::before { position: absolute; diff --git a/assets/css/chartjs.css b/assets/css/chartjs.css deleted file mode 100644 index 608b938622..0000000000 --- a/assets/css/chartjs.css +++ /dev/null @@ -1,10 +0,0 @@ -.chartjs-tooltip { - background-color: rgb(25 30 56); - position: absolute; - font-size: 14px; - font-style: normal; - padding: 10px 12px; - pointer-events: none; - border-radius: 5px; - z-index: 100; -} diff --git a/assets/js/dashboard/components/combobox.js b/assets/js/dashboard/components/combobox.js index 5c01c5a7c4..17670f2180 100644 --- a/assets/js/dashboard/components/combobox.js +++ b/assets/js/dashboard/components/combobox.js @@ -12,10 +12,9 @@ import { useMountedEffect, useDebounce } from '../custom-hooks' function Option({ isHighlighted, onClick, onMouseEnter, text, id }) { const className = classNames( - 'relative cursor-pointer select-none py-2 px-3', + 'relative cursor-pointer select-none py-2 px-3 text-gray-900 dark:text-gray-300', { - 'text-gray-900 dark:text-gray-300': !isHighlighted, - 'bg-indigo-600 text-white': isHighlighted + 'bg-gray-100 dark:bg-gray-700': isHighlighted } ) @@ -340,9 +339,10 @@ export default function PlausibleCombobox({ } const defaultBoxClass = - 'pl-2 pr-8 py-1 w-full dark:bg-gray-900 dark:text-gray-300 rounded-md shadow-xs border border-gray-300 dark:border-gray-700 focus-within:border-indigo-500 focus-within:ring-1 focus-within:ring-indigo-500' + 'pl-2 pr-8 py-1 w-full dark:bg-gray-750 dark:text-gray-300 rounded-md shadow-xs border border-gray-300 dark:border-gray-750' const finalBoxClass = classNames(boxClass || defaultBoxClass, { - 'border-indigo-500 ring-1 ring-indigo-500': isOpen + 'ring-3 ring-indigo-500/20 dark:ring-indigo-500/25 border !border-indigo-500': + isOpen }) return ( @@ -365,7 +365,7 @@ export default function PlausibleCombobox({ >
- {callToAction.action} -
+ +{callToAction.action}