Skip to content

Latest commit

 

History

History
200 lines (154 loc) · 4.15 KB

File metadata and controls

200 lines (154 loc) · 4.15 KB
title hidden
description Guard function that denies access and returns 404 Not Found

hidden()

Returns a guard result that denies access and makes the route return 404 Not Found. The route is also hidden from navigation and search.

Signature

function hidden(): GuardResult;

Return Type

{
  type: "hidden";
}

Usage

import { hidden, type Guard } from "@tailor-platform/app-shell";

const denyAccess: Guard = () => {
  return hidden();
};

When to Use

Use hidden() when:

  • ✅ Access should be denied
  • ✅ User doesn't have required permissions
  • ✅ You want to hide the page completely (404)
  • ✅ Feature is not available for current user

Effects

When hidden() is returned:

  • 🚫 Route returns 404 Not Found
  • 🚫 Hidden from sidebar navigation
  • 🚫 Hidden from CommandPalette search
  • 🚫 Not shown in breadcrumbs
  • 🚫 Direct URL access returns 404

Examples

Deny All Access

const denyAll: Guard = () => hidden();

Role-Based Hiding

const adminOnly: Guard = ({ context }) => {
  if (context.currentUser?.role !== "admin") {
    return hidden(); // Non-admins see 404
  }
  return pass();
};

Permission-Based Hiding

const requirePermission =
  (perm: string): Guard =>
  ({ context }) => {
    if (!context.permissions.includes(perm)) {
      return hidden(); // No permission → 404
    }
    return pass();
  };

Feature Flag

const requireBetaFeature: Guard = ({ context }) => {
  if (!context.featureFlags?.beta) {
    return hidden(); // Feature disabled → 404
  }
  return pass();
};

Subscription Tier

const premiumOnly: Guard = ({ context }) => {
  if (context.currentUser?.plan !== "premium") {
    return hidden(); // Free users see 404
  }
  return pass();
};

Conditional Hiding

const conditionalHide: Guard = ({ context }) => {
  // Multiple conditions
  if (!context.currentUser || context.currentUser.suspended || !context.currentUser.emailVerified) {
    return hidden();
  }
  return pass();
};

Async Permission Check

const asyncHide: Guard = async ({ context }) => {
  const allowed = await fetch("/api/check-access");
  if (!allowed) {
    return hidden();
  }
  return pass();
};

vs redirectTo()

Aspect hidden() redirectTo()
Result 404 Not Found Redirect to page
URL Stays same Changes to new URL
Navigation Hidden Not affected
Use Case Deny access silently Send to login/error page

Example: When to Use Each

// Use hidden() - Silently deny access
const adminFeature: Guard = ({ context }) => {
  if (!isAdmin(context)) {
    return hidden(); // Non-admins don't even see this exists
  }
  return pass();
};

// Use redirectTo() - Explicitly redirect
const requireAuth: Guard = ({ context }) => {
  if (!context.currentUser) {
    return redirectTo("/login"); // Unauthenticated users go to login
  }
  return pass();
};

Navigation Impact

// Before guard (user is not admin):
Sidebar:
 Dashboard
 Products
 Admin Panel   Visible

// After guard returns hidden():
Sidebar:
 Dashboard
 Products
                Admin Panel disappeared

// Direct URL access: /admin
// Result: 404 Not Found

WithGuard Component

hidden() works with WithGuard to hide UI elements:

import { WithGuard, hidden, pass } from "@tailor-platform/app-shell";

const isAdmin = ({ context }) =>
  context.currentUser?.role === "admin" ? pass() : hidden();

<WithGuard guards={[isAdmin]}>
  <Button>Delete All Users</Button>
</WithGuard>
// Non-admins: button doesn't render

Related