A card's actions fit a phone
On a phone the card's action row was about 371px wide against a 228px text column, so the feed scrolled sideways and More and Expand fell off the screen. Below md the author's picture moves from its own column into the card's header, which gives the text, media and polls the whole width (288px at 360), and the actions are five equal cells: Reply, Boost, Favourite, React and More. Bookmark and the thread are entries in More there; the downvotes, the counts icon and Expand show from md. Counts are compacted on phones (1.2k, 12k, 1.2M, GenericExtensions.Compact). React and More open as sheets from the bottom of the screen, the reactions as a grid of four. The author's name and handle stack and are 14px, the place badge is narrower, and "edited" and the booster's name have 44px hit areas; the booster's name opens their profile in the app instead of their site. On touch the extra small buttons' text is 14px, and their hit area is a full 44px (the ::after sits against the padding box, inside the border). Desktop keeps its row. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
This commit is contained in:
1 parent
ffd4acd3d0
commit
0b237b1951
3 files changed
+92
-29
No files matched your search
+58
-28
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
@if (Author is { } author)
|
@if (Author is { } author)
|
||||||
{
|
{
|
||||||
<div class="flex flex-col py-3 pl-3 md:py-4 md:pl-4 flex-none rounded-l-xl bg-cover bg-no-repeat bg-center"
|
<div class="hidden md:flex flex-col py-3 pl-3 md:py-4 md:pl-4 flex-none rounded-l-xl bg-cover bg-no-repeat bg-center"
|
||||||
style="@HeaderBackground(author)">
|
style="@HeaderBackground(author)">
|
||||||
<a class="block h-12 w-12 md:h-14 md:w-14" href="@($"account/{Uri.EscapeDataString(author.Id)}")" title="@author.Acct">
|
<a class="block h-12 w-12 md:h-14 md:w-14" href="@($"account/{Uri.EscapeDataString(author.Id)}")" title="@author.Acct">
|
||||||
@* alt="": the author's name is next to it. *@
|
@* alt="": the author's name is next to it. *@
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="flex flex-col gap-2 flex-1 py-3 pr-3 md:py-4 md:pr-4 min-w-0">
|
<div class="flex flex-col gap-2 flex-1 py-3 pr-3 max-md:pl-3 md:py-4 md:pr-4 min-w-0">
|
||||||
|
|
||||||
@if (Post.Notification is { } notification)
|
@if (Post.Notification is { } notification)
|
||||||
{
|
{
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
{
|
{
|
||||||
<p class="inline-flex flex-1 items-center gap-2 min-w-0 text-xs">
|
<p class="inline-flex flex-1 items-center gap-2 min-w-0 text-xs">
|
||||||
<i class="ion-md-repeat text-info" aria-hidden="true"></i>
|
<i class="ion-md-repeat text-info" aria-hidden="true"></i>
|
||||||
<a class="font-bold truncate" href="@booster.Url" target="_blank" rel="noopener noreferrer" title="@booster.Acct">@CustomEmojis.Text(booster.Name, booster.Emojis)</a>
|
<a class="font-bold truncate pointer-coarse:py-3.5" href="@($"account/{Uri.EscapeDataString(booster.Id)}")" title="@booster.Acct">@CustomEmojis.Text(booster.Name, booster.Emojis)</a>
|
||||||
<span>@Localizer["boosted"]</span>
|
<span>@Localizer["boosted"]</span>
|
||||||
</p>
|
</p>
|
||||||
}
|
}
|
||||||
@@ -79,11 +79,19 @@
|
|||||||
|
|
||||||
@if (Status is { } status)
|
@if (Status is { } status)
|
||||||
{
|
{
|
||||||
<header class="flex flex-wrap items-baseline gap-x-2 gap-y-1 min-w-0 justify-between text-xs md:text-sm">
|
<header class="flex flex-wrap items-baseline gap-x-2 gap-y-1 min-w-0 justify-between text-sm">
|
||||||
<NerdTip Heading="@Localizer["Author"]" Rows="AuthorRows()" Pending="isReadingServer" OnOpen="ReadServer" Align="DTooltipAlign.Start" Class="min-w-0 flex-1">
|
@if (Author is { } phoneAuthor)
|
||||||
<span class="inline-flex gap-2 min-w-0 max-w-full">
|
{
|
||||||
|
<a class="md:hidden flex-none self-center grid place-items-center h-11 w-11" href="@($"account/{Uri.EscapeDataString(phoneAuthor.Id)}")"
|
||||||
|
title="@phoneAuthor.Acct">
|
||||||
|
@* alt="": the author's name is next to it. *@
|
||||||
|
<img alt="" loading="lazy" class="h-10 w-10 object-cover rounded-full neo-raised neo-2xs bg-base-100" src="@(phoneAuthor.Avatar ?? "imgs/icon-192.png")" />
|
||||||
|
</a>
|
||||||
|
}
|
||||||
|
<NerdTip Heading="@Localizer["Author"]" Rows="AuthorRows()" Pending="isReadingServer" OnOpen="ReadServer" Align="DTooltipAlign.Start" Class="min-w-0 flex-1 max-md:self-center">
|
||||||
|
<span class="inline-flex max-md:flex-col md:gap-2 min-w-0 max-w-full">
|
||||||
<b class="shrink truncate" title="@status.Account?.Name">@CustomEmojis.Text(status.Account?.Name, status.Account?.Emojis ?? [])</b>
|
<b class="shrink truncate" title="@status.Account?.Name">@CustomEmojis.Text(status.Account?.Name, status.Account?.Emojis ?? [])</b>
|
||||||
<span class="flex-1 min-w-6 opacity-50 truncate self-center text-xs">@("@" + status.Account?.Acct)</span>
|
<span class="flex-1 min-w-6 opacity-50 truncate md:self-center text-xs">@("@" + status.Account?.Acct)</span>
|
||||||
</span>
|
</span>
|
||||||
</NerdTip>
|
</NerdTip>
|
||||||
<span class="flex-none inline-flex gap-2 items-center">
|
<span class="flex-none inline-flex gap-2 items-center">
|
||||||
@@ -91,7 +99,7 @@
|
|||||||
{
|
{
|
||||||
<NerdTip Heading="@Localizer["The server is behind {0}, so its place is unknown.", fronted.Label]" Rows="CdnRows()" Pending="isReadingServer"
|
<NerdTip Heading="@Localizer["The server is behind {0}, so its place is unknown.", fronted.Label]" Rows="CdnRows()" Pending="isReadingServer"
|
||||||
OnOpen="ReadServer" Placement="DTooltipPlacement.Bottom" Align="DTooltipAlign.End">
|
OnOpen="ReadServer" Placement="DTooltipPlacement.Bottom" Align="DTooltipAlign.End">
|
||||||
<span class="badge badge-ghost badge-sm gap-1 max-w-40">
|
<span class="badge badge-ghost badge-sm gap-1 max-w-28 md:max-w-40">
|
||||||
<i class="ion-md-cloud" aria-hidden="true"></i>
|
<i class="ion-md-cloud" aria-hidden="true"></i>
|
||||||
<span class="truncate">@fronted.Label</span>
|
<span class="truncate">@fronted.Label</span>
|
||||||
</span>
|
</span>
|
||||||
@@ -100,7 +108,7 @@
|
|||||||
else if (Post.Location is { } location)
|
else if (Post.Location is { } location)
|
||||||
{
|
{
|
||||||
<NerdTip Heading="@Localizer["Place"]" Rows="LocationRows()" Placement="DTooltipPlacement.Bottom" Align="DTooltipAlign.End">
|
<NerdTip Heading="@Localizer["Place"]" Rows="LocationRows()" Placement="DTooltipPlacement.Bottom" Align="DTooltipAlign.End">
|
||||||
<span class="badge badge-ghost badge-sm gap-1 max-w-40">
|
<span class="badge badge-ghost badge-sm gap-1 max-w-28 md:max-w-40">
|
||||||
<i class="@LocationIcon(location.Source)" aria-hidden="true"></i>
|
<i class="@LocationIcon(location.Source)" aria-hidden="true"></i>
|
||||||
<span class="truncate">@(location.Label ?? Localizer["Near you"])</span>
|
<span class="truncate">@(location.Label ?? Localizer["Near you"])</span>
|
||||||
</span>
|
</span>
|
||||||
@@ -112,7 +120,7 @@
|
|||||||
</NerdTip>
|
</NerdTip>
|
||||||
@if (status.EditedAt is not null)
|
@if (status.EditedAt is not null)
|
||||||
{
|
{
|
||||||
<button type="button" class="link link-hover opacity-60" data-history title="@Localizer["Edit history"]"
|
<button type="button" class="link link-hover opacity-60 touch-target" data-history title="@Localizer["Edit history"]"
|
||||||
@onclick="() => OpenHistory(status)">@Localizer["edited"]</button>
|
@onclick="() => OpenHistory(status)">@Localizer["edited"]</button>
|
||||||
}
|
}
|
||||||
<i aria-hidden="true" class="@VisibilityIcon(status.Visibility) text-base" title="@VisibilityText(status.Visibility)"></i>
|
<i aria-hidden="true" class="@VisibilityIcon(status.Visibility) text-base" title="@VisibilityText(status.Visibility)"></i>
|
||||||
@@ -220,59 +228,65 @@
|
|||||||
|
|
||||||
@if (!Post.Located && !Compact)
|
@if (!Post.Located && !Compact)
|
||||||
{
|
{
|
||||||
<footer class="flex gap-2 mt-1 justify-between">
|
@* on a phone the actions are five equal cells (Reply, Boost, Favourite, React, More); Bookmark and the thread are in
|
||||||
<div class="flex gap-2">
|
More, and the downvotes, the counts and Expand show from md *@
|
||||||
|
<footer class="grid grid-cols-5 gap-1 mt-1 md:flex md:gap-2 md:justify-between">
|
||||||
|
<div class="contents md:flex md:gap-2">
|
||||||
@if (status.Privapub?.Locked == true)
|
@if (status.Privapub?.Locked == true)
|
||||||
{
|
{
|
||||||
@* its community's moderators locked the thread: no reply is taken *@
|
@* its community's moderators locked the thread: no reply is taken *@
|
||||||
<span class="btn btn-sm btn-disabled" title="@Localizer["Locked by its community's moderators"]" data-locked>
|
<span class="btn btn-sm btn-disabled max-md:w-full" title="@Localizer["Locked by its community's moderators"]" data-locked>
|
||||||
<i aria-hidden="true" class="ion-md-lock text-lg"></i>
|
<i aria-hidden="true" class="ion-md-lock text-lg"></i>
|
||||||
@if (status.RepliesCount > 0)
|
@if (status.RepliesCount > 0)
|
||||||
{
|
{
|
||||||
<span>@status.RepliesCount</span>
|
<span class="md:hidden">@status.RepliesCount.Compact()</span>
|
||||||
|
<span class="hidden md:inline">@status.RepliesCount</span>
|
||||||
}
|
}
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<DButton Size="DSize.Sm" Active="isReplying" Disabled="IsDefaultDisabled" OnClick="ToggleReply" title="@Localizer[isReplying ? "Close" : "Reply"]">
|
<DButton Size="DSize.Sm" class="max-md:w-full" Active="isReplying" Disabled="IsDefaultDisabled" OnClick="ToggleReply" title="@Localizer[isReplying ? "Close" : "Reply"]">
|
||||||
<i aria-hidden="true" class="@(isReplying ? "ion-md-close-circle" : "ion-md-text") text-lg text-success"></i>
|
<i aria-hidden="true" class="@(isReplying ? "ion-md-close-circle" : "ion-md-text") text-lg text-success"></i>
|
||||||
@if (status.RepliesCount > 0)
|
@if (status.RepliesCount > 0)
|
||||||
{
|
{
|
||||||
<span>@status.RepliesCount</span>
|
<span class="md:hidden">@status.RepliesCount.Compact()</span>
|
||||||
|
<span class="hidden md:inline">@status.RepliesCount</span>
|
||||||
}
|
}
|
||||||
</DButton>
|
</DButton>
|
||||||
}
|
}
|
||||||
<DButton Size="DSize.Sm" Active="status.Reblogged" Disabled="IsDefaultDisabled || isActing || !CanBoost(status)"
|
<DButton Size="DSize.Sm" class="max-md:w-full" Active="status.Reblogged" Disabled="IsDefaultDisabled || isActing || !CanBoost(status)"
|
||||||
OnClick="() => Act(status.Reblogged ? StatusAction.Unreblog : StatusAction.Reblog)" title="@Localizer["Boost"]">
|
OnClick="() => Act(status.Reblogged ? StatusAction.Unreblog : StatusAction.Reblog)" title="@Localizer["Boost"]">
|
||||||
<i aria-hidden="true" class="ion-md-repeat text-lg text-info"></i>
|
<i aria-hidden="true" class="ion-md-repeat text-lg text-info"></i>
|
||||||
@if (status.ReblogsCount > 0)
|
@if (status.ReblogsCount > 0)
|
||||||
{
|
{
|
||||||
<span>@status.ReblogsCount</span>
|
<span class="md:hidden">@status.ReblogsCount.Compact()</span>
|
||||||
|
<span class="hidden md:inline">@status.ReblogsCount</span>
|
||||||
}
|
}
|
||||||
</DButton>
|
</DButton>
|
||||||
<DButton Size="DSize.Sm" Active="status.Favourited" Disabled="IsDefaultDisabled || isActing"
|
<DButton Size="DSize.Sm" class="max-md:w-full" Active="status.Favourited" Disabled="IsDefaultDisabled || isActing"
|
||||||
OnClick="() => Act(status.Favourited ? StatusAction.Unfavourite : StatusAction.Favourite)" title="@Localizer["Favourite"]">
|
OnClick="() => Act(status.Favourited ? StatusAction.Unfavourite : StatusAction.Favourite)" title="@Localizer["Favourite"]">
|
||||||
<i aria-hidden="true" class="@(status.Favourited ? "ion-md-heart" : "ion-md-heart-empty") text-lg text-pink-400"></i>
|
<i aria-hidden="true" class="@(status.Favourited ? "ion-md-heart" : "ion-md-heart-empty") text-lg text-pink-400"></i>
|
||||||
@if (status.FavouritesCount > 0)
|
@if (status.FavouritesCount > 0)
|
||||||
{
|
{
|
||||||
<span>@status.FavouritesCount</span>
|
<span class="md:hidden">@status.FavouritesCount.Compact()</span>
|
||||||
|
<span class="hidden md:inline">@status.FavouritesCount</span>
|
||||||
}
|
}
|
||||||
</DButton>
|
</DButton>
|
||||||
@* a threadiverse post's downvotes: its upvotes are its favourites *@
|
@* a threadiverse post's downvotes: its upvotes are its favourites *@
|
||||||
@if (status.Privapub?.Votes is { Down: > 0 } votes)
|
@if (status.Privapub?.Votes is { Down: > 0 } votes)
|
||||||
{
|
{
|
||||||
<span class="inline-flex items-center gap-1 px-1 text-sm opacity-70 tabular-nums" title="@Localizer["Downvotes"]" data-downvotes>
|
<span class="hidden md:inline-flex items-center gap-1 px-1 text-sm opacity-70 tabular-nums" title="@Localizer["Downvotes"]" data-downvotes>
|
||||||
<i aria-hidden="true" class="ion-md-arrow-down"></i>@votes.Down
|
<i aria-hidden="true" class="ion-md-arrow-down"></i>@votes.Down
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
<DButton Size="DSize.Sm" Active="status.Bookmarked" Disabled="IsDefaultDisabled || isActing"
|
<DButton Size="DSize.Sm" class="hidden md:inline-flex" Active="status.Bookmarked" Disabled="IsDefaultDisabled || isActing"
|
||||||
OnClick="() => Act(status.Bookmarked ? StatusAction.Unbookmark : StatusAction.Bookmark)" title="@Localizer["Bookmark"]">
|
OnClick="() => Act(status.Bookmarked ? StatusAction.Unbookmark : StatusAction.Bookmark)" title="@Localizer["Bookmark"]">
|
||||||
<i aria-hidden="true" class="ion-md-bookmark text-lg @(status.Bookmarked ? "text-warning" : null)"></i>
|
<i aria-hidden="true" class="ion-md-bookmark text-lg @(status.Bookmarked ? "text-warning" : null)"></i>
|
||||||
</DButton>
|
</DButton>
|
||||||
<DDropdown @bind-IsOpen="isReactionsOpen" Placement="DDropdownPlacement.Top" CloseOnContentClick="true"
|
<DDropdown @bind-IsOpen="isReactionsOpen" Placement="DDropdownPlacement.Top" CloseOnContentClick="true" SheetOnNarrow="true" class="max-md:w-full"
|
||||||
TriggerClass="@(isReactionsOpen ? "btn btn-sm btn-active" : "btn btn-sm")" ContentClass="mb-2 flex gap-1 p-2 rounded-box"
|
TriggerClass="@(isReactionsOpen ? "btn btn-sm btn-active max-md:w-full" : "btn btn-sm max-md:w-full")"
|
||||||
title="@Localizer["React"]">
|
ContentClass="mb-2 flex gap-1 p-2 rounded-box max-md:grid max-md:grid-cols-4 max-md:gap-2" title="@Localizer["React"]">
|
||||||
<Trigger><i aria-hidden="true" class="ion-md-happy text-lg"></i></Trigger>
|
<Trigger><i aria-hidden="true" class="ion-md-happy text-lg"></i></Trigger>
|
||||||
<ChildContent>
|
<ChildContent>
|
||||||
@foreach (var emoji in QuickReactions)
|
@foreach (var emoji in QuickReactions)
|
||||||
@@ -281,20 +295,36 @@
|
|||||||
}
|
}
|
||||||
</ChildContent>
|
</ChildContent>
|
||||||
</DDropdown>
|
</DDropdown>
|
||||||
|
<span class="hidden md:contents">
|
||||||
<NerdTip Heading="@Localizer["Counts"]" Rows="CountRows(status)" Class="self-center">
|
<NerdTip Heading="@Localizer["Counts"]" Rows="CountRows(status)" Class="self-center">
|
||||||
<i class="ion-md-stats opacity-40" aria-label="@Localizer["Counts"]"></i>
|
<i class="ion-md-stats opacity-40" aria-label="@Localizer["Counts"]"></i>
|
||||||
</NerdTip>
|
</NerdTip>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex gap-2">
|
<div class="contents md:flex md:gap-2">
|
||||||
@* opens sideways and downwards: opened upwards, the first card's menu was cut off by the top of the feed *@
|
@* opens sideways and downwards: opened upwards, the first card's menu was cut off by the top of the feed *@
|
||||||
<DDropdown @bind-IsOpen="isOptionsOpen" Align="DDropdownAlign.Start" CloseOnContentClick="true" Placement="DDropdownPlacement.Left"
|
<DDropdown @bind-IsOpen="isOptionsOpen" Align="DDropdownAlign.Start" CloseOnContentClick="true" Placement="DDropdownPlacement.Left"
|
||||||
TriggerClass="@(isOptionsOpen ? "btn btn-sm btn-active" : "btn btn-sm")"
|
SheetOnNarrow="true" class="max-md:w-full"
|
||||||
|
TriggerClass="@(isOptionsOpen ? "btn btn-sm btn-active max-md:w-full" : "btn btn-sm max-md:w-full")"
|
||||||
ContentClass="mr-2 flex flex-col gap-2 p-2 rounded-box" title="@Localizer["Other"]">
|
ContentClass="mr-2 flex flex-col gap-2 p-2 rounded-box" title="@Localizer["Other"]">
|
||||||
<Trigger>
|
<Trigger>
|
||||||
<i aria-hidden="true" class="ion-md-more text-lg"></i>
|
<i aria-hidden="true" class="ion-md-more text-lg"></i>
|
||||||
</Trigger>
|
</Trigger>
|
||||||
<ChildContent>
|
<ChildContent>
|
||||||
|
@if (IncludeExpand)
|
||||||
|
{
|
||||||
|
<NavLink class="btn btn-sm justify-start whitespace-nowrap md:hidden" href="@($"expand/{Uri.EscapeDataString(status.Id)}")"
|
||||||
|
@onclick="OpenConversation" data-thread-link>
|
||||||
|
<i aria-hidden="true" class="ion-md-expand text-base"></i>
|
||||||
|
<span>@Localizer["Thread"]</span>
|
||||||
|
</NavLink>
|
||||||
|
}
|
||||||
|
<DButton Size="DSize.Sm" class="justify-start whitespace-nowrap md:hidden" Active="status.Bookmarked" Disabled="IsDefaultDisabled || isActing"
|
||||||
|
OnClick="() => Act(status.Bookmarked ? StatusAction.Unbookmark : StatusAction.Bookmark)" data-bookmark-phone>
|
||||||
|
<i aria-hidden="true" class="ion-md-bookmark text-base @(status.Bookmarked ? "text-warning" : null)"></i>
|
||||||
|
<span>@Localizer["Bookmark"]</span>
|
||||||
|
</DButton>
|
||||||
@if (status.Url is { Length: > 0 } url)
|
@if (status.Url is { Length: > 0 } url)
|
||||||
{
|
{
|
||||||
<a class="btn btn-sm justify-start whitespace-nowrap" href="@url" target="_blank" rel="noopener noreferrer">
|
<a class="btn btn-sm justify-start whitespace-nowrap" href="@url" target="_blank" rel="noopener noreferrer">
|
||||||
@@ -368,7 +398,7 @@
|
|||||||
</DDropdown>
|
</DDropdown>
|
||||||
@if (IncludeExpand)
|
@if (IncludeExpand)
|
||||||
{
|
{
|
||||||
<NavLink class="btn btn-sm" href="@($"expand/{Uri.EscapeDataString(status.Id)}")" title="@Localizer["Expand"]"
|
<NavLink class="btn btn-sm hidden md:inline-flex" href="@($"expand/{Uri.EscapeDataString(status.Id)}")" title="@Localizer["Expand"]"
|
||||||
@onclick="OpenConversation">
|
@onclick="OpenConversation">
|
||||||
<i aria-hidden="true" class="ion-md-expand text-lg"></i>
|
<i aria-hidden="true" class="ion-md-expand text-lg"></i>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
|||||||
@@ -57,6 +57,15 @@ public static class GenericExtensions
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// a count as a phone's narrow action buttons show it: 999, 1.2k, 12k, 1.2M
|
||||||
|
public static string Compact(this int count) => count switch
|
||||||
|
{
|
||||||
|
< 1000 => count.ToString(CultureInfo.CurrentCulture),
|
||||||
|
< 10_000 => (count / 1000d).ToString("0.#", CultureInfo.CurrentCulture) + "k",
|
||||||
|
< 1_000_000 => (count / 1000).ToString(CultureInfo.CurrentCulture) + "k",
|
||||||
|
_ => (count / 1_000_000d).ToString("0.#", CultureInfo.CurrentCulture) + "M"
|
||||||
|
};
|
||||||
|
|
||||||
public static string GetFileSize(this long size, CoalescingStringLocalizer localizer) => size switch
|
public static string GetFileSize(this long size, CoalescingStringLocalizer localizer) => size switch
|
||||||
{
|
{
|
||||||
>= 1_048_576 => localizer["{0}MB", size / 1_048_576],
|
>= 1_048_576 => localizer["{0}MB", size / 1_048_576],
|
||||||
|
|||||||
+25
-1
@@ -9,6 +9,25 @@
|
|||||||
fields are 44px tall; the extra small buttons and the badges that act stay 36px to the eye and reach 44px through a
|
fields are 44px tall; the extra small buttons and the badges that act stay 36px to the eye and reach 44px through a
|
||||||
transparent ::after, so the rows that hold them leave 8px between them on touch (pointer-coarse:gap-2), or two hit
|
transparent ::after, so the rows that hold them leave 8px between them on touch (pointer-coarse:gap-2), or two hit
|
||||||
areas would overlap. */
|
areas would overlap. */
|
||||||
|
/* A small text link or button (a name, "edited") keeps its size to the eye and gets a 44px hit area, a transparent box
|
||||||
|
centred on it, on touch only. Not for one that truncates its text: its overflow clips the box, so such a link takes
|
||||||
|
padding instead (pointer-coarse:py-3.5). */
|
||||||
|
@utility touch-target {
|
||||||
|
@media (pointer: coarse) {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
width: max(100%, 2.75rem);
|
||||||
|
height: max(100%, 2.75rem);
|
||||||
|
translate: -50% -50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@layer utilities {
|
@layer utilities {
|
||||||
/* At every width: a checkbox's, radio's or toggle's label wraps (daisyUI's .label never does, and a long one ran past
|
/* At every width: a checkbox's, radio's or toggle's label wraps (daisyUI's .label never does, and a long one ran past
|
||||||
a phone's edge), and the control keeps its size beside it. */
|
a phone's edge), and the control keeps its size beside it. */
|
||||||
@@ -36,6 +55,7 @@
|
|||||||
--fontsize: .875rem;
|
--fontsize: .875rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (the ::after is placed against the padding box, 34px inside a 1px border: 5px around it makes 44) */
|
||||||
.btn-xs,
|
.btn-xs,
|
||||||
:is(button, a).badge {
|
:is(button, a).badge {
|
||||||
--size: 2.25rem;
|
--size: 2.25rem;
|
||||||
@@ -45,10 +65,14 @@
|
|||||||
&::after {
|
&::after {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: -4px;
|
inset: -5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-xs {
|
||||||
|
--fontsize: .875rem;
|
||||||
|
}
|
||||||
|
|
||||||
:is(button, a).badge {
|
:is(button, a).badge {
|
||||||
padding-inline: .75rem;
|
padding-inline: .75rem;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user