[MTM] Tweaks and fixes #120

Merged
jonny merged 3 commits from develop into main 2026-08-21 17:08:14 +02:00
7 changed files with 135 additions and 45 deletions
Showing only changes of commit 6a0bb623fc - Show all commits

Restyle the Micropub tokens admin table

Breaks the table out of the centred content column to full page
width via a subgrid on <main> (adds a reusable .full-bleed utility),
and reworks the table itself to match a Claude Design mockup: a
rounded card wrapper, scope values as pill chips, a dotted status
pill, and proportional column widths. Colours use the site's
existing --primary-hue/light-dark() tokens so it stays correct in
both themes. The card scrolls horizontally on narrow viewports
instead of clipping content.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LHN7V9kyZxrsxaspMSqoGJ
Jonny Barnes 2026-08-21 16:05:48 +01:00
Signed by: jonny
SSH key fingerprint: SHA256:CTuSlns5U7qlD9jqHvtnVmfYV3Zwl2Z7WnJ4/dqOaL8

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View file

@ -1,21 +1,34 @@
@layer components { @layer components {
.token-list-wrapper {
margin-block-start: 1em;
border: 1px solid var(--clr-border);
border-radius: 16px;
overflow: auto hidden;
background: light-dark(
oklch(99% 0.02 var(--primary-hue)),
oklch(22% 0.05 var(--primary-hue))
);
}
.token-list { .token-list {
width: 100%; width: 100%;
min-width: 640px;
table-layout: fixed;
border-collapse: collapse; border-collapse: collapse;
margin-block-start: 1em;
th, th,
td { td {
text-align: left; text-align: left;
padding: 0.6em 0.8em; padding: 0.9em 1.2em;
border-bottom: 1px solid var(--clr-border); border-bottom: 1px solid var(--clr-border);
vertical-align: middle; vertical-align: middle;
} }
th { th {
font-size: 0.85em; font-size: 0.8em;
font-weight: 700;
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.03em; letter-spacing: 0.08em;
opacity: 0.7; opacity: 0.7;
} }
@ -26,14 +39,65 @@
a { a {
word-break: break-all; word-break: break-all;
} }
th:nth-child(1),
td:nth-child(1) {
width: 31%;
}
th:nth-child(2),
td:nth-child(2) {
width: 24%;
}
th:nth-child(3),
td:nth-child(3) {
width: 15%;
}
th:nth-child(4),
td:nth-child(4) {
width: 16%;
}
th:nth-child(5),
td:nth-child(5) {
width: 14%;
text-align: right;
}
tr:last-child td {
border-bottom: none;
}
}
.scope-chips {
display: flex;
flex-wrap: wrap;
gap: 0.4em;
}
.scope-chip {
display: inline-block;
padding: 0.2em 0.7em;
border-radius: 999px;
background: light-dark(
oklch(92% 0.05 var(--primary-hue)),
oklch(35% 0.08 var(--primary-hue))
);
font-size: 0.85em;
white-space: nowrap;
} }
.badge, .badge,
.token-list button.revoke { .token-list button.revoke {
display: inline-block; display: inline-flex;
padding: 0.2em 0.7em; align-items: center;
gap: 0.4em;
padding: 0.3em 0.8em;
border-radius: 999px; border-radius: 999px;
font-size: 0.85em; font-size: 0.85em;
font-weight: 600;
line-height: 1.5; line-height: 1.5;
white-space: nowrap; white-space: nowrap;
} }
@ -45,10 +109,18 @@
.badge-active { .badge-active {
color: light-dark(oklch(35% 0.16 145deg), oklch(75% 0.16 145deg)); color: light-dark(oklch(35% 0.16 145deg), oklch(75% 0.16 145deg));
.dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: currentcolor;
}
} }
.badge-revoked { .badge-revoked {
color: var(--clr-text); color: var(--clr-text);
opacity: 0.7;
} }
.token-list button.revoke { .token-list button.revoke {

View file

@ -18,7 +18,17 @@
} }
> main { > main {
grid-column: 2/3; grid-column: 1/-1;
display: grid;
grid-template-columns: subgrid;
> * {
grid-column: 2/3;
}
> .full-bleed {
grid-column: 1/-1;
}
} }
> footer { > footer {

View file

@ -7,41 +7,49 @@
@if($tokens->isEmpty()) @if($tokens->isEmpty())
<p>No tokens have been issued.</p> <p>No tokens have been issued.</p>
@else @else
<table class="token-list"> <div class="full-bleed token-list-wrapper">
<thead> <table class="token-list">
<tr> <thead>
<th scope="col">Client</th> <tr>
<th scope="col">Scope</th> <th scope="col">Client</th>
<th scope="col">Issued</th> <th scope="col">Scope</th>
<th scope="col">Status</th> <th scope="col">Issued</th>
<th scope="col">Action</th> <th scope="col">Status</th>
</tr> <th scope="col">Action</th>
</thead> </tr>
<tbody> </thead>
@foreach($tokens as $token) <tbody>
<tr class="{{ $token->isRevoked ? 'is-revoked' : '' }}"> @foreach($tokens as $token)
<td><a href="{{ $token->client_id }}" rel="noopener">{{ $token->client_id }}</a></td> <tr class="{{ $token->isRevoked ? 'is-revoked' : '' }}">
<td>{{ $token->scope }}</td> <td><a href="{{ $token->client_id }}" rel="noopener">{{ $token->client_id }}</a></td>
<td><time datetime="{{ $token->created_at->toIso8601String() }}" title="{{ $token->created_at }}">{{ $token->created_at->diffForHumans() }}</time></td> <td>
<td> <span class="scope-chips">
@if($token->isRevoked) @foreach(explode(' ', $token->scope) as $scope)
<span class="badge badge-revoked">Revoked {{ $token->revoked_at->diffForHumans() }}</span> <span class="scope-chip">{{ $scope }}</span>
@else @endforeach
<span class="badge badge-active">Active</span> </span>
@endif </td>
</td> <td><time datetime="{{ $token->created_at->toIso8601String() }}" title="{{ $token->created_at }}">{{ $token->created_at->diffForHumans() }}</time></td>
<td> <td>
@unless($token->isRevoked) @if($token->isRevoked)
<form action="/admin/tokens/{{ $token->id }}/revoke" method="post" onsubmit="return confirm('Revoke this token? This cannot be undone.')"> <span class="badge badge-revoked">Revoked {{ $token->revoked_at->diffForHumans() }}</span>
{{ csrf_field() }} @else
{{ method_field('PUT') }} <span class="badge badge-active"><span class="dot"></span>Active</span>
<button type="submit" class="revoke" name="revoke">Revoke</button> @endif
</form> </td>
@endunless <td>
</td> @unless($token->isRevoked)
</tr> <form action="/admin/tokens/{{ $token->id }}/revoke" method="post" onsubmit="return confirm('Revoke this token? This cannot be undone.')">
@endforeach {{ csrf_field() }}
</tbody> {{ method_field('PUT') }}
</table> <button type="submit" class="revoke" name="revoke">Revoke</button>
</form>
@endunless
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endif @endif
@stop @stop