From e95b87ed8700b586f6734578f263acfd7ad6a6cc Mon Sep 17 00:00:00 2001 From: diondiondion Date: Fri, 17 Jul 2026 10:40:35 +0200 Subject: [PATCH] Add design tokens for 5.0 redesign (#39848) --- .../components/_theme_playground/index.tsx | 1 + .../theme_playground.module.scss | 67 +++++++---- app/javascript/styles/application.scss | 2 +- app/javascript/styles/mastodon/_mixins.scss | 110 ++++++++++++++++++ .../styles/mastodon/_variables.scss | 7 -- .../styles/mastodon/components.scss | 11 +- .../styles/mastodon/tokens/_shape.scss | 22 ++++ .../styles/mastodon/tokens/_type.scss | 25 ++++ .../mastodon/{theme => tokens}/index.scss | 15 ++- .../mastodon/{ => tokens}/theme/_base.scss | 0 .../mastodon/{ => tokens}/theme/_dark.scss | 0 .../mastodon/{ => tokens}/theme/_light.scss | 0 .../mastodon/{ => tokens}/theme/_utils.scss | 0 13 files changed, 221 insertions(+), 39 deletions(-) create mode 100644 app/javascript/styles/mastodon/tokens/_shape.scss create mode 100644 app/javascript/styles/mastodon/tokens/_type.scss rename app/javascript/styles/mastodon/{theme => tokens}/index.scss (67%) rename app/javascript/styles/mastodon/{ => tokens}/theme/_base.scss (100%) rename app/javascript/styles/mastodon/{ => tokens}/theme/_dark.scss (100%) rename app/javascript/styles/mastodon/{ => tokens}/theme/_light.scss (100%) rename app/javascript/styles/mastodon/{ => tokens}/theme/_utils.scss (100%) diff --git a/app/javascript/mastodon/components/_theme_playground/index.tsx b/app/javascript/mastodon/components/_theme_playground/index.tsx index 630ad15af59..efa2d540d26 100644 --- a/app/javascript/mastodon/components/_theme_playground/index.tsx +++ b/app/javascript/mastodon/components/_theme_playground/index.tsx @@ -55,6 +55,7 @@ export const ThemePlayground: React.FC = () => {
Test 1 2 3
+
Hello World
); }; diff --git a/app/javascript/mastodon/components/_theme_playground/theme_playground.module.scss b/app/javascript/mastodon/components/_theme_playground/theme_playground.module.scss index 1e892f9d594..bac775034ae 100644 --- a/app/javascript/mastodon/components/_theme_playground/theme_playground.module.scss +++ b/app/javascript/mastodon/components/_theme_playground/theme_playground.module.scss @@ -1,11 +1,13 @@ +@use '@/styles/mastodon/mixins'; + .wrapper { position: relative; display: grid; grid-template-columns: 250px 1fr; - gap: 1rem; - padding: 2rem; - font-size: 16px; - line-height: 1.5; + gap: var(--space-md); + padding: var(--space-3xl); + font-size: var(--fs-lg); + line-height: var(--lh-normal); overflow-wrap: break-word; color: var(--color-text-primary); background-color: var(--color-bg-blend); @@ -17,18 +19,19 @@ nav { display: block; grid-template-rows: min-content; - font-size: 14px; + font-size: var(--fs-sm); input { display: block; box-sizing: border-box; width: 100%; - margin-block-end: 1rem; - padding: 0.5rem 1rem; + margin-block-end: var(--space-md); + padding: var(--space-xs) var(--space-md); color: var(--color-text-primary); background: transparent; border: 1px solid var(--color-border-primary); - border-radius: 0.5rem; + border-radius: var(--radius-xs); + font: inherit; &:focus { border-color: var(--color-border-brand); @@ -38,9 +41,10 @@ a { display: block; - padding: 0.5rem 1rem 0.45rem; - border-radius: 0.5rem; + padding: var(--space-xs) var(--space-md); + border-radius: var(--radius-xs); color: var(--color-text-secondary); + @include mixins.type-body-compact; &[aria-current='page'] { color: var(--color-text-primary); @@ -55,22 +59,23 @@ 'subtitle button'; grid-template-columns: 1fr min-content; align-items: center; - gap: 0.125rem 0.5rem; - margin-block-start: 1rem; - padding: 0.75rem 1rem; - line-height: 1.2; - border-radius: 1rem; - background-color: var(--color-bg-highlight); + gap: var(--space-3xs) var(--space-xs); + margin-block-start: var(--space-md); + padding: var(--space-sm) var(--space-md); + border-radius: var(--radius-md); + border: 1px solid var(--color-border-primary); h2 { grid-area: title; - font-size: 16px; - font-weight: bold; + @include mixins.type-body; + + line-height: var(--lh-tighter); } .subtitle { grid-area: subtitle; - font-size: 12px; + @include mixins.type-label-sm; + color: var(--color-text-secondary); overflow: hidden; text-overflow: ellipsis; @@ -84,15 +89,31 @@ width: 32px; height: 32px; border: none; - background-color: var(--color-bg-highlight); - border-radius: 99rem; + background-color: transparent; + border-radius: var(--radius-round); + + &:hover { + background-color: var(--color-bg-highlight); + } } } } main { - padding: 2rem; + padding: var(--space-3xl); background-color: var(--color-bg-primary); - border-radius: 1rem; + border-radius: var(--radius-md); + } + + .overlay { + position: absolute; + inset: auto var(--space-md) var(--space-md) auto; + width: 30%; + height: 35%; + padding: var(--space-md); + background-color: var(--color-bg-primary); + border-radius: var(--radius-xl); + + @include mixins.elevation-2; } } diff --git a/app/javascript/styles/application.scss b/app/javascript/styles/application.scss index aca615414f1..bdbe8f067c4 100644 --- a/app/javascript/styles/application.scss +++ b/app/javascript/styles/application.scss @@ -4,7 +4,7 @@ @use 'fonts/roboto-mono'; @use 'mastodon/reset'; -@use 'mastodon/theme'; +@use 'mastodon/tokens'; @use 'mastodon/basics'; @use 'mastodon/branding'; @use 'mastodon/containers'; diff --git a/app/javascript/styles/mastodon/_mixins.scss b/app/javascript/styles/mastodon/_mixins.scss index afc52329f2d..0a12333732a 100644 --- a/app/javascript/styles/mastodon/_mixins.scss +++ b/app/javascript/styles/mastodon/_mixins.scss @@ -1,3 +1,113 @@ +/** + * Type styles + */ + +@mixin type-heading-lg { + // font-family: Syne; + font-size: var(--fs-3xl); + font-weight: bold; + line-height: var(--lh-tighter); + letter-spacing: var(--ls-tighter); +} + +@mixin type-heading-md { + // font-family: Syne; + font-size: var(--fs-2xl); + font-weight: bold; + line-height: var(--lh-tighter); + letter-spacing: var(--ls-tight); +} + +@mixin type-heading-sm { + // font-family: Syne; + font-size: var(--fs-xl); + font-weight: bold; + line-height: var(--lh-tight); + letter-spacing: var(--ls-tight); +} + +@mixin type-body-lg { + // font-family: Inter; + font-size: var(--fs-lg); + font-weight: normal; + line-height: var(--lh-normal); + letter-spacing: var(--ls-normal); +} + +@mixin type-body-strong { + // font-family: Inter; + font-size: var(--fs-md); + font-weight: bold; + line-height: var(--lh-normal); + letter-spacing: var(--ls-normal); +} + +@mixin type-body { + // font-family: Inter; + font-size: var(--fs-md); + font-weight: normal; + line-height: var(--lh-normal); + letter-spacing: var(--ls-normal); +} + +@mixin type-body-compact { + // font-family: Inter; + font-size: var(--fs-sm); + font-weight: normal; + line-height: var(--lh-tight); + letter-spacing: var(--ls-normal); +} + +@mixin type-label-lg { + // font-family: Inter; + font-size: var(--fs-sm); + font-weight: bold; + line-height: var(--lh-tight); + letter-spacing: var(--ls-normal); +} + +@mixin type-label-md { + // font-family: Inter; + font-size: var(--fs-xs); + font-weight: normal; + line-height: var(--lh-tighter); + letter-spacing: var(--ls-loose); +} + +@mixin type-label-sm { + // font-family: Inter; + font-size: var(--fs-2xs); + font-weight: normal; + line-height: var(--lh-tighter); + letter-spacing: var(--ls-loose); +} + +@mixin type-micro { + // font-family: 'JetBrains Mono'; + font-size: var(--fs-3xs); + font-weight: normal; + line-height: var(--lh-tighter); + letter-spacing: var(--ls-looser); +} + +/** + * Elevation styles + */ + +@mixin elevation-1 { + border: 1px solid var(--color-border-strong); + box-shadow: 0 1px 0 var(--color-border-strong); +} + +@mixin elevation-2 { + border: 1px solid var(--color-border-strong); + box-shadow: 1px 2px 0 var(--color-border-strong); +} + +/** + * Search input styles + */ + @mixin search-input { box-sizing: border-box; width: 100%; diff --git a/app/javascript/styles/mastodon/_variables.scss b/app/javascript/styles/mastodon/_variables.scss index 7a947891d52..f0b12a373ff 100644 --- a/app/javascript/styles/mastodon/_variables.scss +++ b/app/javascript/styles/mastodon/_variables.scss @@ -9,17 +9,10 @@ $cjk-langs: ja, ko, zh-CN, zh-HK, zh-TW; // Language codes that is written vertically $vertical-lr-langs: mn-Mong; -// Variables for components -$media-modal-media-max-width: 100%; - -// put margins on top and bottom of image to avoid the screen covered by image. -$media-modal-media-max-height: 80%; - $no-gap-breakpoint: 1175px; $mobile-menu-breakpoint: 760px; $mobile-breakpoint: 630px; $no-columns-breakpoint: 600px; $font-sans-serif: 'mastodon-font-sans-serif' !default; -$font-display: 'mastodon-font-display' !default; $font-monospace: 'mastodon-font-monospace' !default; diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 537afdb1a98..b7c4efc172b 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -2688,6 +2688,9 @@ a.account__display-name { } .zoomable-image { + --media-max-width: 100%; + --media-max-height: 80%; + position: relative; width: 100%; height: 100%; @@ -2699,8 +2702,8 @@ a.account__display-name { user-select: none; img { - max-width: $media-modal-media-max-width; - max-height: $media-modal-media-max-height; + max-width: var(--media-max-width); + max-height: var(--media-max-height); width: auto; height: auto; outline: 1px solid var(--color-border-media); @@ -2729,8 +2732,8 @@ a.account__display-name { } &__preview { - max-width: $media-modal-media-max-width; - max-height: $media-modal-media-max-height; + max-width: var(--media-max-width); + max-height: var(--media-max-height); position: absolute; z-index: 1; outline: 1px solid var(--color-border-media); diff --git a/app/javascript/styles/mastodon/tokens/_shape.scss b/app/javascript/styles/mastodon/tokens/_shape.scss new file mode 100644 index 00000000000..66f1cb96b9c --- /dev/null +++ b/app/javascript/styles/mastodon/tokens/_shape.scss @@ -0,0 +1,22 @@ +@mixin space { + --space-3xs: 2px; + --space-2xs: 4px; + --space-xs: 8px; + --space-sm: 12px; + --space-md: 16px; + --space-lg: 20px; + --space-xl: 24px; + --space-2xl: 28px; + --space-3xl: 32px; + --space-4xl: 36px; + --space-5xl: 40px; +} + +@mixin radius { + --radius-xs: 8px; + --radius-sm: 12px; + --radius-md: 16px; + --radius-lg: 20px; + --radius-xl: 28px; + --radius-round: calc(1px * infinity); +} diff --git a/app/javascript/styles/mastodon/tokens/_type.scss b/app/javascript/styles/mastodon/tokens/_type.scss new file mode 100644 index 00000000000..99865d5d6ff --- /dev/null +++ b/app/javascript/styles/mastodon/tokens/_type.scss @@ -0,0 +1,25 @@ +@mixin font-size { + --fs-3xs: 0.6875rem; // 11px + --fs-2xs: 0.75rem; // 12px + --fs-xs: 0.8125rem; // 13px + --fs-sm: 0.875rem; // 14px + --fs-md: 0.9375rem; // 15px + --fs-lg: 1rem; // 16px + --fs-xl: 1.25rem; // 20px + --fs-2xl: 1.375rem; // 22px + --fs-3xl: 1.625rem; // 26px +} + +@mixin line-height { + --lh-tighter: 1.3; + --lh-tight: 1.4; + --lh-normal: 1.6; +} + +@mixin letter-spacing { + --ls-tighter: -0.02em; + --ls-tight: -0.01em; + --ls-normal: 0; + --ls-loose: 0.01em; + --ls-looser: 0.02em; +} diff --git a/app/javascript/styles/mastodon/theme/index.scss b/app/javascript/styles/mastodon/tokens/index.scss similarity index 67% rename from app/javascript/styles/mastodon/theme/index.scss rename to app/javascript/styles/mastodon/tokens/index.scss index a84b8b80da2..d0e283d27a7 100644 --- a/app/javascript/styles/mastodon/theme/index.scss +++ b/app/javascript/styles/mastodon/tokens/index.scss @@ -1,10 +1,17 @@ -@use 'base'; -@use 'dark'; -@use 'light'; -@use 'utils'; +@use 'theme/base'; +@use 'theme/dark'; +@use 'theme/light'; +@use 'theme/utils'; +@use 'shape'; +@use 'type'; html { @include base.palette; + @include shape.space; + @include shape.radius; + @include type.font-size; + @include type.line-height; + @include type.letter-spacing; } [data-color-scheme='dark'], diff --git a/app/javascript/styles/mastodon/theme/_base.scss b/app/javascript/styles/mastodon/tokens/theme/_base.scss similarity index 100% rename from app/javascript/styles/mastodon/theme/_base.scss rename to app/javascript/styles/mastodon/tokens/theme/_base.scss diff --git a/app/javascript/styles/mastodon/theme/_dark.scss b/app/javascript/styles/mastodon/tokens/theme/_dark.scss similarity index 100% rename from app/javascript/styles/mastodon/theme/_dark.scss rename to app/javascript/styles/mastodon/tokens/theme/_dark.scss diff --git a/app/javascript/styles/mastodon/theme/_light.scss b/app/javascript/styles/mastodon/tokens/theme/_light.scss similarity index 100% rename from app/javascript/styles/mastodon/theme/_light.scss rename to app/javascript/styles/mastodon/tokens/theme/_light.scss diff --git a/app/javascript/styles/mastodon/theme/_utils.scss b/app/javascript/styles/mastodon/tokens/theme/_utils.scss similarity index 100% rename from app/javascript/styles/mastodon/theme/_utils.scss rename to app/javascript/styles/mastodon/tokens/theme/_utils.scss