Skip to content

Instantly share code, notes, and snippets.

View stekhn's full-sized avatar

Steffen Kühne stekhn

View GitHub Profile
@stekhn
stekhn / login.html
Created September 14, 2024 10:03
Expandable login form using the CSS :target selector, hash navigation and ARIA attributes for enhanced accessibility. Initially hidden.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Expandable Form</title>
<style>
html,
body {
height: 75%;
@stekhn
stekhn / consoleColorLog.ts
Created April 25, 2024 07:22
Outputs an array of color strings to the browser console and colors each string according to its hexadecimal or RGB value for visual debugging
const consoleColorLog = (colors: string[]) => {
const strings = colors.map((color: string) => `%c${color}`).join(" ");
const css = colors.map((color: string) => `color: ${color};`);
console.log.apply(console, [strings, css].flat());
};
// consoleColorLog(["#FFFFFF", "#AFD1F9", "#6CA4FF", "#006AFF", "#0515CD"]);
@stekhn
stekhn / DebouncedInput.tsx
Created February 15, 2024 16:42
Debounced input component for React onChange events using useCallback and Lodash debounce
import React, { useCallback } from "react";
import { debounce } from "lodash";
export const Input = () => {
const mySlowFunction = (value) => console.log(value);
const debouncedEventHandler = useCallback(
debounce((value) => mySlowFunction(value), 100),
[]
);
@stekhn
stekhn / slugify.js
Created October 2, 2023 13:42
Convert a string like a headline to a slug than can be used in a URL. German umlauts get transcribed.
const slugify = (string) =>
string
.trim()
.toLowerCase()
.replace(/\s+/g, "-")
.replace(/ä/g, "ae")
.replace(/ö/g, "oe")
.replace(/ü/g, "ue")
.replace(/\u00df/g, "ss")
.replace(/[^a-z0-9-]/g, "");
@stekhn
stekhn / neighbors.py
Created September 19, 2023 15:03
Add the names of all neighboring polygons as a new attribute to every polygon in layer (QGIS 3)
from qgis.utils import iface
from PyQt5.QtCore import QVariant
NAME_COLUMN = 'NAME'
NEIGHBORS_NAME_COLUMN = 'NEIGHBORS'
layer = iface.activeLayer()
layer.startEditing()
layer.dataProvider().addAttributes([QgsField(NEIGHBORS_NAME_COLUMN, QVariant.String)])
layer.updateFields()
@stekhn
stekhn / contrast-ratio.js
Created February 22, 2023 10:20
Get the contrast ratio of two hex colors
const hex2Rgb = (hexString) => {
const groups = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hexString);
return groups
? [
parseInt(result[1], 16),
parseInt(result[2], 16),
parseInt(result[3], 16),
]
: null;
};
@stekhn
stekhn / ci-cd.yml
Created November 27, 2022 21:39
Github Action for building a web application and deploying it to a Google Cloud Storage bucket
# Set up Node.js action: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
# Set up Google Cloud auth action: https://github.com/google-github-actions/auth#usage
# Set up Google Cloud workload identity federation: https://github.com/marketplace/actions/authenticate-to-google-cloud#setting-up-workload-identity-federation
# Upload to Google Cloud Storage: https://github.com/google-github-actions/upload-cloud-storage
name: CI/CD
on:
push:
branches: ['main']
@stekhn
stekhn / transform.ts
Last active November 24, 2022 08:56
Parse the individual values from the CSS/SVG transform attribute into an object with RegEx and serialize them back into a string
// Adapted from https://stackoverflow.com/a/17838403/2037629
// If possible, use getComputedStyle() instead: https://stackoverflow.com/a/64654744/2037629
type TransformValues = {
translate?: string[];
rotate?: string[];
scale?: string[];
};
export const parseTransform = (string: string) => {
@stekhn
stekhn / download-canvas.js
Created August 3, 2022 18:49
Save HTML5 canvas element as PNG file
const canvas = document.getElementsByTagName('canvas')[0];
const dataURL = canvas.toDataURL('image/png');
const timestamp = Math.floor(Date.now() / 1000).toString(36).slice(2);
const link = document.createElement('a');
link.download = `download-${timestamp}.png`;
link.href = dataURL;
link.click();
@stekhn
stekhn / ConditionalWrapper.tsx
Last active June 10, 2022 09:00
React conditional wrapper that add an enclosing element based on a boolean condition
import * as React from 'react';
interface Props {
condition: boolean;
wrapper: Function;
children: React.ReactNode;
}
export const ConditionalWrapper: React.FC<Props> = ({ condition, wrapper, children }) => {
return condition ? wrapper(children) : children;