frontend

typescript
import { http, HttpResponse } from 'msw';

export interface Product {
  id: number;
  name: string;
}

MSW for frontend API mocking in tests

testing frontend react
by codesnips 4 tabs
ruby
class AdminController < ApplicationController
  before_action :authenticate_admin!
  before_action :disable_turbo_cache, only: %i[dashboard moderation_queue]

  helper_method :turbo_cache_control_tag

Turbo Drive: disable caching on volatile admin pages

rails turbo hotwire
by codesnips 3 tabs
erb
<%= form_with model: @document, data: { controller: "upload" } do |form| %>
  <div class="field">
    <%= form.label :file, "Attach a document" %>
    <%= form.file_field :file,
          direct_upload: true,
          data: { upload_target: "input" } %>

Active Storage direct upload progress with Stimulus

rails hotwire stimulus
by codesnips 3 tabs
javascript
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = ["input"]
  static values = { wait: { type: Number, default: 300 }, url: String }

Stimulus: debounced search that plays nicely with Turbo

rails stimulus hotwire
by codesnips 3 tabs
css
.turbo-progress-bar {
  height: 4px;
  background: linear-gradient(
    90deg,
    var(--progress-start, #6366f1),
    var(--progress-end, #ec4899)

Customize Turbo progress bar styling with Tailwind/CSS

rails hotwire turbo
by codesnips 3 tabs
erb
<nav id="main-navbar"
     data-turbo-permanent
     data-controller="navbar"
     data-navbar-menu-open-value="false"
     class="navbar">
  <div class="navbar-inner">

Keep navbar state across Turbo navigations with data-turbo-permanent

rails hotwire turbo
by codesnips 3 tabs
erb
<%= turbo_stream_from :comments %>

<section class="comments">
  <h2>Discussion</h2>

  <%= turbo_frame_tag "new_comment" do %>

Inline create form that prepends into a list with Turbo Streams

rails hotwire turbo
by codesnips 4 tabs
typescript
// 1. Basic types
let username: string = 'Alex';
let age: number = 30;
let isActive: boolean = true;
let items: string[] = ['item1', 'item2'];
let numbers: Array<number> = [1, 2, 3];

TypeScript fundamentals for type-safe front-end code

typescript javascript types
by Alex Chang 2 tabs
javascript
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = ["checkbox", "selectAll", "count", "submit"]
  static values = { selectedIds: Array }

Stimulus: bulk selection + Turbo batch action

rails stimulus hotwire
by codesnips 4 tabs
typescript
import { useCallback, useEffect, useRef, useState } from 'react';

export type CopyStatus = 'idle' | 'copied' | 'error';

function fallbackCopy(text: string): boolean {
  const textarea = document.createElement('textarea');

Frontend: copy-to-clipboard with fallback

frontend ux react
by codesnips 3 tabs
typescript
import * as Sentry from "@sentry/react";

const environment = import.meta.env.VITE_ENVIRONMENT ?? "development";
const isProd = environment === "production";

export function initSentry(): void {

Sentry initialization with release + environment

observability frontend sentry
by codesnips 3 tabs
javascript
import { useCallback, useEffect, useRef, useState } from 'react';

export function usePaginatedFetch(fetchPage, { pageSize = 20 } = {}) {
  const [items, setItems] = useState([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

Infinite Scroll in React with IntersectionObserver and a Paginated Fetch Hook

react hooks infinite-scroll
by codesnips 3 tabs