mirror of
https://code.castopod.org/adaures/castopod.git
synced 2024-09-27 20:21:59 +02:00
feat: restyle episode and person cards + add focus style to interactive elements for a11y
fix components in follow and remote action pages by calling new instances directly
This commit is contained in:
parent
025b2f42e6
commit
a505a1de56
@ -238,7 +238,7 @@ if (! function_exists('location_link')) {
|
||||
icon('map-pin', 'mr-2') . $location->name,
|
||||
[
|
||||
'class' =>
|
||||
'inline-flex items-baseline hover:underline' .
|
||||
'inline-flex items-baseline hover:underline focus:ring-castopod' .
|
||||
($class === '' ? '' : " {$class}"),
|
||||
'target' => '_blank',
|
||||
'rel' => 'noreferrer noopener',
|
||||
|
@ -20,17 +20,17 @@ if (! function_exists('render_page_links')) {
|
||||
{
|
||||
$pages = (new PageModel())->findAll();
|
||||
$links = anchor(route_to('home'), lang('Common.home'), [
|
||||
'class' => 'px-2 py-1 underline hover:no-underline',
|
||||
'class' => 'px-2 py-1 underline hover:no-underline focus:ring-castopod',
|
||||
]);
|
||||
$links .= anchor(route_to('credits'), lang('Person.credits'), [
|
||||
'class' => 'px-2 py-1 underline hover:no-underline',
|
||||
'class' => 'px-2 py-1 underline hover:no-underline focus:ring-castopod',
|
||||
]);
|
||||
$links .= anchor(route_to('map'), lang('Page.map'), [
|
||||
'class' => 'px-2 py-1 underline hover:no-underline',
|
||||
'class' => 'px-2 py-1 underline hover:no-underline focus:ring-castopod',
|
||||
]);
|
||||
foreach ($pages as $page) {
|
||||
$links .= anchor($page->link, $page->title, [
|
||||
'class' => 'px-2 py-1 underline hover:no-underline',
|
||||
'class' => 'px-2 py-1 underline hover:no-underline focus:ring-castopod',
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ return [
|
||||
'no_episode_hint' =>
|
||||
'Navigate the podcast episodes with the navigation bar above.',
|
||||
'follow' => 'Follow',
|
||||
'followTitle' => 'Follow {actorDisplayName} on the fediverse!',
|
||||
'followers' => '{numberOfFollowers, plural,
|
||||
one {<span class="font-semibold">#</span> follower}
|
||||
other {<span class="font-semibold">#</span> followers}
|
||||
|
@ -18,6 +18,7 @@ return [
|
||||
'no_episode_hint' =>
|
||||
'Naviguez au sein des épisodes du podcast episodes grâce à la barre de navigation ci-dessus.',
|
||||
'follow' => 'Suivre',
|
||||
'followTitle' => 'Suivez {actorDisplayName} sur le fédiverse !',
|
||||
'followers' => '{numberOfFollowers, plural,
|
||||
one {<span class="font-semibold">#</span> abonné·e}
|
||||
other {<span class="font-semibold">#</span> abonné·e·s}
|
||||
|
@ -25,9 +25,9 @@ const Dropdown = (): void => {
|
||||
const offsetY = menu.dataset.dropdownOffsetY
|
||||
? parseInt(menu.dataset.dropdownOffsetY)
|
||||
: 0;
|
||||
console.log(offsetX, offsetY);
|
||||
popperInstance = createPopper(button, menu, {
|
||||
placement: menu.dataset.dropdownPlacement as Placement,
|
||||
// strategy: "fixed",
|
||||
modifiers: [
|
||||
{
|
||||
name: "offset",
|
||||
|
@ -17,4 +17,19 @@
|
||||
.rounded-conditional-2xl {
|
||||
border-radius: max(0px, min(1rem, calc((100vw - 1rem - 100%) * 9999)));
|
||||
}
|
||||
|
||||
.backdrop-gradient {
|
||||
background-image: linear-gradient(
|
||||
180deg,
|
||||
hsla(0, 0%, 35.29%, 0) 0%,
|
||||
hsla(0, 0%, 34.53%, 0.034375) 16.36%,
|
||||
hsla(0, 0%, 32.42%, 0.125) 33.34%,
|
||||
hsla(0, 0%, 29.18%, 0.253125) 50.1%,
|
||||
hsla(0, 0%, 24.96%, 0.4) 65.75%,
|
||||
hsla(0, 0%, 19.85%, 0.546875) 79.43%,
|
||||
hsla(0, 0%, 13.95%, 0.675) 90.28%,
|
||||
hsla(0, 0%, 7.32%, 0.765625) 97.43%,
|
||||
hsla(0, 0%, 0%, 0.8) 100%
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -76,11 +76,17 @@ class Button extends Component
|
||||
}
|
||||
|
||||
if ($this->iconLeft !== '') {
|
||||
$this->slot = '<Icon glyph="' . $this->iconLeft . '" class="mr-2 opacity-75" />' . $this->slot;
|
||||
$this->slot = (new Icon([
|
||||
'glyph' => $this->iconLeft,
|
||||
'class' => 'mr-2 opacity-75',
|
||||
]))->render() . $this->slot;
|
||||
}
|
||||
|
||||
if ($this->iconRight !== '') {
|
||||
$this->slot .= '<Icon glyph="' . $this->iconRight . '" class="ml-2 opacity-75" />';
|
||||
$this->slot .= (new Icon([
|
||||
'glyph' => $this->iconRight,
|
||||
'class' => 'ml-2 opacity-75',
|
||||
]))->render();
|
||||
}
|
||||
|
||||
unset($this->attributes['slot']);
|
||||
|
@ -11,6 +11,12 @@ class DropdownMenu extends Component
|
||||
{
|
||||
public string $id = '';
|
||||
|
||||
public string $placement = 'bottom-end';
|
||||
|
||||
public string $offsetX = '0';
|
||||
|
||||
public string $offsetY = '0';
|
||||
|
||||
public array $items = [];
|
||||
|
||||
public function setItems(string $value): void
|
||||
@ -48,7 +54,9 @@ class DropdownMenu extends Component
|
||||
class="absolute z-50 flex flex-col py-2 text-black whitespace-no-wrap bg-white border-black rounded-lg border-3"
|
||||
aria-labelledby="{$this->labelledby}"
|
||||
data-dropdown="menu"
|
||||
data-dropdown-placement="bottom-end">{$menuItems}</nav>
|
||||
data-dropdown-placement="{$this->placement}"
|
||||
data-dropdown-offset-x="{$this->offsetX}"
|
||||
data-dropdown-offset-y="{$this->offsetY}">{$menuItems}</nav>
|
||||
HTML;
|
||||
}
|
||||
}
|
||||
|
@ -17,12 +17,16 @@ class Checkbox extends FormComponent
|
||||
|
||||
public function render(): string
|
||||
{
|
||||
$checkboxInput = form_checkbox(
|
||||
[
|
||||
$attributes = [
|
||||
'id' => $this->value,
|
||||
'name' => $this->name,
|
||||
'class' => 'form-checkbox text-pine-500 border-black border-3 focus:ring-castopod w-6 h-6',
|
||||
],
|
||||
];
|
||||
if ($this->required) {
|
||||
$attributes['required'] = 'required';
|
||||
}
|
||||
$checkboxInput = form_checkbox(
|
||||
$attributes,
|
||||
'yes',
|
||||
old($this->name) ? old($this->name) === $this->value : $this->isChecked,
|
||||
);
|
||||
@ -30,10 +34,7 @@ class Checkbox extends FormComponent
|
||||
$hint = $this->hint === null ? '' : hint_tooltip($this->hint, 'ml-1');
|
||||
|
||||
return <<<HTML
|
||||
<label class="leading-8 {$this->class}">
|
||||
{$checkboxInput}
|
||||
<span class="ml-2">{$this->slot}{$hint}</label>
|
||||
</label>
|
||||
<label class="inline-flex items-center {$this->class}">{$checkboxInput}<span class="ml-2">{$this->slot}{$hint}</span></label>
|
||||
HTML;
|
||||
}
|
||||
}
|
||||
|
@ -40,12 +40,15 @@ class Field extends FormComponent
|
||||
unset($fieldComponentAttributes['helperText']);
|
||||
unset($fieldComponentAttributes['hintText']);
|
||||
|
||||
$fieldComponentAttributes = flatten_attributes($fieldComponentAttributes);
|
||||
$fieldComponentAttributes['class'] = 'mb-1';
|
||||
|
||||
$element = __NAMESPACE__ . '\\' . $this->as;
|
||||
$fieldElement = new $element($fieldComponentAttributes);
|
||||
|
||||
return <<<HTML
|
||||
<div class="flex flex-col {$this->class}">
|
||||
<Forms.Label {$labelAttributes}>{$this->label}</Forms.Label>
|
||||
<Forms.{$this->as} {$fieldComponentAttributes} class="mb-1"/>
|
||||
{$fieldElement->render()}
|
||||
{$helperText}
|
||||
</div>
|
||||
HTML;
|
||||
|
@ -26,7 +26,7 @@ class Radio extends FormComponent
|
||||
);
|
||||
|
||||
return <<<HTML
|
||||
<label class="leading-8">{$radioInput}<span class="ml-2">{$this->slot}</span></label>
|
||||
<label class="inline-flex items-center {$this->class}">{$radioInput}<span class="ml-2">{$this->slot}</span></label>
|
||||
HTML;
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ class Heading extends Component
|
||||
'large' => 'text-3xl',
|
||||
];
|
||||
|
||||
$class = $this->class . ' relative z-10 font-bold text-pine-800 font-display before:w-full before:absolute before:h-1/2 before:left-0 before:bottom-0 before:rounded-full before:bg-pine-100 before:-z-10 ' . $sizeClasses[$this->size];
|
||||
$class = $this->class . ' relative z-10 font-bold text-pine-800 font-display before:w-full before:absolute before:h-1/2 before:left-0 before:bottom-0 before:rounded-full before:bg-pine-100 before:z-[-10] ' . $sizeClasses[$this->size];
|
||||
|
||||
return <<<HTML
|
||||
<{$this->tagName} class="{$class}">{$this->slot}</{$this->tagName}>
|
||||
|
@ -51,20 +51,15 @@ module.exports = {
|
||||
admin: "300px calc(100% - 300px)",
|
||||
podcast: "1fr minmax(auto, 960px) 1fr",
|
||||
podcastMain: "1fr minmax(200px, 300px)",
|
||||
podcasts: "repeat(auto-fill, minmax(14rem, 1fr))",
|
||||
cards: "repeat(auto-fill, minmax(14rem, 1fr))",
|
||||
latestEpisodes: "repeat(5, 1fr)",
|
||||
},
|
||||
gridTemplateRows: {
|
||||
admin: "40px 1fr",
|
||||
},
|
||||
zIndex: {
|
||||
"-10": "-10",
|
||||
},
|
||||
borderWidth: {
|
||||
3: "3px",
|
||||
},
|
||||
ringWidth: {
|
||||
3: "3px",
|
||||
},
|
||||
},
|
||||
},
|
||||
variants: {},
|
||||
|
@ -26,11 +26,11 @@
|
||||
<div class="flex flex-col justify-end w-full -mt-4 sticky-header-inner">
|
||||
<?= render_breadcrumb('text-gray-800 text-xs items-center flex') ?>
|
||||
<div class="flex justify-between py-1">
|
||||
<div class="flex flex-wrap items-center">
|
||||
<Heading tagName="h1" size="large"><?= $this->renderSection('pageTitle') ?></Heading>
|
||||
<div class="flex flex-wrap items-center overflow-x-hidden">
|
||||
<Heading tagName="h1" size="large" class="truncate"><?= $this->renderSection('pageTitle') ?></Heading>
|
||||
<?= $this->renderSection('headerLeft') ?>
|
||||
</div>
|
||||
<div class="flex gap-1"><?= $this->renderSection('headerRight') ?></div>
|
||||
<div class="flex flex-shrink-0 gap-1"><?= $this->renderSection('headerRight') ?></div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
@ -9,7 +9,7 @@
|
||||
<footer class="px-2 py-2 mx-auto text-xs text-right">
|
||||
<?= lang('Common.powered_by', [
|
||||
'castopod' =>
|
||||
'<a class="inline-flex font-semibold hover:underline" href="https://castopod.org/" target="_blank" rel="noreferrer noopener">Castopod' . icon('social/castopod', 'ml-1 text-lg') . '</a> ' .
|
||||
'<a class="inline-flex font-semibold hover:underline focus:ring-castopod" href="https://castopod.org/" target="_blank" rel="noreferrer noopener">Castopod' . icon('social/castopod', 'ml-1 text-lg') . '</a> ' .
|
||||
CP_VERSION,
|
||||
]) ?>
|
||||
</footer>
|
||||
|
@ -22,7 +22,7 @@
|
||||
aria-expanded="false"><div class="relative mr-1">
|
||||
<?= icon('account-circle', 'text-3xl opacity-60') ?>
|
||||
<?= user()
|
||||
->podcasts === [] ? '' : '<img src="' . interact_as_actor()->avatar_image_url . '" class="absolute bottom-0 w-4 h-4 rounded-full -right-1" />' ?>
|
||||
->podcasts === [] ? '' : '<img src="' . interact_as_actor()->avatar_image_url . '" class="absolute bottom-0 w-4 h-4 border rounded-full -right-1 border-pine-800" />' ?>
|
||||
</div>
|
||||
<?= user()->username ?>
|
||||
<?= icon('caret-down', 'ml-auto text-2xl') ?></button>
|
||||
|
50
themes/cp_admin/episode/_card.php
Normal file
50
themes/cp_admin/episode/_card.php
Normal file
@ -0,0 +1,50 @@
|
||||
<article class="relative flex flex-col flex-1 flex-shrink-0 w-full transition group overflow-hidden bg-white border-2 snap-center hover:shadow-lg focus-within:shadow-lg focus-within:ring-castopod border-pine-100 rounded-xl min-w-[12rem] max-w-[17rem]">
|
||||
<a href="<?= route_to('episode-view', $episode->podcast->id, $episode->id) ?>" class="flex flex-col justify-end w-full h-full text-white group">
|
||||
<div class="absolute bottom-0 left-0 z-10 w-full h-full backdrop-gradient"></div>
|
||||
<div class="w-full h-full overflow-hidden">
|
||||
<img src="<?= $episode->image->medium_url ?>" alt="<?= $episode->title ?>" class="object-cover w-full h-full transition duration-200 ease-in-out transform group-focus:scale-105 group-hover:scale-105" />
|
||||
</div>
|
||||
<?= publication_pill($episode->published_at, $episode->publication_status, 'absolute top-0 left-0 ml-2 mt-2 text-sm'); ?>
|
||||
<div class="absolute z-20 flex flex-col items-start px-4 py-2">
|
||||
<?= episode_numbering($episode->number, $episode->season_number, 'text-xs font-semibold !no-underline border px-1 border-gray-500 mr-1', true) ?>
|
||||
<span class="font-semibold leading-tight line-clamp-2"><?= $episode->title ?></span>
|
||||
</div>
|
||||
</a>
|
||||
<button class="absolute top-0 right-0 z-10 p-2 mt-2 mr-2 text-white transition -translate-y-12 rounded-full opacity-0 focus:ring-castopod focus:opacity-100 focus:-translate-y-0 group-hover:translate-y-0 bg-black/50 group-hover:opacity-100" id="more-dropdown-<?= $episode->id ?>" data-dropdown="button" data-dropdown-target="more-dropdown-<?= $episode->id ?>-menu" aria-haspopup="true" aria-expanded="false" title="<?= lang('Common.more') ?>"><?= icon('more') ?></button>
|
||||
<DropdownMenu id="more-dropdown-<?= $episode->id ?>-menu" labelledby="more-dropdown-<?= $episode->id ?>" offsetY="-32" items="<?= esc(json_encode([
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('Episode.go_to_page'),
|
||||
'uri' => route_to('episode', $episode->podcast->handle, $episode->slug),
|
||||
],
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('Episode.edit'),
|
||||
'uri' => route_to('episode-edit', $episode->podcast->id, $episode->id),
|
||||
],
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('Episode.embed.title'),
|
||||
'uri' => route_to('embed-add', $episode->podcast->id, $episode->id),
|
||||
],
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('Person.persons'),
|
||||
'uri' => route_to('episode-persons-manage', $episode->podcast->id, $episode->id),
|
||||
],
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('Episode.soundbites'),
|
||||
'uri' => route_to('soundbites-edit', $episode->podcast->id, $episode->id),
|
||||
],
|
||||
[
|
||||
'type' => 'separator',
|
||||
],
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('Episode.delete'),
|
||||
'uri' => route_to('episode-delete', $episode->podcast->id, $episode->id),
|
||||
'class' => 'font-semibold text-red-600',
|
||||
],
|
||||
])) ?>" />
|
||||
</article>
|
@ -11,7 +11,7 @@
|
||||
|
||||
<?= $this->section('content') ?>
|
||||
|
||||
<Alert variant="danger" glyph="alert"><?= lang('Episode.form.warning') ?></Alert>
|
||||
<Alert variant="danger" glyph="alert" class="max-w-xl"><?= lang('Episode.form.warning') ?></Alert>
|
||||
|
||||
<form action="<?= route_to('episode-create', $podcast->id) ?>" method="POST" enctype="multipart/form-data" class="flex flex-col mt-6 gap-y-8">
|
||||
<?= csrf_field() ?>
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
<?= $this->section('content') ?>
|
||||
|
||||
<Alert variant="danger" glyph="alert"><?= lang('Episode.form.warning') ?></Alert>
|
||||
<Alert variant="danger" glyph="alert" class="max-w-xl"><?= lang('Episode.form.warning') ?></Alert>
|
||||
|
||||
<form id="episode-edit-form" action="<?= route_to('episode-edit', $podcast->id, $episode->id) ?>" method="POST" enctype="multipart/form-data" class="flex flex-col mt-6 gap-y-8">
|
||||
<?= csrf_field() ?>
|
||||
|
@ -73,10 +73,15 @@
|
||||
[
|
||||
'header' => lang('Episode.list.actions'),
|
||||
'cell' => function ($episode, $podcast) {
|
||||
return '<button id="more-dropdown-' . $episode->id . '" type="button" class="inline-flex items-center p-1 focus:ring-castopod" data-dropdown="button" data-dropdown-target="more-dropdown-' . $episode->id . '-menu" aria-haspopup="true" aria-expanded="false">' .
|
||||
return '<button id="more-dropdown-' . $episode->id . '" type="button" class="inline-flex items-center p-1 rounded-full focus:ring-castopod" data-dropdown="button" data-dropdown-target="more-dropdown-' . $episode->id . '-menu" aria-haspopup="true" aria-expanded="false">' .
|
||||
icon('more') .
|
||||
'</button>' .
|
||||
'<DropdownMenu id="more-dropdown-' . $episode->id . '-menu" labelledby="more-dropdown-' . $episode->id . '" items="' . esc(json_encode([
|
||||
'<DropdownMenu id="more-dropdown-' . $episode->id . '-menu" labelledby="more-dropdown-' . $episode->id . '" offsetY="-24" items="' . esc(json_encode([
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('Episode.go_to_page'),
|
||||
'uri' => route_to('episode', $podcast->handle, $episode->slug),
|
||||
],
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('Episode.edit'),
|
||||
@ -97,11 +102,6 @@
|
||||
'title' => lang('Episode.soundbites'),
|
||||
'uri' => route_to('soundbites-edit', $podcast->id, $episode->id),
|
||||
],
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('Episode.go_to_page'),
|
||||
'uri' => route_to('episode', $podcast->handle, $episode->slug),
|
||||
],
|
||||
[
|
||||
'type' => 'separator',
|
||||
],
|
||||
|
@ -14,7 +14,7 @@
|
||||
route_to('episode-view', $podcast->id, $episode->id),
|
||||
icon('arrow-left', 'mr-2 text-lg') . lang('Episode.publish_form.back_to_episode_dashboard'),
|
||||
[
|
||||
'class' => 'inline-flex items-center font-semibold mr-4 text-sm',
|
||||
'class' => 'inline-flex items-center font-semibold mr-4 text-sm focus:ring-castopod',
|
||||
],
|
||||
) ?>
|
||||
|
||||
|
33
themes/cp_admin/person/_card.php
Normal file
33
themes/cp_admin/person/_card.php
Normal file
@ -0,0 +1,33 @@
|
||||
<article class="relative h-full overflow-hidden transition bg-white shadow border-3 border-pine-100 rounded-xl group hover:shadow-xl focus-within:shadow-xl focus-within:ring-castopod">
|
||||
<a href="<?= route_to('person-view', $person->id) ?>" class="flex flex-col justify-end w-full h-full text-white group">
|
||||
<div class="absolute bottom-0 left-0 z-10 w-full h-full backdrop-gradient"></div>
|
||||
<div class="w-full h-full overflow-hidden">
|
||||
<img alt="<?= $person->full_name ?>" src="<?= $person->image->medium_url ?>" class="object-cover w-full h-full transition duration-200 ease-in-out transform group-focus:scale-105 group-hover:scale-105" />
|
||||
</div>
|
||||
<div class="absolute z-20">
|
||||
<h2 class="px-4 py-2 font-semibold leading-tight"><?= $person->full_name ?></h2>
|
||||
</div>
|
||||
</a>
|
||||
<button class="absolute top-0 right-0 z-10 p-2 mt-2 mr-2 text-white transition -translate-y-12 rounded-full opacity-0 focus:ring-castopod focus:opacity-100 focus:-translate-y-0 group-hover:translate-y-0 bg-black/50 group-hover:opacity-100" id="more-dropdown-<?= $person->id ?>" data-dropdown="button" data-dropdown-target="more-dropdown-<?= $person->id ?>-menu" aria-haspopup="true" aria-expanded="false" title="<?= lang('Common.more') ?>"><?= icon('more') ?></button>
|
||||
<DropdownMenu id="more-dropdown-<?= $person->id ?>-menu" labelledby="more-dropdown-<?= $person->id ?>" offsetY="-32" items="<?= esc(json_encode([
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('Person.view'),
|
||||
'uri' => route_to('person-view', $person->id),
|
||||
],
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('Person.edit'),
|
||||
'uri' => route_to('person-edit', $person->id),
|
||||
],
|
||||
[
|
||||
'type' => 'separator',
|
||||
],
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('Person.delete'),
|
||||
'uri' => route_to('person-delete', $person->id),
|
||||
'class' => 'font-semibold text-red-600',
|
||||
],
|
||||
])) ?>" />
|
||||
</article>
|
@ -11,11 +11,9 @@
|
||||
|
||||
<?= $this->section('content') ?>
|
||||
|
||||
<form action="<?= route_to('person-edit', $person->id) ?>" method="POST" class="flex flex-col" enctype="multipart/form-data">
|
||||
<form action="<?= route_to('person-edit', $person->id) ?>" method="POST" class="flex flex-col max-w-sm gap-y-4" enctype="multipart/form-data">
|
||||
<?= csrf_field() ?>
|
||||
|
||||
<img src="<?= $person->image->thumbnail_url ?>" alt="<?= $person->full_name ?>" class="object-cover w-32 h-32 mt-3 rounded" />
|
||||
|
||||
<Forms.Field
|
||||
name="image"
|
||||
label="<?= lang('Person.form.image') ?>"
|
||||
|
@ -14,47 +14,16 @@
|
||||
|
||||
<?= $this->section('content') ?>
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<?php if ($persons !== null): ?>
|
||||
<div class="grid gap-4 grid-cols-cards">
|
||||
<?php foreach ($persons as $person): ?>
|
||||
<article class="w-48 h-full mb-4 mr-4 overflow-hidden bg-white border rounded shadow">
|
||||
<img
|
||||
alt="<?= $person->full_name ?>"
|
||||
src="<?= $person->image
|
||||
->thumbnail_url ?>" class="object-cover w-full" />
|
||||
<div class="p-2">
|
||||
<a href="<?= route_to(
|
||||
'person-view',
|
||||
$person->id,
|
||||
) ?>" class="hover:underline">
|
||||
<h2 class="font-semibold"><?= $person->full_name ?></h2>
|
||||
</a>
|
||||
</div>
|
||||
<footer class="flex items-center justify-end p-2">
|
||||
<a class="inline-flex p-2 mr-2 text-teal-700 bg-teal-100 rounded-full shadow-xs hover:bg-teal-200" href="<?= route_to(
|
||||
'person-edit',
|
||||
$person->id,
|
||||
) ?>" data-toggle="tooltip" data-placement="bottom" title="<?= lang(
|
||||
'Person.edit',
|
||||
) ?>"><?= icon('edit') ?></a>
|
||||
<a class="inline-flex p-2 mr-2 text-gray-700 bg-red-100 rounded-full shadow-xs hover:bg-gray-200" href="<?= route_to(
|
||||
'person-delete',
|
||||
$person->id,
|
||||
) ?>" data-toggle="tooltip" data-placement="bottom" title="<?= lang(
|
||||
'Person.delete',
|
||||
) ?>"><?= icon('delete-bin') ?></a>
|
||||
<a class="inline-flex p-2 text-gray-700 bg-gray-100 rounded-full shadow-xs hover:bg-gray-200" href="<?= route_to(
|
||||
'person-view',
|
||||
$person->id,
|
||||
) ?>" data-toggle="tooltip" data-placement="bottom" title="<?= lang(
|
||||
'Person.view',
|
||||
) ?>"><?= icon('eye') ?></a>
|
||||
</footer>
|
||||
</article>
|
||||
<?= view('person/_card', [
|
||||
'person' => $person,
|
||||
]) ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<p class="italic"><?= lang('Person.no_person') ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?= $this->endSection() ?>
|
||||
|
27
themes/cp_admin/podcast/_card.php
Normal file
27
themes/cp_admin/podcast/_card.php
Normal file
@ -0,0 +1,27 @@
|
||||
<article class="relative h-full overflow-hidden transition bg-white shadow border-3 border-pine-100 group rounded-xl hover:shadow-xl focus-within:shadow-xl focus-within:ring-castopod">
|
||||
<a href="<?= route_to('podcast-view', $podcast->id) ?>" class="flex flex-col justify-end w-full h-full text-white group">
|
||||
<div class="absolute bottom-0 left-0 z-10 w-full h-full backdrop-gradient"></div>
|
||||
<div class="w-full h-full overflow-hidden">
|
||||
<img
|
||||
alt="<?= $podcast->title ?>"
|
||||
src="<?= $podcast->image->medium_url ?>" class="object-cover w-full h-full transition duration-200 ease-in-out transform group-focus:scale-105 group-hover:scale-105" />
|
||||
</div>
|
||||
<div class="absolute z-20 px-4 pb-4 transition duration-75 ease-out translate-y-6 group-focus:translate-y-0 group-hover:translate-y-0">
|
||||
<h2 class="font-bold leading-none truncate font-display"><?= $podcast->title ?></h2>
|
||||
<p class="text-sm transition duration-150 opacity-0 group-focus:opacity-75 group-hover:opacity-75">@<?= $podcast->handle ?></p>
|
||||
</div>
|
||||
</a>
|
||||
<button class="absolute top-0 right-0 z-10 p-2 mt-2 mr-2 text-white transition -translate-y-12 rounded-full opacity-0 focus:ring-castopod focus:opacity-100 focus:-translate-y-0 group-hover:translate-y-0 bg-black/50 group-hover:opacity-100" id="more-dropdown-<?= $podcast->id ?>" data-dropdown="button" data-dropdown-target="more-dropdown-<?= $podcast->id ?>-menu" aria-haspopup="true" aria-expanded="false" title="<?= lang('Common.more') ?>"><?= icon('more') ?></button>
|
||||
<DropdownMenu id="more-dropdown-<?= $podcast->id ?>-menu" labelledby="more-dropdown-<?= $podcast->id ?>" offsetY="-32" items="<?= esc(json_encode([
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('Podcast.view'),
|
||||
'uri' => route_to('podcast-view', $podcast->id),
|
||||
],
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('Podcast.edit'),
|
||||
'uri' => route_to('podcast-edit', $podcast->id),
|
||||
],
|
||||
])) ?>" />
|
||||
</article>
|
@ -10,7 +10,7 @@
|
||||
|
||||
<?= $this->section('content') ?>
|
||||
|
||||
<Alert glyph="alert" variant="danger"><?= lang('PodcastImport.warning') ?></Alert>
|
||||
<Alert glyph="alert" variant="danger" class="max-w-xl"><?= lang('PodcastImport.warning') ?></Alert>
|
||||
|
||||
<form action="<?= route_to('podcast-import') ?>" method="POST" enctype='multipart/form-data' class="flex flex-col mt-6 gap-y-8">
|
||||
<?= csrf_field() ?>
|
||||
|
@ -4,90 +4,17 @@
|
||||
<a href="<?= route_to(
|
||||
'episode-list',
|
||||
$podcast->id,
|
||||
) ?>" class="inline-flex items-center text-sm underline hover:no-underline">
|
||||
) ?>" class="inline-flex items-center text-sm underline hover:no-underline focus:ring-castopod">
|
||||
<?= lang('Podcast.see_all_episodes') ?>
|
||||
<?= icon('chevron-right', 'ml-2') ?>
|
||||
</a>
|
||||
</header>
|
||||
<?php if ($episodes): ?>
|
||||
<div class="flex p-2 overflow-x-auto gap-x-6 snap snap-x snap-proximity">
|
||||
<div class="grid px-4 py-2 -mx-2 overflow-x-auto grid-cols-latestEpisodes gap-x-4 snap snap-x snap-proximity">
|
||||
<?php foreach ($episodes as $episode): ?>
|
||||
<article class="snap-center flex flex-col flex-shrink-0 flex-1 w-full min-w-[12rem] max-w-[17rem] overflow-hidden bg-white border-2 border-pine-100 rounded-xl">
|
||||
<div class="relative">
|
||||
<?= publication_pill(
|
||||
$episode->published_at,
|
||||
$episode->publication_status,
|
||||
'absolute top-2 right-2 text-sm'
|
||||
); ?>
|
||||
<img
|
||||
src="<?= $episode->image->medium_url ?>"
|
||||
alt="<?= $episode->title ?>" class="object-cover w-full" />
|
||||
</div>
|
||||
<div class="flex items-start justify-between p-2">
|
||||
<div class="flex flex-col min-w-0">
|
||||
<a href="<?= route_to(
|
||||
'episode-view',
|
||||
$podcast->id,
|
||||
$episode->id,
|
||||
) ?>"
|
||||
class="text-sm font-semibold truncate hover:underline focus:ring-castopod"
|
||||
>
|
||||
<?= episode_numbering(
|
||||
$episode->number,
|
||||
$episode->season_number,
|
||||
'text-xs font-semibold text-gray-600 !no-underline border px-1 border-gray-500 mr-1',
|
||||
true,
|
||||
) . $episode->title ?>
|
||||
</a>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
class="inline-flex items-center p-1 focus:ring-castopod"
|
||||
id="more-dropdown-<?= $episode->id ?>"
|
||||
data-dropdown="button"
|
||||
data-dropdown-target="more-dropdown-<?= $episode->id ?>-menu"
|
||||
aria-label="<?= lang('Common.more') ?>"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
><?= icon('more') ?></button>
|
||||
<DropdownMenu id="more-dropdown-<?= $episode->id ?>-menu" labelledby="more-dropdown-<?= $episode->id ?>" items="<?= esc(json_encode([
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('Episode.edit'),
|
||||
'uri' => route_to('episode-edit', $podcast->id, $episode->id),
|
||||
],
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('Episode.embed.title'),
|
||||
'uri' => route_to('embed-add', $podcast->id, $episode->id),
|
||||
],
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('Person.persons'),
|
||||
'uri' => route_to('episode-persons-manage', $podcast->id, $episode->id),
|
||||
],
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('Episode.soundbites'),
|
||||
'uri' => route_to('soundbites-edit', $podcast->id, $episode->id),
|
||||
],
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('Episode.go_to_page'),
|
||||
'uri' => route_to('episode', $podcast->handle, $episode->slug),
|
||||
],
|
||||
[
|
||||
'type' => 'separator',
|
||||
],
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('Episode.delete'),
|
||||
'uri' => route_to('episode-delete', $podcast->id, $episode->id),
|
||||
'class' => 'font-semibold text-red-600',
|
||||
],
|
||||
])) ?>" />
|
||||
</div>
|
||||
</article>
|
||||
<?= view('episode/_card', [
|
||||
'episode' => $episode,
|
||||
]) ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
|
@ -16,49 +16,12 @@
|
||||
|
||||
<?= $this->section('content') ?>
|
||||
|
||||
<div class="grid gap-4 grid-cols-podcasts">
|
||||
<div class="grid gap-4 grid-cols-cards">
|
||||
<?php if ($podcasts !== null): ?>
|
||||
<?php foreach ($podcasts as $podcast): ?>
|
||||
<article class="relative h-full overflow-hidden transition bg-white shadow border-3 border-pine-100 rounded-xl group hover:shadow-xl focus-within:ring-castopod">
|
||||
<div class="w-full h-full overflow-hidden">
|
||||
<img
|
||||
alt="<?= $podcast->title ?>"
|
||||
src="<?= $podcast->image->medium_url ?>" class="object-cover w-full h-full transition duration-200 ease-in-out transform group-hover:scale-105" />
|
||||
</div>
|
||||
<a href="<?= route_to(
|
||||
'podcast-view',
|
||||
$podcast->id,
|
||||
) ?>" class="absolute bottom-0 left-0 flex flex-col justify-end w-full h-full text-white" style="
|
||||
background-image: linear-gradient(180deg,
|
||||
hsla(0, 0%, 35.29%, 0) 0%,hsla(0, 0%, 34.53%, 0.034375) 16.36%,
|
||||
hsla(0, 0%, 32.42%, 0.125) 33.34%,
|
||||
hsla(0, 0%, 29.18%, 0.253125) 50.1%,
|
||||
hsla(0, 0%, 24.96%, 0.4) 65.75%,
|
||||
hsla(0, 0%, 19.85%, 0.546875) 79.43%,
|
||||
hsla(0, 0%, 13.95%, 0.675) 90.28%,
|
||||
hsla(0, 0%, 7.32%, 0.765625) 97.43%,
|
||||
hsla(0, 0%, 0%, 0.8) 100%
|
||||
);
|
||||
">
|
||||
<div class="px-4 pb-4 transition duration-75 ease-out translate-y-6 group-hover:translate-y-0">
|
||||
<h2 class="font-bold leading-none truncate font-display"><?= $podcast->title ?></h2>
|
||||
<p class="text-sm transition duration-150 opacity-0 group-hover:opacity-75">@<?= $podcast->handle ?></p>
|
||||
</div>
|
||||
</a>
|
||||
<button class="absolute top-0 right-0 p-2 mt-2 mr-2 text-white transition -translate-y-12 rounded-full opacity-0 group-hover:translate-y-0 bg-black/25 group-hover:opacity-100" id="more-dropdown-<?= $podcast->id ?>" data-dropdown="button" data-dropdown-target="more-dropdown-<?= $podcast->id ?>-menu" aria-haspopup="true" aria-expanded="false" title="<?= lang('Common.more') ?>"><?= icon('more') ?></button>
|
||||
<DropdownMenu id="more-dropdown-<?= $podcast->id ?>-menu" labelledby="more-dropdown-<?= $podcast->id ?>" items="<?= esc(json_encode([
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('Podcast.view'),
|
||||
'uri' => route_to('podcast-view', $podcast->id),
|
||||
],
|
||||
[
|
||||
'type' => 'link',
|
||||
'title' => lang('Podcast.edit'),
|
||||
'uri' => route_to('podcast-edit', $podcast->id),
|
||||
],
|
||||
])) ?>" />
|
||||
</article>
|
||||
<?= view('podcast/_card', [
|
||||
'podcast' => $podcast,
|
||||
]) ?>
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
<p class="italic"><?= lang('Podcast.no_podcast') ?></p>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="sticky top-0 left-0 z-50 flex items-center justify-between w-full h-10 text-white border-b shadow bg-pine-800 border-pine-900">
|
||||
<div class="sticky top-0 left-0 z-50 flex items-center justify-between w-full h-10 text-white border-b bg-pine-800 border-pine-900">
|
||||
<div class="inline-flex items-center h-full">
|
||||
<a href="<?= route_to('home') ?>" class="inline-flex items-center h-full px-2 border-r border-pine-900 focus:ring-inset focus:ring-castopod">
|
||||
<?= svg('castopod-logo-base', 'h-6') ?>
|
||||
@ -20,7 +20,7 @@
|
||||
aria-expanded="false"><div class="relative mr-1">
|
||||
<?= icon('account-circle', 'text-3xl opacity-60') ?>
|
||||
<?= user()
|
||||
->podcasts === [] ? '' : '<img src="' . interact_as_actor()->avatar_image_url . '" class="absolute bottom-0 w-4 h-4 rounded-full -right-1" />' ?>
|
||||
->podcasts === [] ? '' : '<img src="' . interact_as_actor()->avatar_image_url . '" class="absolute bottom-0 w-4 h-4 border rounded-full -right-1 border-pine-800" />' ?>
|
||||
</div>
|
||||
<?= user()->username ?>
|
||||
<?= icon('caret-down', 'ml-auto text-2xl') ?></button>
|
||||
|
@ -24,9 +24,9 @@
|
||||
<?php endif; ?>
|
||||
|
||||
<header class="py-8 text-white border-b bg-pine-800">
|
||||
<div class="container flex flex-col px-2 py-4 mx-auto">
|
||||
<div class="container flex flex-col items-start px-2 py-4 mx-auto">
|
||||
<a href="<?= route_to('home') ?>"
|
||||
class="inline-flex items-center mb-2"><?= icon(
|
||||
class="inline-flex items-center mb-2 focus:ring-castopod"><?= icon(
|
||||
'arrow-left',
|
||||
'mr-2',
|
||||
) . lang('Page.back_to_home') ?></a>
|
||||
@ -42,7 +42,7 @@
|
||||
<?= render_page_links() ?>
|
||||
<small><?= lang('Common.powered_by', [
|
||||
'castopod' =>
|
||||
'<a class="underline hover:no-underline" href="https://castopod.org/" target="_blank" rel="noreferrer noopener">Castopod</a>',
|
||||
'<a class="underline hover:no-underline focus:ring-castopod" href="https://castopod.org/" target="_blank" rel="noreferrer noopener">Castopod</a>',
|
||||
]) ?></small>
|
||||
</footer>
|
||||
</body>
|
||||
|
@ -19,9 +19,9 @@
|
||||
<div class="flex gap-x-2">
|
||||
<img src="<?= $person->image->thumbnail_url ?>" alt="<?= $person->full_name ?>" class="object-cover w-10 h-10 rounded-full" />
|
||||
<div class="flex flex-col">
|
||||
<h4 class="text-sm font-semibold hover:underline focus:ring-castopod">
|
||||
<h4 class="text-sm font-semibold">
|
||||
<?php if ($person->information_url): ?>
|
||||
<a href="<?= $person->information_url ?>" target="_blank" rel="noopener noreferrer"><?= $person->full_name ?></a>
|
||||
<a href="<?= $person->information_url ?>" class="hover:underline focus:ring-castopod" target="_blank" rel="noopener noreferrer"><?= $person->full_name ?></a>
|
||||
<?php else: ?>
|
||||
<?= $person->full_name ?>
|
||||
<?php endif; ?>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<body class="flex" style="background: <?= $themeData['background'] ?>; color: <?= $themeData['text'] ?>;">
|
||||
<img src="<?= $episode->image->thumbnail_url ?>" alt="<?= $episode->title ?>" class="flex-shrink w-36 h-36" />
|
||||
<div class="flex flex-col items-start flex-1 min-w-0 px-4 pt-4 h-36">
|
||||
<a href="https://castopod.org/" class="absolute text-2xl top-1 right-2 text-pine-500 hover:opacity-75" title="<?= lang('Common.powered_by', [
|
||||
<a href="https://castopod.org/" class="absolute top-0 right-0 mt-1 mr-2 text-2xl text-pine-500 hover:opacity-75" title="<?= lang('Common.powered_by', [
|
||||
'castopod' => 'Castopod',
|
||||
]) ?>" target="_blank" rel="noopener noreferrer"><?= icon('podcasting/castopod') ?></a>
|
||||
<div class="flex gap-x-2">
|
||||
|
@ -31,8 +31,8 @@
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<nav class="flex items-center justify-between h-10 col-start-2 px-2 text-white bg-pine-800">
|
||||
<a href="<?= route_to('podcast-episodes', $podcast->handle) ?>" class="inline-flex items-center focus:ring-castopod" title="<?= lang('Episode.back_to_episodes', [
|
||||
<nav class="flex items-center justify-between h-10 col-start-2 text-white bg-pine-800">
|
||||
<a href="<?= route_to('podcast-episodes', $podcast->handle) ?>" class="inline-flex items-center h-full px-2 focus:ring-castopod focus:ring-inset" title="<?= lang('Episode.back_to_episodes', [
|
||||
'podcast' => $podcast->title,
|
||||
]) ?>">
|
||||
<?= icon('arrow-left', 'mr-2 text-lg') ?>
|
||||
@ -46,7 +46,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<div class="inline-flex items-center self-end h-full gap-x-2">
|
||||
<div class="inline-flex items-center self-end h-full px-2 gap-x-2">
|
||||
<?php if (in_array(true, array_column($podcast->fundingPlatforms, 'is_visible'), true)): ?>
|
||||
<IconButton glyph="heart" variant="accent" data-toggle="funding-links" data-toggle-class="hidden"><?= lang('Podcast.sponsor') . lang('Podcast.sponsor_title') ?></IconButton>
|
||||
<?php endif; ?>
|
||||
@ -75,7 +75,7 @@
|
||||
<h1 class="inline-flex items-baseline max-w-md mt-2 text-2xl font-bold leading-none sm:text-3xl font-display line-clamp-2"><?= $episode->title ?></h1>
|
||||
<div class="flex items-center mt-4 gap-x-8">
|
||||
<?php if ($episode->persons !== []): ?>
|
||||
<button class="flex items-center text-xs font-semibold gap-x-2 hover:underline" data-toggle="persons-list" data-toggle-class="hidden">
|
||||
<button class="flex items-center text-xs font-semibold gap-x-2 hover:underline focus:ring-castopod" data-toggle="persons-list" data-toggle-class="hidden">
|
||||
<div class="inline-flex flex-row-reverse">
|
||||
<?php $i = 0; ?>
|
||||
<?php foreach ($episode->persons as $person): ?>
|
||||
|
@ -16,7 +16,7 @@ $navigationItems = [
|
||||
<nav class="sticky z-40 flex col-start-2 px-4 pt-4 bg-white shadow md:px-8 gap-x-2 md:gap-x-4 -top-4 rounded-conditional-b-xl">
|
||||
<?php foreach ($navigationItems as $item): ?>
|
||||
<?php $isActive = url_is($item['uri']); ?>
|
||||
<a href="<?= $item['uri'] ?>" class="px-4 py-1 text-sm font-semibold uppercase border-b-4<?= $isActive ? ' border-b-4 text-pine-500 border-pine-500' : ' text-gray-500 hover:text-gray-900 hover:border-gray-200 border-transparent' ?>"><?= $item['label'] ?><span class="px-2 ml-1 font-semibold rounded-full <?= $isActive ? ' bg-pine-100' : ' bg-gray-100' ?>"><?= $item['labelInfo'] ?></span></a>
|
||||
<a href="<?= $item['uri'] ?>" class="px-4 py-1 text-sm font-semibold uppercase focus:ring-castopod border-b-4<?= $isActive ? ' border-b-4 text-pine-500 border-pine-500' : ' text-gray-500 hover:text-gray-900 hover:border-gray-200 border-transparent' ?>"><?= $item['label'] ?><span class="px-2 ml-1 font-semibold rounded-full <?= $isActive ? ' bg-pine-100' : ' bg-gray-100' ?>"><?= $item['labelInfo'] ?></span></a>
|
||||
<?php endforeach; ?>
|
||||
<button type="button" class="p-2 ml-auto rotate-180 rounded-full md:hidden focus:ring-castopod" data-toggle="podcast-sidebar" data-toggle-class="absolute sticky top-0 right-0 hidden bg-white top-12"><?= icon('menu') ?></button>
|
||||
</nav>
|
@ -32,16 +32,19 @@
|
||||
<h1 class="mb-2 text-xl"><?= lang('Home.all_podcasts') ?> (<?= count(
|
||||
$podcasts,
|
||||
) ?>)</h1>
|
||||
<section class="grid gap-4 grid-cols-podcasts">
|
||||
<section class="grid gap-4 grid-cols-cards">
|
||||
<?php if ($podcasts): ?>
|
||||
<?php foreach ($podcasts as $podcast): ?>
|
||||
<a href="<?= $podcast->link ?>" class="w-full">
|
||||
<article class="w-full h-full overflow-hidden bg-white border shadow rounded-xl hover:bg-gray-100 hover:shadow">
|
||||
<img alt="<?= $podcast->title ?>"
|
||||
src="<?= $podcast->image->medium_url ?>"
|
||||
class="object-cover w-full h-48 mb-2" />
|
||||
<h2 class="px-2 font-semibold leading-tight truncate"><?= $podcast->title ?></h2>
|
||||
<p class="px-2 pb-2 text-gray-600">@<?= $podcast->handle ?></p>
|
||||
<a href="<?= $podcast->link ?>" class="relative w-full h-full overflow-hidden transition shadow focus:ring-castopod rounded-xl border-pine-100 hover:shadow-xl focus:shadow-xl group border-3">
|
||||
<article class="text-white">
|
||||
<div class="absolute bottom-0 left-0 z-10 w-full h-full backdrop-gradient"></div>
|
||||
<div class="w-full h-full overflow-hidden">
|
||||
<img alt="<?= $podcast->title ?>" src="<?= $podcast->image->medium_url ?>" class="object-cover w-full h-full transition duration-200 ease-in-out transform group-focus:scale-105 group-hover:scale-105" />
|
||||
</div>
|
||||
<div class="absolute bottom-0 left-0 z-20 px-4 pb-2">
|
||||
<h2 class="font-bold leading-none truncate font-display"><?= $podcast->title ?></h2>
|
||||
<p class="text-sm opacity-75">@<?= $podcast->handle ?></p>
|
||||
</div>
|
||||
</article>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
@ -54,7 +57,7 @@
|
||||
<?= render_page_links() ?>
|
||||
<small><?= lang('Common.powered_by', [
|
||||
'castopod' =>
|
||||
'<a class="inline-flex font-semibold hover:underline" href="https://castopod.org/" target="_blank" rel="noreferrer noopener">Castopod' . icon('social/castopod', 'ml-1 text-lg') . '</a>',
|
||||
'<a class="inline-flex font-semibold hover:underline focus:ring-castopod" href="https://castopod.org/" target="_blank" rel="noreferrer noopener">Castopod' . icon('social/castopod', 'ml-1 text-lg') . '</a>',
|
||||
]) ?></small>
|
||||
</footer>
|
||||
</body>
|
||||
|
@ -23,9 +23,9 @@
|
||||
<?php endif; ?>
|
||||
|
||||
<header class="py-8 text-white border-b bg-pine-800">
|
||||
<div class="container flex flex-col px-2 py-4 mx-auto">
|
||||
<div class="container flex flex-col items-start px-2 py-4 mx-auto">
|
||||
<a href="<?= route_to('home') ?>"
|
||||
class="inline-flex items-center mb-2"><?= icon(
|
||||
class="inline-flex items-center mb-2 focus:ring-castopod"><?= icon(
|
||||
'arrow-left',
|
||||
'mr-2',
|
||||
) . lang('Page.back_to_home') ?></a>
|
||||
@ -39,7 +39,7 @@
|
||||
<?= render_page_links() ?>
|
||||
<small><?= lang('Common.powered_by', [
|
||||
'castopod' =>
|
||||
'<a class="inline-flex font-semibold hover:underline" href="https://castopod.org/" target="_blank" rel="noreferrer noopener">Castopod' . icon('social/castopod', 'ml-1 text-lg') . '</a>',
|
||||
'<a class="inline-flex font-semibold hover:underline focus:ring-castopod" href="https://castopod.org/" target="_blank" rel="noreferrer noopener">Castopod' . icon('social/castopod', 'ml-1 text-lg') . '</a>',
|
||||
]) ?></small>
|
||||
</footer>
|
||||
</body>
|
||||
|
@ -20,9 +20,9 @@
|
||||
<?php endif; ?>
|
||||
|
||||
<header class="py-8 text-white border-b bg-pine-800">
|
||||
<div class="container flex flex-col px-2 py-4 mx-auto">
|
||||
<div class="container flex flex-col items-start px-2 py-4 mx-auto">
|
||||
<a href="<?= route_to('home') ?>"
|
||||
class="inline-flex items-center mb-2"><?= icon(
|
||||
class="inline-flex items-center mb-2 focus:ring-castopod"><?= icon(
|
||||
'arrow-left',
|
||||
'mr-2',
|
||||
) . lang('Page.back_to_home') ?></a>
|
||||
@ -38,7 +38,7 @@
|
||||
<?= render_page_links() ?>
|
||||
<small><?= lang('Common.powered_by', [
|
||||
'castopod' =>
|
||||
'<a class="inline-flex font-semibold hover:underline" href="https://castopod.org/" target="_blank" rel="noreferrer noopener">Castopod' . icon('social/castopod', 'ml-1 text-lg') . '</a>',
|
||||
'<a class="inline-flex font-semibold hover:underline focus:ring-castopod" href="https://castopod.org/" target="_blank" rel="noreferrer noopener">Castopod' . icon('social/castopod', 'ml-1 text-lg') . '</a>',
|
||||
]) ?></small>
|
||||
</footer>
|
||||
</body>
|
||||
|
@ -18,7 +18,7 @@ $navigationItems = [
|
||||
<nav class="sticky z-40 flex col-start-2 px-4 pt-8 bg-white shadow gap-x-2 md:gap-x-4 md:px-8 -top-8 md:-top-12 rounded-conditional-b-xl md:pt-12 ">
|
||||
<?php foreach ($navigationItems as $item): ?>
|
||||
<?php $isActive = url_is($item['uri']); ?>
|
||||
<a href="<?= $item['uri'] ?>" class="px-4 py-1 text-sm font-semibold uppercase border-b-4<?= $isActive ? ' border-b-4 text-pine-500 border-pine-500' : ' text-gray-500 hover:text-gray-900 hover:border-gray-200 border-transparent' ?>"><?= $item['label'] ?></a>
|
||||
<a href="<?= $item['uri'] ?>" class="px-4 py-1 text-sm font-semibold uppercase focus:ring-castopod border-b-4<?= $isActive ? ' border-b-4 text-pine-500 border-pine-500' : ' text-gray-500 hover:text-gray-900 hover:border-gray-200 border-transparent' ?>"><?= $item['label'] ?></a>
|
||||
<?php endforeach; ?>
|
||||
<button type="button" class="p-2 ml-auto rotate-180 rounded-full md:hidden focus:ring-castopod"><?= icon('menu') ?></button>
|
||||
</nav>
|
@ -1,7 +1,7 @@
|
||||
<aside id="podcast-sidebar" class="sticky hidden col-span-1 md:block top-12">
|
||||
<div class="absolute z-0 w-full h-full sm:hidden bg-pine-800/50"></div>
|
||||
<div class="z-10 bg-pine-50">
|
||||
<a href="<?= route_to('podcast_feed', $podcast->handle) ?>" class="inline-flex items-center mb-6 text-sm font-semibold text-pine-800 group" target="_blank" rel="noopener noreferrer">
|
||||
<a href="<?= route_to('podcast_feed', $podcast->handle) ?>" class="inline-flex items-center mb-6 text-sm font-semibold focus:ring-castopod text-pine-800 group" target="_blank" rel="noopener noreferrer">
|
||||
<?= icon('rss', ' mr-2 bg-orange-500 text-xl text-white group-hover:bg-orange-700 p-1 w-6 h-6 inline-flex items-center justify-center rounded-lg') . lang('Podcast.feed') ?>
|
||||
</a>
|
||||
<?php if (
|
||||
@ -61,7 +61,7 @@
|
||||
<p><?= $podcast->copyright ?></p>
|
||||
<p><?= lang('Common.powered_by', [
|
||||
'castopod' =>
|
||||
'<a class="inline-flex font-semibold text-gray-500 hover:underline" href="https://castopod.org" target="_blank" rel="noreferrer noopener">Castopod' . icon('social/castopod', 'ml-1 text-lg') . '</a>',
|
||||
'<a class="inline-flex font-semibold text-gray-500 hover:underline focus:ring-castopod" href="https://castopod.org" target="_blank" rel="noreferrer noopener">Castopod' . icon('social/castopod', 'ml-1 text-lg') . '</a>',
|
||||
]) ?></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
@ -48,7 +48,7 @@
|
||||
|
||||
<div class="flex items-center mt-4 gap-x-8">
|
||||
<?php if ($podcast->persons !== []): ?>
|
||||
<button class="flex items-center text-xs font-semibold gap-x-2 hover:underline" data-toggle="persons-list" data-toggle-class="hidden">
|
||||
<button class="flex items-center text-xs font-semibold gap-x-2 hover:underline focus:ring-castopod" data-toggle="persons-list" data-toggle-class="hidden">
|
||||
<div class="inline-flex flex-row-reverse">
|
||||
<?php $i = 0; ?>
|
||||
<?php foreach ($podcast->persons as $person): ?>
|
||||
|
@ -10,11 +10,11 @@
|
||||
<link rel="shortcut icon" type="image/png" href="/favicon.ico" />
|
||||
<?= service('vite')->asset('styles/index.css', 'css') ?>
|
||||
|
||||
<title><?= lang('Podcast.follow.title', [
|
||||
<title><?= lang('Podcast.followTitle', [
|
||||
'actorDisplayName' => $actor->display_name,
|
||||
]) ?></title>
|
||||
<meta name="description" content="<?= $actor->summary ?>"/>
|
||||
<meta property="og:title" content="<?= lang('Podcast.follow.title', [
|
||||
<meta property="og:title" content="<?= lang('Podcast.followTitle', [
|
||||
'actorDisplayName' => $actor->display_name,
|
||||
]) ?>"/>
|
||||
<meta property="og:locale" content="<?= service(
|
||||
@ -26,6 +26,8 @@
|
||||
|
||||
<?= service('vite')
|
||||
->asset('styles/index.css', 'css') ?>
|
||||
<?= service('vite')
|
||||
->asset('js/podcast.ts', 'js') ?>
|
||||
</head>
|
||||
|
||||
|
||||
@ -38,7 +40,7 @@
|
||||
<img src="<?= $actor->cover_image_url ?>" alt="" class="object-cover w-full h-32 bg-pine-800" />
|
||||
<div class="flex px-4 py-2">
|
||||
<img src="<?= $actor->avatar_image_url ?>" alt="<?= $actor->display_name ?>"
|
||||
class="w-16 h-16 mr-4 -mt-8 rounded-full shadow-xl ring-2 ring-white" />
|
||||
class="w-16 h-16 mr-4 -mt-8 rounded-full ring-2 ring-white" />
|
||||
<div class="">
|
||||
<p class="font-semibold"><?= $actor->display_name ?></p>
|
||||
<p class="text-sm text-gray-500">@<?= $actor->username ?></p>
|
||||
@ -58,7 +60,7 @@
|
||||
hint="<?= lang('Fediverse.your_handle_hint') ?>"
|
||||
required="true"
|
||||
/>
|
||||
<Button variant="primary" type="submit" class="self-end"><?= lang('Fediverse.follow.submit') ?></Button>
|
||||
<Button variant="primary" type="submit" class="self-end" iconRight="send-plane"><?= lang('Fediverse.follow.submit') ?></Button>
|
||||
</form>
|
||||
</main>
|
||||
|
||||
@ -68,7 +70,7 @@
|
||||
<p>
|
||||
<?= lang('Common.powered_by', [
|
||||
'castopod' =>
|
||||
'<a class="inline-flex font-semibold hover:underline" href="https://castopod.org" target="_blank" rel="noreferrer noopener">Castopod' . icon('social/castopod', 'ml-1 text-lg') . '</a>',
|
||||
'<a class="inline-flex font-semibold hover:underline focus:ring-castopod" href="https://castopod.org" target="_blank" rel="noreferrer noopener">Castopod' . icon('social/castopod', 'ml-1 text-lg') . '</a>',
|
||||
]) ?>
|
||||
</p>
|
||||
</footer>
|
||||
|
@ -50,7 +50,7 @@
|
||||
hint="<?= lang('Fediverse.your_handle_hint') ?>"
|
||||
required="true" />
|
||||
|
||||
<Button variant="primary" type="submit" class="self-end"><?= lang('Fediverse.' . $action . '.submit') ?></Button>
|
||||
<Button variant="primary" type="submit" class="self-end" iconRight="send-plane"><?= lang('Fediverse.' . $action . '.submit') ?></Button>
|
||||
</form>
|
||||
</main>
|
||||
</body>
|
||||
|
@ -16,7 +16,7 @@
|
||||
<header class="mb-4">
|
||||
<a href="<?= route_to(
|
||||
'home',
|
||||
) ?>" class="inline-flex items-baseline text-4xl font-bold font-display text-pine-500">
|
||||
) ?>" class="inline-flex items-baseline text-4xl font-bold font-display text-pine-500 focus:ring-castopod">
|
||||
<?= 'castopod' . svg('castopod-logo', 'h-8 ml-2') ?>
|
||||
</a>
|
||||
</header>
|
||||
@ -31,7 +31,7 @@
|
||||
<?= $this->renderSection('footer') ?>
|
||||
<small class="py-4 text-center border-t-2 border-pine-100"><?= lang('Common.powered_by', [
|
||||
'castopod' =>
|
||||
'<a class="inline-flex font-semibold hover:underline" target="_blank" rel="noreferrer noopener">Castopod' . icon('social/castopod', 'ml-1 text-lg') . '</a>',
|
||||
'<a class="inline-flex font-semibold hover:underline focus:ring-castopod" target="_blank" rel="noreferrer noopener">Castopod' . icon('social/castopod', 'ml-1 text-lg') . '</a>',
|
||||
]) ?></small>
|
||||
</footer>
|
||||
</body>
|
||||
|
@ -26,7 +26,7 @@
|
||||
<footer class="container px-2 py-4 mx-auto text-sm text-right border-t">
|
||||
<small><?= lang('Common.powered_by', [
|
||||
'castopod' =>
|
||||
'<a class="inline-flex font-semibold hover:underline" href="https://castopod.org" target="_blank" rel="noreferrer noopener">Castopod' . icon('social/castopod', 'ml-1 text-lg') . '</a>',
|
||||
'<a class="inline-flex font-semibold hover:underline focus:ring-castopod" href="https://castopod.org" target="_blank" rel="noreferrer noopener">Castopod' . icon('social/castopod', 'ml-1 text-lg') . '</a>',
|
||||
]) ?></small>
|
||||
</footer>
|
||||
</body>
|
||||
|
Loading…
Reference in New Issue
Block a user