Align layout with Figma design
This commit is contained in:
@@ -7,8 +7,6 @@
|
|||||||
|
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
<link rel="preconnect" href="https://rsms.me/" />
|
|
||||||
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
|
|
||||||
<link
|
<link
|
||||||
href="https://fonts.googleapis.com/css2?family=Work+Sans:ital,wght@0,100..900;1,100..900&display=swap"
|
href="https://fonts.googleapis.com/css2?family=Work+Sans:ital,wght@0,100..900;1,100..900&display=swap"
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.5 KiB |
31
src/App.tsx
31
src/App.tsx
@@ -1,15 +1,14 @@
|
|||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import * as d3 from "d3";
|
import * as d3 from "d3";
|
||||||
|
|
||||||
import { config } from "./config";
|
|
||||||
import { getSampleData } from "./lib/data";
|
|
||||||
import { fetchCategoryMetadata } from "./lib/metadata";
|
import { fetchCategoryMetadata } from "./lib/metadata";
|
||||||
|
|
||||||
import { Instructions } from "./components/Instructions";
|
import { Instructions } from "./components/Instructions";
|
||||||
import Legend from "./components/Legend";
|
import Legend from "./components/Legend";
|
||||||
import QRCode from "./components/QRCode";
|
import QRCode from "./components/QRCode";
|
||||||
import { QuestionGroupChart } from "./components/QuestionGroupChart";
|
import { WaffleChart } from "./components/WaffleChart";
|
||||||
|
|
||||||
|
import { fetchGoogleSheet } from "./lib/parser";
|
||||||
import "./styles/App.scss";
|
import "./styles/App.scss";
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
@@ -19,8 +18,9 @@ function App() {
|
|||||||
});
|
});
|
||||||
const responseQuery = useQuery({
|
const responseQuery = useQuery({
|
||||||
queryKey: ["responses"],
|
queryKey: ["responses"],
|
||||||
queryFn: getSampleData,
|
queryFn: fetchGoogleSheet,
|
||||||
refetchInterval: 2 * 1000, // Refresh every 5 seconds
|
// queryFn: getSampleData,
|
||||||
|
refetchInterval: 5 * 1000, // Refresh every 5 seconds
|
||||||
});
|
});
|
||||||
|
|
||||||
if (metadataQuery.isPending || responseQuery.isPending)
|
if (metadataQuery.isPending || responseQuery.isPending)
|
||||||
@@ -28,7 +28,10 @@ function App() {
|
|||||||
if (metadataQuery.isError || responseQuery.isError)
|
if (metadataQuery.isError || responseQuery.isError)
|
||||||
return <div>Error loading data</div>;
|
return <div>Error loading data</div>;
|
||||||
|
|
||||||
const responses = responseQuery.data;
|
// Sort responses by timestamp to easily find the latest response
|
||||||
|
const responses = responseQuery.data.sort(
|
||||||
|
(a, b) => a.timestamp - b.timestamp
|
||||||
|
);
|
||||||
const categoryMetadata = metadataQuery.data;
|
const categoryMetadata = metadataQuery.data;
|
||||||
|
|
||||||
if (!responses.length) return null;
|
if (!responses.length) return null;
|
||||||
@@ -38,27 +41,21 @@ function App() {
|
|||||||
d3.group(responses, (d) => d.question).entries()
|
d3.group(responses, (d) => d.question).entries()
|
||||||
);
|
);
|
||||||
|
|
||||||
// Get unique response categories (sorted for consistent ordering)
|
|
||||||
const allResponses = [...new Set(responses.map((d) => d.response))];
|
|
||||||
const sortedResponses = allResponses.sort((a, b) => a - b);
|
|
||||||
|
|
||||||
// Create scales
|
// Create scales
|
||||||
const xScale = d3
|
|
||||||
.scaleBand<number>()
|
|
||||||
.domain(sortedResponses)
|
|
||||||
.range([0, sortedResponses.length * config.groupSpacing]);
|
|
||||||
return (
|
return (
|
||||||
<div className="layout">
|
<div className="layout">
|
||||||
<div className="chart-container">
|
<div className="chart-container">
|
||||||
<div className="charts">
|
<div className="charts">
|
||||||
{questionGroups.map(([question, groupData]) => (
|
{questionGroups.map(([question, groupData]) => (
|
||||||
<QuestionGroupChart
|
<WaffleChart
|
||||||
key={question}
|
key={question}
|
||||||
question={question}
|
question={question}
|
||||||
metadata={categoryMetadata.find((m) => m.category === question)}
|
metadata={categoryMetadata.find((m) => m.category === question)}
|
||||||
groupData={groupData}
|
groupData={groupData}
|
||||||
responses={sortedResponses}
|
responses={[...new Set(responses.map((d) => d.response))]}
|
||||||
xScale={xScale}
|
latestResponseTimestamp={
|
||||||
|
responses[responses.length - 1].timestamp
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export function Instructions() {
|
export function Instructions() {
|
||||||
return (
|
return (
|
||||||
<div className="instructions-container">
|
<>
|
||||||
<img src="/placeholder-instructions.svg" alt="Instructions" />
|
<img width="400" src="/placeholder-instructions.svg" alt="Instructions" />
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,12 @@ export default function QRCode() {
|
|||||||
Scanne den Code und zeige, welche KI-Skills du mitbringst — ganz
|
Scanne den Code und zeige, welche KI-Skills du mitbringst — ganz
|
||||||
egal, auf welchem Level du bist.
|
egal, auf welchem Level du bist.
|
||||||
</p>
|
</p>
|
||||||
<div className="qr-code bracket-frame">
|
<div className="qr-code">
|
||||||
<img src="/qr_code_ki-skills-umfrage.png" />
|
<img
|
||||||
|
className="viewfinder"
|
||||||
|
src="/qr_code_ki-skills-umfrage.png"
|
||||||
|
alt="QR Code"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,25 +1,27 @@
|
|||||||
import MaterialIcon from "@mui/material/Icon";
|
import MaterialIcon from "@mui/material/Icon";
|
||||||
import * as d3 from "d3";
|
import * as d3 from "d3";
|
||||||
import { useEffect, useRef } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
|
|
||||||
import { colorScheme, config } from "../config";
|
import { colorScheme, config } from "../config";
|
||||||
|
|
||||||
import { CategoryMetadata } from "../lib/metadata";
|
import { CategoryMetadata } from "../lib/metadata";
|
||||||
|
import { ResponseData } from "../lib/parser";
|
||||||
|
|
||||||
import "./Chart.css";
|
import "../styles/Chart.scss";
|
||||||
|
|
||||||
interface QuestionGroupChartProps {
|
interface QuestionGroupChartProps {
|
||||||
question: string;
|
question: string;
|
||||||
metadata?: CategoryMetadata;
|
metadata?: CategoryMetadata;
|
||||||
groupData: { response: number }[];
|
groupData: ResponseData[];
|
||||||
responses: number[];
|
responses: number[];
|
||||||
xScale: d3.ScaleBand<number>;
|
latestResponseTimestamp: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeDot(
|
function makeDot(
|
||||||
g: d3.Selection<SVGGElement, unknown, null, undefined>,
|
g: d3.Selection<SVGGElement, unknown, null, undefined>,
|
||||||
dotX: number,
|
dotX: number,
|
||||||
dotY: number
|
dotY: number
|
||||||
) {
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
): d3.Selection<any, unknown, null, undefined> {
|
||||||
const shape = config.dotShape;
|
const shape = config.dotShape;
|
||||||
if (shape === "circle") {
|
if (shape === "circle") {
|
||||||
return g
|
return g
|
||||||
@@ -40,23 +42,30 @@ function makeDot(
|
|||||||
throw new Error(`Unsupported shape: ${shape}`);
|
throw new Error(`Unsupported shape: ${shape}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function QuestionGroupChart({
|
export function WaffleChart({
|
||||||
question,
|
question,
|
||||||
metadata,
|
metadata,
|
||||||
groupData,
|
groupData,
|
||||||
responses,
|
responses,
|
||||||
xScale,
|
latestResponseTimestamp,
|
||||||
}: QuestionGroupChartProps) {
|
}: QuestionGroupChartProps) {
|
||||||
const svgRef = useRef(null);
|
const svgRef = useRef(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const sortedResponses = [...responses].sort((a, b) => a - b);
|
||||||
|
|
||||||
|
const chartHeight = config.chartHeight;
|
||||||
|
const chartWidth = responses.length * config.groupSpacing;
|
||||||
|
const xScale = d3
|
||||||
|
.scaleBand<number>()
|
||||||
|
.domain([0, 1, 2, 3, 4])
|
||||||
|
.range([0, chartWidth]);
|
||||||
|
|
||||||
// Clear SVG
|
// Clear SVG
|
||||||
d3.select(svgRef.current).selectAll("*").remove();
|
d3.select(svgRef.current).selectAll("*").remove();
|
||||||
|
|
||||||
// Group responses by category (within this group only)
|
// Group responses by category (within this group only)
|
||||||
const responseGroups = d3.group(groupData, (d) => d.response);
|
const responseGroups = d3.group(groupData, (d) => d.response);
|
||||||
const chartHeight = config.chartHeight;
|
|
||||||
const chartWidth = xScale.range()[1];
|
|
||||||
|
|
||||||
const svg = d3
|
const svg = d3
|
||||||
.select(svgRef.current)
|
.select(svgRef.current)
|
||||||
@@ -64,25 +73,45 @@ export function QuestionGroupChart({
|
|||||||
.attr("height", chartHeight);
|
.attr("height", chartHeight);
|
||||||
const g = svg.append("g");
|
const g = svg.append("g");
|
||||||
|
|
||||||
|
// Create x-axis
|
||||||
|
if (config.renderXAxis) {
|
||||||
|
const axisY = chartHeight - config.dotRadius - config.dotSpacing;
|
||||||
|
g.append("line")
|
||||||
|
.attr("x1", 0)
|
||||||
|
.attr("y1", axisY)
|
||||||
|
.attr("x2", chartWidth)
|
||||||
|
.attr("y2", axisY)
|
||||||
|
.attr("stroke", "#000")
|
||||||
|
.attr("stroke-width", 0.5)
|
||||||
|
.attr("stroke-dasharray", "2,2");
|
||||||
|
}
|
||||||
|
|
||||||
// Dots
|
// Dots
|
||||||
responses.forEach((response) => {
|
sortedResponses.forEach((response) => {
|
||||||
const responseData = responseGroups.get(response) || [];
|
const responseData = responseGroups.get(response) || [];
|
||||||
const x = xScale(response) || 0;
|
// Use xScale(response) as the group center
|
||||||
responseData.forEach((_, index) => {
|
const x = (xScale(response) || 0) + config.dotRadius;
|
||||||
|
responseData.forEach((entry, index) => {
|
||||||
const row = Math.floor(index / config.columnsPerGroup);
|
const row = Math.floor(index / config.columnsPerGroup);
|
||||||
const col = index % config.columnsPerGroup;
|
const col = index % config.columnsPerGroup;
|
||||||
const dotX =
|
const dotX =
|
||||||
x +
|
x +
|
||||||
xScale.bandwidth() / 2 +
|
|
||||||
(col - (config.columnsPerGroup - 1) / 2) *
|
(col - (config.columnsPerGroup - 1) / 2) *
|
||||||
(config.dotRadius * 2 + config.dotSpacing);
|
(config.dotRadius * 2 + config.dotSpacing);
|
||||||
const dotY =
|
const dotY =
|
||||||
chartHeight - (row + 1) * (config.dotRadius * 2 + config.dotSpacing);
|
chartHeight - (row + 1) * (config.dotRadius * 2 + config.dotSpacing);
|
||||||
|
|
||||||
makeDot(g, dotX, dotY).attr("fill", colorScheme[response] || "#666");
|
const dot = makeDot(g, dotX, dotY).attr(
|
||||||
|
"fill",
|
||||||
|
colorScheme[response] || "#666"
|
||||||
|
);
|
||||||
|
const isLatest = entry.timestamp === latestResponseTimestamp;
|
||||||
|
if (isLatest) {
|
||||||
|
dot.attr("class", "latest");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}, [groupData, responses, xScale, question]);
|
}, [groupData, responses, question, latestResponseTimestamp]);
|
||||||
return (
|
return (
|
||||||
<div className="question-group">
|
<div className="question-group">
|
||||||
<svg ref={svgRef}></svg>
|
<svg ref={svgRef}></svg>
|
||||||
@@ -94,5 +123,3 @@ export function QuestionGroupChart({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default QuestionGroupChart;
|
|
||||||
@@ -1,15 +1,16 @@
|
|||||||
const dotRadius = 8;
|
const dotRadius = 7;
|
||||||
const dotSpacing = 2;
|
const dotSpacing = 1;
|
||||||
const columnsPerGroup = 3;
|
const columnsPerGroup = 3;
|
||||||
const groupGap = 8;
|
const groupGap = dotRadius;
|
||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
dotRadius,
|
dotRadius,
|
||||||
dotSpacing,
|
dotSpacing,
|
||||||
columnsPerGroup,
|
columnsPerGroup,
|
||||||
groupSpacing: (2 * dotRadius + dotSpacing) * columnsPerGroup + groupGap,
|
groupSpacing: (2 * dotRadius + dotSpacing) * columnsPerGroup + groupGap,
|
||||||
chartHeight: 150,
|
chartHeight: 50,
|
||||||
dotShape: "rect", // "circle" or "rect"
|
dotShape: "rect", // "circle" or "rect"
|
||||||
|
renderXAxis: true, // Whether to render the x-axis
|
||||||
};
|
};
|
||||||
|
|
||||||
// Color scheme for Likert scale responses
|
// Color scheme for Likert scale responses
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"main qr"
|
"main qr"
|
||||||
"main instructions";
|
"main instructions";
|
||||||
grid-template-columns: auto 25%;
|
grid-template-columns: auto 400px;
|
||||||
grid-template-rows: auto auto;
|
grid-template-rows: 1fr 1fr;
|
||||||
grid-gap: 25px;
|
grid-gap: 36px;
|
||||||
|
|
||||||
margin: 25px;
|
margin: 75px 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chart-container {
|
.chart-container {
|
||||||
@@ -19,7 +19,10 @@
|
|||||||
grid-area: main;
|
grid-area: main;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 50px;
|
align-items: center;
|
||||||
|
|
||||||
|
padding: 75px 50px;
|
||||||
|
margin: 0;
|
||||||
gap: 50px;
|
gap: 50px;
|
||||||
|
|
||||||
background-color: $bg-grey;
|
background-color: $bg-grey;
|
||||||
@@ -31,40 +34,45 @@
|
|||||||
gap: 25px;
|
gap: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.qr {
|
||||||
|
grid-area: qr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.instructions {
|
||||||
|
grid-area: instructions;
|
||||||
|
}
|
||||||
|
|
||||||
.question-group {
|
.question-group {
|
||||||
@include rounded;
|
@include shadow-small;
|
||||||
@include shadow;
|
|
||||||
|
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 16px;
|
|
||||||
|
|
||||||
flex: 1 1 300px;
|
padding: 28px 14px;
|
||||||
|
|
||||||
|
flex: 0 1 250px;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: start;
|
align-items: start;
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.question-group svg {
|
svg {
|
||||||
align-self: center;
|
align-self: center;
|
||||||
margin-bottom: 16px;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.question-group p {
|
p {
|
||||||
font-size: 14px;
|
margin: 0;
|
||||||
color: #666;
|
}
|
||||||
line-height: 1.4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.question-title {
|
.question-title {
|
||||||
font-size: 16px;
|
margin-block: 13px;
|
||||||
font-weight: bold;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.question-title .material-icons {
|
font-size: 15px;
|
||||||
vertical-align: top;
|
font-weight: 600;
|
||||||
margin-right: 1ex;
|
|
||||||
|
.material-icons {
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
|
@use "shared" as *;
|
||||||
|
|
||||||
.dot {
|
.dot {
|
||||||
stroke: #fff;
|
stroke: #fff;
|
||||||
stroke-width: 1;
|
stroke-width: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.selected {
|
.latest {
|
||||||
fill: rgb(223 110 38);
|
fill: rgba(255, 125, 67, 1); //$aai-orange;
|
||||||
}
|
}
|
||||||
|
|
||||||
.axis-label {
|
.axis-label {
|
||||||
@@ -6,18 +6,21 @@
|
|||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
margin-right: 8px;
|
margin-right: 5px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
@include shadow;
|
@include shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin: 16px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 16px;
|
gap: 20px;
|
||||||
|
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,12 @@
|
|||||||
|
|
||||||
.qr-code-container {
|
.qr-code-container {
|
||||||
@include rounded;
|
@include rounded;
|
||||||
|
@include shadow;
|
||||||
|
|
||||||
background-color: $aai-orange;
|
background-color: $aai-orange;
|
||||||
flex-basis: 20%;
|
padding: 40px 25px;
|
||||||
flex-shrink: 0;
|
|
||||||
padding: 16px;
|
|
||||||
|
|
||||||
color: #fff;
|
color: $bg-grey;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -16,14 +15,92 @@
|
|||||||
|
|
||||||
p {
|
p {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.qr-code {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: $border-radius;
|
||||||
|
padding: 25px;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
display: block;
|
display: block;
|
||||||
margin: 0 auto;
|
width: 150px;
|
||||||
background-color: #fff;
|
}
|
||||||
border-radius: 16px;
|
|
||||||
padding: 16px;
|
|
||||||
width: 50%;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.viewfinder {
|
||||||
|
$viewfinder-size: 24px;
|
||||||
|
$viewfinder-color: $aai-orange;
|
||||||
|
$viewfinder-width: 4px;
|
||||||
|
padding: $viewfinder-width;
|
||||||
|
background:
|
||||||
|
/* Top-left corner */ linear-gradient(
|
||||||
|
to right,
|
||||||
|
$viewfinder-color 0%,
|
||||||
|
$viewfinder-color $viewfinder-size,
|
||||||
|
transparent $viewfinder-size
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
to bottom,
|
||||||
|
$viewfinder-color 0%,
|
||||||
|
$viewfinder-color $viewfinder-size,
|
||||||
|
transparent $viewfinder-size
|
||||||
|
),
|
||||||
|
/* Top-right corner */
|
||||||
|
linear-gradient(
|
||||||
|
to left,
|
||||||
|
$viewfinder-color 0%,
|
||||||
|
$viewfinder-color $viewfinder-size,
|
||||||
|
transparent $viewfinder-size
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
to bottom,
|
||||||
|
$viewfinder-color 0%,
|
||||||
|
$viewfinder-color $viewfinder-size,
|
||||||
|
transparent $viewfinder-size
|
||||||
|
),
|
||||||
|
/* Bottom-left corner */
|
||||||
|
linear-gradient(
|
||||||
|
to right,
|
||||||
|
$viewfinder-color 0%,
|
||||||
|
$viewfinder-color $viewfinder-size,
|
||||||
|
transparent $viewfinder-size
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
to top,
|
||||||
|
$viewfinder-color 0%,
|
||||||
|
$viewfinder-color $viewfinder-size,
|
||||||
|
transparent $viewfinder-size
|
||||||
|
),
|
||||||
|
/* Bottom-right corner */
|
||||||
|
linear-gradient(
|
||||||
|
to left,
|
||||||
|
$viewfinder-color 0%,
|
||||||
|
$viewfinder-color $viewfinder-size,
|
||||||
|
transparent $viewfinder-size
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
to top,
|
||||||
|
$viewfinder-color 0%,
|
||||||
|
$viewfinder-color $viewfinder-size,
|
||||||
|
transparent $viewfinder-size
|
||||||
|
);
|
||||||
|
|
||||||
|
background-size:
|
||||||
|
/* Top-left */ 100% $viewfinder-width,
|
||||||
|
$viewfinder-width 100%, /* Top-right */ 100% $viewfinder-width,
|
||||||
|
$viewfinder-width 100%, /* Bottom-left */ 100% $viewfinder-width,
|
||||||
|
$viewfinder-width 100%, /* Bottom-right */ 100% $viewfinder-width,
|
||||||
|
$viewfinder-width 100%;
|
||||||
|
|
||||||
|
background-position:
|
||||||
|
/* Top-left */ 0 0, 0 0,
|
||||||
|
/* Top-right */ 100% 0, 100% 0, /* Bottom-left */ 0 100%, 0 100%,
|
||||||
|
/* Bottom-right */ 100% 100%, 100% 100%;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,44 +9,19 @@ $aai-orange: hsl(18.6deg 100% 55.1%);
|
|||||||
|
|
||||||
$bg-grey: #f8f9fa;
|
$bg-grey: #f8f9fa;
|
||||||
|
|
||||||
|
$border-radius: 30px;
|
||||||
@mixin rounded {
|
@mixin rounded {
|
||||||
border-radius: 16px;
|
border-radius: $border-radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin shadow {
|
@mixin shadow {
|
||||||
box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25);
|
box-shadow: 0px 4px 4px 0 rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin shadow-small {
|
||||||
|
box-shadow: 0px 2px 2px 0 rgba(0, 0, 0, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin no-shadow {
|
@mixin no-shadow {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
$border-radius: 16px;
|
|
||||||
|
|
||||||
@mixin button {
|
|
||||||
@include shadow;
|
|
||||||
|
|
||||||
background-color: $aai-action-button;
|
|
||||||
color: #ffffff;
|
|
||||||
|
|
||||||
border-radius: $border-radius;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
@include no-shadow;
|
|
||||||
}
|
|
||||||
|
|
||||||
span {
|
|
||||||
flex: 1 auto;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-align: center;
|
|
||||||
font-weight: bold;
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,21 +1,15 @@
|
|||||||
@use "shared" as *;
|
@use "shared" as *;
|
||||||
@import "normalize-scss";
|
@use "normalize-scss" as normalize;
|
||||||
|
|
||||||
@include normalize();
|
@include normalize.normalize();
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
font-family: "Work Sans", system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||||
line-height: 1.5;
|
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|
||||||
color-scheme: only light;
|
color-scheme: only light;
|
||||||
color: #213547;
|
color: $aai-blue-dark;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
|
|
||||||
font-synthesis: none;
|
|
||||||
text-rendering: optimizeLegibility;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h1,
|
h1,
|
||||||
@@ -24,8 +18,8 @@ h3,
|
|||||||
h4,
|
h4,
|
||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
font-family: "Work Sans", sans-serif;
|
font-weight: 600;
|
||||||
font-weight: 800;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
@@ -36,11 +30,3 @@ a {
|
|||||||
a:hover {
|
a:hover {
|
||||||
color: $aai-blue-light;
|
color: $aai-blue-light;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
display: flex;
|
|
||||||
place-items: center;
|
|
||||||
min-width: 320px;
|
|
||||||
min-height: 100vh;
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user