Skip to content

Commit 4370170

Browse files
committed
Add Blade and JavaScript callout playground
1 parent ba2ed03 commit 4370170

15 files changed

Lines changed: 575 additions & 0 deletions

File tree

‎README.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,9 @@ Here are some specific things to poke at if you're learning Filament:
8484
| Global search | Press Cmd+K anywhere |
8585
| Keyboard shortcuts | Cmd+Shift+P to quick-publish a post |
8686
| Navigation badges | Check sidebar counts on orders, leave requests, and expenses |
87+
88+
## Callout playground
89+
90+
Open `/callout-playground` after signing in to compare the Blade callout with plain-JavaScript React, Vue, and Svelte consumers. Change the color (including the registered `brand` palette), icon artwork, independent icon color and size, description, and actions. Review and dismiss operate only on local state; Reset restores the notice. No release is published.
91+
92+
The framework examples import Support's `Callout` from the Composer path package and use the existing Filament theme. Run `npm run build` after changing them. Each renderer unmounts through `HasJsRenderer` when its host is removed. For browser checks, scope selectors to `[data-framework="react"]`, `vue`, `svelte`, or `blade`, then use `data-testid="callout"`, `color`, `icon`, `override`, `details`, `actions`, `review`, `dismiss`, `result`, and `reset`.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace App\Filament\Pages;
4+
5+
use App\Filament\Widgets\CalloutBlade;
6+
use App\Filament\Widgets\CalloutReact;
7+
use App\Filament\Widgets\CalloutSvelte;
8+
use App\Filament\Widgets\CalloutVue;
9+
use Filament\Pages\Dashboard;
10+
11+
class CalloutPlayground extends Dashboard
12+
{
13+
protected static string $routePath = 'callout-playground';
14+
15+
protected static ?string $title = 'Callout playground';
16+
17+
public function getWidgets(): array
18+
{
19+
return [CalloutBlade::class, CalloutReact::class, CalloutVue::class, CalloutSvelte::class];
20+
}
21+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace App\Filament\Widgets;
4+
5+
use Filament\Widgets\Widget;
6+
7+
class CalloutBlade extends Widget
8+
{
9+
protected string $view = 'filament.widgets.callout-blade';
10+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace App\Filament\Widgets;
4+
5+
use Filament\Widgets\Concerns\HasJsRenderer;
6+
use Filament\Widgets\Widget;
7+
use Illuminate\Support\Facades\Vite;
8+
9+
class CalloutReact extends Widget
10+
{
11+
use HasJsRenderer;
12+
13+
public function getRenderer(): string
14+
{
15+
return Vite::asset('resources/js/filament/widgets/callout-react.jsx');
16+
}
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace App\Filament\Widgets;
4+
5+
use Filament\Widgets\Concerns\HasJsRenderer;
6+
use Filament\Widgets\Widget;
7+
use Illuminate\Support\Facades\Vite;
8+
9+
class CalloutSvelte extends Widget
10+
{
11+
use HasJsRenderer;
12+
13+
public function getRenderer(): string
14+
{
15+
return Vite::asset('resources/js/filament/widgets/callout-svelte.svelte.js');
16+
}
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace App\Filament\Widgets;
4+
5+
use Filament\Widgets\Concerns\HasJsRenderer;
6+
use Filament\Widgets\Widget;
7+
use Illuminate\Support\Facades\Vite;
8+
9+
class CalloutVue extends Widget
10+
{
11+
use HasJsRenderer;
12+
13+
public function getRenderer(): string
14+
{
15+
return Vite::asset('resources/js/filament/widgets/callout-vue.js');
16+
}
17+
}

‎app/Providers/Filament/AdminPanelProvider.php‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public function panel(Panel $panel): Panel
5959
->spa()
6060
->colors([
6161
'primary' => Color::Blue,
62+
'brand' => Color::Violet,
6263
])
6364
->font('Albert Sans');
6465
}

‎resources/css/filament/admin/theme.css‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,3 +160,7 @@
160160
.radio-demo-controls {
161161
@apply flex flex-wrap gap-4;
162162
}
163+
164+
.callout-demo {
165+
@apply grid gap-4;
166+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<script>
2+
import { Info, CircleCheck } from '@lucide/svelte'
3+
import Callout from '../../../../vendor/filament/support/resources/js/svelte/Callout.svelte'
4+
let color = $state('gray')
5+
let icon = $state('none')
6+
let override = $state(false)
7+
let details = $state(true)
8+
let actions = $state(true)
9+
let visible = $state(true)
10+
let message = $state('No changes published.')
11+
</script>
12+
13+
{#snippet artwork()}{#if icon === 'info'}<Info />{:else}<CircleCheck
14+
/>{/if}{/snippet}
15+
{#snippet description()}Review the <strong>release notes</strong> before publishing.{/snippet}
16+
{#snippet footer()}<button
17+
type="button"
18+
data-testid="review"
19+
onclick={() => (message = 'Release notes reviewed locally.')}
20+
>Review notes</button
21+
><a href="#svelte-release">View release</a>{/snippet}
22+
{#snippet controls()}<button
23+
type="button"
24+
data-testid="dismiss"
25+
aria-label="Dismiss release notice"
26+
onclick={() => {
27+
visible = false
28+
message = 'Release notice dismissed locally.'
29+
}}>×</button
30+
>{/snippet}
31+
<section class="callout-demo" data-framework="svelte">
32+
<h2 class="fi-section-header-heading">Svelte · JavaScript</h2>
33+
{#if visible}<Callout
34+
data-testid="callout"
35+
{color}
36+
heading="Your next release"
37+
description={details ? description : undefined}
38+
icon={icon === 'none' ? undefined : artwork}
39+
footer={actions ? footer : undefined}
40+
controls={actions ? controls : undefined}
41+
iconColor={override ? 'success' : undefined}
42+
iconSize={override ? 'sm' : 'lg'}
43+
/>{/if}
44+
<div class="icon-demo-controls">
45+
<label
46+
>Color <select bind:value={color} data-testid="color"
47+
>{#each ['gray', 'primary', 'info', 'success', 'warning', 'danger', 'brand'] as value}<option
48+
>{value}</option
49+
>{/each}</select
50+
></label
51+
>
52+
<label
53+
>Icon <select bind:value={icon} data-testid="icon"
54+
>{#each ['none', 'info', 'check'] as value}<option
55+
>{value}</option
56+
>{/each}</select
57+
></label
58+
>
59+
<label
60+
><input
61+
bind:checked={override}
62+
type="checkbox"
63+
data-testid="override"
64+
/>Small success icon</label
65+
>
66+
<label
67+
><input
68+
bind:checked={details}
69+
type="checkbox"
70+
data-testid="details"
71+
/>Description</label
72+
>
73+
<label
74+
><input
75+
bind:checked={actions}
76+
type="checkbox"
77+
data-testid="actions"
78+
/>Actions and controls</label
79+
>
80+
<button
81+
type="button"
82+
data-testid="reset"
83+
onclick={() => {
84+
color = 'gray'
85+
icon = 'none'
86+
override = false
87+
details = true
88+
actions = true
89+
visible = true
90+
message = 'No changes published.'
91+
}}>Reset</button
92+
>
93+
</div>
94+
<p role="status" data-testid="result">{message}</p>
95+
<p id="svelte-release" tabindex="-1">
96+
September release · Ready for review
97+
</p>
98+
</section>
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
<script setup>
2+
import { ref } from 'vue'
3+
import { Info, CircleCheck } from '@lucide/vue'
4+
import Callout from '../../../../vendor/filament/support/resources/js/vue/Callout.vue'
5+
const color = ref('gray')
6+
const icon = ref('none')
7+
const override = ref(false)
8+
const details = ref(true)
9+
const actions = ref(true)
10+
const visible = ref(true)
11+
const message = ref('No changes published.')
12+
function dismiss() {
13+
visible.value = false
14+
message.value = 'Release notice dismissed locally.'
15+
}
16+
function reset() {
17+
color.value = 'gray'
18+
icon.value = 'none'
19+
override.value = false
20+
details.value = true
21+
actions.value = true
22+
visible.value = true
23+
message.value = 'No changes published.'
24+
}
25+
</script>
26+
<template>
27+
<section class="callout-demo" data-framework="vue">
28+
<h2 class="fi-section-header-heading">Vue · JavaScript</h2>
29+
<Callout
30+
v-if="visible"
31+
data-testid="callout"
32+
:color="color"
33+
heading="Your next release"
34+
:icon-color="override ? 'success' : undefined"
35+
:icon-size="override ? 'sm' : 'lg'"
36+
>
37+
<template v-if="icon !== 'none'" #icon
38+
><Info v-if="icon === 'info'" /><CircleCheck v-else
39+
/></template>
40+
<template v-if="details" #description
41+
>Review the <strong>release notes</strong> before
42+
publishing.</template
43+
>
44+
<template v-if="actions" #footer
45+
><button
46+
type="button"
47+
data-testid="review"
48+
@click="message = 'Release notes reviewed locally.'"
49+
>
50+
Review notes</button
51+
><a href="#vue-release">View release</a></template
52+
>
53+
<template v-if="actions" #controls
54+
><button
55+
type="button"
56+
data-testid="dismiss"
57+
aria-label="Dismiss release notice"
58+
@click="dismiss"
59+
>
60+
×
61+
</button></template
62+
>
63+
</Callout>
64+
<div class="icon-demo-controls">
65+
<label
66+
>Color
67+
<select v-model="color" data-testid="color">
68+
<option
69+
v-for="value in [
70+
'gray',
71+
'primary',
72+
'info',
73+
'success',
74+
'warning',
75+
'danger',
76+
'brand',
77+
]"
78+
:key="value"
79+
>
80+
{{ value }}
81+
</option>
82+
</select></label
83+
>
84+
<label
85+
>Icon
86+
<select v-model="icon" data-testid="icon">
87+
<option
88+
v-for="value in ['none', 'info', 'check']"
89+
:key="value"
90+
>
91+
{{ value }}
92+
</option>
93+
</select></label
94+
>
95+
<label
96+
><input
97+
v-model="override"
98+
type="checkbox"
99+
data-testid="override"
100+
/>Small success icon</label
101+
>
102+
<label
103+
><input
104+
v-model="details"
105+
type="checkbox"
106+
data-testid="details"
107+
/>Description</label
108+
>
109+
<label
110+
><input
111+
v-model="actions"
112+
type="checkbox"
113+
data-testid="actions"
114+
/>Actions and controls</label
115+
>
116+
<button type="button" data-testid="reset" @click="reset">
117+
Reset
118+
</button>
119+
</div>
120+
<p role="status" data-testid="result">{{ message }}</p>
121+
<p id="vue-release" tabindex="-1">
122+
September release · Ready for review
123+
</p>
124+
</section>
125+
</template>

0 commit comments

Comments
 (0)