Add Forgejo theme and homepage
This commit is contained in:
commit
92363fca9b
31 changed files with 4044 additions and 0 deletions
494
themes/theme-neumorphism.css
Normal file
494
themes/theme-neumorphism.css
Normal file
|
|
@ -0,0 +1,494 @@
|
|||
/*
|
||||
* theme-neumorphism.css
|
||||
* ─────────────────────────────────────────────────────────────────────────
|
||||
* Shared "soft UI" / neumorphic layer for Forgejo.
|
||||
*
|
||||
* This file contains no palette of its own — it only defines soft-shadow
|
||||
* primitives and restyles components to look extruded or recessed. Import it
|
||||
* at the TOP of a theme (right after the base palette import) and then set the
|
||||
* --nm-* primitives + colours in that theme's :root.
|
||||
*
|
||||
* Themes that import this: gruvbox-dark, gruvbox-light, terminal,
|
||||
* forgejo-dark, forgejo-light, forgejo-auto.
|
||||
*/
|
||||
|
||||
:root {
|
||||
/* Derived primitives — themes override --nm-shadow-* / --nm-radius */
|
||||
--nm-bg: var(--color-body, #282828);
|
||||
--nm-radius: 14px;
|
||||
--nm-radius-sm: 10px;
|
||||
--nm-raised: 7px 7px 16px var(--nm-shadow-dark, rgba(0, 0, 0, 0.5)),
|
||||
-7px -7px 16px var(--nm-shadow-light, rgba(255, 255, 255, 0.05));
|
||||
--nm-raised-sm: 4px 4px 10px var(--nm-shadow-dark, rgba(0, 0, 0, 0.45)),
|
||||
-4px -4px 10px var(--nm-shadow-light, rgba(255, 255, 255, 0.04));
|
||||
/* Buttons sit between the two — clearly lifted, but not chunky */
|
||||
--nm-raised-xs: 2px 2px 5px var(--nm-shadow-dark, rgba(0, 0, 0, 0.4)),
|
||||
-2px -2px 5px var(--nm-shadow-light, rgba(255, 255, 255, 0.04));
|
||||
--nm-inset: inset 5px 5px 12px var(--nm-shadow-dark, rgba(0, 0, 0, 0.5)),
|
||||
inset -5px -5px 12px var(--nm-shadow-light, rgba(255, 255, 255, 0.05));
|
||||
--nm-inset-sm: inset 3px 3px 7px var(--nm-shadow-dark, rgba(0, 0, 0, 0.45)),
|
||||
inset -3px -3px 7px var(--nm-shadow-light, rgba(255, 255, 255, 0.04));
|
||||
--nm-flat: 2px 2px 4px var(--nm-shadow-dark, rgba(0, 0, 0, 0.4)),
|
||||
-2px -2px 4px var(--nm-shadow-light, rgba(255, 255, 255, 0.04));
|
||||
--nm-divider: var(--nm-divider-color, rgba(255, 255, 255, 0.07));
|
||||
--nm-ease: cubic-bezier(0.2, 0.7, 0.3, 1);
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════
|
||||
Surfaces — raised soft panels
|
||||
═══════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
.ui.segment,
|
||||
.ui.segments,
|
||||
.ui.secondary.segment,
|
||||
.ui.tertiary.segment,
|
||||
.ui.raised.segment,
|
||||
.ui.stacked.segment,
|
||||
.ui.card,
|
||||
.ui.cards > .card,
|
||||
.ui.message,
|
||||
.repository .repo-header,
|
||||
.ui.modal,
|
||||
.ui.popup,
|
||||
.ui.fluid.popup,
|
||||
.ui.dropdown .menu {
|
||||
background: var(--color-box-body, var(--color-secondary-bg)) !important;
|
||||
border: 1px solid transparent !important;
|
||||
border-radius: var(--nm-radius) !important;
|
||||
box-shadow: var(--nm-raised) !important;
|
||||
}
|
||||
|
||||
/* Nested / attached pieces are part of a parent panel. Keep them flat so we
|
||||
never stack soft shadows (repo summary + tab bar, attached tables, rows
|
||||
inside a segments group, ...). One panel = one shadow. */
|
||||
.ui.attached.segment,
|
||||
.ui.attached.header,
|
||||
.ui.attached.table,
|
||||
.ui.top.attached.segment,
|
||||
.ui.middle.attached.segment,
|
||||
.ui.bottom.attached.segment,
|
||||
.ui.segments > .ui.segment,
|
||||
.ui.segments .ui.segment {
|
||||
background: transparent !important;
|
||||
border-radius: 0 !important;
|
||||
border-color: var(--nm-divider) !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.ui.card,
|
||||
.ui.cards > .card {
|
||||
transition: box-shadow 0.2s var(--nm-ease), transform 0.2s var(--nm-ease);
|
||||
}
|
||||
.ui.card:hover,
|
||||
.ui.cards > .card:hover {
|
||||
box-shadow: var(--nm-raised), 0 0 0 1px var(--color-primary-alpha-20, transparent) !important;
|
||||
}
|
||||
|
||||
/* Headings inside boxes */
|
||||
.ui.segment > .ui.header,
|
||||
.ui.attached.header,
|
||||
.ui.header.segment {
|
||||
background: transparent !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════
|
||||
Buttons — extruded, pressed state sinks in
|
||||
═══════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
.ui.button,
|
||||
.ui.buttons .button {
|
||||
background: var(--color-box-body, var(--color-button)) !important;
|
||||
color: var(--color-text) !important;
|
||||
border: 1px solid transparent !important;
|
||||
border-radius: var(--nm-radius-sm) !important;
|
||||
box-shadow: var(--nm-raised-xs) !important;
|
||||
font-weight: 500 !important;
|
||||
text-transform: none !important;
|
||||
transition: box-shadow 0.16s var(--nm-ease), color 0.16s var(--nm-ease),
|
||||
filter 0.16s var(--nm-ease);
|
||||
}
|
||||
.ui.button:hover,
|
||||
.ui.buttons .button:hover {
|
||||
color: var(--color-primary) !important;
|
||||
box-shadow: var(--nm-raised-sm) !important;
|
||||
}
|
||||
.ui.button:active,
|
||||
.ui.buttons .button:active {
|
||||
box-shadow: var(--nm-inset-sm) !important;
|
||||
transform: none !important;
|
||||
}
|
||||
|
||||
.ui.primary.button,
|
||||
.ui.primary.buttons .button,
|
||||
.ui.primary.label {
|
||||
background: linear-gradient(
|
||||
145deg,
|
||||
var(--color-primary-light-1, var(--color-primary)),
|
||||
var(--color-primary)
|
||||
) !important;
|
||||
color: var(--color-primary-contrast, #101010) !important;
|
||||
border: 1px solid transparent !important;
|
||||
font-weight: 600 !important;
|
||||
box-shadow: var(--nm-raised-xs), 0 0 0 1px var(--color-primary-alpha-20, transparent) !important;
|
||||
}
|
||||
.ui.primary.button:hover,
|
||||
.ui.primary.buttons .button:hover {
|
||||
filter: brightness(1.06);
|
||||
color: var(--color-primary-contrast, #101010) !important;
|
||||
box-shadow: var(--nm-raised-sm), 0 0 0 1px var(--color-primary-alpha-40, transparent) !important;
|
||||
}
|
||||
.ui.primary.button:active {
|
||||
filter: brightness(0.95);
|
||||
box-shadow: var(--nm-inset-sm) !important;
|
||||
}
|
||||
|
||||
/* Ghost / basic buttons: no extrusion until hover */
|
||||
.ui.basic.button,
|
||||
.ui.basic.buttons .button {
|
||||
background: transparent !important;
|
||||
color: var(--color-text-light, var(--color-text)) !important;
|
||||
border: 1px solid var(--nm-divider) !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
.ui.basic.button:hover,
|
||||
.ui.basic.buttons .button:hover {
|
||||
background: transparent !important;
|
||||
color: var(--color-primary) !important;
|
||||
border-color: var(--color-primary-alpha-40, var(--color-primary)) !important;
|
||||
box-shadow: var(--nm-flat) !important;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════
|
||||
Inputs — recessed wells
|
||||
═══════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
input,
|
||||
textarea,
|
||||
select,
|
||||
.ui.input input,
|
||||
.ui.form input:not([type="checkbox"]):not([type="radio"]),
|
||||
.ui.form textarea,
|
||||
.ui.form select,
|
||||
.ui.search input,
|
||||
.ui.action.input input,
|
||||
.CodeMirror {
|
||||
background: var(--color-body, var(--nm-bg)) !important;
|
||||
color: var(--color-input-text, var(--color-text)) !important;
|
||||
border: 1px solid transparent !important;
|
||||
border-radius: var(--nm-radius-sm) !important;
|
||||
box-shadow: var(--nm-inset-sm) !important;
|
||||
}
|
||||
input::placeholder,
|
||||
textarea::placeholder,
|
||||
.ui.input input::placeholder {
|
||||
color: var(--color-placeholder-text, var(--color-text-light-3)) !important;
|
||||
}
|
||||
input:focus,
|
||||
textarea:focus,
|
||||
select:focus,
|
||||
.ui.input input:focus,
|
||||
.ui.form input:focus,
|
||||
.ui.form textarea:focus,
|
||||
.ui.search input:focus {
|
||||
border-color: transparent !important;
|
||||
box-shadow: var(--nm-inset-sm),
|
||||
0 0 0 2px var(--color-primary-alpha-30, transparent) !important;
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════
|
||||
Input groups (clone panel, code search, explore search)
|
||||
One integrated well instead of separate extruded buttons floating next
|
||||
to a recessed input.
|
||||
═══════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
.ui.action.input {
|
||||
background: var(--color-box-body, var(--color-secondary-bg)) !important;
|
||||
border-radius: var(--nm-radius-sm) !important;
|
||||
box-shadow: var(--nm-inset-sm) !important;
|
||||
overflow: visible !important;
|
||||
align-items: stretch !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
/* Every segment is transparent on ONE shared rounded surface. Because no
|
||||
child paints an opaque rectangle, the outer corners always follow the
|
||||
group's radius — a child can never square them off. */
|
||||
.ui.action.input > input,
|
||||
.ui.action.input > .button,
|
||||
.ui.action.input > .buttons .button,
|
||||
.ui.action.input > .ui.dropdown,
|
||||
.ui.action.input > .ui.selection.dropdown {
|
||||
background: transparent !important;
|
||||
color: var(--color-text) !important;
|
||||
border: none !important;
|
||||
border-radius: 0 !important;
|
||||
box-shadow: none !important;
|
||||
margin: 0 !important;
|
||||
align-self: stretch !important;
|
||||
}
|
||||
.ui.action.input > input {
|
||||
flex: 1 1 auto !important;
|
||||
min-width: 0 !important;
|
||||
}
|
||||
.ui.action.input > .ui.dropdown .text,
|
||||
.ui.action.input > .ui.dropdown .dropdown.icon,
|
||||
.ui.action.input > .ui.dropdown .search.icon,
|
||||
.ui.action.input > .ui.dropdown .delete.icon {
|
||||
color: var(--color-text) !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
/* The search-type selector hugs its label instead of the 10em default. */
|
||||
.ui.action.input > .ui.dropdown.selection {
|
||||
min-width: 0 !important;
|
||||
width: auto !important;
|
||||
}
|
||||
/* Hairline separators. */
|
||||
.ui.action.input > :not(:first-child) {
|
||||
border-left: 1px solid var(--nm-divider) !important;
|
||||
}
|
||||
/* Hover = colour only, never an opaque block. */
|
||||
.ui.action.input .button:hover,
|
||||
.ui.action.input > .ui.dropdown.selection:hover,
|
||||
.ui.action.input > .ui.dropdown.selection:hover .text,
|
||||
.ui.action.input > .ui.dropdown.selection:hover .dropdown.icon {
|
||||
color: var(--color-primary) !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
.ui.action.input:focus-within {
|
||||
box-shadow: var(--nm-inset-sm),
|
||||
0 0 0 2px var(--color-primary-alpha-30, transparent) !important;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════
|
||||
Navigation & footer — soft, borderless
|
||||
═══════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
.navbar,
|
||||
#navbar,
|
||||
nav.navbar,
|
||||
.ui.menu.navbar,
|
||||
.ui.secondary.menu.navbar {
|
||||
background: var(--color-nav-bg, var(--color-body)) !important;
|
||||
border: none !important;
|
||||
box-shadow: 0 8px 18px -12px var(--nm-shadow-dark, rgba(0, 0, 0, 0.6)) !important;
|
||||
}
|
||||
|
||||
.page-footer,
|
||||
footer,
|
||||
.ui.page-footer {
|
||||
background: var(--color-footer, var(--color-body)) !important;
|
||||
border: none !important;
|
||||
box-shadow: 0 -8px 18px -14px var(--nm-shadow-dark, rgba(0, 0, 0, 0.6)) !important;
|
||||
}
|
||||
|
||||
.ui.tabular.menu,
|
||||
.ui.secondary.pointing.menu {
|
||||
border: none !important;
|
||||
}
|
||||
.ui.tabular.menu .active.item,
|
||||
.ui.secondary.pointing.menu .active.item {
|
||||
background: transparent !important;
|
||||
border-color: var(--color-primary) !important;
|
||||
color: var(--color-primary) !important;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════
|
||||
Menus, sidebar, breadcrumbs
|
||||
═══════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
.ui.vertical.menu,
|
||||
.ui.fluid.vertical.menu,
|
||||
.ui.secondary.vertical.menu,
|
||||
.settings .ui.menu {
|
||||
background: transparent !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
.ui.vertical.menu .item {
|
||||
border: none !important;
|
||||
border-radius: var(--nm-radius-sm) !important;
|
||||
color: var(--color-text-light, var(--color-text)) !important;
|
||||
transition: box-shadow 0.16s var(--nm-ease), color 0.16s var(--nm-ease);
|
||||
}
|
||||
.ui.vertical.menu .item:hover {
|
||||
box-shadow: var(--nm-raised-xs) !important;
|
||||
color: var(--color-text) !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
.ui.vertical.menu .active.item,
|
||||
.ui.vertical.menu .item.active {
|
||||
background: transparent !important;
|
||||
color: var(--color-primary) !important;
|
||||
box-shadow: var(--nm-inset-sm) !important;
|
||||
}
|
||||
|
||||
.ui.dropdown .menu > .item,
|
||||
.ui.popup .item {
|
||||
border: none !important;
|
||||
}
|
||||
.ui.dropdown .menu > .item:hover,
|
||||
.ui.dropdown .menu > .item.active,
|
||||
.ui.popup .item:hover {
|
||||
background: var(--color-primary-alpha-10, rgba(127, 127, 127, 0.12)) !important;
|
||||
color: var(--color-primary) !important;
|
||||
border-radius: var(--nm-radius-sm) !important;
|
||||
}
|
||||
|
||||
.ui.divider {
|
||||
border-color: var(--nm-divider) !important;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════
|
||||
Tables — one raised sheet, recessed header
|
||||
═══════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
.ui.table {
|
||||
background: var(--color-box-body, var(--color-secondary-bg)) !important;
|
||||
border: none !important;
|
||||
border-radius: var(--nm-radius-sm) !important;
|
||||
/* No extrusion — tables usually live inside a raised segment already, and
|
||||
stacked shadows are what made list pages look off. */
|
||||
box-shadow: none !important;
|
||||
}
|
||||
.ui.table thead th,
|
||||
.ui.table > thead > tr > th {
|
||||
background: transparent !important;
|
||||
border-color: var(--nm-divider) !important;
|
||||
color: var(--color-text-light, var(--color-text)) !important;
|
||||
box-shadow: inset 0 -1px 0 var(--nm-divider);
|
||||
}
|
||||
.ui.table > tbody > tr > td {
|
||||
background: transparent !important;
|
||||
border-color: var(--nm-divider) !important;
|
||||
}
|
||||
.ui.table tbody tr:hover td {
|
||||
background: var(--color-primary-alpha-10, rgba(127, 127, 127, 0.08)) !important;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════
|
||||
Labels, badges, avatars
|
||||
═══════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
.ui.label,
|
||||
.ui.labels .label {
|
||||
border: 1px solid transparent !important;
|
||||
border-radius: 999px !important;
|
||||
/* Flat pills: soft shadows on every badge turn busy lists into noise. */
|
||||
box-shadow: none !important;
|
||||
}
|
||||
.ui.basic.label {
|
||||
background: transparent !important;
|
||||
box-shadow: none !important;
|
||||
border: 1px solid var(--nm-divider) !important;
|
||||
}
|
||||
|
||||
.ui.avatar,
|
||||
.avatar,
|
||||
img.ui.avatar,
|
||||
.repository .small-thumbnail,
|
||||
.repo-avatar {
|
||||
border: 1px solid var(--nm-divider) !important;
|
||||
border-radius: var(--nm-radius-sm) !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════
|
||||
Messages — raised with a soft accent edge
|
||||
═══════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
.ui.message {
|
||||
box-shadow: var(--nm-raised), inset 4px 0 0 var(--color-primary-alpha-40, transparent) !important;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════
|
||||
Pagination, progress, code, scrollbars
|
||||
═══════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
.ui.pagination.menu {
|
||||
background: transparent !important;
|
||||
box-shadow: none !important;
|
||||
border: none !important;
|
||||
}
|
||||
.ui.pagination.menu .item {
|
||||
border: none !important;
|
||||
border-radius: var(--nm-radius-sm) !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
.ui.pagination.menu .active.item {
|
||||
background: linear-gradient(145deg, var(--color-primary-light-1, var(--color-primary)), var(--color-primary)) !important;
|
||||
color: var(--color-primary-contrast, #101010) !important;
|
||||
box-shadow: var(--nm-raised-sm) !important;
|
||||
}
|
||||
|
||||
.progress,
|
||||
.ui.progress {
|
||||
background: var(--color-body) !important;
|
||||
border-radius: 999px !important;
|
||||
box-shadow: var(--nm-inset-sm) !important;
|
||||
}
|
||||
.progress .bar,
|
||||
.ui.progress .bar {
|
||||
background: linear-gradient(90deg, var(--color-primary), var(--color-primary-light-1, var(--color-primary))) !important;
|
||||
border-radius: 999px !important;
|
||||
}
|
||||
|
||||
/* Block code: recess the rectangle that holds the code, never the text.
|
||||
Inline `code` and the text inside a block stay flat, so an empty line or a
|
||||
short snippet never gets its own hugging shadow. */
|
||||
pre,
|
||||
.code-view {
|
||||
border-radius: var(--nm-radius-sm) !important;
|
||||
box-shadow: var(--nm-inset-sm) !important;
|
||||
}
|
||||
code,
|
||||
pre code,
|
||||
pre > code,
|
||||
.highlight code,
|
||||
.code-view .lines-code,
|
||||
.markup,
|
||||
.file-content {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
* {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--color-secondary, var(--nm-divider)) transparent;
|
||||
}
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--color-secondary, var(--nm-divider));
|
||||
border-radius: 999px;
|
||||
}
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--color-primary-alpha-40, var(--color-secondary));
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════════
|
||||
Misc polish
|
||||
═══════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
.flex-item,
|
||||
.repository.file.list .file-row {
|
||||
border-color: var(--nm-divider) !important;
|
||||
}
|
||||
:focus-visible {
|
||||
outline: 2px solid var(--color-primary) !important;
|
||||
outline-offset: 2px !important;
|
||||
}
|
||||
|
||||
/* Respect users who prefer less motion */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.ui.button,
|
||||
.ui.card,
|
||||
.ui.cards > .card {
|
||||
transition: none !important;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue