Refactor styles and components for consistency

- Updated background styles in event join page to a solid color.
- Simplified button styles across various components, replacing complex gradient backgrounds with utility classes.
- Adjusted layout and spacing in profile dropdown and user menu for improved accessibility and readability.
- Enhanced alert and badge components with new styling classes for better visual consistency.
- Refined tab component styles for better alignment and spacing.
- Cleaned up button component attributes for clarity and maintainability.
- Improved test readability by formatting multiline statements.
This commit is contained in:
Alex Lion
2026-01-23 23:45:16 +01:00
parent ce6db03065
commit 0d8d563282
32 changed files with 623 additions and 638 deletions

View File

@@ -1,4 +1,5 @@
@import "tailwindcss";
@import './theme-config.css';
@plugin "daisyui";
@utility btn {
@@ -20,44 +21,3 @@
@utility fieldset-legend {
@apply ml-3;
}
@plugin "daisyui/theme" {
name: "claper";
default: true; /* set as default */
prefersdark: false; /* set as default dark mode (prefers-color-scheme:dark) */
color-scheme: light; /* color of browser-provided UI */
--color-primary: #140753;
--color-primary-content: #ffffff;
--color-secondary: #f4f4f4;
--color-secondary-content: #140553;
--color-accent: #8611ed;
--color-accent-content: #ffffff;
--color-neutral: #000000;
--color-neutral-content: #ffffff;
--color-info: #79bfe2;
--color-info-content: #0e3649;
--color-success: #3cb957;
--color-success-content: #143e1d;
--color-warning: #ffb62e;
--color-warning-content: #523500;
--color-error: #e7000b;
--color-error-content: #fff;
/* border radius */
--radius-selector: 1rem;
--radius-field: 0.25rem;
--radius-box: 0.5rem;
/* base sizes */
--size-selector: 0.25rem;
--size-field: 0.25rem;
/* border size */
--border: 1px;
/* effects */
--depth: 1;
--noise: 0;
}
@import "./modern.css" layer(theme);

View File

@@ -2,11 +2,22 @@
@import 'animate.css/animate.min.css';
@import 'tailwindcss';
@import './theme.css' layer(theme);
@import './theme-config.css';
@plugin "daisyui" {
themes: light --default;
include: toggle;
themes: claper --default;
}
@utility btn {
@apply rounded-full !font-display text-small-body;
}
@utility input {
@apply rounded-full focus:outline-none focus-within:outline-none focus:border-2 focus-within:border-2 !font-display text-small-body transition-all;
}
@utility select {
@apply rounded-full focus:outline-none focus-within:outline-none focus:border-2 focus-within:border-2 !font-display text-small-body transition-all;
}
@layer base {
@@ -17,6 +28,11 @@
::file-selector-button {
border-color: var(--color-gray-200, currentcolor);
}
button,
[role="button"] {
cursor: pointer;
}
}
* {
@@ -321,23 +337,6 @@
src: url('/fonts/Montserrat/Montserrat-Italic-VariableFont_wght.ttf');
}
.bg-gradient-animate {
background: linear-gradient(-45deg, var(--color-secondary-500), var(--color-secondary-600), var(--color-primary-400), var(--color-primary-400));
background-size: 400% 400%;
animation: gradient 15s ease infinite;
}
@keyframes gradient {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
.arrow_box {
position: relative;

View File

@@ -1,152 +0,0 @@
@theme {
/* Colors */
/* Main colors */
--color-*: initial;
--color-sky-blue: #81EBFE;
--color-teal: #14BFDB;
--color-azure: #29ACED;
--color-mauve: #8611ED;
--color-purple: #B80FEF;
--color-navy: #140553;
/* Light colors */
--color-cold-pink: #F3DEFA;
--color-warm-pink: #FFD2F6;
--color-yeallaw: #FFEAC2;
--color-pistacio: #D4FFF4;
--color-sky-tern: #C8EDFF;
--color-tealy: #81EBFE;
--color-earl-night: #0A7BB4;
--color-dark-night: #184992;
/* Gradient */
--gradient-primary: 123deg, var(--color-sky-blue) -36%, var(--color-teal) -12%, var(--color-azure) 21%, var(--color-mauve) 81%, var(--color-purple) 130%;
--gradient-secondary: 123deg, rgba(129, 235, 254, 0.9) -36%, rgba(20, 191, 219, 0.9) -12%, rgba(41, 172, 237, 0.9) 21%, rgba(134, 17, 237, 0.9) 81%, rgba(184, 15, 239, 0.9) 130%;
/* Grayscale */
--color-white: #FFFFFF;
--color-black: #191919;
--color-gray-20: #CCCCCC;
--color-gray-40: #9F9F9F;
--color-gray-60: #737373;
--color-gray-80: #464646;
--color-gray-100: #191919;
--color-gray-120: #000000;
--color-platinum: #F0F0F0;
--color-platinum-20: #FFFFFF;
--color-platinum-40: #FCFCFC;
--color-platinum-60: #F8F8F8;
--color-platinum-80: #F4F4F4;
--color-platinum-100: #F0F0F0;
--color-platinum-120: #EEEEEE;
/* Typography */
--font-display: "Montserrat", sans-serif;
/* Font Sizes - Desktop */
--text-h1: 80px;
--leading-h1: 120%;
--font-weight-h1: 900;
--text-h2: 40px;
--leading-h2: 120%;
--font-weight-h2: 700;
--text-h3: 32px;
--leading-h3: 120%;
--font-weight-h3: 600;
--text-h4: 24px;
--leading-h4: 120%;
--font-weight-h4: 500;
--text-h5: 18px;
--leading-h5: 120%;
--font-weight-h5: 600;
--text-h6: 16px;
--leading-h6: 120%;
--font-weight-h6: 500;
--text-subheading: 20px;
--leading-subheading: 150%;
--font-weight-subheading: 300;
--text-body-bold: 16px;
--leading-body-bold: 150%;
--font-weight-body-bold: 700;
--text-body: 16px;
--leading-body: 150%;
--font-weight-body: 400;
--text-small-body-bold: 14px;
--leading-small-body-bold: 150%;
--font-weight-small-body-bold: 600;
--text-small-body: 14px;
--leading-small-body: 150%;
--font-weight-small-body: 400;
--text-caption: 14px;
--leading-caption: 150%;
--font-weight-caption: 300;
/* Font Sizes - Mobile */
--text-mobile-h1: 32px;
--leading-mobile-h1: 120%;
--font-weight-mobile-h1: 900;
--text-mobile-h2: 28px;
--leading-mobile-h2: 120%;
--font-weight-mobile-h2: 700;
--text-mobile-h3: 22px;
--leading-mobile-h3: 120%;
--font-weight-mobile-h3: 600;
--text-mobile-h4: 18px;
--leading-mobile-h4: 120%;
--font-weight-mobile-h4: 500;
--text-mobile-h5: 16px;
--leading-mobile-h5: 120%;
--font-weight-mobile-h5: 600;
--text-mobile-h6: 14px;
--leading-mobile-h6: 120%;
--font-weight-mobile-h6: 500;
/* Spacing */
--spacing-0: 0px;
--spacing-4: 4px;
--spacing-8: 8px;
--spacing-12: 12px;
--spacing-16: 16px;
--spacing-20: 20px;
--spacing-24: 24px;
--spacing-28: 28px;
--spacing-32: 32px;
--spacing-36: 36px;
--spacing-40: 40px;
--spacing-44: 44px;
--spacing-48: 48px;
--spacing-52: 52px;
--spacing-56: 56px;
--spacing-60: 60px;
--spacing-64: 64px;
--spacing-68: 68px;
--spacing-72: 72px;
--spacing-76: 76px;
--spacing-80: 80px;
--spacing-128: 128px;
/* Font Weights */
--font-weight-regular: 400;
--font-weight-bold: 700;
/* Shadows */
--shadow-3xl: 0px 902px 253px 0px rgba(65, 69, 124, 0.00), 0px 577px 231px 0px rgba(65, 69, 124, 0.01), 0px 325px 195px 0px rgba(65, 69, 124, 0.05), 0px 144px 144px 0px rgba(65, 69, 124, 0.09), 0px 36px 79px 0px rgba(65, 69, 124, 0.10)
}

View File

@@ -1,19 +1,67 @@
@plugin "daisyui/theme" {
name: "claper";
default: true;
prefersdark: false;
color-scheme: light;
/* Map custom colors to DaisyUI semantic tokens */
--color-primary: #8611ed; /* primary-500 */
--color-primary-content: #ffffff;
--color-secondary: #140553; /* secondary-500 */
--color-secondary-content: #ffffff;
--color-accent: #507DAA; /* neutral-500 */
--color-accent-content: #ffffff;
--color-neutral: #374151; /* gray-700 */
--color-neutral-content: #ffffff;
--color-base-100: #ffffff;
--color-base-200: #f9fafb; /* gray-50 */
--color-base-300: #e5e7eb; /* gray-200 */
--color-base-content: #1f2937; /* gray-800 */
--color-info: #79bfe2;
--color-info-content: #0e3649;
--color-success: #10B981; /* supporting-green-500 */
--color-success-content: #064E3B; /* supporting-green-900 */
--color-warning: #F59E0B; /* supporting-yellow-500 */
--color-warning-content: #78350F; /* supporting-yellow-900 */
--color-error: #E12D39; /* supporting-red-500 */
--color-error-content: #ffffff;
/* Border radius (preserve from admin.css) */
--radius-selector: 1rem;
--radius-field: 0.25rem;
--radius-box: 0.5rem;
/* Border and effects */
--border: 1px;
--depth: 1;
--noise: 0;
}
@theme {
/* Gray Colors (Tailwind default) */
--color-gray-50: #f9fafb;
--color-gray-100: #f3f4f6;
--color-gray-200: #e5e7eb;
--color-gray-300: #d1d5db;
--color-gray-400: #9ca3af;
--color-gray-500: #6b7280;
--color-gray-600: #4b5563;
--color-gray-700: #374151;
--color-gray-800: #1f2937;
--color-gray-900: #111827;
--color-gray-950: #030712;
/* Preserve custom CSS variables for non-DaisyUI usage */
--font-display: "Montserrat", sans-serif;
--font-family-sans: "Roboto", sans-serif;
--font-family-serif: "Merriweather", serif;
/* Primary Colors - Claper Purple */
/* Preserve shadows from theme.css */
--shadow-base: 0px 1px 3px 0px rgba(0,0,0,0.1), 0px 1px 2px 0px rgba(0,0,0,0.06);
--shadow-md: 0px 4px 6px 0px rgba(0,0,0,0.1), 0px 2px 4px 0px rgba(0,0,0,0.06);
--shadow-lg: 0px 4px 6px 0px rgba(0,0,0,0.05), 0px 10px 15px 0px rgba(0,0,0,0.1);
--shadow-xl: 0px 10px 10px 0px rgba(0,0,0,0.04), 0px 20px 25px 0px rgba(0,0,0,0.1);
--shadow-2xl: 0px 25px 50px 0px rgba(0,0,0,0.25);
--shadow-inner: inset 0px 2px 4px 0px rgba(0,0,0,0.06);
/* Typography scale from modern.css (if needed by templates) */
--text-h1: 80px;
--text-h2: 40px;
--text-h3: 32px;
--text-h4: 24px;
--text-h5: 18px;
--text-h6: 16px;
--text-body: 16px;
--text-small-body: 14px;
/* Primary Colors - Claper Purple (from old theme.css) */
--color-primary-50: #f3defa;
--color-primary-100: #e8bef5;
--color-primary-200: #d08def;
@@ -25,7 +73,7 @@
--color-primary-800: #35065f;
--color-primary-900: #1a032f;
/* Secondary Colors - Navy Purple */
/* Secondary Colors - Navy Purple (from old theme.css) */
--color-secondary-50: #e8e6f0;
--color-secondary-100: #c5c0db;
--color-secondary-200: #9f97c2;
@@ -36,8 +84,8 @@
--color-secondary-700: #0c0332;
--color-secondary-800: #080221;
--color-secondary-900: #040111;
/* Neutral Colors (wedgewood) */
/* Neutral Colors - Wedgewood (from old theme.css) */
--color-neutral-50: #F0F4F8;
--color-neutral-100: #D9E3ED;
--color-neutral-200: #B9CCDF;
@@ -48,8 +96,8 @@
--color-neutral-700: #314D68;
--color-neutral-800: #253B50;
--color-neutral-900: #1A2938;
/* Supporting Red Colors (rose-madder) */
/* Supporting Red Colors (from old theme.css) */
--color-supporting-red-50: #FCEDEE;
--color-supporting-red-100: #F9D5D7;
--color-supporting-red-200: #F3ABB0;
@@ -60,8 +108,8 @@
--color-supporting-red-700: #871B22;
--color-supporting-red-800: #5A1217;
--color-supporting-red-900: #2D090B;
/* Supporting Yellow Colors (school-bus-yellow) */
/* Supporting Yellow Colors (from old theme.css) */
--color-supporting-yellow-50: #FFFBEB;
--color-supporting-yellow-100: #FEF3C7;
--color-supporting-yellow-200: #FDE68A;
@@ -72,8 +120,8 @@
--color-supporting-yellow-700: #B45309;
--color-supporting-yellow-800: #92400E;
--color-supporting-yellow-900: #78350F;
/* Supporting Green Colors (green-teal) */
/* Supporting Green Colors (from old theme.css) */
--color-supporting-green-50: #ECFDF5;
--color-supporting-green-100: #D1FAE5;
--color-supporting-green-200: #A7F3D0;
@@ -84,17 +132,4 @@
--color-supporting-green-700: #047857;
--color-supporting-green-800: #065F46;
--color-supporting-green-900: #064E3B;
/* Font Family */
--font-family-sans: 'Roboto', sans-serif;
--font-family-serif: 'Merriweather', serif;
--font-display: 'Montserrat', sans-serif;
/* Box Shadows */
--shadow-base: 0px 1px 3px 0px rgba(0,0,0,0.1), 0px 1px 2px 0px rgba(0,0,0,0.06);
--shadow-md: 0px 4px 6px 0px rgba(0,0,0,0.1), 0px 2px 4px 0px rgba(0,0,0,0.06);
--shadow-lg: 0px 4px 6px 0px rgba(0,0,0,0.05), 0px 10px 15px 0px rgba(0,0,0,0.1);
--shadow-xl: 0px 10px 10px 0px rgba(0,0,0,0.04), 0px 20px 25px 0px rgba(0,0,0,0.1);
--shadow-2xl: 0px 25px 50px 0px rgba(0,0,0,0.25);
--shadow-inner: inset 0px 2px 4px 0px rgba(0,0,0,0.06);
}

View File

@@ -54,11 +54,7 @@
</div>
<div class="flex space-x-3">
<button
type="submit"
phx_disable_with="Loading..."
class="w-full lg:w-auto px-6 text-white py-2 rounded-md tracking-wide font-bold focus:outline-hidden focus:shadow-outline bg-linear-to-tl from-primary-500 to-secondary-500 bg-size-[200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500"
>
<button type="submit" phx_disable_with="Loading..." class="btn btn-primary w-full lg:w-auto">
{case @live_action do
:new -> gettext("Create")
:edit -> gettext("Save")
@@ -73,8 +69,7 @@
data: [
confirm: gettext("This will delete the web content, are you sure?")
],
class:
"w-full lg:w-auto px-6 text-center text-white py-2 rounded-md tracking-wide font-bold focus:outline-hidden focus:shadow-outline bg-linear-to-tl from-supporting-red-600 to-supporting-red-400 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500"
class: "btn btn-error w-full lg:w-auto"
)}
<% end %>
</div>

View File

@@ -26,187 +26,255 @@ defmodule ClaperWeb.EventLive.EventCardComponent do
~H"""
<div
id={"event-#{@event.uuid}"}
class="group bg-white border border-gray-200 rounded-2xl overflow-hidden hover:shadow-lg transition-shadow duration-200"
x-data="{showActions: false}"
class="group relative bg-white border border-gray-200 rounded-2xl overflow-hidden hover:shadow-lg transition-shadow duration-200 h-80"
x-data="{showActions: false, showJoinMenu: false}"
@mouseenter="showActions = true"
@mouseleave="showActions = false"
@mouseleave="showActions = false; showJoinMenu = false"
>
<!-- Thumbnail Area -->
<div class="relative h-52 border-b border-gray-200 rounded-t-xl overflow-hidden">
<!-- Full-height Thumbnail Area -->
<div class="absolute inset-0">
<%= if @thumbnail_url do %>
<img
src={@thumbnail_url}
alt={@event.name}
class="w-full h-full object-cover"
/>
<img src={@thumbnail_url} alt={@event.name} class="w-full h-full object-cover" />
<% else %>
<div class="w-full h-full bg-gray-100 flex items-center justify-center">
<img src="/images/logo.svg" class="h-12 opacity-30" alt="Claper" />
</div>
<% end %>
</div>
<!-- Status Badge -->
<div class="absolute top-4 left-4">
<%= if Event.started?(@event) && !Event.finished?(@event) do %>
<div class="px-3 py-1 text-xs font-medium rounded-tr-lg rounded-br-lg rounded-bl-lg bg-red-600 text-white flex items-center gap-1">
<span class="h-1.5 w-1.5 bg-white rounded-full animate-pulse"></span>
{gettext("Live")}
</div>
<% end %>
<%= if !Event.started?(@event) && !Event.finished?(@event) do %>
<div class="px-3 py-1 text-xs font-medium rounded-tr-lg rounded-br-lg rounded-bl-lg bg-green-100 text-green-800">
{gettext("Incoming")}
</div>
<% end %>
<%= if Event.finished?(@event) do %>
<div class="px-3 py-1 text-xs font-medium rounded-tr-lg rounded-br-lg rounded-bl-lg bg-gray-100 text-gray-800">
{gettext("Finished")}
</div>
<% end %>
</div>
<!-- LTI Badge -->
<div :if={@event.lti_resource} class="absolute top-4 right-4">
<div class="px-2 py-0.5 text-xs font-medium rounded-md bg-gray-500 text-white flex items-center gap-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="h-3 w-3">
<path fill-rule="evenodd" d="M9.664 1.319a.75.75 0 0 1 .672 0 41.059 41.059 0 0 1 8.198 5.424.75.75 0 0 1-.254 1.285 31.372 31.372 0 0 0-7.86 3.83.75.75 0 0 1-.84 0 31.508 31.508 0 0 0-2.08-1.287V9.394c0-.244.116-.463.302-.592a35.504 35.504 0 0 1 3.305-2.033.75.75 0 0 0-.714-1.319 37 37 0 0 0-3.446 2.12A2.216 2.216 0 0 0 6 9.393v.38a31.293 31.293 0 0 0-4.28-1.746.75.75 0 0 1-.254-1.285 41.059 41.059 0 0 1 8.198-5.424ZM6 11.459a29.848 29.848 0 0 0-2.455-1.158 41.029 41.029 0 0 0-.39 3.114.75.75 0 0 0 .419.74c.528.256 1.046.53 1.554.82-.21.324-.455.63-.739.914a.75.75 0 1 0 1.06 1.06c.37-.369.69-.77.96-1.193a26.61 26.61 0 0 1 3.095 2.348.75.75 0 0 0 .992 0 26.547 26.547 0 0 1 5.93-3.95.75.75 0 0 0 .42-.739 41.053 41.053 0 0 0-.39-3.114 29.925 29.925 0 0 0-5.199 2.801 2.25 2.25 0 0 1-2.514 0c-.41-.275-.826-.541-1.25-.797a6.985 6.985 0 0 1-1.084 3.45 26.503 26.503 0 0 0-1.281-.78A5.487 5.487 0 0 0 6 12v-.54Z" clip-rule="evenodd" />
</svg>
<span>LTI</span>
<!-- Status Badge -->
<div class="absolute top-4 left-4 z-10">
<%= if Event.started?(@event) && !Event.finished?(@event) do %>
<div class="px-3 py-1 text-xs font-medium rounded-tr-lg rounded-br-lg rounded-bl-lg bg-red-600 text-white flex items-center gap-1">
<span class="h-1.5 w-1.5 bg-white rounded-full animate-pulse"></span>
{gettext("Live")}
</div>
</div>
<% end %>
<%= if !Event.started?(@event) && !Event.finished?(@event) do %>
<div class="px-3 py-1 text-xs font-medium rounded-tr-lg rounded-br-lg rounded-bl-lg bg-green-100 text-green-800">
{gettext("Incoming")}
</div>
<% end %>
<%= if Event.finished?(@event) do %>
<div class="px-3 py-1 text-xs font-medium rounded-tr-lg rounded-br-lg rounded-bl-lg bg-gray-100 text-gray-800">
{gettext("Finished")}
</div>
<% end %>
</div>
<!-- Hover Actions Overlay -->
<div
x-show="showActions"
x-transition:enter="transition ease-out duration-150"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="transition ease-in duration-100"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
class="absolute inset-0 bg-black/40 flex items-center justify-center gap-2"
:if={@event.presentation_file.status == "done" && !Event.finished?(@event)}
>
<a
href={~p"/e/#{@event.code}/manage"}
class="flex items-center gap-2 px-4 py-2 bg-white text-gray-700 rounded-full font-bold text-sm hover:bg-gray-100 transition"
<!-- LTI Badge -->
<div :if={@event.lti_resource} class="absolute top-4 right-4 z-10">
<div class="px-2 py-0.5 text-xs font-medium rounded-md bg-gray-500 text-white flex items-center gap-1">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="h-3 w-3"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-5 h-5">
<path fill-rule="evenodd" d="M2.25 2.25a.75.75 0 0 0 0 1.5H3v10.5a3 3 0 0 0 3 3h1.21l-1.172 3.513a.75.75 0 0 0 1.424.474l.329-.987h8.418l.33.987a.75.75 0 0 0 1.422-.474l-1.17-3.513H18a3 3 0 0 0 3-3V3.75h.75a.75.75 0 0 0 0-1.5H2.25Zm6.04 16.5.5-1.5h6.42l.5 1.5H8.29Zm7.46-12a.75.75 0 0 0-1.5 0v6a.75.75 0 0 0 1.5 0v-6Zm-3 2.25a.75.75 0 0 0-1.5 0v3.75a.75.75 0 0 0 1.5 0V9Zm-3 2.25a.75.75 0 0 0-1.5 0v1.5a.75.75 0 0 0 1.5 0v-1.5Z" clip-rule="evenodd" />
</svg>
{gettext("Manager")}
</a>
<a
href={~p"/e/#{@event.code}"}
class="flex items-center gap-2 px-4 py-2 bg-white text-gray-700 rounded-full font-bold text-sm hover:bg-gray-100 transition"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-5 h-5">
<path fill-rule="evenodd" d="M8.25 6.75a3.75 3.75 0 1 1 7.5 0 3.75 3.75 0 0 1-7.5 0ZM15.75 9.75a3 3 0 1 1 6 0 3 3 0 0 1-6 0ZM2.25 9.75a3 3 0 1 1 6 0 3 3 0 0 1-6 0ZM6.31 15.117A6.745 6.745 0 0 1 12 12a6.745 6.745 0 0 1 6.709 7.498.75.75 0 0 1-.372.568A12.696 12.696 0 0 1 12 21.75c-2.305 0-4.47-.612-6.337-1.684a.75.75 0 0 1-.372-.568 6.787 6.787 0 0 1 1.019-4.38Z" clip-rule="evenodd" />
<path d="M5.082 14.254a8.287 8.287 0 0 0-1.308 5.135 9.687 9.687 0 0 1-1.764-.44l-.115-.04a.563.563 0 0 1-.373-.487l-.01-.121a3.75 3.75 0 0 1 3.57-4.047ZM20.226 19.389a8.287 8.287 0 0 0-1.308-5.135 3.75 3.75 0 0 1 3.57 4.047l-.01.121a.563.563 0 0 1-.373.486l-.115.04c-.567.2-1.156.349-1.764.441Z" />
</svg>
{gettext("Attendees")}
</a>
<path
fill-rule="evenodd"
d="M9.664 1.319a.75.75 0 0 1 .672 0 41.059 41.059 0 0 1 8.198 5.424.75.75 0 0 1-.254 1.285 31.372 31.372 0 0 0-7.86 3.83.75.75 0 0 1-.84 0 31.508 31.508 0 0 0-2.08-1.287V9.394c0-.244.116-.463.302-.592a35.504 35.504 0 0 1 3.305-2.033.75.75 0 0 0-.714-1.319 37 37 0 0 0-3.446 2.12A2.216 2.216 0 0 0 6 9.393v.38a31.293 31.293 0 0 0-4.28-1.746.75.75 0 0 1-.254-1.285 41.059 41.059 0 0 1 8.198-5.424ZM6 11.459a29.848 29.848 0 0 0-2.455-1.158 41.029 41.029 0 0 0-.39 3.114.75.75 0 0 0 .419.74c.528.256 1.046.53 1.554.82-.21.324-.455.63-.739.914a.75.75 0 1 0 1.06 1.06c.37-.369.69-.77.96-1.193a26.61 26.61 0 0 1 3.095 2.348.75.75 0 0 0 .992 0 26.547 26.547 0 0 1 5.93-3.95.75.75 0 0 0 .42-.739 41.053 41.053 0 0 0-.39-3.114 29.925 29.925 0 0 0-5.199 2.801 2.25 2.25 0 0 1-2.514 0c-.41-.275-.826-.541-1.25-.797a6.985 6.985 0 0 1-1.084 3.45 26.503 26.503 0 0 0-1.281-.78A5.487 5.487 0 0 0 6 12v-.54Z"
clip-rule="evenodd"
/>
</svg>
<span>LTI</span>
</div>
</div>
<!-- Card Body -->
<div class="p-2">
<div class="flex items-start justify-between gap-4">
<div class="flex-1 min-w-0">
<h3 class="font-bold text-gray-800 truncate">
{@event.name}
</h3>
<p class="text-gray-500 text-base">
# {@event.code}
</p>
</div>
<!-- Sliding Bottom Panel -->
<div
class="absolute bottom-0 left-0 right-0 bg-white transition-transform duration-300 ease-out z-20"
x-bind:class="showActions ? 'translate-y-0' : 'translate-y-16'"
>
<!-- Card Body (Title, Code, Menu) -->
<div class="p-2 border-t border-gray-200">
<div class="flex items-start justify-between gap-4">
<div class="flex-1 min-w-0">
<h3 class="font-bold text-gray-800 truncate">
{@event.name}
</h3>
<p class="text-gray-500 text-base">
# {@event.code}
</p>
</div>
<!-- 3-dot Menu -->
<div class="relative shrink-0">
<!-- 3-dot Menu -->
<div class="relative shrink-0">
<button
phx-click-away={JS.hide(to: "#dropdown-menu-#{@event.uuid}")}
phx-click={JS.toggle(to: "#dropdown-menu-#{@event.uuid}")}
phx-target={@myself}
class="p-1 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6"
fill="currentColor"
viewBox="0 0 24 24"
>
<circle cx="12" cy="5" r="2" />
<circle cx="12" cy="12" r="2" />
<circle cx="12" cy="19" r="2" />
</svg>
</button>
<div
id={"dropdown-menu-#{@event.uuid}"}
phx-hook="Dropdown"
class="hidden absolute right-0 bottom-full mb-2 w-44 rounded-lg shadow-lg bg-white border z-30"
>
{render_dropdown_menu(assigns)}
</div>
</div>
</div>
</div>
<!-- Action Buttons (revealed on hover) -->
<div
:if={@event.presentation_file.status == "done" && !Event.finished?(@event)}
class="px-2 pb-2 flex gap-2"
>
<!-- Join Button with Dropdown -->
<div class="relative flex-1">
<button
phx-click-away={JS.hide(to: "#dropdown-menu-#{@event.uuid}")}
phx-click={JS.toggle(to: "#dropdown-menu-#{@event.uuid}")}
phx-target={@myself}
class="p-1 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded"
@click="showJoinMenu = !showJoinMenu"
@click.away="showJoinMenu = false"
class="w-full flex items-center justify-center gap-2 px-4 py-3 bg-primary-500 text-white rounded-full font-bold hover:bg-primary-600 transition"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="currentColor" viewBox="0 0 24 24">
<circle cx="12" cy="5" r="2" />
<circle cx="12" cy="12" r="2" />
<circle cx="12" cy="19" r="2" />
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M5.22 14.78a.75.75 0 001.06 0l7.22-7.22v5.69a.75.75 0 001.5 0v-7.5a.75.75 0 00-.75-.75h-7.5a.75.75 0 000 1.5h5.69l-7.22 7.22a.75.75 0 000 1.06z"
clip-rule="evenodd"
/>
</svg>
{gettext("Join")}
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4 transition-transform"
x-bind:class="showJoinMenu ? 'rotate-180' : ''"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z"
clip-rule="evenodd"
/>
</svg>
</button>
<!-- Dropdown Menu -->
<div
id={"dropdown-menu-#{@event.uuid}"}
phx-hook="Dropdown"
class="hidden absolute right-0 top-8 w-44 rounded-lg shadow-lg bg-white border z-30"
x-show="showJoinMenu"
x-transition:enter="transition ease-out duration-100"
x-transition:enter-start="opacity-0 scale-95"
x-transition:enter-end="opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
class="absolute bottom-full left-0 right-0 mb-2 bg-white rounded-xl shadow-lg border border-gray-200 overflow-hidden"
>
{render_dropdown_menu(assigns)}
<a
href={~p"/e/#{@event.code}/manage"}
class="flex items-center gap-3 px-4 py-3 text-gray-700 hover:bg-gray-50 transition"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="w-5 h-5"
>
<path
fill-rule="evenodd"
d="M2.25 2.25a.75.75 0 0 0 0 1.5H3v10.5a3 3 0 0 0 3 3h1.21l-1.172 3.513a.75.75 0 0 0 1.424.474l.329-.987h8.418l.33.987a.75.75 0 0 0 1.422-.474l-1.17-3.513H18a3 3 0 0 0 3-3V3.75h.75a.75.75 0 0 0 0-1.5H2.25Zm6.04 16.5.5-1.5h6.42l.5 1.5H8.29Zm7.46-12a.75.75 0 0 0-1.5 0v6a.75.75 0 0 0 1.5 0v-6Zm-3 2.25a.75.75 0 0 0-1.5 0v3.75a.75.75 0 0 0 1.5 0V9Zm-3 2.25a.75.75 0 0 0-1.5 0v1.5a.75.75 0 0 0 1.5 0v-1.5Z"
clip-rule="evenodd"
/>
</svg>
<span class="font-medium">{gettext("Event Manager")}</span>
</a>
<a
href={~p"/e/#{@event.code}"}
class="flex items-center gap-3 px-4 py-3 text-gray-700 hover:bg-gray-50 transition border-t border-gray-100"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="w-5 h-5"
>
<path
fill-rule="evenodd"
d="M8.25 6.75a3.75 3.75 0 1 1 7.5 0 3.75 3.75 0 0 1-7.5 0ZM15.75 9.75a3 3 0 1 1 6 0 3 3 0 0 1-6 0ZM2.25 9.75a3 3 0 1 1 6 0 3 3 0 0 1-6 0ZM6.31 15.117A6.745 6.745 0 0 1 12 12a6.745 6.745 0 0 1 6.709 7.498.75.75 0 0 1-.372.568A12.696 12.696 0 0 1 12 21.75c-2.305 0-4.47-.612-6.337-1.684a.75.75 0 0 1-.372-.568 6.787 6.787 0 0 1 1.019-4.38Z"
clip-rule="evenodd"
/>
<path d="M5.082 14.254a8.287 8.287 0 0 0-1.308 5.135 9.687 9.687 0 0 1-1.764-.44l-.115-.04a.563.563 0 0 1-.373-.487l-.01-.121a3.75 3.75 0 0 1 3.57-4.047ZM20.226 19.389a8.287 8.287 0 0 0-1.308-5.135 3.75 3.75 0 0 1 3.57 4.047l-.01.121a.563.563 0 0 1-.373.486l-.115.04c-.567.2-1.156.349-1.764.441Z" />
</svg>
<span class="font-medium">{gettext("Attendant Room")}</span>
</a>
</div>
</div>
<!-- End Event Button -->
<.link
:if={Event.started?(@event) && not @is_leader}
data-confirm={
gettext("Are you sure you want to terminate this event? This action cannot be undone.")
}
phx-value-id={@event.uuid}
phx-click="terminate"
class="flex-1 flex items-center justify-center gap-2 px-4 py-3 bg-gray-100 text-gray-700 rounded-full font-bold hover:bg-gray-200 transition"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
d="M6.28 5.22a.75.75 0 0 0-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 1 0 1.06 1.06L10 11.06l3.72 3.72a.75.75 0 1 0 1.06-1.06L11.06 10l3.72-3.72a.75.75 0 0 0-1.06-1.06L10 8.94 6.28 5.22Z"
/>
</svg>
{gettext("End Event")}
</.link>
</div>
</div>
<!-- Action Buttons (shown on hover for active events) -->
<div
:if={@event.presentation_file.status == "done" && !Event.finished?(@event)}
x-show="showActions"
x-transition:enter="transition ease-out duration-150"
x-transition:enter-start="opacity-0 translate-y-2"
x-transition:enter-end="opacity-100 translate-y-0"
class="px-2 pb-2 flex gap-2"
>
<a
href={~p"/e/#{@event.code}/manage"}
class="flex-1 flex items-center justify-center gap-2 px-4 py-3 bg-primary-500 text-white rounded-full font-bold hover:bg-primary-600 transition"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L12.586 11H5a1 1 0 110-2h7.586l-2.293-2.293a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>
{gettext("Join")}
</a>
<.link
:if={Event.started?(@event) && not @is_leader}
data-confirm={gettext("Are you sure you want to terminate this event? This action cannot be undone.")}
phx-value-id={@event.uuid}
phx-click="terminate"
class="flex-1 flex items-center justify-center gap-2 px-4 py-3 bg-gray-100 text-gray-700 rounded-full font-bold hover:bg-gray-200 transition"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8 7a1 1 0 00-1 1v4a1 1 0 001 1h4a1 1 0 001-1V8a1 1 0 00-1-1H8z" clip-rule="evenodd" />
</svg>
{gettext("End Event")}
</.link>
</div>
<!-- Processing Status -->
<div
:if={@event.presentation_file.status == "progress"}
class="px-2 pb-2 flex items-center gap-2"
>
<img src="/images/loading.gif" class="h-6" />
<span class="text-sm text-gray-500">{gettext("Processing your file...")}</span>
</div>
<div
:if={@event.presentation_file.status == "progress"}
class="px-2 pb-2 flex items-center gap-2"
>
<img src="/images/loading.gif" class="h-6" />
<span class="text-sm text-gray-500">{gettext("Processing your file...")}</span>
</div>
<!-- Error Status -->
<div
:if={@event.presentation_file.status == "fail"}
class="px-2 pb-2"
>
<span class="text-sm text-supporting-red-500">{gettext("Error when processing the file")}</span>
</div>
<div :if={@event.presentation_file.status == "fail"} class="px-2 pb-2">
<span class="text-sm text-supporting-red-500">
{gettext("Error when processing the file")}
</span>
</div>
<!-- Finished Event Actions -->
<div :if={Event.finished?(@event)} class="px-2 pb-2">
<a
href={~p"/events/#{@event.uuid}/stats"}
class="w-full flex items-center justify-center gap-2 px-4 py-3 bg-primary-500 text-white rounded-full font-bold hover:bg-primary-600 transition"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path d="M2 10a8 8 0 018-8v8h8a8 8 0 11-16 0z" />
<path d="M12 2.252A8.014 8.014 0 0117.748 8H12V2.252z" />
</svg>
{gettext("View report")}
</a>
<div :if={Event.finished?(@event)} class="px-2 pb-2">
<a
href={~p"/events/#{@event.uuid}/stats"}
class="w-full flex items-center justify-center gap-2 px-4 py-3 bg-primary-500 text-white rounded-full font-bold hover:bg-primary-600 transition"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path d="M2 10a8 8 0 018-8v8h8a8 8 0 11-16 0z" />
<path d="M12 2.252A8.014 8.014 0 0117.748 8H12V2.252z" />
</svg>
{gettext("View report")}
</a>
</div>
</div>
</div>
"""
@@ -228,7 +296,7 @@ defmodule ClaperWeb.EventLive.EventCardComponent do
<% end %>
</div>
<!-- Event Info -->
<!-- Event Info -->
<div class="flex-1 min-w-0">
<div class="flex items-center gap-2">
<a
@@ -241,8 +309,17 @@ defmodule ClaperWeb.EventLive.EventCardComponent do
:if={@event.lti_resource}
class="text-xs text-white rounded-md px-2 py-0.5 bg-gray-500 flex items-center gap-1"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="h-3 w-3">
<path fill-rule="evenodd" d="M9.664 1.319a.75.75 0 0 1 .672 0 41.059 41.059 0 0 1 8.198 5.424.75.75 0 0 1-.254 1.285 31.372 31.372 0 0 0-7.86 3.83.75.75 0 0 1-.84 0 31.508 31.508 0 0 0-2.08-1.287V9.394c0-.244.116-.463.302-.592a35.504 35.504 0 0 1 3.305-2.033.75.75 0 0 0-.714-1.319 37 37 0 0 0-3.446 2.12A2.216 2.216 0 0 0 6 9.393v.38a31.293 31.293 0 0 0-4.28-1.746.75.75 0 0 1-.254-1.285 41.059 41.059 0 0 1 8.198-5.424ZM6 11.459a29.848 29.848 0 0 0-2.455-1.158 41.029 41.029 0 0 0-.39 3.114.75.75 0 0 0 .419.74c.528.256 1.046.53 1.554.82-.21.324-.455.63-.739.914a.75.75 0 1 0 1.06 1.06c.37-.369.69-.77.96-1.193a26.61 26.61 0 0 1 3.095 2.348.75.75 0 0 0 .992 0 26.547 26.547 0 0 1 5.93-3.95.75.75 0 0 0 .42-.739 41.053 41.053 0 0 0-.39-3.114 29.925 29.925 0 0 0-5.199 2.801 2.25 2.25 0 0 1-2.514 0c-.41-.275-.826-.541-1.25-.797a6.985 6.985 0 0 1-1.084 3.45 26.503 26.503 0 0 0-1.281-.78A5.487 5.487 0 0 0 6 12v-.54Z" clip-rule="evenodd" />
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="h-3 w-3"
>
<path
fill-rule="evenodd"
d="M9.664 1.319a.75.75 0 0 1 .672 0 41.059 41.059 0 0 1 8.198 5.424.75.75 0 0 1-.254 1.285 31.372 31.372 0 0 0-7.86 3.83.75.75 0 0 1-.84 0 31.508 31.508 0 0 0-2.08-1.287V9.394c0-.244.116-.463.302-.592a35.504 35.504 0 0 1 3.305-2.033.75.75 0 0 0-.714-1.319 37 37 0 0 0-3.446 2.12A2.216 2.216 0 0 0 6 9.393v.38a31.293 31.293 0 0 0-4.28-1.746.75.75 0 0 1-.254-1.285 41.059 41.059 0 0 1 8.198-5.424ZM6 11.459a29.848 29.848 0 0 0-2.455-1.158 41.029 41.029 0 0 0-.39 3.114.75.75 0 0 0 .419.74c.528.256 1.046.53 1.554.82-.21.324-.455.63-.739.914a.75.75 0 1 0 1.06 1.06c.37-.369.69-.77.96-1.193a26.61 26.61 0 0 1 3.095 2.348.75.75 0 0 0 .992 0 26.547 26.547 0 0 1 5.93-3.95.75.75 0 0 0 .42-.739 41.053 41.053 0 0 0-.39-3.114 29.925 29.925 0 0 0-5.199 2.801 2.25 2.25 0 0 1-2.514 0c-.41-.275-.826-.541-1.25-.797a6.985 6.985 0 0 1-1.084 3.45 26.503 26.503 0 0 0-1.281-.78A5.487 5.487 0 0 0 6 12v-.54Z"
clip-rule="evenodd"
/>
</svg>
<span>LTI</span>
</p>
@@ -254,19 +331,17 @@ defmodule ClaperWeb.EventLive.EventCardComponent do
id={"event-date-#{@event.uuid}"}
phx-update="ignore"
>
{gettext("Starting on")} <span x-text={"moment.utc('#{@event.started_at}').local().format('lll')"}></span>
{gettext("Starting on")}
<span x-text={"moment.utc('#{@event.started_at}').local().format('lll')"}></span>
</span>
<span
:if={Event.finished?(@event)}
id={"event-date-#{@event.uuid}"}
phx-update="ignore"
>
{gettext("Finished on")} <span x-text={"moment.utc('#{@event.expired_at}').local().format('lll')"}></span>
<span :if={Event.finished?(@event)} id={"event-date-#{@event.uuid}"} phx-update="ignore">
{gettext("Finished on")}
<span x-text={"moment.utc('#{@event.expired_at}').local().format('lll')"}></span>
</span>
</div>
</div>
<!-- Status Badge -->
<!-- Status Badge -->
<div class="shrink-0">
<%= if Event.started?(@event) && !Event.finished?(@event) do %>
<div class="px-3 py-1 text-xs font-semibold rounded-full bg-red-500 text-white flex items-center gap-1">
@@ -286,7 +361,7 @@ defmodule ClaperWeb.EventLive.EventCardComponent do
<% end %>
</div>
<!-- Actions -->
<!-- Actions -->
<div class="shrink-0 flex items-center gap-2">
<%= if @event.presentation_file.status == "done" && !Event.finished?(@event) do %>
<a
@@ -297,7 +372,11 @@ defmodule ClaperWeb.EventLive.EventCardComponent do
</a>
<.link
:if={Event.started?(@event) && not @is_leader}
data-confirm={gettext("Are you sure you want to terminate this event? This action cannot be undone.")}
data-confirm={
gettext(
"Are you sure you want to terminate this event? This action cannot be undone."
)
}
phx-value-id={@event.uuid}
phx-click="terminate"
class="flex items-center gap-2 px-4 py-2 bg-gray-100 text-gray-700 rounded-full font-bold text-sm hover:bg-gray-200 transition"
@@ -326,7 +405,7 @@ defmodule ClaperWeb.EventLive.EventCardComponent do
</a>
<% end %>
<!-- 3-dot Menu -->
<!-- 3-dot Menu -->
<div class="relative">
<button
phx-click-away={JS.hide(to: "#dropdown-menu-#{@event.uuid}")}
@@ -334,7 +413,12 @@ defmodule ClaperWeb.EventLive.EventCardComponent do
phx-target={@myself}
class="p-2 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
fill="currentColor"
viewBox="0 0 24 24"
>
<circle cx="12" cy="5" r="2" />
<circle cx="12" cy="12" r="2" />
<circle cx="12" cy="19" r="2" />
@@ -360,34 +444,16 @@ defmodule ClaperWeb.EventLive.EventCardComponent do
<ul class="py-1">
<%= if !Event.finished?(@event) && not @is_leader do %>
<li>
<a
href={~p"/e/#{@event.code}/manage"}
class="flex items-center gap-2 px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-5 h-5">
<path fill-rule="evenodd" d="M2.25 2.25a.75.75 0 0 0 0 1.5H3v10.5a3 3 0 0 0 3 3h1.21l-1.172 3.513a.75.75 0 0 0 1.424.474l.329-.987h8.418l.33.987a.75.75 0 0 0 1.422-.474l-1.17-3.513H18a3 3 0 0 0 3-3V3.75h.75a.75.75 0 0 0 0-1.5H2.25Zm6.04 16.5.5-1.5h6.42l.5 1.5H8.29Zm7.46-12a.75.75 0 0 0-1.5 0v6a.75.75 0 0 0 1.5 0v-6Zm-3 2.25a.75.75 0 0 0-1.5 0v3.75a.75.75 0 0 0 1.5 0V9Zm-3 2.25a.75.75 0 0 0-1.5 0v1.5a.75.75 0 0 0 1.5 0v-1.5Z" clip-rule="evenodd" />
</svg>
{gettext("Event manager")}
</a>
</li>
<li>
<a
href={~p"/e/#{@event.code}"}
class="flex items-center gap-2 px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-5 h-5">
<path fill-rule="evenodd" d="M8.25 6.75a3.75 3.75 0 1 1 7.5 0 3.75 3.75 0 0 1-7.5 0ZM15.75 9.75a3 3 0 1 1 6 0 3 3 0 0 1-6 0ZM2.25 9.75a3 3 0 1 1 6 0 3 3 0 0 1-6 0ZM6.31 15.117A6.745 6.745 0 0 1 12 12a6.745 6.745 0 0 1 6.709 7.498.75.75 0 0 1-.372.568A12.696 12.696 0 0 1 12 21.75c-2.305 0-4.47-.612-6.337-1.684a.75.75 0 0 1-.372-.568 6.787 6.787 0 0 1 1.019-4.38Z" clip-rule="evenodd" />
<path d="M5.082 14.254a8.287 8.287 0 0 0-1.308 5.135 9.687 9.687 0 0 1-1.764-.44l-.115-.04a.563.563 0 0 1-.373-.487l-.01-.121a3.75 3.75 0 0 1 3.57-4.047ZM20.226 19.389a8.287 8.287 0 0 0-1.308-5.135 3.75 3.75 0 0 1 3.57 4.047l-.01.121a.563.563 0 0 1-.373.486l-.115.04c-.567.2-1.156.349-1.764.441Z" />
</svg>
{gettext("Attendees room")}
</a>
</li>
<li class="border-t border-gray-100">
<a
href={~p"/events/#{@event.uuid}/edit"}
class="flex items-center gap-2 px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="h-5 w-5">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="h-5 w-5"
>
<path d="m5.433 13.917 1.262-3.155A4 4 0 0 1 7.58 9.42l6.92-6.918a2.121 2.121 0 0 1 3 3l-6.92 6.918c-.383.383-.84.685-1.343.886l-3.154 1.262a.5.5 0 0 1-.65-.65Z" />
<path d="M3.5 5.75c0-.69.56-1.25 1.25-1.25H10A.75.75 0 0 0 10 3H4.75A2.75 2.75 0 0 0 2 5.75v9.5A2.75 2.75 0 0 0 4.75 18h9.5A2.75 2.75 0 0 0 17 15.25V10a.75.75 0 0 0-1.5 0v5.25c0 .69-.56 1.25-1.25 1.25h-9.5c-.69 0-1.25-.56-1.25-1.25v-9.5Z" />
</svg>
@@ -400,7 +466,12 @@ defmodule ClaperWeb.EventLive.EventCardComponent do
phx-click="duplicate"
class="w-full flex items-center gap-2 px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-5 h-5"
>
<path d="M7 3.5A1.5 1.5 0 0 1 8.5 2h3.879a1.5 1.5 0 0 1 1.06.44l3.122 3.12A1.5 1.5 0 0 1 17 6.622V12.5a1.5 1.5 0 0 1-1.5 1.5h-1v-3.379a3 3 0 0 0-.879-2.121L10.5 5.379A3 3 0 0 0 8.379 4.5H7v-1Z" />
<path d="M4.5 6A1.5 1.5 0 0 0 3 7.5v9A1.5 1.5 0 0 0 4.5 18h7a1.5 1.5 0 0 0 1.5-1.5v-5.879a1.5 1.5 0 0 0-.44-1.06L9.44 6.439A1.5 1.5 0 0 0 8.378 6H4.5Z" />
</svg>
@@ -416,7 +487,12 @@ defmodule ClaperWeb.EventLive.EventCardComponent do
phx-click="duplicate"
class="w-full flex items-center gap-2 px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-5 h-5"
>
<path d="M7 3.5A1.5 1.5 0 0 1 8.5 2h3.879a1.5 1.5 0 0 1 1.06.44l3.122 3.12A1.5 1.5 0 0 1 17 6.622V12.5a1.5 1.5 0 0 1-1.5 1.5h-1v-3.379a3 3 0 0 0-.879-2.121L10.5 5.379A3 3 0 0 0 8.379 4.5H7v-1Z" />
<path d="M4.5 6A1.5 1.5 0 0 0 3 7.5v9A1.5 1.5 0 0 0 4.5 18h7a1.5 1.5 0 0 0 1.5-1.5v-5.879a1.5 1.5 0 0 0-.44-1.06L9.44 6.439A1.5 1.5 0 0 0 8.378 6H4.5Z" />
</svg>
@@ -427,11 +503,24 @@ defmodule ClaperWeb.EventLive.EventCardComponent do
<.link
phx-click="delete"
phx-value-id={@event.uuid}
data-confirm={gettext("This will delete all data related to your event, this cannot be undone. Confirm ?")}
data-confirm={
gettext(
"This will delete all data related to your event, this cannot be undone. Confirm ?"
)
}
class="w-full flex items-center gap-2 px-4 py-2 text-sm text-red-500 hover:bg-gray-100 cursor-pointer"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="h-5 w-5">
<path fill-rule="evenodd" d="M5 3.25V4H2.75a.75.75 0 0 0 0 1.5h.3l.815 8.15A1.5 1.5 0 0 0 5.357 15h5.285a1.5 1.5 0 0 0 1.493-1.35l.815-8.15h.3a.75.75 0 0 0 0-1.5H11v-.75A2.25 2.25 0 0 0 8.75 1h-1.5A2.25 2.25 0 0 0 5 3.25Zm2.25-.75a.75.75 0 0 0-.75.75V4h3v-.75a.75.75 0 0 0-.75-.75h-1.5ZM6.05 6a.75.75 0 0 1 .787.713l.275 5.5a.75.75 0 0 1-1.498.075l-.275-5.5A.75.75 0 0 1 6.05 6Zm3.9 0a.75.75 0 0 1 .712.787l-.275 5.5a.75.75 0 0 1-1.498-.075l.275-5.5a.75.75 0 0 1 .786-.711Z" clip-rule="evenodd" />
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="h-5 w-5"
>
<path
fill-rule="evenodd"
d="M5 3.25V4H2.75a.75.75 0 0 0 0 1.5h.3l.815 8.15A1.5 1.5 0 0 0 5.357 15h5.285a1.5 1.5 0 0 0 1.493-1.35l.815-8.15h.3a.75.75 0 0 0 0-1.5H11v-.75A2.25 2.25 0 0 0 8.75 1h-1.5A2.25 2.25 0 0 0 5 3.25Zm2.25-.75a.75.75 0 0 0-.75.75V4h3v-.75a.75.75 0 0 0-.75-.75h-1.5ZM6.05 6a.75.75 0 0 1 .787.713l.275 5.5a.75.75 0 0 1-1.498.075l-.275-5.5A.75.75 0 0 1 6.05 6Zm3.9 0a.75.75 0 0 1 .712.787l-.275 5.5a.75.75 0 0 1-1.498-.075l.275-5.5a.75.75 0 0 1 .786-.711Z"
clip-rule="evenodd"
/>
</svg>
{gettext("Delete")}
</.link>

View File

@@ -48,7 +48,7 @@
type="submit"
form="event-form"
phx_disable_with="Loading..."
class="w-full lg:w-auto px-6 text-white py-2 rounded-md tracking-wide font-bold focus:outline-hidden focus:shadow-outline bg-linear-to-tl from-primary-500 to-secondary-500 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500"
class="btn btn-primary w-full lg:w-auto"
>
{case @action do
:edit -> gettext("Save")
@@ -56,7 +56,7 @@
end}
</button>
<% else %>
<div class="opacity-25 cursor-default w-full lg:w-auto px-6 text-white py-2 rounded-md tracking-wide font-bold focus:outline-hidden focus:shadow-outline bg-linear-to-tl from-primary-500 to-secondary-500 bg-size-[200%_200%] bg-position-[0%_0%]">
<div class="btn btn-primary btn-disabled opacity-25 cursor-default w-full lg:w-auto">
{case @action do
:edit -> gettext("Save")
:new -> gettext("Create")
@@ -69,8 +69,7 @@
phx_click: "delete",
phx_value_id: @event.uuid,
data: [confirm: gettext("Are you sure?")],
class:
"w-full lg:w-auto px-6 text-center text-white py-2 rounded-md tracking-wide font-bold focus:outline-hidden focus:shadow-outline bg-linear-to-tl from-supporting-red-600 to-supporting-red-400 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500"
class: "btn btn-error w-full lg:w-auto"
)}
<% end %>
</div>

View File

@@ -26,8 +26,18 @@
>
</div>
<div class="mx-auto max-w-xl transform divide-y divide-gray-100 overflow-hidden rounded-xl bg-white shadow-2xl ring-1 ring-black/5 transition-all relative">
<button phx-click="toggle-quick-create" class="absolute right-3 top-3 text-gray-400 hover:text-gray-600">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<button
phx-click="toggle-quick-create"
class="absolute right-3 top-3 text-gray-400 hover:text-gray-600"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2"
>
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
@@ -60,24 +70,38 @@
</div>
</div>
</div>
<!-- Filter Bar and Actions -->
<!-- Filter Bar and Actions -->
<div class="pt-6 pb-6">
<div class="flex flex-col lg:flex-row items-start lg:items-center justify-between gap-4">
<!-- Left: Filter Tabs -->
<.tabs style={:boxed}>
<:tab active={@active_tab == "not_expired"} phx-click="change-tab" phx-value-tab="not_expired">
<:tab
active={@active_tab == "not_expired"}
phx-click="change-tab"
phx-value-tab="not_expired"
>
{gettext("Active")}
</:tab>
<:tab active={@active_tab == "expired"} disabled={not @has_expired_events} phx-click="change-tab" phx-value-tab="expired">
<:tab
active={@active_tab == "expired"}
disabled={not @has_expired_events}
phx-click="change-tab"
phx-value-tab="expired"
>
{gettext("Done")}
</:tab>
<:tab active={@active_tab == "invited"} disabled={not @has_invited_events} phx-click="change-tab" phx-value-tab="invited">
<:tab
active={@active_tab == "invited"}
disabled={not @has_invited_events}
phx-click="change-tab"
phx-value-tab="invited"
>
{gettext("Shared with you")}
</:tab>
</.tabs>
<!-- Right: View Toggle & Action Buttons -->
<!-- Right: View Toggle & Action Buttons -->
<div class="flex items-center gap-2 flex-wrap">
<!-- View Toggle -->
<div class="flex items-center gap-1 bg-white border border-gray-200 rounded-full p-1">
@@ -86,8 +110,17 @@
phx-value-view="grid"
class={"p-2 rounded-full transition #{if @view_mode == "grid", do: "bg-primary-50 border-b-2 border-primary-500", else: "hover:bg-gray-100"}"}
>
<svg xmlns="http://www.w3.org/2000/svg" class={"w-5 h-5 #{if @view_mode == "grid", do: "text-primary-500", else: "text-secondary-500"}"} viewBox="0 0 24 24" fill="currentColor">
<path fill-rule="evenodd" d="M3 6a3 3 0 0 1 3-3h2.25a3 3 0 0 1 3 3v2.25a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3V6Zm9.75 0a3 3 0 0 1 3-3H18a3 3 0 0 1 3 3v2.25a3 3 0 0 1-3 3h-2.25a3 3 0 0 1-3-3V6ZM3 15.75a3 3 0 0 1 3-3h2.25a3 3 0 0 1 3 3V18a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3v-2.25Zm9.75 0a3 3 0 0 1 3-3H18a3 3 0 0 1 3 3V18a3 3 0 0 1-3 3h-2.25a3 3 0 0 1-3-3v-2.25Z" clip-rule="evenodd" />
<svg
xmlns="http://www.w3.org/2000/svg"
class={"w-5 h-5 #{if @view_mode == "grid", do: "text-primary-500", else: "text-secondary-500"}"}
viewBox="0 0 24 24"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M3 6a3 3 0 0 1 3-3h2.25a3 3 0 0 1 3 3v2.25a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3V6Zm9.75 0a3 3 0 0 1 3-3H18a3 3 0 0 1 3 3v2.25a3 3 0 0 1-3 3h-2.25a3 3 0 0 1-3-3V6ZM3 15.75a3 3 0 0 1 3-3h2.25a3 3 0 0 1 3 3V18a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3v-2.25Zm9.75 0a3 3 0 0 1 3-3H18a3 3 0 0 1 3 3V18a3 3 0 0 1-3 3h-2.25a3 3 0 0 1-3-3v-2.25Z"
clip-rule="evenodd"
/>
</svg>
</button>
<button
@@ -95,38 +128,65 @@
phx-value-view="list"
class={"p-2 rounded-full transition #{if @view_mode == "list", do: "bg-primary-50 border-b-2 border-primary-500", else: "hover:bg-gray-100"}"}
>
<svg xmlns="http://www.w3.org/2000/svg" class={"w-5 h-5 #{if @view_mode == "list", do: "text-primary-500", else: "text-secondary-500"}"} viewBox="0 0 24 24" fill="currentColor">
<path fill-rule="evenodd" d="M2.625 6.75a1.125 1.125 0 1 1 2.25 0 1.125 1.125 0 0 1-2.25 0Zm4.875 0A.75.75 0 0 1 8.25 6h12a.75.75 0 0 1 0 1.5h-12a.75.75 0 0 1-.75-.75ZM2.625 12a1.125 1.125 0 1 1 2.25 0 1.125 1.125 0 0 1-2.25 0ZM7.5 12a.75.75 0 0 1 .75-.75h12a.75.75 0 0 1 0 1.5h-12A.75.75 0 0 1 7.5 12Zm-4.875 5.25a1.125 1.125 0 1 1 2.25 0 1.125 1.125 0 0 1-2.25 0Zm4.875 0a.75.75 0 0 1 .75-.75h12a.75.75 0 0 1 0 1.5h-12a.75.75 0 0 1-.75-.75Z" clip-rule="evenodd" />
<svg
xmlns="http://www.w3.org/2000/svg"
class={"w-5 h-5 #{if @view_mode == "list", do: "text-primary-500", else: "text-secondary-500"}"}
viewBox="0 0 24 24"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M2.625 6.75a1.125 1.125 0 1 1 2.25 0 1.125 1.125 0 0 1-2.25 0Zm4.875 0A.75.75 0 0 1 8.25 6h12a.75.75 0 0 1 0 1.5h-12a.75.75 0 0 1-.75-.75ZM2.625 12a1.125 1.125 0 1 1 2.25 0 1.125 1.125 0 0 1-2.25 0ZM7.5 12a.75.75 0 0 1 .75-.75h12a.75.75 0 0 1 0 1.5h-12A.75.75 0 0 1 7.5 12Zm-4.875 5.25a1.125 1.125 0 1 1 2.25 0 1.125 1.125 0 0 1-2.25 0Zm4.875 0a.75.75 0 0 1 .75-.75h12a.75.75 0 0 1 0 1.5h-12a.75.75 0 0 1-.75-.75Z"
clip-rule="evenodd"
/>
</svg>
</button>
</div>
<!-- Quick Event Button -->
<!-- Quick Event Button -->
<button
phx-click="toggle-quick-create"
class="flex items-center gap-2 px-4 py-3 border border-secondary-500 text-secondary-500 rounded-full font-bold hover:bg-secondary-50 transition"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z" clip-rule="evenodd" />
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z"
clip-rule="evenodd"
/>
</svg>
<span class="hidden sm:inline">{gettext("Create a quick event")}</span>
</button>
<!-- Create Event Button -->
<!-- Create Event Button -->
<.link
href={~p"/events/new"}
class="flex items-center gap-2 px-4 py-3 bg-primary-500 text-white rounded-full font-bold hover:bg-primary-600 transition"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z" clip-rule="evenodd" />
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z"
clip-rule="evenodd"
/>
</svg>
<span class="hidden sm:inline">{gettext("Create an event")}</span>
</.link>
</div>
</div>
</div>
<!-- Events Grid/List -->
<!-- Events Grid/List -->
<div class="relative">
<%= if @view_mode == "grid" do %>
<!-- Grid View -->
@@ -159,8 +219,8 @@
<% end %>
</ul>
<% end %>
<!-- Load More Button -->
<!-- Load More Button -->
<%= if @page < @total_pages do %>
<div class="flex justify-center my-8">
<button
@@ -171,20 +231,40 @@
</button>
</div>
<% end %>
<!-- Empty State -->
<!-- Empty State -->
<%= if Enum.count(@events) == 0 do %>
<div class="w-full py-16 text-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-16 w-16 mx-auto text-gray-300 mb-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1">
<path stroke-linecap="round" stroke-linejoin="round" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-16 w-16 mx-auto text-gray-300 mb-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="1"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
/>
</svg>
<p class="text-xl text-gray-400">{gettext("Create your first event")}</p>
<.link
href={~p"/events/new"}
class="inline-flex items-center gap-2 mt-4 px-6 py-3 bg-primary-500 text-white rounded-full font-bold hover:bg-primary-600 transition"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z" clip-rule="evenodd" />
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z"
clip-rule="evenodd"
/>
</svg>
<span>{gettext("Create an event")}</span>
</.link>

View File

@@ -1,8 +1,6 @@
<style>
body {
background: linear-gradient(-45deg, #2C033A, #21033A, #053138, #053138);
background-size: 400% 400%;
animation: gradient 15s ease infinite;
background: #140553;
height: 100vh;
}
</style>
@@ -24,17 +22,11 @@
{gettext("About")}
</a>
<%= if @current_user do %>
<.link
href={~p"/events"}
class="relative inline-flex items-center px-4 py-1 text-base font-sm rounded-md text-white bg-linear-to-tl from-primary-500 to-secondary-500 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500"
>
<.link href={~p"/events"} class="btn btn-primary">
{gettext("Dashboard")}
</.link>
<% else %>
<.link
href={~p"/users/log_in"}
class="relative inline-flex items-center px-4 py-1 text-base font-sm rounded-md text-white bg-linear-to-tl from-primary-500 to-secondary-500 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500"
>
<.link href={~p"/users/log_in"} class="btn btn-primary">
{gettext("Login")}
</.link>
<% end %>
@@ -47,17 +39,11 @@
{gettext("About")}
</a>
<%= if @current_user do %>
<.link
href={~p"/events"}
class="relative inline-flex items-center px-4 py-1 text-base font-sm rounded-md text-white bg-linear-to-tl from-primary-500 to-secondary-500 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500"
>
<.link href={~p"/events"} class="btn btn-primary">
{gettext("Dashboard")}
</.link>
<% else %>
<.link
href={~p"/users/log_in"}
class="relative inline-flex items-center px-4 py-1 text-base font-sm rounded-md text-white bg-linear-to-tl from-primary-500 to-secondary-500 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500"
>
<.link href={~p"/users/log_in"} class="btn btn-primary">
{gettext("Login")}
</.link>
<% end %>
@@ -86,11 +72,7 @@
</div>
<div class="mt-10">
<button
type="submit"
id="submit"
class="w-full flex justify-center text-white p-4 rounded-full tracking-wide font-bold outline-hidden focus:shadow-outline shadow-lg bg-linear-to-tl from-primary-500 to-secondary-500 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500"
>
<button type="submit" id="submit" class="btn btn-primary w-full">
{gettext("Join")}
</button>
<img src="/images/loading.gif" id="loading" class="hidden h-12 mx-auto" />

View File

@@ -173,7 +173,7 @@
href={~p"/e/#{@event.code}/manage/add/poll"}
class="group flex select-none rounded-xl p-3 w-full hover:bg-gray-200 cursor-pointer"
>
<div class="flex h-12 w-12 flex-none text-white items-center justify-center rounded-lg bg-linear-to-br from-primary-500 to-secondary-500">
<div class="flex h-12 w-12 flex-none text-white items-center justify-center rounded-lg bg-primary">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-7 w-7"
@@ -206,7 +206,7 @@
href={~p"/e/#{@event.code}/manage/add/form"}
class="group flex select-none rounded-xl p-3 w-full hover:bg-gray-200 cursor-pointer"
>
<div class="flex h-12 w-12 flex-none text-white items-center justify-center rounded-lg bg-linear-to-br from-primary-500 to-secondary-500">
<div class="flex h-12 w-12 flex-none text-white items-center justify-center rounded-lg bg-primary">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-7 w-7"
@@ -239,7 +239,7 @@
href={~p"/e/#{@event.code}/manage/add/embed"}
class="group flex select-none rounded-xl p-3 w-full hover:bg-gray-200 cursor-pointer"
>
<div class="flex h-12 w-12 flex-none text-white items-center justify-center rounded-lg bg-linear-to-br from-primary-500 to-secondary-500">
<div class="flex h-12 w-12 flex-none text-white items-center justify-center rounded-lg bg-primary">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
@@ -270,7 +270,7 @@
href={~p"/e/#{@event.code}/manage/add/quiz"}
class="group flex select-none rounded-xl p-3 w-full hover:bg-gray-200 cursor-pointer"
>
<div class="flex h-12 w-12 flex-none text-white items-center justify-center rounded-lg bg-linear-to-br from-primary-500 to-secondary-500">
<div class="flex h-12 w-12 flex-none text-white items-center justify-center rounded-lg bg-primary">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
@@ -546,7 +546,7 @@
data-tg-order="4"
data-tg-tour={"<p>#{gettext("Click here to open the presentation window. Press <strong>F</strong> in the presentation window to enable fullscreen.")}</p>"}
data-tg-group="manage"
class="hidden lg:inline-flex items-center py-1 px-5 rounded-r-sm text-base font-medium text-white bg-linear-to-tl from-primary-500 to-secondary-500 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500"
class="hidden lg:inline-flex items-center py-1 px-5 rounded-r-sm text-base font-medium btn btn-primary"
>
<svg
xmlns="http://www.w3.org/2000/svg"
@@ -761,7 +761,7 @@
<% %Claper.Polls.Poll{} -> %>
<div class="flex items-center justify-between mb-2">
<div class="flex items-center w-full">
<div class="flex h-8 w-8 flex-none text-white items-center justify-center rounded-lg bg-linear-to-br from-primary-500 to-secondary-500 mr-2">
<div class="flex h-8 w-8 flex-none text-white items-center justify-center rounded-lg bg-primary mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
@@ -805,7 +805,7 @@
<% %Claper.Forms.Form{} -> %>
<div class="flex items-center justify-between mb-2">
<div class="flex items-center w-full">
<div class="flex h-8 w-8 flex-none text-white items-center justify-center rounded-lg bg-linear-to-br from-primary-500 to-secondary-500 mr-2">
<div class="flex h-8 w-8 flex-none text-white items-center justify-center rounded-lg bg-primary mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
@@ -846,7 +846,7 @@
<% %Claper.Embeds.Embed{} -> %>
<div class="flex items-center justify-between mb-2">
<div class="flex items-center w-full">
<div class="flex h-8 w-8 flex-none text-white items-center justify-center rounded-lg bg-linear-to-br from-primary-500 to-secondary-500 mr-2">
<div class="flex h-8 w-8 flex-none text-white items-center justify-center rounded-lg bg-primary mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
@@ -891,7 +891,7 @@
<% %Claper.Quizzes.Quiz{} -> %>
<div class="flex items-center justify-between mb-2">
<div class="flex items-center w-full">
<div class="flex h-8 w-8 flex-none text-white items-center justify-center rounded-lg bg-linear-to-br from-primary-500 to-secondary-500 mr-2">
<div class="flex h-8 w-8 flex-none text-white items-center justify-center rounded-lg bg-primary mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"

View File

@@ -59,7 +59,7 @@
<div class={"#{if @iframe, do: "py-1", else: "py-4"} bg-gray-500 px-6 rounded-3xl flex justify-between items-center relative text-white"}>
<div
style={"width: #{opt.percentage}%;"}
class="bg-linear-to-r from-primary-500 to-secondary-500 rounded-3xl h-full absolute left-0 transition-all"
class="bg-primary rounded-3xl h-full absolute left-0 transition-all"
>
</div>
<div class="flex space-x-3 z-10 text-left">

View File

@@ -1,5 +1,5 @@
<%= if @started || @is_leader do %>
<div class="relative min-h-screen lg:flex lg:flex-col lg:items-center lg:w-full bg-black lg:bg-linear-to-tl from-primary-500 to-secondary-500">
<div class="relative min-h-screen lg:flex lg:flex-col lg:items-center lg:w-full bg-black lg:bg-primary">
<div class="relative w-full">
<div
id="side-menu-shadow"
@@ -42,7 +42,7 @@
<div class="flex justify-between items-center px-5 py-3">
<button
phx-click={toggle_side_menu()}
class="bg-black rounded-full text-sm px-3 py-1 bg-linear-to-tl from-primary-500 to-secondary-500 bg-size-[200%_200%] bg-position-[0%_0%] text-white uppercase flex items-center"
class="bg-primary rounded-full text-sm px-3 py-1 text-white uppercase flex items-center"
>
<img src="/images/icons/menu-outline.svg" class="h-6" />
<span class="ml-1">#{@event.code}</span>
@@ -458,7 +458,7 @@
</div>
</div>
<div class="hidden lg:block lg:w-1/2">
<div class="h-full object-cover bg-gradient-animate">
<div class="h-full object-cover bg-primary">
<div class="h-full bg-black/50 text-white text-center flex flex-col items-center justify-center">
<span class="text-4xl font-semibold mb-10">
{gettext("Scan to interact in real-time")}

View File

@@ -84,11 +84,7 @@
</button>
<div class="flex space-x-3">
<button
type="submit"
phx_disable_with="Loading..."
class="w-full lg:w-auto px-6 text-white py-2 rounded-md tracking-wide font-bold focus:outline-hidden focus:shadow-outline bg-linear-to-tl from-primary-500 to-secondary-500 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500"
>
<button type="submit" phx_disable_with="Loading..." class="btn btn-primary w-full lg:w-auto">
{case @live_action do
:new -> gettext("Create")
:edit -> gettext("Save")
@@ -106,8 +102,7 @@
"This will delete all responses associated and the form itself, are you sure?"
)
],
class:
"w-full lg:w-auto px-6 text-center text-white py-2 rounded-md tracking-wide font-bold focus:outline-hidden focus:shadow-outline bg-linear-to-tl from-supporting-red-600 to-supporting-red-400 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500"
class: "btn btn-error w-full lg:w-auto"
)}
<% end %>
</div>

View File

@@ -93,11 +93,7 @@
</div>
<div class="flex space-x-3">
<button
type="submit"
phx_disable_with="Loading..."
class="w-full lg:w-auto px-6 text-white py-2 rounded-md tracking-wide font-bold focus:outline-hidden focus:shadow-outline bg-linear-to-tl from-primary-500 to-secondary-500 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500"
>
<button type="submit" phx_disable_with="Loading..." class="btn btn-primary w-full lg:w-auto">
{case @live_action do
:new -> gettext("Create")
:edit -> gettext("Save")
@@ -115,8 +111,7 @@
"This will delete all responses associated and the poll itself, are you sure?"
)
],
class:
"w-full lg:w-auto px-6 text-center text-white py-2 rounded-md tracking-wide font-bold focus:outline-hidden focus:shadow-outline bg-linear-to-tl from-supporting-red-600 to-supporting-red-400 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500"
class: "btn btn-error w-full lg:w-auto"
)}
<% end %>
</div>

View File

@@ -148,7 +148,7 @@
<%= if Ecto.Changeset.get_field(@changeset, :quiz_questions) |> length() > 1 do %>
<label phx-click="remove_quiz_question" phx-target={@myself}>
<div class="cursor-pointer mt-4 w-full lg:w-auto px-6 text-center text-white py-2 rounded-md tracking-wide font-bold focus:outline-hidden focus:shadow-outline bg-linear-to-tl from-supporting-red-600 to-supporting-red-400 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500">
<div class="btn btn-error cursor-pointer mt-4 w-full lg:w-auto">
{gettext("Remove question")}
</div>
<input
@@ -181,7 +181,7 @@
type="submit"
phx_disable_with="Loading..."
disabled={!@changeset.valid?}
class="w-full lg:w-auto px-6 text-white py-2 rounded-md tracking-wide font-bold focus:outline-hidden focus:shadow-outline bg-linear-to-tl from-primary-500 to-secondary-500 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500 disabled:opacity-50 disabled:cursor-not-allowed"
class="btn btn-primary w-full lg:w-auto disabled:opacity-50 disabled:cursor-not-allowed"
>
{case @live_action do
:new -> gettext("Create")
@@ -201,8 +201,7 @@
"This will delete all responses associated and the quiz itself, are you sure?"
)
],
class:
"w-full lg:w-auto px-6 text-center text-white py-2 rounded-md tracking-wide font-bold focus:outline-hidden focus:shadow-outline bg-linear-to-tl from-supporting-red-600 to-supporting-red-400 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500"
class: "btn btn-error w-full lg:w-auto"
)}
<% end %>
</div>

View File

@@ -252,7 +252,7 @@
>
<div
style={"width: #{percentage}%;"}
class={"bg-linear-to-r from-primary-500 to-secondary-500 h-full absolute left-0 transition-all rounded-l-lg #{if percentage == "100", do: "rounded-r-lg"}"}
class={"bg-primary h-full absolute left-0 transition-all rounded-l-lg #{if percentage == "100", do: "rounded-r-lg"}"}
>
</div>
<div class="flex space-x-3 items-center z-10 text-left">

View File

@@ -299,8 +299,7 @@
method: :delete,
"data-confirm":
gettext("All your events and files will be permanently deleted, are you sure?"),
class:
"w-full lg:w-auto px-6 text-center text-white py-2 rounded-md tracking-wide font-bold focus:outline-hidden focus:shadow-outline bg-linear-to-tl from-supporting-red-600 to-supporting-red-400 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500"
class: "btn btn-error w-full lg:w-auto"
)}
</div>
</dl>

View File

@@ -2,7 +2,11 @@
<div class="hidden bg-primary-50 backdrop-blur-sm py-3 px-12">
<div class="flex items-center justify-center gap-2">
<span class="font-bold text-secondary-500">{gettext("NEWS:")}</span>
<span class="text-secondary-500">{gettext("Exciting News: Seamlessly join live events and elevate your audience engagement today!")}</span>
<span class="text-secondary-500">
{gettext(
"Exciting News: Seamlessly join live events and elevate your audience engagement today!"
)}
</span>
</div>
</div>
@@ -13,18 +17,29 @@
<a href={~p"/events"} class="shrink-0 bg-white p-2 rounded-full shadow-md">
<img src="/images/logo.svg" class="h-5" alt="Claper" />
</a>
<!-- Title -->
<!-- Title -->
<h1 class="text-2xl font-bold text-secondary-500 capitalize shrink-0">
{gettext("My events")}
</h1>
<!-- Search Bar -->
<!-- Search Bar -->
<div class="flex-1 max-w-md">
<form phx-submit="search" phx-change="search" class="relative">
<div class="flex items-center gap-2 bg-white border border-gray-200 rounded-full px-4 py-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-secondary-500" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5 text-secondary-500"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
/>
</svg>
<input
type="text"
@@ -36,37 +51,37 @@
</div>
</form>
</div>
<!-- Spacer -->
<!-- Spacer -->
<div class="flex-1"></div>
<!-- User Menu -->
<div class="flex items-center relative shrink-0">
<button
phx-click-away={JS.hide(to: "#profile-dropdown")}
phx-click={JS.toggle(to: "#profile-dropdown")}
type="button"
class="flex items-center gap-2 bg-gray-100 border border-gray-100 rounded-full px-4 py-3 hover:bg-gray-200 transition"
id="user-menu-button"
aria-expanded="false"
aria-haspopup="true"
<!-- User Menu -->
<div class="dropdown dropdown-end shrink-0 bg-white p-1 shadow-md rounded-full">
<div
tabindex="0"
role="button"
class="flex items-center gap-2 bg-gray-100 border border-gray-100 rounded-full px-4 py-3 hover:bg-gray-200 transition cursor-pointer"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-5 h-5 text-gray-700">
<path fill-rule="evenodd" d="M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z" clip-rule="evenodd" />
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="w-5 h-5 text-gray-700"
>
<path
fill-rule="evenodd"
d="M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z"
clip-rule="evenodd"
/>
</svg>
<span class="hidden md:block text-sm font-bold text-gray-700">{@user.email}</span>
</button>
<div
id="profile-dropdown"
class="hidden origin-top-right absolute right-0 top-14 w-48 rounded-lg shadow-lg bg-white ring-1 ring-black/5 divide-y divide-gray-200 focus:outline-hidden z-50"
role="menu"
aria-orientation="vertical"
aria-labelledby="user-menu-button"
tabindex="-1"
</div>
<ul
tabindex="0"
class="dropdown-content menu bg-base-100 rounded-box z-50 w-52 shadow-lg mt-2"
>
{render("_user_menu.html", conn: @conn, user: @user)}
</div>
</ul>
</div>
</div>
</div>

View File

@@ -1,33 +1,27 @@
<div class="py-1" role="none">
<a
href={~p"/users/settings"}
class="text-gray-700 block px-4 py-2 text-sm hover:bg-gray-100 hover:text-gray-900"
>
<li>
<a href={~p"/users/settings"}>
{gettext("My account")}
</a>
<a
:if={Claper.Accounts.user_has_role?(@user, "admin")}
href={~p"/admin"}
class="text-gray-700 block px-4 py-2 text-sm hover:bg-gray-100 hover:text-gray-900"
>
</li>
<li :if={Claper.Accounts.user_has_role?(@user, "admin")}>
<a href={~p"/admin"}>
{gettext("Admin")}
</a>
<a
href="https://docs.claper.co"
class="text-gray-700 block px-4 py-2 text-sm hover:bg-gray-100 hover:text-gray-900"
>
</li>
<li>
<a href="https://docs.claper.co">
{gettext("Documentation")}
</a>
</div>
<div class="py-1" role="none">
</li>
<li>
{link(gettext("Logout"),
to: ~p"/users/log_out",
method: :delete,
class: "text-gray-700 block px-4 py-2 text-sm hover:bg-gray-100 hover:text-gray-900"
class: "text-error"
)}
</div>
<div class="py-1" role="none">
<p class="text-gray-500 block px-4 text-xs py-1">
</li>
<li class="menu-title pointer-events-none">
<span class="text-xs text-gray-400">
Version {Application.spec(:claper, :vsn)}
</p>
</div>
</span>
</li>

View File

@@ -12,7 +12,7 @@
<script defer phx-track-static type="text/javascript" src="/assets/app.js">
</script>
</head>
<body class="bg-gray-100">
<body>
<div class="min-h-full">
<!-- Main column -->
<div class="flex flex-col" x-data="{profileMobileDropdown: false}">

View File

@@ -10,10 +10,7 @@
</p>
<pre class="text-gray-200 my-4 text-sm bg-gray-800 p-2 rounded-lg"><%= @msg %></pre>
</div>
<button
class="mx-auto mt-8 flex justify-center text-white p-4 rounded-md tracking-wide font-bold focus:outline-hidden focus:shadow-outline shadow-lg bg-linear-to-tl from-primary-500 to-secondary-500 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500"
onclick="window.close()"
>
<button class="btn btn-primary mx-auto mt-8" onclick="window.close()">
{gettext("Close")}
</button>
</div>

View File

@@ -32,11 +32,7 @@
<form action={~p"/lti/register"} method="post">
<input type="hidden" name="openid_configuration" value={@conf} />
<input type="hidden" name="registration_token" value={@token} />
<button
:if={@current_user}
type="submit"
class="flex justify-center text-white p-4 rounded-md tracking-wide font-bold focus:outline-hidden focus:shadow-outline shadow-lg bg-linear-to-tl from-primary-500 to-secondary-500 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500"
>
<button :if={@current_user} type="submit" class="btn btn-primary">
{gettext("Add Claper")}
</button>
<p :if={!@current_user} class="text-white italic">

View File

@@ -20,7 +20,7 @@
</div>
</div>
<button
class="mx-auto mt-8 flex justify-center text-white p-4 rounded-md tracking-wide font-bold focus:outline-hidden focus:shadow-outline shadow-lg bg-linear-to-tl from-primary-500 to-secondary-500 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500"
class="btn btn-primary mx-auto mt-8"
onclick="(window.opener || window.parent).postMessage({subject:'org.imsglobal.lti.close'}, '*');"
>
{gettext("Finish")}

View File

@@ -39,10 +39,7 @@
/>
<div>
<button
type="submit"
class="w-full flex justify-center text-white p-4 rounded-full tracking-wide font-bold focus:outline-hidden focus:shadow-outline shadow-lg bg-linear-to-tl from-primary-500 to-secondary-500 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500"
>
<button type="submit" class="btn btn-primary w-full">
{gettext("Create account")}
</button>
</div>

View File

@@ -44,10 +44,7 @@
/>
<div>
<button
type="submit"
class="w-full flex justify-center text-white p-4 rounded-full tracking-wide font-bold focus:outline-hidden focus:shadow-outline shadow-lg bg-linear-to-tl from-primary-500 to-secondary-500 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500"
>
<button type="submit" class="btn btn-primary w-full">
{gettext("Confirm new password")}
</button>
</div>

View File

@@ -29,10 +29,7 @@
required="true"
/>
<div>
<button
type="submit"
class="w-full flex justify-center text-white p-4 rounded-full tracking-wide font-bold focus:outline-hidden focus:shadow-outline shadow-lg bg-linear-to-tl from-primary-500 to-secondary-500 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500"
>
<button type="submit" class="btn btn-primary w-full">
{gettext("Send link to reset password")}
</button>
</div>

View File

@@ -55,10 +55,7 @@
</div>
<div class="pt-5">
<button
type="submit"
class="w-full flex justify-center text-white p-4 rounded-md tracking-wide font-bold focus:outline-hidden focus:shadow-outline shadow-lg bg-linear-to-tl from-primary-500 to-secondary-500 bg-size-[200%_200%] bg-position-[0%_0%] hover:bg-position-[100%_100%] transition-all duration-500"
>
<button type="submit" class="btn btn-primary w-full">
{gettext("Login")}
</button>
</div>

View File

@@ -8,7 +8,7 @@ defmodule ClaperWeb.Component.Alert do
~H"""
<div
class="bg-supporting-green-50 border-t-4 rounded-b-md shadow-md border-supporting-green-400 p-4 mb-3"
class="alert alert-success shadow-md p-4 mb-3"
x-data="{ open: true }"
x-show={if @stick, do: "true", else: "open"}
x-init="setTimeout(() => {open = false}, 4000)"
@@ -17,7 +17,7 @@ defmodule ClaperWeb.Component.Alert do
<div class="flex">
<div class="shrink-0">
<svg
class="h-5 w-5 text-green-400"
class="h-5 w-5 text-success"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
@@ -31,7 +31,7 @@ defmodule ClaperWeb.Component.Alert do
</svg>
</div>
<div class="ml-3">
<p class="text-sm text-supporting-green-700">
<p class="text-sm text-success-content">
{@message}
</p>
</div>
@@ -47,7 +47,7 @@ defmodule ClaperWeb.Component.Alert do
~H"""
<div
class="bg-supporting-red-50 border-t-4 rounded-b-md shadow-md border-supporting-red-400 p-4 mb-3"
class="alert alert-error shadow-md p-4 mb-3"
x-data="{ open: true }"
x-show={if @stick, do: "true", else: "open"}
x-init="setTimeout(() => {open = false}, 4000)"
@@ -57,7 +57,7 @@ defmodule ClaperWeb.Component.Alert do
<div class="shrink-0">
<!-- Heroicon name: solid/exclamation -->
<svg
class="h-5 w-5 text-supporting-red-400"
class="h-5 w-5 text-error"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
@@ -71,7 +71,7 @@ defmodule ClaperWeb.Component.Alert do
</svg>
</div>
<div class="ml-3">
<p class="text-sm text-supporting-red-700">
<p class="text-sm text-error-content">
{@message}
</p>
</div>

View File

@@ -30,7 +30,11 @@ defmodule ClaperWeb.Component.Badge do
use ClaperWeb, :view_component
attr :type, :atom, default: :contained, values: [:contained, :outlined]
attr :style, :atom, default: :default, values: [:default, :neutral, :primary, :secondary, :accent, :ghost]
attr :style, :atom,
default: :default,
values: [:default, :neutral, :primary, :secondary, :accent, :ghost]
attr :size, :atom, default: :xs, values: [:xs, :sm, :md, :lg]
attr :class, :string, default: nil
attr :rest, :global

View File

@@ -30,12 +30,18 @@ defmodule ClaperWeb.Component.Button do
use ClaperWeb, :view_component
attr :type, :string, default: "button"
attr :style, :atom, default: :primary, values: [:primary, :secondary, :neutral, :accent, :ghost, :default]
attr :style, :atom,
default: :primary,
values: [:primary, :secondary, :neutral, :accent, :ghost, :default]
attr :size, :atom, default: :md, values: [:xs, :sm, :md, :lg]
attr :shape, :atom, default: :square, values: [:square, :circle]
attr :disabled, :boolean, default: false
attr :class, :string, default: nil
attr :rest, :global, include: ~w(phx-click phx-target phx-disable-with phx-value-id form name value)
attr :rest, :global,
include: ~w(phx-click phx-target phx-disable-with phx-value-id form name value)
slot :inner_block, required: true
slot :icon_left
@@ -72,12 +78,18 @@ defmodule ClaperWeb.Component.Button do
end
attr :type, :string, default: "button"
attr :style, :atom, default: :default, values: [:primary, :secondary, :neutral, :accent, :ghost, :default]
attr :style, :atom,
default: :default,
values: [:primary, :secondary, :neutral, :accent, :ghost, :default]
attr :size, :atom, default: :md, values: [:xs, :sm, :md, :lg]
attr :shape, :atom, default: :square, values: [:square, :circle]
attr :disabled, :boolean, default: false
attr :class, :string, default: nil
attr :rest, :global, include: ~w(phx-click phx-target phx-disable-with phx-value-id form name value)
attr :rest, :global,
include: ~w(phx-click phx-target phx-disable-with phx-value-id form name value)
slot :inner_block, required: true

View File

@@ -123,7 +123,7 @@ defmodule ClaperWeb.Component.Tabs do
end
defp container_classes(:boxed) do
"inline-flex items-center bg-gray-100 p-0.5 rounded-full"
"inline-flex items-center bg-gray-100 rounded-full"
end
# Base tab classes based on style
@@ -136,7 +136,7 @@ defmodule ClaperWeb.Component.Tabs do
end
defp tab_base_classes(:boxed) do
"px-4 py-1.5 text-sm font-normal font-display transition-all duration-200 rounded-full"
"px-5 py-3 text-sm font-normal font-display transition-all duration-200 rounded-full"
end
# Tab state classes (active/inactive) based on style

View File

@@ -37,7 +37,9 @@ defmodule ClaperWeb.EventCardComponentTest do
{:ok, view, _html} = live(conn, "/events")
# Expired events are shown in the "Done" tab
html = view |> element("[phx-click='change-tab'][phx-value-tab='expired']") |> render_click()
html =
view |> element("[phx-click='change-tab'][phx-value-tab='expired']") |> render_click()
assert html =~ "Finished"
end
@@ -50,7 +52,9 @@ defmodule ClaperWeb.EventCardComponentTest do
{:ok, view, _html} = live(conn, "/events")
# Expired events are shown in the "Done" tab
html = view |> element("[phx-click='change-tab'][phx-value-tab='expired']") |> render_click()
html =
view |> element("[phx-click='change-tab'][phx-value-tab='expired']") |> render_click()
assert html =~ "Finished"
end
end