diff --git a/assets/css/beacon_live_admin.css b/assets/css/beacon_live_admin.css index 11232c7a..20d37c1a 100644 --- a/assets/css/beacon_live_admin.css +++ b/assets/css/beacon_live_admin.css @@ -1,3 +1,5 @@ +@import "./station-ui.css"; +@import "./station-ui-fonts.css"; @import "tailwindcss/base"; @import "tailwindcss/components"; @import "tailwindcss/utilities"; diff --git a/assets/css/station-ui-fonts.css b/assets/css/station-ui-fonts.css new file mode 100644 index 00000000..1bb3ee2c --- /dev/null +++ b/assets/css/station-ui-fonts.css @@ -0,0 +1,146 @@ +/* Inter-100 */ +@font-face { + font-family: "Inter"; + font-weight: 100; + font-style: normal; + font-display: swap; + src: + url("/fonts/inter/Inter-Thin.woff2"), + /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ url("/fonts/inter/Inter-Thin.woff"), + /* Chrome 5+, Firefox 3.6+, IE 9+, Safari 5.1+, iOS 5+ */ url("/fonts/inter/Inter-Thin.ttf"); + /* Chrome 4+, Firefox 3.5+, IE 9+, Safari 3.1+, iOS 4.2+, Android Browser 2.2+ */ +} + +/* Inter-200 */ +@font-face { + font-family: "Inter"; + font-weight: 200; + font-style: normal; + font-display: swap; + src: + url("/fonts/inter/Inter-ExtraLight.woff2"), + /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ url("/fonts/inter/Inter-ExtraLight.woff"), + /* Chrome 5+, Firefox 3.6+, IE 9+, Safari 5.1+, iOS 5+ */ url("/fonts/inter/Inter-ExtraLight.ttf"); + /* Chrome 4+, Firefox 3.5+, IE 9+, Safari 3.1+, iOS 4.2+, Android Browser 2.2+ */ +} + +/* Inter-300 */ +@font-face { + font-family: "Inter"; + font-weight: 300; + font-style: normal; + font-display: swap; + src: + url("/fonts/inter/Inter-Light.woff2"), + /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ url("/fonts/inter/Inter-Light.woff"), + /* Chrome 5+, Firefox 3.6+, IE 9+, Safari 5.1+, iOS 5+ */ url("/fonts/inter/Inter-Light.ttf"); + /* Chrome 4+, Firefox 3.5+, IE 9+, Safari 3.1+, iOS 4.2+, Android Browser 2.2+ */ +} + +/* Inter-400 */ +@font-face { + font-family: "Inter"; + font-weight: 400; + font-style: normal; + font-display: swap; + src: + url("/fonts/inter/Inter-Regular.woff2"), + /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ url("/fonts/inter/Inter-Regular.woff"), + /* Chrome 5+, Firefox 3.6+, IE 9+, Safari 5.1+, iOS 5+ */ url("/fonts/inter/Inter-Regular.ttf"); + /* Chrome 4+, Firefox 3.5+, IE 9+, Safari 3.1+, iOS 4.2+, Android Browser 2.2+ */ +} + +/* Inter-500 */ +@font-face { + font-family: "Inter"; + font-weight: 500; + font-style: normal; + font-display: swap; + src: + url("/fonts/inter/Inter-Medium.woff2"), + /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ url("/fonts/inter/Inter-Medium.woff"), + /* Chrome 5+, Firefox 3.6+, IE 9+, Safari 5.1+, iOS 5+ */ url("/fonts/inter/Inter-Medium.ttf"); + /* Chrome 4+, Firefox 3.5+, IE 9+, Safari 3.1+, iOS 4.2+, Android Browser 2.2+ */ +} + +/* Inter-600 */ +@font-face { + font-family: "Inter"; + font-weight: 600; + font-style: normal; + font-display: swap; + src: + url("/fonts/inter/Inter-SemiBold.woff2"), + /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ url("/fonts/inter/Inter-SemiBold.woff"), + /* Chrome 5+, Firefox 3.6+, IE 9+, Safari 5.1+, iOS 5+ */ url("/fonts/inter/Inter-SemiBold.ttf"); + /* Chrome 4+, Firefox 3.5+, IE 9+, Safari 3.1+, iOS 4.2+, Android Browser 2.2+ */ +} + +/* Inter-700 */ +@font-face { + font-family: "Inter"; + font-weight: 700; + font-style: normal; + font-display: swap; + src: + url("/fonts/inter/Inter-Bold.woff2"), + /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ url("/fonts/inter/Inter-Bold.woff"), + /* Chrome 5+, Firefox 3.6+, IE 9+, Safari 5.1+, iOS 5+ */ url("/fonts/inter/Inter-Bold.ttf"); + /* Chrome 4+, Firefox 3.5+, IE 9+, Safari 3.1+, iOS 4.2+, Android Browser 2.2+ */ +} + +/* Inter-800 */ +@font-face { + font-family: "Inter"; + font-weight: 800; + font-style: normal; + font-display: swap; + src: + url("/fonts/inter/Inter-ExtraBold.woff2"), + /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ url("/fonts/inter/Inter-ExtraBold.woff"), + /* Chrome 5+, Firefox 3.6+, IE 9+, Safari 5.1+, iOS 5+ */ url("/fonts/inter/Inter-ExtraBold.ttf"); + /* Chrome 4+, Firefox 3.5+, IE 9+, Safari 3.1+, iOS 4.2+, Android Browser 2.2+ */ +} + +/* Inter-900 */ +@font-face { + font-family: "Inter"; + font-weight: 900; + font-style: normal; + font-display: swap; + src: + url("/fonts/inter/Inter-Black.woff2"), + /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ url("/fonts/inter/Inter-Black.woff"), + /* Chrome 5+, Firefox 3.6+, IE 9+, Safari 5.1+, iOS 5+ */ url("/fonts/inter/Inter-Black.ttf"); + /* Chrome 4+, Firefox 3.5+, IE 9+, Safari 3.1+, iOS 4.2+, Android Browser 2.2+ */ +} + +/* roboto-mono-300 - latin_latin-ext */ +@font-face { + font-family: "Roboto Mono"; + font-weight: 300; + font-style: normal; + font-display: swap; + src: + url("/fonts/roboto-mono/roboto-mono-v23-latin_latin-ext-300.woff2"), + /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ + url("/fonts/roboto-mono/roboto-mono-v23-latin_latin-ext-300.woff"), + /* Chrome 5+, Firefox 3.6+, IE 9+, Safari 5.1+, iOS 5+ */ + url("/fonts/roboto-mono/roboto-mono-v23-latin_latin-ext-300.ttf"); + /* Chrome 4+, Firefox 3.5+, IE 9+, Safari 3.1+, iOS 4.2+, Android Browser 2.2+ */ +} + +/* roboto-mono-500 - latin_latin-ext */ +@font-face { + font-family: "Roboto Mono"; + font-weight: 500; + font-style: normal; + font-display: swap; + src: + url("/fonts/roboto-mono/roboto-mono-v23-latin_latin-ext-500.woff2"), + /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ + url("/fonts/roboto-mono/roboto-mono-v23-latin_latin-ext-500.woff"), + /* Chrome 5+, Firefox 3.6+, IE 9+, Safari 5.1+, iOS 5+ */ + url("/fonts/roboto-mono/roboto-mono-v23-latin_latin-ext-500.ttf"); + /* Chrome 4+, Firefox 3.5+, IE 9+, Safari 3.1+, iOS 4.2+, Android Browser 2.2+ */ +} diff --git a/assets/css/station-ui.css b/assets/css/station-ui.css new file mode 100644 index 00000000..5182614c --- /dev/null +++ b/assets/css/station-ui.css @@ -0,0 +1,111 @@ +@layer base { + :root { + /* primary */ + --sui-brand-primary: theme("colors.indigo.700"); + --sui-brand-primary-bg: theme("colors.indigo.600"); + --sui-brand-primary-bg-disabled: theme("colors.slate.50"); + --sui-brand-primary-muted: theme("colors.indigo.500"); + --sui-brand-primary-shadow: theme("colors.slate.100"); + --sui-brand-primary-text: theme("colors.slate.800"); + --sui-brand-primary-text-inverted: theme("colors.white"); + --sui-brand-primary-text-disabled: theme("colors.slate.300"); + --sui-brand-primary-border: theme("colors.slate.300"); + --sui-brand-primary-border-inverted: theme("colors.slate.600"); + --sui-brand-primary-focus: theme("colors.purple.500"); + --sui-brand-primary-error: theme("colors.rose.500"); + --sui-brand-primary-success: theme("colors.emerald.500"); + --sui-brand-primary-icon: theme("colors.slate.500"); + --sui-brand-primary-icon-inverted: theme("colors.slate.400"); + + /* secondary */ + --sui-brand-secondary-bg: theme("colors.white"); + --sui-brand-secondary-bg-inverted: theme("colors.black"); + --sui-brand-secondary-text: theme("colors.slate.600"); + --sui-brand-secondary-text-muted: theme("colors.gray.500"); + --sui-brand-secondary-text-inverted: theme("colors.slate.400"); + + /* buttons */ + --sui-text-btn-disabled: theme("colors.slate.300"); + --sui-bg-btn-disabled: theme("colors.slate.50"); + --sui-border-btn-disabled: theme("colors.slate.50"); + + /* forms */ + --sui-form-bg-slider-progress: theme("colors.indigo.600"); + --sui-form-bg-slider-progress-disabled: theme("colors.zinc.300"); + --sui-form-bg-slider-thumb: theme("colors.indigo.600"); + --sui-form-bg-slider-thumb-active: theme("colors.indigo.800"); + --sui-form-bg-slider-thumb-disabled: theme("colors.slate.100"); + --sui-form-bg-slider-thumb-hover: theme("colors.indigo.500"); + --sui-form-bg-slider-track: theme("colors.white"); + --sui-form-bg-slider-track-disabled: theme("colors.slate.50"); + --sui-form-border-slider-thumb: theme("colors.indigo.500"); + --sui-form-border-slider-thumb-active: theme("colors.indigo.700"); + --sui-form-border-slider-thumb-disabled: theme("colors.zinc.300"); + --sui-form-border-slider-thumb-hover: theme("colors.indigo.400"); + --sui-form-border-slider-track: theme("colors.gray.400"); + --sui-form-border-slider-track-disabled: theme("colors.zinc.300"); + --sui-form-text: var(--sui-brand-primary-text); + --sui-form-text-disabled: theme("colors.gray.500"); + --sui-form-text-error: theme("colors.rose.700"); + } + + .sui-primary { + --sui-text-btn: theme("colors.white"); + --sui-text-btn-hover: theme("colors.white"); + --sui-text-btn-active: theme("colors.white"); + --sui-bg-btn: theme("colors.indigo.700"); + --sui-bg-btn-hover: theme("colors.indigo.600"); + --sui-bg-btn-active: theme("colors.indigo.800"); + --sui-border-btn: theme("colors.indigo.700"); + --sui-border-btn-hover: theme("colors.indigo.600"); + --sui-border-btn-active: theme("colors.indigo.800"); + } + + .sui-secondary { + --sui-text-btn: theme("colors.slate.800"); + --sui-text-btn-hover: theme("colors.slate.800"); + --sui-text-btn-active: theme("colors.slate.800"); + --sui-bg-btn: theme("colors.white"); + --sui-bg-btn-hover: theme("colors.slate.50"); + --sui-bg-btn-active: theme("colors.slate.200"); + --sui-border-btn: theme("colors.slate.800"); + --sui-border-btn-hover: theme("colors.slate.800"); + --sui-border-btn-active: theme("colors.slate.800"); + } + + .sui-tertiary { + --sui-text-btn: theme("colors.white"); + --sui-text-btn-hover: theme("colors.white"); + --sui-text-btn-active: theme("colors.white"); + --sui-bg-btn: theme("colors.slate.800"); + --sui-bg-btn-hover: theme("colors.slate.700"); + --sui-bg-btn-active: theme("colors.slate.900"); + --sui-border-btn: theme("colors.slate.800"); + --sui-border-btn-hover: theme("colors.slate.700"); + --sui-border-btn-active: theme("colors.slate.900"); + } + + .sui-primary-destructive { + --sui-text-btn: theme("colors.white"); + --sui-text-btn-hover: theme("colors.white"); + --sui-text-btn-active: theme("colors.white"); + --sui-bg-btn: theme("colors.rose.700"); + --sui-bg-btn-hover: theme("colors.rose.600"); + --sui-bg-btn-active: theme("colors.rose.800"); + --sui-border-btn: theme("colors.rose.700"); + --sui-border-btn-hover: theme("colors.rose.600"); + --sui-border-btn-active: theme("colors.rose.800"); + } + + .sui-secondary-destructive { + --sui-text-btn: theme("colors.rose.700"); + --sui-text-btn-hover: theme("colors.rose.600"); + --sui-text-btn-active: theme("colors.rose.800"); + --sui-bg-btn: theme("colors.white"); + --sui-bg-btn-hover: theme("colors.white"); + --sui-bg-btn-active: theme("colors.white"); + --sui-border-btn: theme("colors.rose.700"); + --sui-border-btn-hover: theme("colors.rose.600"); + --sui-border-btn-active: theme("colors.rose.800"); + } +} diff --git a/assets/js/station-ui.js b/assets/js/station-ui.js new file mode 100644 index 00000000..660557c8 --- /dev/null +++ b/assets/js/station-ui.js @@ -0,0 +1,40 @@ +// Tailwind CSS presets for Station UI +const defaultTheme = require("tailwindcss/defaultTheme") + +module.exports = { + theme: { + container: { + center: true, + }, + extend: { + animation: { + "spin-reverse": "spin-reverse 1s linear infinite", + }, + fontFamily: { + sans: ["Inter", ...defaultTheme.fontFamily.sans], + mono: ["Roboto Mono", ...defaultTheme.fontFamily.mono], + }, + boxShadow: { + "inner-sm": "inset 0 1px 2px 0 rgb(0 0 0 / 0.05)", // shadow-sm + "inner-md": "inset 0 4px 6px -1px rgb(0 0 0 / 0.1), inset 0 2px 4px -2px rgb(0 0 0 / 0.1)", // shadow-md + "inner-lg": "inset 0 10px 15px -3px rgb(0 0 0 / 0.1), inset 0 4px 6px -4px rgb(0 0 0 / 0.1)", // shadow-lg + "inner-xl": "inset 0 20px 25px -5px rgb(0 0 0 / 0.1), inset 0 8px 10px -6px rgb(0 0 0 / 0.1)", // shadow-xl + "inner-2xl": "inset 0 25px 50px -12px rgb(0 0 0 / 0.25)", // shadow-2xl + }, + keyframes: { + "spin-reverse": { + from: { + transform: "rotate(360deg)", + }, + }, + }, + spacing: { + 4.5: "1.125rem", //18px + }, + transitionProperty: { + "grid-rows": "grid-template-rows", + }, + }, + }, + plugins: [require("@tailwindcss/container-queries")], +} diff --git a/assets/tailwind.config.js b/assets/tailwind.config.js index 31e97108..048423ae 100644 --- a/assets/tailwind.config.js +++ b/assets/tailwind.config.js @@ -12,6 +12,7 @@ const fs = require("fs") const path = require("path") module.exports = { + presets: [require("./js/station-ui.js")], content: ["./js/**/*.js", "../lib/beacon/live_admin/**/*.*ex", "./svelte/**/*.svelte"], theme: { extend: { diff --git a/lib/beacon/live_admin/components/admin_components.ex b/lib/beacon/live_admin/components/admin_components.ex index ecdd2983..ea59b7f6 100644 --- a/lib/beacon/live_admin/components/admin_components.ex +++ b/lib/beacon/live_admin/components/admin_components.ex @@ -14,16 +14,16 @@ defmodule Beacon.LiveAdmin.AdminComponents do import Beacon.LiveAdmin.Router, only: [beacon_live_admin_path: 3] defdelegate header(assigns), to: CoreComponents - defdelegate icon(assigns), to: CoreComponents - defdelegate show_modal(assigns), to: CoreComponents defdelegate hide_modal(assigns), to: CoreComponents defdelegate show(selector), to: CoreComponents defdelegate show(js, selector), to: CoreComponents defdelegate hide(selector), to: CoreComponents defdelegate hide(js, selector), to: CoreComponents - defdelegate translate_error(error), to: CoreComponents defdelegate translate_errors(errors, field), to: CoreComponents + defp icon(assigns), do: Beacon.LiveAdmin.StationUI.HTML.Icon.icon(assigns) + defp input(assigns), do: Beacon.LiveAdmin.CoreComponents.input(assigns) + @menu_link_active_class "inline-block p-4 text-blue-600 border-b-2 border-blue-600 rounded-t-lg active" @menu_link_regular_class "inline-block p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300" @@ -211,58 +211,6 @@ defmodule Beacon.LiveAdmin.AdminComponents do """ end - @doc """ - Renders a modal. - - ## Examples - - <.modal id="confirm-modal"> - This is a modal. - - - JS commands may be passed to the `:on_cancel` to configure - the closing/cancel event, for example: - - <.modal id="confirm" on_cancel={JS.navigate(~p"/posts")}> - This is another modal. - - - """ - attr :id, :string, required: true - attr :show, :boolean, default: false - attr :on_cancel, JS, default: %JS{} - slot :inner_block, required: true - - def modal(assigns) do - ~H""" -