Applets: retitle My Sky → SkyDrive + My Sea → Sea of Cards w. planetary recolor; match the gear-menu entries — TDD
Some checks failed
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline failed

Applet titles + gear-menu toggle labels (Applet.name, via data migration 0014)
both retitled — a deliberate departure from the "My X" applet convention for
these two surfaces. Slugs (my-sky / my-sea) stay put.

Recolor (applet shells only — the standalone pages are tomorrow's todo):
• SkyDrive (uranium ramp): --sixU light-green title font, --priU deep-green
  shell bg; hover keeps the palette --ninUser highlight, glow takes the --sixU
  tint. Reverses to --priU font / --sixU bg on *-light palettes.
• Sea of Cards (neptunium ramp): --sixNp light-teal font, --priNp deep-teal shell;
  the conjunction "of" is a lowercase-italic span against the h2 uppercase
  transform. Reverses to --priNp / --sixNp on *-light palettes.

Mechanism: the shared applet title-link rule now reads --applet-title-fg (with a
--terUser fallback so every other applet is untouched); each applet sets that +
--applet-shell-bg, and a body[class*="-light"] override swaps the pair. No
specificity war.

Tests: data migration 0014 (reversible); FT/IT applet seeds + the My Sky heading
assertion updated to the new names; 531 dashboard/gameboard/applets ITs green.

[[feedback-applet-vs-page-naming-convention]] [[feedback-scss-id-context-specificity-trap]]

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Disco DeDisco
2026-06-08 01:29:29 -04:00
parent 945d110171
commit 564100cadb
9 changed files with 97 additions and 21 deletions

View File

@@ -0,0 +1,33 @@
"""Retitle the My Sky + My Sea applets — "SkyDrive" / "Sea of Cards".
User-spec 2026-06-08: the Sky/Sea applets get distinct planetary identities
(SkyDrive on the uranium ramp, Sea of Cards on the neptunium ramp). This updates
the gear-menu toggle label, which renders `Applet.name` (the applet h2 titles are
hardcoded in the partials and were changed alongside). A deliberate departure
from the "My X" applet-naming convention (see migration 0010) for these two
surfaces. Slugs (my-sky / my-sea) stay put — URLs + selectors unchanged.
"""
from django.db import migrations
def rename(apps, schema_editor):
Applet = apps.get_model("applets", "Applet")
Applet.objects.filter(slug="my-sky").update(name="SkyDrive")
Applet.objects.filter(slug="my-sea").update(name="Sea of Cards")
def unrename(apps, schema_editor):
Applet = apps.get_model("applets", "Applet")
Applet.objects.filter(slug="my-sky").update(name="My Sky")
Applet.objects.filter(slug="my-sea").update(name="My Sea")
class Migration(migrations.Migration):
dependencies = [
("applets", "0013_wallet_shop_display_order"),
]
operations = [
migrations.RunPython(rename, unrename),
]

View File

@@ -98,7 +98,7 @@ class StargazerNoteFromDashboardTest(FunctionalTest):
self.browser.set_window_size(800, 1200)
Applet.objects.get_or_create(
slug="my-sky",
defaults={"name": "My Sky", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
defaults={"name": "SkyDrive", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
)
Applet.objects.get_or_create(
slug="palette",
@@ -331,7 +331,7 @@ class StargazerNoteFromSkyPageTest(FunctionalTest):
self.browser.set_window_size(800, 1200)
Applet.objects.get_or_create(
slug="my-sky",
defaults={"name": "My Sky", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
defaults={"name": "SkyDrive", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
)
Applet.objects.get_or_create(
slug="notes",

View File

@@ -55,7 +55,7 @@ class MySkyAppletTest(FunctionalTest):
super().setUp()
Applet.objects.get_or_create(
slug="my-sky",
defaults={"name": "My Sky", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
defaults={"name": "SkyDrive", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
)
self.gamer = User.objects.create(email="stargazer@test.io")
@@ -72,9 +72,10 @@ class MySkyAppletTest(FunctionalTest):
lambda: self.browser.find_element(By.ID, "id_applet_my_sky")
)
# 2. Heading contains a link whose text is "My Sky"
# 2. Heading contains a link whose text is "SkyDrive" (applet retitled
# 2026-06-08; the h2's uppercase transform renders it SKYDRIVE)
link = applet.find_element(By.CSS_SELECTOR, "h2 a")
self.assertIn("MY SKY", link.text.upper())
self.assertIn("SKYDRIVE", link.text.upper())
# 3. Clicking the link navigates to /dashboard/sky/
link.click()
@@ -99,7 +100,7 @@ class MySkyLocalStorageTest(FunctionalTest):
super().setUp()
Applet.objects.get_or_create(
slug="my-sky",
defaults={"name": "My Sky", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
defaults={"name": "SkyDrive", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
)
self.gamer = User.objects.create(email="stargazer@test.io")
self.sky_url = self.live_server_url + "/dashboard/sky/"
@@ -161,7 +162,7 @@ class MySkyAppletWheelTest(FunctionalTest):
super().setUp()
Applet.objects.get_or_create(
slug="my-sky",
defaults={"name": "My Sky", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
defaults={"name": "SkyDrive", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
)
self.gamer = User.objects.create(email="stargazer@test.io")
self.gamer.sky_chart_data = _CHART_FIXTURE
@@ -207,7 +208,7 @@ class MySkyAppletFormTest(FunctionalTest):
super().setUp()
Applet.objects.get_or_create(
slug="my-sky",
defaults={"name": "My Sky", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
defaults={"name": "SkyDrive", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
)
self.gamer = User.objects.create(email="stargazer@test.io")
@@ -306,7 +307,7 @@ class MySkyTimezoneRefreshTest(FunctionalTest):
super().setUp()
Applet.objects.get_or_create(
slug="my-sky",
defaults={"name": "My Sky", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
defaults={"name": "SkyDrive", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
)
self.gamer = User.objects.create(email="stargazer@test.io")
self.gamer.sky_chart_data = _CHART_FIXTURE
@@ -381,7 +382,7 @@ class MySkyApertureSnapScrollTest(FunctionalTest):
super().setUp()
Applet.objects.get_or_create(
slug="my-sky",
defaults={"name": "My Sky", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
defaults={"name": "SkyDrive", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
)
self.gamer = User.objects.create(email="stargazer@test.io")
self.gamer.sky_chart_data = _CHART_FIXTURE
@@ -477,7 +478,7 @@ class MySkyAppletDelTest(FunctionalTest):
super().setUp()
Applet.objects.get_or_create(
slug="my-sky",
defaults={"name": "My Sky", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
defaults={"name": "SkyDrive", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
)
self.gamer = User.objects.create(email="stargazer@test.io")
self.gamer.sky_chart_data = _CHART_FIXTURE
@@ -539,7 +540,7 @@ class MySkyAsyncSaveTest(FunctionalTest):
super().setUp()
Applet.objects.get_or_create(
slug="my-sky",
defaults={"name": "My Sky", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
defaults={"name": "SkyDrive", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
)
self.gamer = User.objects.create(email="newcomer@test.io")
self.sky_url = self.live_server_url + "/dashboard/sky/"
@@ -611,7 +612,7 @@ class MySkyDeleteFlowTest(FunctionalTest):
super().setUp()
Applet.objects.get_or_create(
slug="my-sky",
defaults={"name": "My Sky", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
defaults={"name": "SkyDrive", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
)
self.gamer = User.objects.create(email="stargazer@test.io")
self.gamer.sky_chart_data = _CHART_FIXTURE
@@ -717,7 +718,7 @@ class MySkyWheelConjunctionTest(FunctionalTest):
super().setUp()
Applet.objects.get_or_create(
slug="my-sky",
defaults={"name": "My Sky", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
defaults={"name": "SkyDrive", "grid_cols": 6, "grid_rows": 6, "context": "dashboard"},
)
self.gamer = User.objects.create(email="stargazer@test.io")
self.gamer.sky_chart_data = _CHART_FIXTURE

View File

@@ -60,7 +60,7 @@ def _seed_gameboard_applets():
Mirrors the migration seed (0003 + 0008) — every slug must have a
matching _applet-<slug>.html partial under apps/gameboard/_partials/."""
for slug, name, cols, rows, ctx in [
("my-sea", "My Sea", 12, 4, "gameboard"),
("my-sea", "Sea of Cards", 12, 4, "gameboard"),
("game-kit", "Game Kit", 4, 3, "gameboard"),
("new-game", "New Game", 4, 3, "gameboard"),
("my-games", "My Games", 4, 4, "gameboard"),

View File

@@ -288,12 +288,17 @@
z-index: 1;
a {
color: rgba(var(--terUser), 1);
// Per-applet title tint: an applet may set --applet-title-fg (e.g.
// SkyDrive --sixU, Sea of Cards --sixNp) to recolor the link AND its
// hover glow; applets that don't fall back to the shared --terUser
// (unchanged). The hover COLOR stays the palette --ninUser highlight
// either way.
color: rgba(var(--applet-title-fg, var(--terUser)), 1);
text-decoration: none;
&:hover {
color: rgba(var(--ninUser), 1);
text-shadow: 0 0 0.5rem rgba(var(--terUser), 1);
text-shadow: 0 0 0.5rem rgba(var(--applet-title-fg, var(--terUser)), 1);
}
}
}

View File

@@ -952,7 +952,21 @@ body.page-gameboard {
flex-direction: column;
// Anchor for #id_applet_sky_delete_btn's absolute centering.
position: relative;
background-color: rgba(var(--duoUser), 1) !important;
// Sea of Cards (neptunium ramp): a --sixNp light-teal title font over a
// --priNp deep-teal shell. The pair REVERSES on *-light palettes — see the
// body[class*="-light"] override below. --applet-title-fg is read by the
// shared applet title-link rule (_applets.scss); the hover keeps the palette
// --ninUser highlight, only its glow takes the --sixNp tint.
--applet-title-fg: var(--sixNp);
--applet-shell-bg: var(--priNp);
background-color: rgba(var(--applet-shell-bg), 1) !important;
// "Sea of Cards" — the conjunction stays lowercase + italic against the h2's
// uppercase transform (user-spec 2026-06-08).
> h2 .my-sea-title-of {
text-transform: none;
font-style: italic;
}
h2 {
flex-shrink: 0;
@@ -1216,3 +1230,11 @@ body.page-gameboard {
margin: 0;
}
}
// *-light palettes: reverse the Sea of Cards --sixNp/--priNp pair (deep --priNp
// to the title font + glow, light --sixNp to the shell bg). Higher specificity
// than #id_applet_my_sea.
body[class*="-light"] #id_applet_my_sea {
--applet-title-fg: var(--priNp);
--applet-shell-bg: var(--sixNp);
}

View File

@@ -1113,7 +1113,14 @@ body[class*="-light"] #id_sky_tooltip_2 {
flex-direction: column;
// Anchor for #id_applet_sky_delete_btn's absolute centering.
position: relative;
background-color: rgba(var(--duoUser), 1) !important;
// SkyDrive (uranium ramp): a --sixU light-green title font over a --priU
// deep-green shell. The pair REVERSES on *-light palettes (a deep bg swamps
// a light page) — see the body[class*="-light"] override below. --applet-
// title-fg is read by the shared applet title-link rule (_applets.scss); the
// hover keeps the palette --ninUser highlight, only its glow takes the tint.
--applet-title-fg: var(--sixU);
--applet-shell-bg: var(--priU);
background-color: rgba(var(--applet-shell-bg), 1) !important;
h2 {
flex-shrink: 0;
@@ -1155,6 +1162,14 @@ body[class*="-light"] #id_sky_tooltip_2 {
}
}
// *-light palettes: reverse the SkyDrive --sixU/--priU pair so the deep --priU
// drops to the title font + glow and the light --sixU lifts to the shell bg
// (legible against a light page). Higher specificity than #id_applet_my_sky.
body[class*="-light"] #id_applet_my_sky {
--applet-title-fg: var(--priU);
--applet-shell-bg: var(--sixU);
}
// ── Sky full page (column layout) ─────────────────────────────────────────
//
// Aperture foundation lives universally in _base.scss; nothing sky-specific

View File

@@ -6,7 +6,7 @@
data-save-url="{% url 'sky_save' %}"
style="--applet-cols: {{ entry.applet.grid_cols }}; --applet-rows: {{ entry.applet.grid_rows }};"
>
<h2><a href="{% url 'sky' %}">My Sky</a></h2>
<h2><a href="{% url 'sky' %}">SkyDrive</a></h2>
{% if not request.user.sky_chart_data %}
<div id="id_applet_sky_form_wrap">

View File

@@ -2,7 +2,7 @@
id="id_applet_my_sea"
style="--applet-cols: {{ entry.applet.grid_cols }}; --applet-rows: {{ entry.applet.grid_rows }};"
>
<h2><a href="{% url 'my_sea' %}">My Sea</a></h2>
<h2><a href="{% url 'my_sea' %}">Sea <span class="my-sea-title-of">of</span> Cards</a></h2>
{# `my_sea_slots` (built by `latest_draw_slots()` in `gameboard.models`) #}
{# carries one entry per spread position in DRAW_ORDER — filled slots #}
{# render the drawn card, empty slots render as labelled placeholders. #}