Administración pública y servicios públicos · Nuevo recurso

Sistema de diseño Suomi.fi.

Crea formularios legibles para los servicios públicos finlandeses con Source Sans 3, tokens de espaciado explícitos y un patrón recuperable de selección de documentos.

Guía de OpenDesign8 capítulos16 entradas de referenciaGuía de aplicación original
01

Vista previa de la interfaz de sistema de diseño Suomi.fi

Prueba con un PDF, rechaza un archivo no compatible y elimina el documento seleccionado. Los archivos permanecen en tu navegador.

Selecciona y elimina un archivo adjuntoAbrir ejemplo completo
Interpretación original de HTML/CSS del patrón documentado para un solo archivo; alternativa Arial. · Referencia de implementación
02

Referencia de diseño de sistema de diseño Suomi.fi

Documentación oficial, repositorio de tokens inspeccionado y metadatos de suomifi-ui-components 18.0.0. La vista previa es una interpretación original, no el entorno de ejecución nativo de React.

Tipografía

Fuente
Nombre / ReglaValor / ConfiguraciónUso
FamilySource Sans 3Versión 18; la versión 17 y las anteriores usaban Source Sans Pro. Carga las fuentes por separado.
Body text18pxEl mismo valor predeterminado en móviles y ordenadores.
Small body16pxTratamiento smallScreen de Text, no una regla automática según el tamaño de la ventana.
Lead22px / 20px smallScreenUna introducción por vista; no uses lead en todos los párrafos.
Weights300 / 400 / 600Recursos de fuentes requeridos por el paquete de componentes.

Espaciado y superficies

Fuente
Nombre / ReglaValor / ConfiguraciónUso
Space scale5, 10, 15, 20, 25, 30, 40, 60, 80pxDe xxs a xxxxl en el JSON del repositorio inspeccionado.
Inset scale2, 4, 6, 8, 10, 16, 20pxDe insetXxs a insetXxl; no es la escala de espaciado exterior.
Basic radius2pxrepository radius.basic; no deduzcas de ahí un radio grande para las tarjetas.
Highlight basehsl(212, 63%, 45%)Azul interactivo predeterminado.
Highlight dark 1hsl(212, 63%, 37%)Rol de interacción más oscuro.
Highlight light 2hsl(212, 63%, 90%)Rol de superficie clara; comprueba el contraste con el texto elegido.

Distribución e idioma de FileInput

Fuente
Nombre / ReglaValor / ConfiguraciónUso
Default maximum width600pxAncho específico del componente, no una cuadrícula para todo el sitio.
fullWidthBoolean layout optionOcupa todo el espacio disponible dentro del contenedor cuando el formulario lo necesite.
smallScreenExplicit compact presentation optionNo deduzcas de esta propiedad un punto de ruptura global automático.
Single selectionChosen file replaces picker and drop areaLa selección múltiple es un patrón distinto, con los archivos enumerados debajo.
Required copy roleslabelText, hintText, dragAreaText, removeFileText, addedFileAriaTextLocaliza cada función; el nombre del archivo por sí solo no es un anuncio accesible completo.
03

Guía completa de sistema de diseño Suomi.fi

Una guía práctica para elegir, aplicar y revisar este sistema en una interfaz real.

DESIGN-suomi-fi.md

Orientación completa, un punto de partida para la implementación y enlaces al código fuente.

Descargar la guía

Límites de la implementación de sistema de diseño Suomi.fi

Sistema de componentes de React

Suomi.fi proporciona React componentes con estilos mediante styled-components y un paquete de tokens independiente. La versión 18 establece Source Sans 3 como fuente esperada. Es posible que las páginas existentes de la versión 17 sigan usando Source Sans Pro; comparar sus capturas de pantalla sin comprobar la versión del paquete puede llevar a corregir la tipografía sin necesidad.

De esta guía de OpenDesign

La vista previa integrada sigue siendo una interpretación, claramente etiquetada, del patrón documentado de archivo único en HTML/CSS. A continuación se incluye un ejemplo independiente de FileInput nativo de React con su callback verificado, valor controlado, dependencias e importaciones de fuentes. Son dos implementaciones de la misma tarea de selección local; el ejemplo nativo no convierte retroactivamente la vista previa integrada de HTML en el componente de React.

Consulta la especificación complementaria

Tipografía y carga de fuentes de sistema de diseño Suomi.fi

Mantén el texto fácil de leer

Usa el tamaño de texto para el cuerpo documentado de 18px tanto en móviles como en ordenadores. Una ventana gráfica estrecha no justifica reducir todas las explicaciones de los formularios. El tratamiento de texto pequeño es de 16px y corresponde a la información secundaria. El texto introductorio es de 22px, y se reduce a 20px con el tratamiento compacto; resérvalo para la introducción de la página.

Carga los pesos de fuente previstos antes de comparar el ajuste de línea. El paquete del componente requiere recursos de Source Sans 3, mientras que esta vista previa independiente usa Arial deliberadamente. Esta sustitución se indica en la nota de la vista previa y no debe presentarse como una representación exacta del componente nativo.

Consulta la especificación complementaria

Espaciado y anchura de sistema de diseño Suomi.fi

Dos escalas de espaciado diferentes

La fuente de tokens distingue entre el espaciado normal y el espaciado interno. En el JSON inspeccionado, l corresponde a 25px; no copies un ejemplo antiguo del README que indica que l equivale a 32px. El espaciado interno empieza en 2px y sigue una secuencia diferente. Genera los estilos a partir de las exportaciones reales de la versión instalada.

FileInput tiene una anchura máxima documentada de 600px y una opción fullWidth. Es una restricción del componente, no una prueba de que todas las páginas deban tener un contenedor de 600px. Un formulario para recopilar documentos puede situar el campo en una disposición más amplia y mantener el texto explicativo cerca de su etiqueta.

Consulta la especificación complementaria

Anatomía del selector de archivos de sistema de diseño Suomi.fi

El texto forma parte del contrato del componente

La etiqueta visible indica el documento solicitado. La indicación explica los formatos admitidos, el tamaño y el número de archivos antes de que la persona abra el selector. El área para arrastrar y soltar ofrece un atajo con el puntero, pero no debe sustituir al campo de entrada de archivos. Las indicaciones oficiales especifican que el control de selección debe ser la etiqueta de un campo de entrada de archivos nativo oculto.

En el modo de archivo único, el documento seleccionado sustituye al selector y al área para arrastrar y soltar. Mantén una acción clara para quitarlo junto al documento. El modo de varios archivos usa una disposición de lista diferente; no añadas archivos adicionales silenciosamente a una solicitud de archivo único.

  • labelText: indica el justificante o documento solicitado, no te limites a «Subir».
  • removeFileText: haz que la acción para quitar el archivo se entienda en su contexto.
  • addedFileAriaText: proporciona contexto de selección antes de que se anuncie el nombre del archivo.

Consulta la especificación complementaria

Selección y recuperación de sistema de diseño Suomi.fi

Una máquina de estados para archivos adjuntos locales

El ejemplo acepta un único PDF de hasta 5,000,000 bytes. Estas reglas de la aplicación se han elegido para este caso práctico. No son valores predeterminados del paquete ni una política oficial de carga de Suomi.fi. El filtro accept del navegador es solo una indicación para el selector; el ejemplo comprueba por separado el nombre y el tamaño del archivo después de seleccionarlo o arrastrarlo.

Si los metadatos no son válidos, el selector sigue disponible y se explica cómo recuperarse. Una selección válida muestra el nombre mediante textContent, indica el número de bytes y mueve el foco al control para quitar el archivo. Al quitarlo, se borra el valor del campo de entrada subyacente, se restaura el selector y se devuelve el foco, lo que permite seleccionar de nuevo el mismo archivo.

  1. Selecciona o arrastra exactamente un archivo; si hay varios, recházalos con un mensaje específico.
  2. Comprueba las reglas del ejemplo local y anuncia el error o el nombre del archivo seleccionado.
  3. Quita el archivo adjunto y restaura la opción de selección original.

Consulta la especificación complementaria

Integración nativa de sistema de diseño Suomi.fi

Instala un conjunto de dependencias compatible

La implementación publicada de FileInput de la versión 18.0.0 llama a onChange con un FileList, no con un evento React change. El valor controlado es una matriz de objetos de archivo; el ejemplo convierte cada File aceptado en { file }. El mismo callback se ejecuta cuando la acción integrada para quitar archivos modifica la lista, por lo que un FileList vacío vacía la matriz controlada. Estos contratos se comprobaron en el módulo publicado dist/esm/core/Form/FileInput/FileInput.js.

Mantén el valor controlado desde el primer renderizado, inicializándolo como una matriz vacía. Valida el FileList recibido antes de convertirlo en esa matriz. Este ejemplo rechaza los archivos cuyos nombres no terminan en .pdf o cuyo tamaño supera los 5,000,000 bytes, y borra la selección si se rechazan. Son reglas locales del ejemplo, no una comprobación de seguridad ni una política de Suomi.fi. Antes de aceptar una carga real, sigue siendo necesario validar el contenido en el servidor.

El ejemplo nativo de abajo carga Source Sans 3 con los pesos 400 y 600, monta React en un elemento raíz explícito y usa styled-components a través de la biblioteca. Incluye tslib explícitamente: los módulos ESM de la versión 18.0.0 importan sus funciones auxiliares, y una compilación limpia falló sin esa dependencia. La configuración fijada de abajo incluye el recurso de ejecución que faltaba y los recursos de las fuentes. Este ejemplo con el tema predeterminado no necesita ningún proveedor de temas adicional.

Consulta la especificación complementaria

Usa exportaciones de tokens verificadas

La guía oficial de estilos muestra suomifiDesignTokens.spacing y suomifiDesignTokens.colors. El ejemplo de abajo usa esas rutas exportadas para un contenedor personalizado; no es una implementación sustitutiva de los componentes internos de FileInput.

tsx
import { suomifiDesignTokens } from 'suomifi-design-tokens';
// Real exported token paths. Use values instead of copying README example numbers.
const attachmentStyle = {
  maxWidth: 600,
  padding: suomifiDesignTokens.spacing.m,
  borderColor: suomifiDesignTokens.colors.highlightBase
};

Referencia de código

Consulta la especificación complementaria

Accesibilidad y uso adaptable de sistema de diseño Suomi.fi

Accede al campo sin arrastrar

Mantén un campo de entrada de archivos nativo y operable con el teclado, aunque el área para arrastrar y soltar sea prominente. Asocia la indicación y el error mediante aria-describedby. Anuncia los cambios de selección y la eliminación sin volver a leer toda la página. Si en un formulario puede haber varios controles de este tipo, el botón para quitar el archivo debe identificar el archivo seleccionado.

La propiedad oficial smallScreen ofrece una presentación compacta. No establece un punto de ruptura global. Esta vista previa independiente aplica un ajuste de relleno de 480px específico de la aplicación y mantiene el texto del cuerpo en 18px. Prueba nombres de archivo largos, el zoom y las etiquetas traducidas; permite que los nombres de archivo se ajusten en varias líneas sin ensanchar toda la página.

Consulta la especificación complementaria

Sistema de diseño Suomi.fi Responsabilidades de producción

Un archivo seleccionado no es un archivo subido

La demostración nunca lee el contenido de los documentos ni envía solicitudes. El nombre y el tamaño en bytes de un archivo seleccionado no demuestran que el documento sea válido, esté almacenado o se haya aceptado. Los servicios reales necesitan validación en el servidor, progreso de carga, gestión de errores recuperable, reglas de conservación y una confirmación vinculada a una respuesta real.

El código del componente está bajo licencia MIT. Esa licencia no autoriza a un proyecto independiente a presentarse como un servicio del Gobierno de Finlandia ni a utilizar una identidad institucional restringida. Usa un nombre de proyecto neutral para los experimentos y solicita las directrices de marca pertinentes para una implementación oficial.

Consulta la especificación complementaria

Sistema de diseño Suomi.fi Ejemplos de componentes del sistema de diseño

Usa las exportaciones oficiales de tokens

Rutas verificadas de exportación de espaciado y color para un contenedor personalizado.

tsx
import { suomifiDesignTokens } from 'suomifi-design-tokens';
// Real exported token paths. Use values instead of copying README example numbers.
const attachmentStyle = {
  maxWidth: 600,
  padding: suomifiDesignTokens.spacing.m,
  borderColor: suomifiDesignTokens.colors.highlightBase
};

Referencia de código

Selección y eliminación de un solo archivo

Interpretación local completa. Los límites de PDF y tamaño son decisiones del escenario; no se sube ningún archivo.

HTML
<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Attachment example</title><style>*{box-sizing:border-box}body{margin:0;padding:30px 20px;font:18px/1.5 Arial,sans-serif;color:#202020;background:#fff}main{max-width:600px;margin:auto}h1{font-size:32px;line-height:1.2;font-weight:400;margin:0 0 20px}p{margin:0 0 20px}label{font-weight:600;display:block}small{display:block;font-size:16px}.drop{margin-top:15px;border:2px dashed hsl(212,63%,45%);padding:30px;text-align:center;background:hsl(212,63%,90%)}button,input::file-selector-button{font:600 18px Arial;padding:12px 20px;border:1px solid hsl(212,63%,37%);border-radius:2px;background:hsl(212,63%,45%);color:white;cursor:pointer}button:focus-visible,input:focus-visible{outline:3px solid #202020;outline-offset:3px}input{width:100%;font-size:16px;margin:15px 0}input::file-selector-button{margin-right:10px}.file{border:1px solid #777;padding:20px;margin:20px 0;overflow-wrap:anywhere}.file button{margin-top:15px;background:white;color:hsl(212,63%,37%)}#error{color:#a32020;font-weight:bold}footer{font-size:14px;margin-top:30px;border-top:1px solid #ccc;padding-top:15px}[hidden]{display:none!important}@media(max-width:480px){body{padding:20px 15px}.drop{padding:20px}h1{font-size:28px}}</style><main><small>COMMUNITY WORKSHOP · ATTACHMENT</small><h1>Add your project outline</h1><p>Choose one PDF up to 5 MB. This local example checks file metadata; it does not read or send the document.</p><div id="picker"><label for="file">Project outline</label><small id="hint">One PDF file. Maximum 5 MB (5,000,000 bytes).</small><input id="file" type="file" accept=".pdf,application/pdf" aria-describedby="hint error"><div class="drop" id="drop">Or drop one PDF here</div></div><p id="error" role="alert" hidden></p><section id="selected" class="file" hidden aria-label="Selected attachment"><strong id="name"></strong><small id="size"></small><button id="remove" type="button">Remove file</button></section><p id="status" role="status">No file selected.</p><footer>OpenDesign interpretation of the Suomi.fi attachment pattern. Arial fallback; no official identity or React component runtime. PDF and 5 MB are example rules.</footer></main><script>const input=document.querySelector('#file'),picker=document.querySelector('#picker'),selected=document.querySelector('#selected'),error=document.querySelector('#error'),status=document.querySelector('#status');function choose(files){error.hidden=true;if(files.length!==1){error.textContent='Choose exactly one file.';error.hidden=false;input.value='';return}const file=files[0];if(!/\.pdf$/i.test(file.name)||file.size>5000000){error.textContent='Choose a PDF no larger than 5 MB.';error.hidden=false;input.setAttribute('aria-invalid','true');input.value='';return}input.removeAttribute('aria-invalid');document.querySelector('#name').textContent=file.name;document.querySelector('#size').textContent=file.size.toLocaleString('en')+' bytes · selected locally';document.querySelector('#remove').setAttribute('aria-label','Remove '+file.name);picker.hidden=true;selected.hidden=false;status.textContent='Selected file: '+file.name;document.querySelector('#remove').focus()}input.addEventListener('change',()=>{if(input.files.length)choose(input.files)});document.querySelector('#drop').addEventListener('dragover',e=>e.preventDefault());document.querySelector('#drop').addEventListener('drop',e=>{e.preventDefault();choose(e.dataTransfer.files)});document.querySelector('#remove').onclick=()=>{input.value='';picker.hidden=false;selected.hidden=true;error.hidden=true;input.removeAttribute('aria-invalid');status.textContent='File removed. Choose another file.';input.focus()};</script></html>

Referencia de código

  • No es el componente nativo React.
  • En un servicio de producción, valida el contenido de los archivos en el servidor.

FileInput nativo con validación controlada

Guárdalo como main.jsx. Estos tres archivos juntos reproducen el ejemplo nativo de React mediante los comandos de configuración.

jsx
import React, { useState } from 'react';
import { createRoot } from 'react-dom/client';
import { FileInput } from 'suomifi-ui-components';
import '@fontsource/source-sans-3/400.css';
import '@fontsource/source-sans-3/600.css';
import './app.css';
function App() {
  const [value, setValue] = useState([]);
  const [error, setError] = useState('');
  function change(files) {
    const next = Array.from(files);
    const invalid = next.length > 1 || next.some(file => !/\.pdf$/i.test(file.name) || file.size > 5000000);
    if (invalid) {
      setValue([]);
      setError('Choose one PDF no larger than 5 MB.');
      return;
    }
    setValue(next.map(file => ({ file })));
    setError('');
  }
  return <main><h1>Select a workshop document</h1><p>This local example does not upload or read the document.</p>
    <FileInput id="document" labelText="Workshop document" hintText="One PDF, maximum 5 MB (5,000,000 bytes)."
      inputButtonText="Choose PDF" dragAreaText="or drop a PDF here" removeFileText="Remove file"
      addedFileAriaText="Selected file" accept=".pdf" value={value} onChange={change}
      status={error ? 'error' : 'default'} statusText={error} />
    <p role="status">{value.length ? `${value[0].file.name} selected locally.` : 'No file selected.'}</p>
  </main>;
}
createRoot(document.getElementById('root')).render(<App />);

Referencia de código

  • La aplicación se encarga de la validación; el componente nativo proporciona la selección, la eliminación y sus controles de archivo accesibles.

Diseño de página del ejemplo nativo

Guárdalo como app.css. Estos tres archivos juntos reproducen el ejemplo nativo de React mediante los comandos de configuración.

css
body{margin:0;font:18px/1.5 'Source Sans 3',sans-serif;color:#292929;background:#fff}main{max-width:600px;margin:0 auto;padding:24px}h1{font-size:32px;line-height:1.2}*{box-sizing:border-box}

Referencia de código

  • La aplicación se encarga de la validación; el componente nativo proporciona la selección, la eliminación y sus controles de archivo accesibles.

Montaje del ejemplo nativo y recursos emitidos

Guárdalo como index.html. Estos tres archivos juntos reproducen el ejemplo nativo de React mediante los comandos de configuración.

HTML
<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Native Suomi.fi FileInput</title><link rel="stylesheet" href="./app.css"><div id="root"></div><script type="module" src="./app.js"></script></html>

Referencia de código

  • La aplicación se encarga de la validación; el componente nativo proporciona la selección, la eliminación y sus controles de archivo accesibles.
04

Sistema de diseño Suomi.fi Configuración del agente

Punto de partida para la implementación

Esto compila el ejemplo nativo de React que aparece a continuación, incluidos los archivos locales de la fuente Source Sans 3. Se probó con un formato no válido, una selección válida, la eliminación integrada y un PDF demasiado grande, a 390px y 1440px. El ZIP de vista previa descargable existente es una interpretación separada de HTML/CSS; su README sigue siendo preciso.

bash
npm install --save-exact [email protected] [email protected] [email protected] [email protected] [email protected] @fontsource/[email protected]
npm install --save-dev --save-exact [email protected]
# Save main.jsx, app.css and index.html from the complete examples below.
npx esbuild main.jsx --bundle --outdir=dist --entry-names=app --loader:.woff=copy --loader:.woff2=copy
cp index.html dist/index.html
python3 -m http.server 8080 --directory dist
# Open http://localhost:8080

Una instrucción para tu proyecto

Instrucción para el agente
Usa el ejemplo nativo proporcionado de Suomi.fi FileInput 18.0.0 React con Source Sans 3 y las dependencias de ejecución fijadas, incluida tslib. Controla value como una matriz de objetos { file } y recibe FileList directamente en onChange; no leas event.target desde esa devolución de llamada. Valida el formato y el tamaño antes de aceptar una selección local, gestiona la lista vacía que se emite al eliminar y mantén visibles el texto de ayuda y el de error. Presenta la vista previa integrada de HTML como una interpretación con su propia etiqueta. Ninguna de las implementaciones sube archivos; la validación en el servidor, el progreso y la confirmación del almacenamiento requieren un contrato de backend real.
05

Sistema de diseño Suomi.fi Fuentes y alcance

La vista previa integrada y el ZIP descargable son una interpretación de OpenDesign HTML/CSS. El ejemplo completo y separado de React usa suomifi-ui-components 18.0.0 y los contratos verificados de value y onChange de FileInput. Ambos ejemplos permiten seleccionar archivos localmente; ninguno sube ni almacena documentos en un servidor.